From 44288db4414158ac9b98a507b15e81d0d3c66ca6 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 28 Jun 2013 15:26:06 +0700 Subject: Initial import of old CVS repository --- FxCop/CustomDictionary.xml | 119 + crypto-test/App.ico | Bin 0 -> 1078 bytes crypto-test/CryptoTest.cs | 51 + crypto-test/crypto-test.csproj | 104 + crypto-test/crypto-test.mdp | 27 + crypto/Contributors.html | 116 + crypto/License.html | 39 + crypto/NBuild.build | 265 + crypto/Readme.html | 455 + crypto/bzip2/src/BZip2Constants.cs | 103 + crypto/bzip2/src/CBZip2InputStream.cs | 919 ++ crypto/bzip2/src/CBZip2OutputStream.cs | 1691 +++ crypto/bzip2/src/CRC.cs | 134 + crypto/checklist.txt | 16 + crypto/crypto.csproj | 10628 +++++++++++++++++++ crypto/crypto.mdp | 2310 ++++ crypto/src/AssemblyInfo.cs | 81 + crypto/src/asn1/ASN1Generator.cs | 27 + crypto/src/asn1/ASN1OctetStringParser.cs | 10 + crypto/src/asn1/ASN1SequenceParser.cs | 8 + crypto/src/asn1/ASN1SetParser.cs | 8 + crypto/src/asn1/ASN1StreamParser.cs | 235 + crypto/src/asn1/ASN1TaggedObjectParser.cs | 10 + crypto/src/asn1/Asn1Encodable.cs | 78 + crypto/src/asn1/Asn1EncodableVector.cs | 93 + crypto/src/asn1/Asn1Exception.cs | 30 + crypto/src/asn1/Asn1InputStream.cs | 368 + crypto/src/asn1/Asn1Null.cs | 18 + crypto/src/asn1/Asn1Object.cs | 63 + crypto/src/asn1/Asn1OctetString.cs | 119 + crypto/src/asn1/Asn1OutputStream.cs | 35 + crypto/src/asn1/Asn1ParsingException.cs | 29 + crypto/src/asn1/Asn1Sequence.cs | 268 + crypto/src/asn1/Asn1Set.cs | 351 + crypto/src/asn1/Asn1TaggedObject.cs | 178 + crypto/src/asn1/Asn1Tags.cs | 36 + crypto/src/asn1/BERGenerator.cs | 102 + crypto/src/asn1/BEROctetStringGenerator.cs | 117 + crypto/src/asn1/BEROctetStringParser.cs | 36 + crypto/src/asn1/BERSequenceGenerator.cs | 24 + crypto/src/asn1/BERSequenceParser.cs | 24 + crypto/src/asn1/BERSetGenerator.cs | 24 + crypto/src/asn1/BERSetParser.cs | 24 + crypto/src/asn1/BERTaggedObjectParser.cs | 71 + crypto/src/asn1/BerApplicationSpecific.cs | 15 + crypto/src/asn1/BerApplicationSpecificParser.cs | 29 + crypto/src/asn1/BerNull.cs | 35 + crypto/src/asn1/BerOctetString.cs | 135 + crypto/src/asn1/BerOutputStream.cs | 36 + crypto/src/asn1/BerSequence.cs | 69 + crypto/src/asn1/BerSet.cs | 70 + crypto/src/asn1/BerTaggedObject.cs | 108 + crypto/src/asn1/ConstructedOctetStream.cs | 102 + crypto/src/asn1/DERExternal.cs | 207 + crypto/src/asn1/DERExternalParser.cs | 26 + crypto/src/asn1/DERGenerator.cs | 107 + crypto/src/asn1/DEROctetStringParser.cs | 36 + crypto/src/asn1/DERSequenceGenerator.cs | 40 + crypto/src/asn1/DERSequenceParser.cs | 24 + crypto/src/asn1/DERSetGenerator.cs | 40 + crypto/src/asn1/DERSetParser.cs | 24 + crypto/src/asn1/DefiniteLengthInputStream.cs | 100 + crypto/src/asn1/DerApplicationSpecific.cs | 237 + crypto/src/asn1/DerBMPString.cs | 115 + crypto/src/asn1/DerBitString.cs | 248 + crypto/src/asn1/DerBoolean.cs | 110 + crypto/src/asn1/DerEnumerated.cs | 100 + crypto/src/asn1/DerGeneralString.cs | 81 + crypto/src/asn1/DerGeneralizedTime.cs | 305 + crypto/src/asn1/DerIA5String.cs | 145 + crypto/src/asn1/DerInteger.cs | 117 + crypto/src/asn1/DerNull.cs | 41 + crypto/src/asn1/DerNumericString.cs | 138 + crypto/src/asn1/DerObjectIdentifier.cs | 347 + crypto/src/asn1/DerOctetString.cs | 34 + crypto/src/asn1/DerOutputStream.cs | 160 + crypto/src/asn1/DerPrintableString.cs | 163 + crypto/src/asn1/DerSequence.cs | 85 + crypto/src/asn1/DerSet.cs | 108 + crypto/src/asn1/DerStringBase.cs | 22 + crypto/src/asn1/DerT61String.cs | 102 + crypto/src/asn1/DerTaggedObject.cs | 72 + crypto/src/asn1/DerUTCTime.cs | 263 + crypto/src/asn1/DerUTF8String.cs | 96 + crypto/src/asn1/DerUniversalString.cs | 107 + crypto/src/asn1/DerUnknownTag.cs | 80 + crypto/src/asn1/DerVisibleString.cs | 111 + crypto/src/asn1/IAsn1ApplicationSpecificParser.cs | 10 + crypto/src/asn1/IAsn1Choice.cs | 17 + crypto/src/asn1/IAsn1Convertible.cs | 7 + crypto/src/asn1/IAsn1String.cs | 10 + crypto/src/asn1/IndefiniteLengthInputStream.cs | 170 + crypto/src/asn1/LazyASN1InputStream.cs | 33 + crypto/src/asn1/LazyDERSequence.cs | 80 + crypto/src/asn1/LazyDERSet.cs | 80 + crypto/src/asn1/LimitedInputStream.cs | 35 + crypto/src/asn1/OidTokenizer.cs | 45 + crypto/src/asn1/bc/BCObjectIdentifiers.cs | 39 + crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs | 60 + crypto/src/asn1/cmp/CertConfirmContent.cs | 47 + crypto/src/asn1/cmp/CertOrEncCert.cs | 85 + crypto/src/asn1/cmp/CertRepMessage.cs | 94 + crypto/src/asn1/cmp/CertResponse.cs | 115 + crypto/src/asn1/cmp/CertStatus.cs | 84 + crypto/src/asn1/cmp/CertifiedKeyPair.cs | 114 + crypto/src/asn1/cmp/Challenge.cs | 79 + crypto/src/asn1/cmp/CmpCertificate.cs | 80 + crypto/src/asn1/cmp/CmpObjectIdentifiers.cs | 106 + crypto/src/asn1/cmp/CrlAnnContent.cs | 49 + crypto/src/asn1/cmp/ErrorMsgContent.cs | 94 + crypto/src/asn1/cmp/GenMsgContent.cs | 52 + crypto/src/asn1/cmp/GenRepContent.cs | 52 + crypto/src/asn1/cmp/InfoTypeAndValue.cs | 121 + crypto/src/asn1/cmp/KeyRecRepContent.cs | 115 + crypto/src/asn1/cmp/OobCertHash.cs | 87 + crypto/src/asn1/cmp/PKIBody.cs | 186 + crypto/src/asn1/cmp/PKIConfirmContent.cs | 34 + crypto/src/asn1/cmp/PKIFailureInfo.cs | 73 + crypto/src/asn1/cmp/PKIFreeText.cs | 97 + crypto/src/asn1/cmp/PKIHeader.cs | 237 + crypto/src/asn1/cmp/PKIHeaderBuilder.cs | 223 + crypto/src/asn1/cmp/PKIMessage.cs | 140 + crypto/src/asn1/cmp/PKIMessages.cs | 52 + crypto/src/asn1/cmp/PKIStatus.cs | 62 + crypto/src/asn1/cmp/PKIStatusInfo.cs | 165 + crypto/src/asn1/cmp/PbmParameter.cs | 100 + crypto/src/asn1/cmp/PollRepContent.cs | 66 + crypto/src/asn1/cmp/PollReqContent.cs | 59 + crypto/src/asn1/cmp/PopoDecKeyChallContent.cs | 47 + crypto/src/asn1/cmp/PopoDecKeyRespContent.cs | 47 + crypto/src/asn1/cmp/ProtectedPart.cs | 58 + crypto/src/asn1/cmp/RevAnnContent.cs | 86 + crypto/src/asn1/cmp/RevDetails.cs | 75 + crypto/src/asn1/cmp/RevRepContent.cs | 112 + crypto/src/asn1/cmp/RevRepContentBuilder.cs | 55 + crypto/src/asn1/cmp/RevReqContent.cs | 52 + crypto/src/asn1/cms/Attribute.cs | 70 + crypto/src/asn1/cms/AttributeTable.cs | 231 + crypto/src/asn1/cms/Attributes.cs | 55 + crypto/src/asn1/cms/AuthEnvelopedData.cs | 203 + crypto/src/asn1/cms/AuthEnvelopedDataParser.cs | 145 + crypto/src/asn1/cms/AuthenticatedData.cs | 270 + crypto/src/asn1/cms/AuthenticatedDataParser.cs | 182 + crypto/src/asn1/cms/CMSAttributes.cs | 14 + crypto/src/asn1/cms/CMSObjectIdentifiers.cs | 28 + crypto/src/asn1/cms/CompressedData.cs | 96 + crypto/src/asn1/cms/CompressedDataParser.cs | 47 + crypto/src/asn1/cms/ContentInfo.cs | 88 + crypto/src/asn1/cms/ContentInfoParser.cs | 40 + crypto/src/asn1/cms/EncryptedContentInfo.cs | 94 + crypto/src/asn1/cms/EncryptedContentInfoParser.cs | 46 + crypto/src/asn1/cms/EncryptedData.cs | 95 + crypto/src/asn1/cms/EnvelopedData.cs | 176 + crypto/src/asn1/cms/EnvelopedDataParser.cs | 107 + crypto/src/asn1/cms/Evidence.cs | 47 + crypto/src/asn1/cms/IssuerAndSerialNumber.cs | 64 + crypto/src/asn1/cms/KEKIdentifier.cs | 119 + crypto/src/asn1/cms/KEKRecipientInfo.cs | 106 + crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs | 92 + crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs | 141 + crypto/src/asn1/cms/KeyTransRecipientInfo.cs | 99 + crypto/src/asn1/cms/MetaData.cs | 94 + crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs | 168 + crypto/src/asn1/cms/OriginatorInfo.cs | 121 + crypto/src/asn1/cms/OriginatorPublicKey.cs | 87 + crypto/src/asn1/cms/OtherKeyAttribute.cs | 70 + crypto/src/asn1/cms/OtherRecipientInfo.cs | 83 + crypto/src/asn1/cms/OtherRevocationInfoFormat.cs | 77 + crypto/src/asn1/cms/PasswordRecipientInfo.cs | 133 + crypto/src/asn1/cms/RecipientEncryptedKey.cs | 88 + crypto/src/asn1/cms/RecipientIdentifier.cs | 89 + crypto/src/asn1/cms/RecipientInfo.cs | 145 + crypto/src/asn1/cms/RecipientKeyIdentifier.cs | 137 + crypto/src/asn1/cms/SCVPReqRes.cs | 77 + crypto/src/asn1/cms/SignedData.cs | 287 + crypto/src/asn1/cms/SignedDataParser.cs | 112 + crypto/src/asn1/cms/SignerIdentifier.cs | 89 + crypto/src/asn1/cms/SignerInfo.cs | 185 + crypto/src/asn1/cms/Time.cs | 118 + crypto/src/asn1/cms/TimeStampAndCRL.cs | 62 + crypto/src/asn1/cms/TimeStampTokenEvidence.cs | 65 + crypto/src/asn1/cms/TimeStampedData.cs | 95 + crypto/src/asn1/cms/TimeStampedDataParser.cs | 76 + crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs | 103 + crypto/src/asn1/crmf/AttributeTypeAndValue.cs | 66 + crypto/src/asn1/crmf/CertId.cs | 58 + crypto/src/asn1/crmf/CertReqMessages.cs | 52 + crypto/src/asn1/crmf/CertReqMsg.cs | 106 + crypto/src/asn1/crmf/CertRequest.cs | 82 + crypto/src/asn1/crmf/CertTemplate.cs | 149 + crypto/src/asn1/crmf/CertTemplateBuilder.cs | 125 + crypto/src/asn1/crmf/Controls.cs | 52 + crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs | 23 + crypto/src/asn1/crmf/EncKeyWithID.cs | 103 + crypto/src/asn1/crmf/EncryptedKey.cs | 78 + crypto/src/asn1/crmf/EncryptedValue.cs | 154 + crypto/src/asn1/crmf/OptionalValidity.cs | 71 + crypto/src/asn1/crmf/PKIArchiveOptions.cs | 105 + crypto/src/asn1/crmf/PKIPublicationInfo.cs | 64 + crypto/src/asn1/crmf/PKMacValue.cs | 89 + crypto/src/asn1/crmf/PopoPrivKey.cs | 84 + crypto/src/asn1/crmf/PopoSigningKey.cs | 115 + crypto/src/asn1/crmf/PopoSigningKeyInput.cs | 115 + crypto/src/asn1/crmf/ProofOfPossession.cs | 98 + crypto/src/asn1/crmf/SinglePubInfo.cs | 58 + crypto/src/asn1/crmf/SubsequentMessage.cs | 27 + .../asn1/cryptopro/CryptoProObjectIdentifiers.cs | 51 + crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs | 179 + .../asn1/cryptopro/ECGOST3410ParamSetParameters.cs | 86 + crypto/src/asn1/cryptopro/GOST28147Parameters.cs | 63 + .../src/asn1/cryptopro/GOST3410NamedParameters.cs | 123 + .../asn1/cryptopro/GOST3410ParamSetParameters.cs | 87 + .../cryptopro/GOST3410PublicKeyAlgParameters.cs | 99 + crypto/src/asn1/eac/EACObjectIdentifiers.cs | 50 + crypto/src/asn1/esf/CertificateValues.cs | 85 + crypto/src/asn1/esf/CommitmentTypeIdentifier.cs | 17 + crypto/src/asn1/esf/CommitmentTypeIndication.cs | 95 + crypto/src/asn1/esf/CommitmentTypeQualifier.cs | 119 + crypto/src/asn1/esf/CompleteCertificateRefs.cs | 84 + crypto/src/asn1/esf/CompleteRevocationRefs.cs | 84 + crypto/src/asn1/esf/CrlIdentifier.cs | 110 + crypto/src/asn1/esf/CrlListID.cs | 89 + crypto/src/asn1/esf/CrlOcspRef.cs | 111 + crypto/src/asn1/esf/CrlValidatedID.cs | 89 + crypto/src/asn1/esf/ESFAttributes.cs | 25 + crypto/src/asn1/esf/OcspIdentifier.cs | 77 + crypto/src/asn1/esf/OcspListID.cs | 88 + crypto/src/asn1/esf/OcspResponsesID.cs | 92 + crypto/src/asn1/esf/OtherCertID.cs | 93 + crypto/src/asn1/esf/OtherHash.cs | 88 + crypto/src/asn1/esf/OtherHashAlgAndValue.cs | 94 + crypto/src/asn1/esf/OtherRevRefs.cs | 78 + crypto/src/asn1/esf/OtherRevVals.cs | 78 + crypto/src/asn1/esf/OtherSigningCertificate.cs | 138 + crypto/src/asn1/esf/RevocationValues.cs | 165 + crypto/src/asn1/esf/SigPolicyQualifierInfo.cs | 71 + crypto/src/asn1/esf/SignaturePolicyId.cs | 145 + crypto/src/asn1/esf/SignaturePolicyIdentifier.cs | 64 + crypto/src/asn1/esf/SignerAttribute.cs | 96 + crypto/src/asn1/esf/SignerLocation.cs | 144 + crypto/src/asn1/ess/ContentHints.cs | 92 + crypto/src/asn1/ess/ContentIdentifier.cs | 65 + crypto/src/asn1/ess/ESSCertID.cs | 93 + crypto/src/asn1/ess/ESSCertIDv2.cs | 146 + crypto/src/asn1/ess/OtherCertID.cs | 132 + crypto/src/asn1/ess/OtherSigningCertificate.cs | 109 + crypto/src/asn1/ess/SigningCertificate.cs | 108 + crypto/src/asn1/ess/SigningCertificateV2.cs | 112 + crypto/src/asn1/gnu/GNUObjectIdentifiers.cs | 31 + crypto/src/asn1/iana/IANAObjectIdentifiers.cs | 18 + crypto/src/asn1/icao/CscaMasterList.cs | 83 + crypto/src/asn1/icao/DataGroupHash.cs | 86 + crypto/src/asn1/icao/ICAOObjectIdentifiers.cs | 34 + crypto/src/asn1/icao/LDSSecurityObject.cs | 145 + crypto/src/asn1/icao/LDSVersionInfo.cs | 61 + .../src/asn1/isismtt/ISISMTTObjectIdentifiers.cs | 177 + crypto/src/asn1/isismtt/ocsp/CertHash.cs | 121 + .../src/asn1/isismtt/ocsp/RequestedCertificate.cs | 186 + .../isismtt/x509/AdditionalInformationSyntax.cs | 70 + crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs | Bin 0 -> 20844 bytes crypto/src/asn1/isismtt/x509/Admissions.cs | 186 + .../src/asn1/isismtt/x509/DeclarationOfMajority.cs | 170 + crypto/src/asn1/isismtt/x509/MonetaryLimit.cs | 121 + crypto/src/asn1/isismtt/x509/NamingAuthority.cs | 214 + crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs | 232 + crypto/src/asn1/isismtt/x509/ProfessionInfo.cs | 386 + crypto/src/asn1/isismtt/x509/Restriction.cs | 81 + crypto/src/asn1/kisa/KISAObjectIdentifiers.cs | 8 + .../asn1/microsoft/MicrosoftObjectIdentifiers.cs | 18 + crypto/src/asn1/misc/CAST5CBCParameters.cs | 74 + crypto/src/asn1/misc/IDEACBCPar.cs | 68 + crypto/src/asn1/misc/MiscObjectIdentifiers.cs | 48 + crypto/src/asn1/misc/NetscapeCertType.cs | 54 + crypto/src/asn1/misc/NetscapeRevocationURL.cs | 18 + crypto/src/asn1/misc/VerisignCzagExtension.cs | 18 + crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs | 67 + crypto/src/asn1/nist/NISTNamedCurves.cs | 108 + crypto/src/asn1/nist/NISTObjectIdentifiers.cs | 65 + crypto/src/asn1/ntt/NTTObjectIdentifiers.cs | 14 + crypto/src/asn1/ocsp/BasicOCSPResponse.cs | 131 + crypto/src/asn1/ocsp/CertID.cs | 98 + crypto/src/asn1/ocsp/CertStatus.cs | 94 + crypto/src/asn1/ocsp/CrlID.cs | 82 + crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs | 23 + crypto/src/asn1/ocsp/OCSPRequest.cs | 89 + crypto/src/asn1/ocsp/OCSPResponse.cs | 90 + crypto/src/asn1/ocsp/OCSPResponseStatus.cs | 41 + crypto/src/asn1/ocsp/Request.cs | 90 + crypto/src/asn1/ocsp/ResponderID.cs | 107 + crypto/src/asn1/ocsp/ResponseBytes.cs | 82 + crypto/src/asn1/ocsp/ResponseData.cs | 158 + crypto/src/asn1/ocsp/RevokedInfo.cs | 96 + crypto/src/asn1/ocsp/ServiceLocator.cs | 95 + crypto/src/asn1/ocsp/Signature.cs | 110 + crypto/src/asn1/ocsp/SingleResponse.cs | 137 + crypto/src/asn1/ocsp/TBSRequest.cs | 151 + crypto/src/asn1/oiw/ElGamalParameter.cs | 47 + crypto/src/asn1/oiw/OIWObjectIdentifiers.cs | 29 + crypto/src/asn1/pkcs/Attribute.cs | 79 + crypto/src/asn1/pkcs/AuthenticatedSafe.cs | 37 + crypto/src/asn1/pkcs/CertBag.cs | 46 + crypto/src/asn1/pkcs/CertificationRequest.cs | 81 + crypto/src/asn1/pkcs/CertificationRequestInfo.cs | 123 + crypto/src/asn1/pkcs/ContentInfo.cs | 74 + crypto/src/asn1/pkcs/DHParameter.cs | 72 + crypto/src/asn1/pkcs/EncryptedData.cs | 104 + crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs | 78 + crypto/src/asn1/pkcs/EncryptionScheme.cs | 49 + crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs | 71 + crypto/src/asn1/pkcs/KeyDerivationFunc.cs | 21 + crypto/src/asn1/pkcs/MacData.cs | 96 + crypto/src/asn1/pkcs/PBEParameter.cs | 60 + crypto/src/asn1/pkcs/PBES2Parameters.cs | 65 + crypto/src/asn1/pkcs/PBKDF2Params.cs | 86 + crypto/src/asn1/pkcs/PKCS12PBEParams.cs | 63 + crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 256 + crypto/src/asn1/pkcs/Pfx.cs | 65 + crypto/src/asn1/pkcs/PrivateKeyInfo.cs | 126 + crypto/src/asn1/pkcs/RC2CBCParameter.cs | 81 + crypto/src/asn1/pkcs/RSAESOAEPparams.cs | 145 + crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs | 131 + crypto/src/asn1/pkcs/RSASSAPSSparams.cs | 165 + crypto/src/asn1/pkcs/SafeBag.cs | 70 + crypto/src/asn1/pkcs/SignedData.cs | 157 + crypto/src/asn1/pkcs/SignerInfo.cs | 154 + crypto/src/asn1/sec/ECPrivateKeyStructure.cs | 118 + crypto/src/asn1/sec/SECNamedCurves.cs | 1191 +++ crypto/src/asn1/sec/SECObjectIdentifiers.cs | 52 + crypto/src/asn1/smime/SMIMEAttributes.cs | 11 + crypto/src/asn1/smime/SMIMECapabilities.cs | 128 + .../src/asn1/smime/SMIMECapabilitiesAttribute.cs | 16 + crypto/src/asn1/smime/SMIMECapability.cs | 101 + crypto/src/asn1/smime/SMIMECapabilityVector.cs | 37 + .../smime/SMIMEEncryptionKeyPreferenceAttribute.cs | 44 + crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs | 427 + .../asn1/teletrust/TeleTrusTObjectIdentifiers.cs | 45 + crypto/src/asn1/tsp/Accuracy.cs | 149 + crypto/src/asn1/tsp/MessageImprint.cs | 74 + crypto/src/asn1/tsp/TSTInfo.cs | 249 + crypto/src/asn1/tsp/TimeStampReq.cs | 164 + crypto/src/asn1/tsp/TimeStampResp.cs | 80 + crypto/src/asn1/util/Asn1Dump.cs | 378 + crypto/src/asn1/util/Dump.cs | 28 + crypto/src/asn1/util/FilterStream.cs | 67 + crypto/src/asn1/x500/DirectoryString.cs | 75 + crypto/src/asn1/x509/AccessDescription.cs | 83 + crypto/src/asn1/x509/AlgorithmIdentifier.cs | 109 + crypto/src/asn1/x509/AttCertIssuer.cs | 86 + crypto/src/asn1/x509/AttCertValidityPeriod.cs | 78 + crypto/src/asn1/x509/Attribute.cs | 82 + crypto/src/asn1/x509/AttributeCertificate.cs | 81 + crypto/src/asn1/x509/AttributeCertificateInfo.cs | 156 + crypto/src/asn1/x509/AttributeTable.cs | 73 + crypto/src/asn1/x509/AuthorityInformationAccess.cs | 105 + crypto/src/asn1/x509/AuthorityKeyIdentifier.cs | 211 + crypto/src/asn1/x509/BasicConstraints.cs | 133 + crypto/src/asn1/x509/CRLDistPoint.cs | 93 + crypto/src/asn1/x509/CRLNumber.cs | 30 + crypto/src/asn1/x509/CRLReason.cs | 61 + crypto/src/asn1/x509/CertPolicyId.cs | 20 + crypto/src/asn1/x509/CertificateList.cs | 108 + crypto/src/asn1/x509/CertificatePair.cs | 160 + crypto/src/asn1/x509/CertificatePolicies.cs | 81 + crypto/src/asn1/x509/DSAParameter.cs | 77 + crypto/src/asn1/x509/DigestInfo.cs | 76 + crypto/src/asn1/x509/DisplayText.cs | 172 + crypto/src/asn1/x509/DistributionPoint.cs | 161 + crypto/src/asn1/x509/DistributionPointName.cs | 130 + crypto/src/asn1/x509/ExtendedKeyUsage.cs | 131 + crypto/src/asn1/x509/GeneralName.cs | 418 + crypto/src/asn1/x509/GeneralNames.cs | 95 + crypto/src/asn1/x509/GeneralSubtree.cs | 189 + crypto/src/asn1/x509/Holder.cs | 257 + crypto/src/asn1/x509/IetfAttrSyntax.cs | 161 + crypto/src/asn1/x509/IssuerSerial.cs | 98 + crypto/src/asn1/x509/IssuingDistributionPoint.cs | 247 + crypto/src/asn1/x509/KeyPurposeId.cs | 36 + crypto/src/asn1/x509/KeyUsage.cs | 79 + crypto/src/asn1/x509/NameConstraints.cs | 118 + crypto/src/asn1/x509/NoticeReference.cs | 138 + crypto/src/asn1/x509/ObjectDigestInfo.cs | 177 + crypto/src/asn1/x509/PolicyInformation.cs | 80 + crypto/src/asn1/x509/PolicyMappings.cs | 70 + crypto/src/asn1/x509/PolicyQualifierId.cs | 28 + crypto/src/asn1/x509/PolicyQualifierInfo.cs | 101 + crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs | 82 + crypto/src/asn1/x509/RSAPublicKeyStructure.cs | 92 + crypto/src/asn1/x509/ReasonFlags.cs | 46 + crypto/src/asn1/x509/RoleSyntax.cs | 230 + crypto/src/asn1/x509/SubjectDirectoryAttributes.cs | 142 + crypto/src/asn1/x509/SubjectKeyIdentifier.cs | 141 + crypto/src/asn1/x509/SubjectPublicKeyInfo.cs | 102 + crypto/src/asn1/x509/TBSCertList.cs | 274 + crypto/src/asn1/x509/TBSCertificateStructure.cs | 185 + crypto/src/asn1/x509/Target.cs | 139 + crypto/src/asn1/x509/TargetInformation.cs | 123 + crypto/src/asn1/x509/Targets.cs | 121 + crypto/src/asn1/x509/Time.cs | 120 + crypto/src/asn1/x509/UserNotice.cs | 104 + crypto/src/asn1/x509/V1TBSCertificateGenerator.cs | 108 + .../x509/V2AttributeCertificateInfoGenerator.cs | 137 + crypto/src/asn1/x509/V2Form.cs | 137 + crypto/src/asn1/x509/V2TBSCertListGenerator.cs | 201 + crypto/src/asn1/x509/V3TBSCertificateGenerator.cs | 168 + crypto/src/asn1/x509/X509Attributes.cs | 9 + crypto/src/asn1/x509/X509CertificateStructure.cs | 129 + crypto/src/asn1/x509/X509DefaultEntryConverter.cs | 63 + crypto/src/asn1/x509/X509Extension.cs | 79 + crypto/src/asn1/x509/X509Extensions.cs | 451 + crypto/src/asn1/x509/X509ExtensionsGenerator.cs | 81 + crypto/src/asn1/x509/X509Name.cs | 1188 +++ crypto/src/asn1/x509/X509NameEntryConverter.cs | 89 + crypto/src/asn1/x509/X509NameTokenizer.cs | 104 + crypto/src/asn1/x509/X509ObjectIdentifiers.cs | 59 + crypto/src/asn1/x509/qualified/BiometricData.cs | 112 + .../asn1/x509/qualified/ETSIQCObjectIdentifiers.cs | 19 + .../src/asn1/x509/qualified/Iso4217CurrencyCode.cs | 84 + crypto/src/asn1/x509/qualified/MonetaryValue.cs | 83 + crypto/src/asn1/x509/qualified/QCStatement.cs | 85 + .../x509/qualified/RFC3739QCObjectIdentifiers.cs | 21 + .../asn1/x509/qualified/SemanticsInformation.cs | 124 + .../src/asn1/x509/qualified/TypeOfBiometricData.cs | 91 + crypto/src/asn1/x509/sigi/NameOrPseudonym.cs | 177 + crypto/src/asn1/x509/sigi/PersonalData.cs | 210 + crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs | 49 + crypto/src/asn1/x9/DHDomainParameters.cs | 116 + crypto/src/asn1/x9/DHPublicKey.cs | 44 + crypto/src/asn1/x9/DHValidationParms.cs | 62 + crypto/src/asn1/x9/KeySpecificInfo.cs | 58 + crypto/src/asn1/x9/OtherInfo.cs | 88 + crypto/src/asn1/x9/X962NamedCurves.cs | 732 ++ crypto/src/asn1/x9/X962Parameters.cs | 53 + crypto/src/asn1/x9/X9Curve.cs | 147 + crypto/src/asn1/x9/X9ECParameters.cs | 170 + crypto/src/asn1/x9/X9ECParametersHolder.cs | 22 + crypto/src/asn1/x9/X9ECPoint.cs | 44 + crypto/src/asn1/x9/X9FieldElement.cs | 69 + crypto/src/asn1/x9/X9FieldID.cs | 102 + crypto/src/asn1/x9/X9IntegerConverter.cs | 48 + crypto/src/asn1/x9/X9ObjectIdentifiers.cs | 137 + crypto/src/bcpg/ArmoredInputStream.cs | 513 + crypto/src/bcpg/ArmoredOutputStream.cs | 330 + crypto/src/bcpg/BcpgInputStream.cs | 355 + crypto/src/bcpg/BcpgObject.cs | 22 + crypto/src/bcpg/BcpgOutputStream.cs | 390 + crypto/src/bcpg/CompressedDataPacket.cs | 24 + crypto/src/bcpg/CompressionAlgorithmTags.cs | 11 + crypto/src/bcpg/ContainedPacket.cs | 22 + crypto/src/bcpg/Crc24.cs | 46 + crypto/src/bcpg/DsaPublicBcpgKey.cs | 80 + crypto/src/bcpg/DsaSecretBcpgKey.cs | 61 + crypto/src/bcpg/ElGamalPublicBcpgKey.cs | 71 + crypto/src/bcpg/ElGamalSecretBcpgKey.cs | 61 + crypto/src/bcpg/ExperimentalPacket.cs | 38 + crypto/src/bcpg/HashAlgorithmTags.cs | 19 + crypto/src/bcpg/IBcpgKey.cs | 16 + crypto/src/bcpg/InputStreamPacket.cs | 20 + crypto/src/bcpg/LiteralDataPacket.cs | 57 + crypto/src/bcpg/MPInteger.cs | 59 + crypto/src/bcpg/MarkerPacket.cs | 24 + crypto/src/bcpg/ModDetectionCodePacket.cs | 42 + crypto/src/bcpg/OnePassSignaturePacket.cs | 93 + crypto/src/bcpg/OutputStreamPacket.cs | 24 + crypto/src/bcpg/Packet.cs | 7 + crypto/src/bcpg/PacketTags.cs | 30 + crypto/src/bcpg/PublicKeyAlgorithmTags.cs | 28 + crypto/src/bcpg/PublicKeyEncSessionPacket.cs | 103 + crypto/src/bcpg/PublicKeyPacket.cs | 115 + crypto/src/bcpg/PublicSubkeyPacket.cs | 30 + crypto/src/bcpg/RsaPublicBcpgKey.cs | 66 + crypto/src/bcpg/RsaSecretBcpgKey.cs | 114 + crypto/src/bcpg/S2k.cs | 147 + crypto/src/bcpg/SecretKeyPacket.cs | 170 + crypto/src/bcpg/SecretSubkeyPacket.cs | 43 + crypto/src/bcpg/SignaturePacket.cs | 472 + crypto/src/bcpg/SignatureSubpacket.cs | 76 + crypto/src/bcpg/SignatureSubpacketTags.cs | 33 + crypto/src/bcpg/SignatureSubpacketsReader.cs | 88 + crypto/src/bcpg/SymmetricEncDataPacket.cs | 15 + crypto/src/bcpg/SymmetricEncIntegrityPacket.cs | 18 + crypto/src/bcpg/SymmetricKeyAlgorithmTags.cs | 20 + crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs | 91 + crypto/src/bcpg/TrustPacket.cs | 43 + crypto/src/bcpg/UserAttributePacket.cs | 61 + crypto/src/bcpg/UserAttributeSubpacket.cs | 86 + crypto/src/bcpg/UserAttributeSubpacketTags.cs | 10 + crypto/src/bcpg/UserAttributeSubpacketsReader.cs | 63 + crypto/src/bcpg/UserIdPacket.cs | 37 + crypto/src/bcpg/attr/ImageAttrib.cs | 68 + crypto/src/bcpg/sig/EmbeddedSignature.cs | 18 + crypto/src/bcpg/sig/Exportable.cs | 47 + crypto/src/bcpg/sig/IssuerKeyId.cs | 61 + crypto/src/bcpg/sig/KeyExpirationTime.cs | 56 + crypto/src/bcpg/sig/KeyFlags.cs | 74 + crypto/src/bcpg/sig/NotationData.cs | 112 + crypto/src/bcpg/sig/PreferredAlgorithms.cs | 54 + crypto/src/bcpg/sig/PrimaryUserId.cs | 48 + crypto/src/bcpg/sig/Revocable.cs | 48 + crypto/src/bcpg/sig/RevocationKey.cs | 62 + crypto/src/bcpg/sig/RevocationKeyTags.cs | 9 + crypto/src/bcpg/sig/RevocationReason.cs | 59 + crypto/src/bcpg/sig/RevocationReasonTags.cs | 14 + crypto/src/bcpg/sig/SignatureCreationTime.cs | 47 + crypto/src/bcpg/sig/SignatureExpirationTime.cs | 54 + crypto/src/bcpg/sig/SignerUserId.cs | 52 + crypto/src/bcpg/sig/TrustSignature.cs | 43 + crypto/src/cms/BaseDigestCalculator.cs | 23 + .../cms/CMSAttributeTableGenerationException.cs | 28 + crypto/src/cms/CMSAttributeTableGenerator.cs | 25 + crypto/src/cms/CMSAuthEnvelopedData.cs | 112 + crypto/src/cms/CMSAuthEnvelopedGenerator.cs | 16 + crypto/src/cms/CMSAuthenticatedData.cs | 137 + crypto/src/cms/CMSAuthenticatedDataGenerator.cs | 156 + crypto/src/cms/CMSAuthenticatedDataParser.cs | 214 + .../src/cms/CMSAuthenticatedDataStreamGenerator.cs | 272 + crypto/src/cms/CMSAuthenticatedGenerator.cs | 35 + crypto/src/cms/CMSCompressedData.cs | 107 + crypto/src/cms/CMSCompressedDataGenerator.cs | 66 + crypto/src/cms/CMSCompressedDataParser.cs | 57 + crypto/src/cms/CMSCompressedDataStreamGenerator.cs | 140 + crypto/src/cms/CMSContentInfoParser.cs | 47 + crypto/src/cms/CMSEnvelopedData.cs | 115 + crypto/src/cms/CMSEnvelopedDataGenerator.cs | 178 + crypto/src/cms/CMSEnvelopedDataParser.cs | 161 + crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs | 281 + crypto/src/cms/CMSEnvelopedGenerator.cs | 331 + crypto/src/cms/CMSEnvelopedHelper.cs | 311 + crypto/src/cms/CMSException.cs | 28 + crypto/src/cms/CMSPBEKey.cs | 109 + crypto/src/cms/CMSProcessable.cs | 19 + crypto/src/cms/CMSProcessableByteArray.cs | 36 + crypto/src/cms/CMSProcessableFile.cs | 54 + crypto/src/cms/CMSProcessableInputStream.cs | 52 + crypto/src/cms/CMSReadable.cs | 10 + crypto/src/cms/CMSSecureReadable.cs | 14 + crypto/src/cms/CMSSignedData.cs | 425 + crypto/src/cms/CMSSignedDataGenerator.cs | 551 + crypto/src/cms/CMSSignedDataParser.cs | 455 + crypto/src/cms/CMSSignedDataStreamGenerator.cs | 913 ++ crypto/src/cms/CMSSignedGenerator.cs | 261 + crypto/src/cms/CMSSignedHelper.cs | 319 + crypto/src/cms/CMSStreamException.cs | 29 + crypto/src/cms/CMSTypedStream.cs | 72 + crypto/src/cms/CMSUtils.cs | 186 + crypto/src/cms/CounterSignatureDigestCalculator.cs | 28 + .../DefaultAuthenticatedAttributeTableGenerator.cs | 90 + .../cms/DefaultSignedAttributeTableGenerator.cs | 124 + crypto/src/cms/DigOutputStream.cs | 28 + crypto/src/cms/IDigestCalculator.cs | 9 + crypto/src/cms/KEKRecipientInfoGenerator.cs | 137 + crypto/src/cms/KEKRecipientInformation.cs | 62 + crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs | 171 + crypto/src/cms/KeyAgreeRecipientInformation.cs | 226 + crypto/src/cms/KeyTransRecipientInfoGenerator.cs | 87 + crypto/src/cms/KeyTransRecipientInformation.cs | 113 + crypto/src/cms/MacOutputStream.cs | 28 + crypto/src/cms/NullOutputStream.cs | 20 + crypto/src/cms/OriginatorId.cs | 51 + crypto/src/cms/OriginatorInfoGenerator.cs | 42 + crypto/src/cms/OriginatorInformation.cs | 96 + crypto/src/cms/PKCS5Scheme2PBEKey.cs | 64 + crypto/src/cms/PKCS5Scheme2UTF8PBEKey.cs | 64 + crypto/src/cms/PasswordRecipientInfoGenerator.cs | 69 + crypto/src/cms/PasswordRecipientInformation.cs | 79 + crypto/src/cms/RecipientId.cs | 58 + crypto/src/cms/RecipientInfoGenerator.cs | 26 + crypto/src/cms/RecipientInformation.cs | 126 + crypto/src/cms/RecipientInformationStore.cs | 86 + crypto/src/cms/SigOutputStream.cs | 43 + crypto/src/cms/SignerId.cs | 51 + crypto/src/cms/SignerInfoGenerator.cs | 14 + crypto/src/cms/SignerInformation.cs | 758 ++ crypto/src/cms/SignerInformationStore.cs | 74 + crypto/src/cms/SimpleAttributeTableGenerator.cs | 28 + crypto/src/crypto/AsymmetricCipherKeyPair.cs | 52 + crypto/src/crypto/AsymmetricKeyParameter.cs | 47 + crypto/src/crypto/BufferedAeadBlockCipher.cs | 247 + crypto/src/crypto/BufferedAsymmetricBlockCipher.cs | 152 + crypto/src/crypto/BufferedBlockCipher.cs | 377 + crypto/src/crypto/BufferedCipherBase.cs | 113 + crypto/src/crypto/BufferedIesCipher.cs | 113 + crypto/src/crypto/BufferedStreamCipher.cs | 131 + crypto/src/crypto/CipherKeyGenerator.cs | 83 + crypto/src/crypto/CryptoException.cs | 28 + crypto/src/crypto/DataLengthException.cs | 42 + crypto/src/crypto/IAsymmetricBlockCipher.cs | 30 + .../crypto/IAsymmetricCipherKeyPairGenerator.cs | 24 + crypto/src/crypto/IBasicAgreement.cs | 29 + crypto/src/crypto/IBlockCipher.cs | 36 + crypto/src/crypto/IBufferedCipher.cs | 44 + crypto/src/crypto/ICipherParameters.cs | 11 + crypto/src/crypto/IDSA.cs | 40 + crypto/src/crypto/IDerivationFunction.cs | 24 + crypto/src/crypto/IDerivationParameters.cs | 11 + crypto/src/crypto/IDigest.cs | 61 + crypto/src/crypto/IMac.cs | 69 + crypto/src/crypto/ISigner.cs | 50 + crypto/src/crypto/ISignerWithRecovery.cs | 37 + crypto/src/crypto/IStreamCipher.cs | 45 + crypto/src/crypto/IWrapper.cs | 18 + crypto/src/crypto/InvalidCipherTextException.cs | 40 + crypto/src/crypto/KeyGenerationParameters.cs | 55 + crypto/src/crypto/MaxBytesExceededException.cs | 32 + crypto/src/crypto/PbeParametersGenerator.cs | 202 + crypto/src/crypto/StreamBlockCipher.cs | 109 + crypto/src/crypto/agreement/DHAgreement.cs | 93 + crypto/src/crypto/agreement/DHBasicAgreement.cs | 64 + crypto/src/crypto/agreement/ECDHBasicAgreement.cs | 54 + crypto/src/crypto/agreement/ECDHCBasicAgreement.cs | 62 + .../crypto/agreement/ECDHWithKdfBasicAgreement.cs | 64 + crypto/src/crypto/agreement/ECMqvBasicAgreement.cs | 90 + .../crypto/agreement/ECMqvWithKdfBasicAgreement.cs | 64 + crypto/src/crypto/agreement/kdf/DHKdfParameters.cs | 57 + crypto/src/crypto/agreement/kdf/DHKekGenerator.cs | 112 + .../src/crypto/agreement/kdf/ECDHKekGenerator.cs | 55 + crypto/src/crypto/agreement/srp/SRP6Client.cs | 93 + crypto/src/crypto/agreement/srp/SRP6Server.cs | 90 + crypto/src/crypto/agreement/srp/SRP6Utilities.cs | 85 + .../crypto/agreement/srp/SRP6VerifierGenerator.cs | 49 + crypto/src/crypto/digests/GOST3411Digest.cs | 343 + crypto/src/crypto/digests/GeneralDigest.cs | 118 + crypto/src/crypto/digests/LongDigest.cs | 346 + crypto/src/crypto/digests/MD2Digest.cs | 247 + crypto/src/crypto/digests/MD4Digest.cs | 271 + crypto/src/crypto/digests/MD5Digest.cs | 293 + crypto/src/crypto/digests/NullDigest.cs | 49 + crypto/src/crypto/digests/RipeMD128Digest.cs | 462 + crypto/src/crypto/digests/RipeMD160Digest.cs | 423 + crypto/src/crypto/digests/RipeMD256Digest.cs | 409 + crypto/src/crypto/digests/RipeMD320Digest.cs | 438 + crypto/src/crypto/digests/SHA3Digest.cs | 541 + crypto/src/crypto/digests/Sha1Digest.cs | 263 + crypto/src/crypto/digests/Sha224Digest.cs | 268 + crypto/src/crypto/digests/Sha256Digest.cs | 309 + crypto/src/crypto/digests/Sha384Digest.cs | 87 + crypto/src/crypto/digests/Sha512Digest.cs | 90 + crypto/src/crypto/digests/Sha512tDigest.cs | 179 + crypto/src/crypto/digests/ShortenedDigest.cs | 82 + crypto/src/crypto/digests/TigerDigest.cs | 868 ++ crypto/src/crypto/digests/WhirlpoolDigest.cs | 397 + crypto/src/crypto/encodings/ISO9796d1Encoding.cs | 273 + crypto/src/crypto/encodings/OaepEncoding.cs | 349 + crypto/src/crypto/encodings/Pkcs1Encoding.cs | 232 + crypto/src/crypto/engines/AesEngine.cs | 546 + crypto/src/crypto/engines/AesFastEngine.cs | 878 ++ crypto/src/crypto/engines/AesLightEngine.cs | 441 + crypto/src/crypto/engines/AesWrapEngine.cs | 16 + crypto/src/crypto/engines/BlowfishEngine.cs | 561 + crypto/src/crypto/engines/CamelliaEngine.cs | 669 ++ crypto/src/crypto/engines/CamelliaLightEngine.cs | 581 + crypto/src/crypto/engines/CamelliaWrapEngine.cs | 16 + crypto/src/crypto/engines/Cast5Engine.cs | 802 ++ crypto/src/crypto/engines/Cast6Engine.cs | 279 + crypto/src/crypto/engines/DesEdeEngine.cs | 100 + crypto/src/crypto/engines/DesEdeWrapEngine.cs | 322 + crypto/src/crypto/engines/DesEngine.cs | 475 + crypto/src/crypto/engines/ElGamalEngine.cs | 178 + crypto/src/crypto/engines/GOST28147Engine.cs | 376 + crypto/src/crypto/engines/HC128Engine.cs | 235 + crypto/src/crypto/engines/HC256Engine.cs | 224 + crypto/src/crypto/engines/ISAACEngine.cs | 212 + crypto/src/crypto/engines/IdeaEngine.cs | 341 + crypto/src/crypto/engines/IesEngine.cs | 233 + crypto/src/crypto/engines/NaccacheSternEngine.cs | 432 + crypto/src/crypto/engines/NoekeonEngine.cs | 240 + crypto/src/crypto/engines/NullEngine.cs | 70 + crypto/src/crypto/engines/RC2Engine.cs | 312 + crypto/src/crypto/engines/RC2WrapEngine.cs | 370 + crypto/src/crypto/engines/RC4Engine.cs | 147 + crypto/src/crypto/engines/RC532Engine.cs | 294 + crypto/src/crypto/engines/RC564Engine.cs | 295 + crypto/src/crypto/engines/RC6Engine.cs | 362 + crypto/src/crypto/engines/RFC3211WrapEngine.cs | 168 + crypto/src/crypto/engines/RFC3394WrapEngine.cs | 178 + crypto/src/crypto/engines/RSABlindedEngine.cs | 124 + crypto/src/crypto/engines/RSABlindingEngine.cs | 139 + crypto/src/crypto/engines/RSACoreEngine.cs | 156 + crypto/src/crypto/engines/RijndaelEngine.cs | 747 ++ crypto/src/crypto/engines/RsaEngine.cs | 78 + crypto/src/crypto/engines/SEEDEngine.cs | 361 + crypto/src/crypto/engines/SEEDWrapEngine.cs | 16 + crypto/src/crypto/engines/Salsa20Engine.cs | 299 + crypto/src/crypto/engines/SerpentEngine.cs | 779 ++ crypto/src/crypto/engines/SkipjackEngine.cs | 255 + crypto/src/crypto/engines/TEAEngine.cs | 168 + crypto/src/crypto/engines/TwofishEngine.cs | 675 ++ crypto/src/crypto/engines/VMPCEngine.cs | 140 + crypto/src/crypto/engines/VMPCKSA3Engine.cs | 51 + crypto/src/crypto/engines/XTEAEngine.cs | 168 + .../src/crypto/generators/BaseKdfBytesGenerator.cs | 132 + .../crypto/generators/DHBasicKeyPairGenerator.cs | 38 + .../src/crypto/generators/DHKeyGeneratorHelper.cs | 53 + crypto/src/crypto/generators/DHKeyPairGenerator.cs | 38 + .../src/crypto/generators/DHParametersGenerator.cs | 45 + crypto/src/crypto/generators/DHParametersHelper.cs | 138 + crypto/src/crypto/generators/DesEdeKeyGenerator.cs | 67 + crypto/src/crypto/generators/DesKeyGenerator.cs | 57 + .../src/crypto/generators/DsaKeyPairGenerator.cs | 61 + .../crypto/generators/DsaParametersGenerator.cs | 390 + crypto/src/crypto/generators/ECKeyPairGenerator.cs | 153 + .../crypto/generators/ElGamalKeyPairGenerator.cs | 40 + .../generators/ElGamalParametersGenerator.cs | 46 + .../crypto/generators/GOST3410KeyPairGenerator.cs | 73 + .../generators/GOST3410ParametersGenerator.cs | 530 + crypto/src/crypto/generators/Kdf1BytesGenerator.cs | 26 + crypto/src/crypto/generators/Kdf2BytesGenerator.cs | 27 + crypto/src/crypto/generators/Mgf1BytesGenerator.cs | 117 + .../generators/NaccacheSternKeyPairGenerator.cs | 333 + .../generators/OpenSSLPBEParametersGenerator.cs | 167 + .../crypto/generators/Pkcs12ParametersGenerator.cs | 245 + .../generators/Pkcs5S1ParametersGenerator.cs | 162 + .../generators/Pkcs5S2ParametersGenerator.cs | 180 + .../generators/RSABlindingFactorGenerator.cs | 69 + .../src/crypto/generators/RsaKeyPairGenerator.cs | 139 + crypto/src/crypto/generators/SCrypt.cs | 140 + crypto/src/crypto/io/CipherStream.cs | 234 + crypto/src/crypto/io/DigestStream.cs | 137 + crypto/src/crypto/io/MacStream.cs | 136 + crypto/src/crypto/io/SignerStream.cs | 137 + crypto/src/crypto/macs/CMac.cs | 241 + crypto/src/crypto/macs/CbcBlockCipherMac.cs | 209 + crypto/src/crypto/macs/CfbBlockCipherMac.cs | 368 + crypto/src/crypto/macs/GOST28147Mac.cs | 296 + crypto/src/crypto/macs/HMac.cs | 124 + crypto/src/crypto/macs/ISO9797Alg3Mac.cs | 275 + crypto/src/crypto/macs/SipHash.cs | 170 + crypto/src/crypto/macs/VMPCMac.cs | 173 + crypto/src/crypto/modes/CbcBlockCipher.cs | 241 + crypto/src/crypto/modes/CcmBlockCipher.cs | 383 + crypto/src/crypto/modes/CfbBlockCipher.cs | 224 + crypto/src/crypto/modes/CtsBlockCipher.cs | 253 + crypto/src/crypto/modes/EAXBlockCipher.cs | 365 + crypto/src/crypto/modes/GCMBlockCipher.cs | 506 + crypto/src/crypto/modes/GOFBBlockCipher.cs | 227 + crypto/src/crypto/modes/IAeadBlockCipher.cs | 102 + crypto/src/crypto/modes/OCBBlockCipher.cs | 543 + crypto/src/crypto/modes/OfbBlockCipher.cs | 182 + crypto/src/crypto/modes/OpenPgpCfbBlockCipher.cs | 337 + crypto/src/crypto/modes/SicBlockCipher.cs | 115 + .../src/crypto/modes/gcm/BasicGcmExponentiator.cs | 40 + crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs | 22 + crypto/src/crypto/modes/gcm/GcmUtilities.cs | 237 + crypto/src/crypto/modes/gcm/IGcmExponentiator.cs | 10 + crypto/src/crypto/modes/gcm/IGcmMultiplier.cs | 10 + .../crypto/modes/gcm/Tables1kGcmExponentiator.cs | 60 + .../src/crypto/modes/gcm/Tables64kGcmMultiplier.cs | 77 + .../src/crypto/modes/gcm/Tables8kGcmMultiplier.cs | 103 + crypto/src/crypto/paddings/BlockCipherPadding.cs | 43 + crypto/src/crypto/paddings/ISO10126d2Padding.cs | 76 + crypto/src/crypto/paddings/ISO7816d4Padding.cs | 79 + .../crypto/paddings/PaddedBufferedBlockCipher.cs | 288 + crypto/src/crypto/paddings/Pkcs7Padding.cs | 79 + crypto/src/crypto/paddings/TbcPadding.cs | 79 + crypto/src/crypto/paddings/X923Padding.cs | 82 + crypto/src/crypto/paddings/ZeroBytePadding.cs | 68 + crypto/src/crypto/parameters/AEADParameters.cs | 65 + crypto/src/crypto/parameters/CcmParameters.cs | 26 + .../crypto/parameters/DHKeyGenerationParameters.cs | 31 + crypto/src/crypto/parameters/DHKeyParameters.cs | 76 + crypto/src/crypto/parameters/DHParameters.cs | 184 + .../crypto/parameters/DHPrivateKeyParameters.cs | 60 + .../src/crypto/parameters/DHPublicKeyParameters.cs | 66 + .../crypto/parameters/DHValidationParameters.cs | 59 + .../parameters/DSAParameterGenerationParameters.cs | 74 + crypto/src/crypto/parameters/DesEdeParameters.cs | 95 + crypto/src/crypto/parameters/DesParameters.cs | 130 + .../parameters/DsaKeyGenerationParameters.cs | 26 + crypto/src/crypto/parameters/DsaKeyParameters.cs | 59 + crypto/src/crypto/parameters/DsaParameters.cs | 85 + .../crypto/parameters/DsaPrivateKeyParameters.cs | 53 + .../crypto/parameters/DsaPublicKeyParameters.cs | 52 + .../crypto/parameters/DsaValidationParameters.cs | 72 + crypto/src/crypto/parameters/ECDomainParameters.cs | 116 + .../crypto/parameters/ECKeyGenerationParameters.cs | 41 + crypto/src/crypto/parameters/ECKeyParameters.cs | 136 + .../crypto/parameters/ECPrivateKeyParameters.cs | 87 + .../src/crypto/parameters/ECPublicKeyParameters.cs | 86 + .../parameters/ElGamalKeyGenerationParameters.cs | 31 + .../src/crypto/parameters/ElGamalKeyParameters.cs | 59 + crypto/src/crypto/parameters/ElGamalParameters.cs | 81 + .../parameters/ElGamalPrivateKeyParameters.cs | 53 + .../parameters/ElGamalPublicKeyParameters.cs | 53 + .../parameters/GOST3410KeyGenerationParameters.cs | 55 + .../src/crypto/parameters/GOST3410KeyParameters.cs | 58 + crypto/src/crypto/parameters/GOST3410Parameters.cs | 86 + .../parameters/GOST3410PrivateKeyParameters.cs | 41 + .../parameters/GOST3410PublicKeyParameters.cs | 40 + .../parameters/GOST3410ValidationParameters.cs | 51 + .../src/crypto/parameters/ISO18033KDFParameters.cs | 25 + crypto/src/crypto/parameters/IesParameters.cs | 49 + .../crypto/parameters/IesWithCipherParameters.cs | 33 + crypto/src/crypto/parameters/KdfParameters.cs | 33 + crypto/src/crypto/parameters/KeyParameter.cs | 43 + crypto/src/crypto/parameters/MgfParameters.cs | 31 + .../src/crypto/parameters/MqvPrivateParameters.cs | 44 + .../src/crypto/parameters/MqvPublicParameters.cs | 29 + .../NaccacheSternKeyGenerationParameters.cs | 101 + .../parameters/NaccacheSternKeyParameters.cs | 44 + .../NaccacheSternPrivateKeyParameters.cs | 79 + crypto/src/crypto/parameters/ParametersWithIV.cs | 43 + .../src/crypto/parameters/ParametersWithRandom.cs | 48 + crypto/src/crypto/parameters/ParametersWithSBox.cs | 24 + crypto/src/crypto/parameters/ParametersWithSalt.cs | 39 + crypto/src/crypto/parameters/RC2Parameters.cs | 47 + crypto/src/crypto/parameters/RC5Parameters.cs | 27 + .../src/crypto/parameters/RSABlindingParameters.cs | 34 + .../parameters/RsaKeyGenerationParameters.cs | 55 + crypto/src/crypto/parameters/RsaKeyParameters.cs | 63 + .../parameters/RsaPrivateCrtKeyParameters.cs | 104 + crypto/src/crypto/prng/CryptoApiRandomGenerator.cs | 66 + crypto/src/crypto/prng/DigestRandomGenerator.cs | 129 + crypto/src/crypto/prng/IRandomGenerator.cs | 26 + crypto/src/crypto/prng/ReversedWindowGenerator.cs | 98 + crypto/src/crypto/prng/ThreadedSeedGenerator.cs | 117 + crypto/src/crypto/prng/VMPCRandomGenerator.cs | 114 + crypto/src/crypto/signers/DsaDigestSigner.cs | 145 + crypto/src/crypto/signers/DsaSigner.cs | 136 + crypto/src/crypto/signers/ECDsaSigner.cs | 159 + crypto/src/crypto/signers/ECGOST3410Signer.cs | 157 + crypto/src/crypto/signers/ECNRSigner.cs | 189 + crypto/src/crypto/signers/GOST3410DigestSigner.cs | 145 + crypto/src/crypto/signers/GOST3410Signer.cs | 132 + crypto/src/crypto/signers/GenericSigner.cs | 129 + crypto/src/crypto/signers/Iso9796d2PssSigner.cs | 617 ++ crypto/src/crypto/signers/Iso9796d2Signer.cs | 563 + crypto/src/crypto/signers/PssSigner.cs | 345 + crypto/src/crypto/signers/RsaDigestSigner.cs | 228 + crypto/src/crypto/tls/AlertDescription.cs | 47 + crypto/src/crypto/tls/AlertLevel.cs | 11 + crypto/src/crypto/tls/AlwaysValidVerifyer.cs | 24 + crypto/src/crypto/tls/ByteQueue.cs | 147 + crypto/src/crypto/tls/Certificate.cs | 111 + crypto/src/crypto/tls/CertificateRequest.cs | 28 + crypto/src/crypto/tls/CipherSuite.cs | 136 + crypto/src/crypto/tls/ClientCertificateType.cs | 20 + crypto/src/crypto/tls/CombinedHash.cs | 82 + crypto/src/crypto/tls/CompressionMethod.cs | 20 + crypto/src/crypto/tls/ContentType.cs | 13 + .../crypto/tls/DefaultTlsAgreementCredentials.cs | 76 + crypto/src/crypto/tls/DefaultTlsCipherFactory.cs | 86 + crypto/src/crypto/tls/DefaultTlsClient.cs | 272 + .../src/crypto/tls/DefaultTlsSignerCredentials.cs | 76 + crypto/src/crypto/tls/DigestAlgorithm.cs | 21 + crypto/src/crypto/tls/ECCurveType.cs | 29 + crypto/src/crypto/tls/ECPointFormat.cs | 16 + crypto/src/crypto/tls/EncryptionAlgorithm.cs | 32 + crypto/src/crypto/tls/ExtensionType.cs | 31 + crypto/src/crypto/tls/HandshakeType.cs | 19 + crypto/src/crypto/tls/ICertificateVerifyer.cs | 18 + crypto/src/crypto/tls/KeyExchangeAlgorithm.cs | 36 + crypto/src/crypto/tls/LegacyTlsAuthentication.cs | 30 + crypto/src/crypto/tls/LegacyTlsClient.cs | 26 + crypto/src/crypto/tls/NamedCurve.cs | 72 + crypto/src/crypto/tls/PskTlsClient.cs | 191 + crypto/src/crypto/tls/RecordStream.cs | 166 + crypto/src/crypto/tls/SecurityParameters.cs | 26 + crypto/src/crypto/tls/SrpTlsClient.cs | 188 + crypto/src/crypto/tls/Ssl3Mac.cs | 114 + crypto/src/crypto/tls/TlsAgreementCredentials.cs | 11 + crypto/src/crypto/tls/TlsAuthentication.cs | 31 + crypto/src/crypto/tls/TlsBlockCipher.cs | 251 + crypto/src/crypto/tls/TlsCipher.cs | 14 + crypto/src/crypto/tls/TlsCipherFactory.cs | 12 + crypto/src/crypto/tls/TlsClient.cs | 129 + crypto/src/crypto/tls/TlsClientContext.cs | 15 + crypto/src/crypto/tls/TlsClientContextImpl.cs | 37 + crypto/src/crypto/tls/TlsCompression.cs | 12 + crypto/src/crypto/tls/TlsCredentials.cs | 9 + crypto/src/crypto/tls/TlsDHKeyExchange.cs | 201 + crypto/src/crypto/tls/TlsDHUtilities.cs | 75 + crypto/src/crypto/tls/TlsDeflateCompression.cs | 68 + crypto/src/crypto/tls/TlsDheKeyExchange.cs | 56 + crypto/src/crypto/tls/TlsDsaSigner.cs | 51 + crypto/src/crypto/tls/TlsDssSigner.cs | 21 + crypto/src/crypto/tls/TlsECDHKeyExchange.cs | 236 + crypto/src/crypto/tls/TlsECDheKeyExchange.cs | 110 + crypto/src/crypto/tls/TlsECDsaSigner.cs | 21 + crypto/src/crypto/tls/TlsException.cs | 14 + crypto/src/crypto/tls/TlsFatalAlert.cs | 21 + crypto/src/crypto/tls/TlsKeyExchange.cs | 38 + crypto/src/crypto/tls/TlsMac.cs | 142 + crypto/src/crypto/tls/TlsNullCipher.cs | 28 + crypto/src/crypto/tls/TlsNullCompression.cs | 19 + crypto/src/crypto/tls/TlsProtocolHandler.cs | 1233 +++ crypto/src/crypto/tls/TlsPskIdentity.cs | 15 + crypto/src/crypto/tls/TlsPskKeyExchange.cs | 206 + crypto/src/crypto/tls/TlsRsaKeyExchange.cs | 165 + crypto/src/crypto/tls/TlsRsaSigner.cs | 60 + crypto/src/crypto/tls/TlsRsaUtilities.cs | 42 + crypto/src/crypto/tls/TlsSigner.cs | 18 + crypto/src/crypto/tls/TlsSignerCredentials.cs | 11 + crypto/src/crypto/tls/TlsSrpKeyExchange.cs | 203 + crypto/src/crypto/tls/TlsStream.cs | 86 + crypto/src/crypto/tls/TlsStreamCipher.cs | 108 + crypto/src/crypto/tls/TlsUtilities.cs | 286 + crypto/src/crypto/util/Pack.cs | 257 + crypto/src/math/BigInteger.cs | 3575 +++++++ crypto/src/math/ec/ECAlgorithms.cs | 93 + crypto/src/math/ec/ECCurve.cs | 651 ++ crypto/src/math/ec/ECFieldElement.cs | 1253 +++ crypto/src/math/ec/ECPoint.cs | 572 + crypto/src/math/ec/IntArray.cs | 485 + crypto/src/math/ec/abc/SimpleBigDecimal.cs | 241 + crypto/src/math/ec/abc/Tnaf.cs | 834 ++ crypto/src/math/ec/abc/ZTauElement.cs | 36 + crypto/src/math/ec/multiplier/ECMultiplier.cs | 18 + crypto/src/math/ec/multiplier/FpNafMultiplier.cs | 39 + crypto/src/math/ec/multiplier/PreCompInfo.cs | 11 + .../src/math/ec/multiplier/ReferenceMultiplier.cs | 30 + crypto/src/math/ec/multiplier/WNafMultiplier.cs | 241 + crypto/src/math/ec/multiplier/WNafPreCompInfo.cs | 46 + crypto/src/math/ec/multiplier/WTauNafMultiplier.cs | 120 + .../src/math/ec/multiplier/WTauNafPreCompInfo.cs | 41 + crypto/src/ocsp/BasicOCSPResp.cs | 220 + crypto/src/ocsp/BasicOCSPRespGenerator.cs | 318 + crypto/src/ocsp/CertificateID.cs | 141 + crypto/src/ocsp/CertificateStatus.cs | 9 + crypto/src/ocsp/OCSPException.cs | 28 + crypto/src/ocsp/OCSPReq.cs | 268 + crypto/src/ocsp/OCSPReqGenerator.cs | 243 + crypto/src/ocsp/OCSPResp.cs | 100 + crypto/src/ocsp/OCSPRespGenerator.cs | 54 + crypto/src/ocsp/OCSPRespStatus.cs | 22 + crypto/src/ocsp/OCSPUtil.cs | 132 + crypto/src/ocsp/Req.cs | 38 + crypto/src/ocsp/RespData.cs | 60 + crypto/src/ocsp/RespID.cs | 72 + crypto/src/ocsp/RevokedStatus.cs | 58 + crypto/src/ocsp/SingleResp.cs | 81 + crypto/src/ocsp/UnknownStatus.cs | 15 + crypto/src/openpgp/IStreamGenerator.cs | 7 + crypto/src/openpgp/PGPKeyRing.cs | 79 + crypto/src/openpgp/PGPObject.cs | 9 + .../PGPUserAttributeSubpacketVectorGenerator.cs | 33 + crypto/src/openpgp/PgpCompressedData.cs | 50 + crypto/src/openpgp/PgpCompressedDataGenerator.cs | 197 + crypto/src/openpgp/PgpDataValidationException.cs | 18 + crypto/src/openpgp/PgpEncryptedData.cs | 151 + crypto/src/openpgp/PgpEncryptedDataGenerator.cs | 506 + crypto/src/openpgp/PgpEncryptedDataList.cs | 72 + crypto/src/openpgp/PgpException.cs | 22 + crypto/src/openpgp/PgpExperimental.cs | 16 + crypto/src/openpgp/PgpKeyFlags.cs | 13 + crypto/src/openpgp/PgpKeyPair.cs | 67 + crypto/src/openpgp/PgpKeyRingGenerator.cs | 167 + crypto/src/openpgp/PgpKeyValidationException.cs | 18 + crypto/src/openpgp/PgpLiteralData.cs | 63 + crypto/src/openpgp/PgpLiteralDataGenerator.cs | 180 + crypto/src/openpgp/PgpMarker.cs | 18 + crypto/src/openpgp/PgpObjectFactory.cs | 143 + crypto/src/openpgp/PgpOnePassSignature.cs | 179 + crypto/src/openpgp/PgpOnePassSignatureList.cs | 51 + crypto/src/openpgp/PgpPbeEncryptedData.cs | 135 + crypto/src/openpgp/PgpPrivateKey.cs | 42 + crypto/src/openpgp/PgpPublicKey.cs | 890 ++ crypto/src/openpgp/PgpPublicKeyEncryptedData.cs | 252 + crypto/src/openpgp/PgpPublicKeyRing.cs | 200 + crypto/src/openpgp/PgpPublicKeyRingBundle.cs | 279 + crypto/src/openpgp/PgpSecretKey.cs | 666 ++ crypto/src/openpgp/PgpSecretKeyRing.cs | 301 + crypto/src/openpgp/PgpSecretKeyRingBundle.cs | 281 + crypto/src/openpgp/PgpSignature.cs | 422 + crypto/src/openpgp/PgpSignatureGenerator.cs | 393 + crypto/src/openpgp/PgpSignatureList.cs | 51 + .../src/openpgp/PgpSignatureSubpacketGenerator.cs | 193 + crypto/src/openpgp/PgpSignatureSubpacketVector.cs | 229 + .../src/openpgp/PgpUserAttributeSubpacketVector.cs | 81 + crypto/src/openpgp/PgpUtilities.cs | 426 + crypto/src/openpgp/PgpV3SignatureGenerator.cs | 199 + crypto/src/openpgp/WrappedGeneratorStream.cs | 25 + crypto/src/openssl/EncryptionException.cs | 25 + crypto/src/openssl/IPasswordFinder.cs | 9 + crypto/src/openssl/MiscPemGenerator.cs | 276 + crypto/src/openssl/PEMException.cs | 25 + crypto/src/openssl/PEMReader.cs | 407 + crypto/src/openssl/PEMUtilities.cs | 158 + crypto/src/openssl/PEMWriter.cs | 61 + crypto/src/openssl/PasswordException.cs | 25 + crypto/src/openssl/Pkcs8Generator.cs | 111 + crypto/src/pkcs/AsymmetricKeyEntry.cs | 60 + crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs | 64 + crypto/src/pkcs/PKCS12StoreBuilder.cs | 41 + crypto/src/pkcs/Pkcs10CertificationRequest.cs | 465 + .../pkcs/Pkcs10CertificationRequestDelaySigned.cs | 150 + crypto/src/pkcs/Pkcs12Entry.cs | 64 + crypto/src/pkcs/Pkcs12Store.cs | 1228 +++ crypto/src/pkcs/Pkcs12Utilities.cs | 77 + crypto/src/pkcs/PrivateKeyInfoFactory.cs | 208 + crypto/src/pkcs/X509CertificateEntry.cs | 60 + crypto/src/pkix/CertStatus.cs | 35 + crypto/src/pkix/PkixAttrCertChecker.cs | 57 + crypto/src/pkix/PkixAttrCertPathBuilder.cs | 215 + crypto/src/pkix/PkixAttrCertPathValidator.cs | 76 + crypto/src/pkix/PkixBuilderParameters.cs | 140 + crypto/src/pkix/PkixCertPath.cs | 460 + crypto/src/pkix/PkixCertPathBuilder.cs | 205 + crypto/src/pkix/PkixCertPathBuilderException.cs | 22 + crypto/src/pkix/PkixCertPathBuilderResult.cs | 45 + crypto/src/pkix/PkixCertPathChecker.cs | 101 + crypto/src/pkix/PkixCertPathValidator.cs | 420 + crypto/src/pkix/PkixCertPathValidatorException.cs | 221 + crypto/src/pkix/PkixCertPathValidatorResult.cs | 69 + crypto/src/pkix/PkixCertPathValidatorUtilities.cs | 1194 +++ crypto/src/pkix/PkixCrlUtilities.cs | 114 + crypto/src/pkix/PkixNameConstraintValidator.cs | 1937 ++++ .../pkix/PkixNameConstraintValidatorException.cs | 16 + crypto/src/pkix/PkixParameters.cs | 893 ++ crypto/src/pkix/PkixPolicyNode.cs | 158 + crypto/src/pkix/ReasonsMask.cs | 96 + crypto/src/pkix/Rfc3280CertPathUtilities.cs | 2448 +++++ crypto/src/pkix/Rfc3281CertPathUtilities.cs | 608 ++ crypto/src/pkix/TrustAnchor.cs | 259 + crypto/src/security/AgreementUtilities.cs | 105 + crypto/src/security/CipherUtilities.cs | 739 ++ crypto/src/security/DigestUtilities.cs | 202 + crypto/src/security/DotNetUtilities.cs | 222 + crypto/src/security/GeneralSecurityException.cs | 29 + crypto/src/security/GeneratorUtilities.cs | 349 + crypto/src/security/InvalidKeyException.cs | 14 + crypto/src/security/InvalidParameterException.cs | 14 + crypto/src/security/KeyException.cs | 14 + crypto/src/security/MacUtilities.cs | 243 + crypto/src/security/NoSuchAlgorithmException.cs | 15 + crypto/src/security/ParameterUtilities.cs | 327 + crypto/src/security/PbeUtilities.cs | 663 ++ crypto/src/security/PrivateKeyFactory.cs | 221 + crypto/src/security/PublicKeyFactory.cs | 253 + crypto/src/security/SecureRandom.cs | 228 + crypto/src/security/SecurityUtilityException.cs | 36 + crypto/src/security/SignatureException.cs | 14 + crypto/src/security/SignerUtilities.cs | 549 + crypto/src/security/WrapperUtilities.cs | 153 + .../security/cert/CertificateEncodingException.cs | 14 + crypto/src/security/cert/CertificateException.cs | 14 + .../security/cert/CertificateExpiredException.cs | 14 + .../cert/CertificateNotYetValidException.cs | 14 + .../security/cert/CertificateParsingException.cs | 14 + crypto/src/security/cert/CrlException.cs | 14 + crypto/src/tsp/GenTimeAccuracy.cs | 33 + crypto/src/tsp/TSPAlgorithms.cs | 48 + crypto/src/tsp/TSPException.cs | 28 + crypto/src/tsp/TSPUtil.cs | 202 + crypto/src/tsp/TSPValidationException.cs | 44 + crypto/src/tsp/TimeStampRequest.cs | 196 + crypto/src/tsp/TimeStampRequestGenerator.cs | 139 + crypto/src/tsp/TimeStampResponse.cs | 184 + crypto/src/tsp/TimeStampResponseGenerator.cs | 210 + crypto/src/tsp/TimeStampToken.cs | 305 + crypto/src/tsp/TimeStampTokenGenerator.cs | 245 + crypto/src/tsp/TimeStampTokenInfo.cs | 107 + crypto/src/util/Arrays.cs | 233 + crypto/src/util/BigIntegers.cs | 94 + crypto/src/util/Enums.cs | 73 + crypto/src/util/Platform.cs | 182 + crypto/src/util/Strings.cs | 107 + crypto/src/util/collections/CollectionUtilities.cs | 71 + crypto/src/util/collections/EmptyEnumerable.cs | 44 + crypto/src/util/collections/EnumerableProxy.cs | 25 + crypto/src/util/collections/HashSet.cs | 99 + crypto/src/util/collections/ISet.cs | 19 + crypto/src/util/collections/LinkedDictionary.cs | 178 + .../src/util/collections/UnmodifiableDictionary.cs | 64 + .../collections/UnmodifiableDictionaryProxy.cs | 66 + crypto/src/util/collections/UnmodifiableList.cs | 67 + .../src/util/collections/UnmodifiableListProxy.cs | 61 + crypto/src/util/collections/UnmodifiableSet.cs | 59 + .../src/util/collections/UnmodifiableSetProxy.cs | 56 + crypto/src/util/date/DateTimeObject.cs | 25 + crypto/src/util/date/DateTimeUtilities.cs | 47 + crypto/src/util/encoders/Base64.cs | 120 + crypto/src/util/encoders/Base64Encoder.cs | 307 + crypto/src/util/encoders/BufferedDecoder.cs | 117 + crypto/src/util/encoders/BufferedEncoder.cs | 117 + crypto/src/util/encoders/Hex.cs | 130 + crypto/src/util/encoders/HexEncoder.cs | 163 + crypto/src/util/encoders/HexTranslator.cs | 108 + crypto/src/util/encoders/IEncoder.cs | 18 + crypto/src/util/encoders/Translator.cs | 19 + crypto/src/util/encoders/UrlBase64.cs | 127 + crypto/src/util/encoders/UrlBase64Encoder.cs | 31 + crypto/src/util/io/BaseInputStream.cs | 47 + crypto/src/util/io/BaseOutputStream.cs | 47 + crypto/src/util/io/PushbackStream.cs | 52 + crypto/src/util/io/StreamOverflowException.cs | 30 + crypto/src/util/io/Streams.cs | 94 + crypto/src/util/io/TeeInputStream.cs | 51 + crypto/src/util/io/TeeOutputStream.cs | 39 + crypto/src/util/io/pem/PemGenerationException.cs | 29 + crypto/src/util/io/pem/PemHeader.cs | 55 + crypto/src/util/io/pem/PemObject.cs | 47 + crypto/src/util/io/pem/PemObjectGenerator.cs | 13 + crypto/src/util/io/pem/PemObjectParser.cs | 17 + crypto/src/util/io/pem/PemReader.cs | 94 + crypto/src/util/io/pem/PemWriter.cs | 120 + crypto/src/util/net/IPAddress.cs | 197 + crypto/src/util/zlib/Adler32.cs | 88 + crypto/src/util/zlib/Deflate.cs | 1640 +++ crypto/src/util/zlib/InfBlocks.cs | 618 ++ crypto/src/util/zlib/InfCodes.cs | 611 ++ crypto/src/util/zlib/InfTree.cs | 523 + crypto/src/util/zlib/Inflate.cs | 387 + crypto/src/util/zlib/JZlib.cs | 73 + crypto/src/util/zlib/StaticTree.cs | 152 + crypto/src/util/zlib/Tree.cs | 367 + crypto/src/util/zlib/ZDeflaterOutputStream.cs | 151 + crypto/src/util/zlib/ZInflaterInputStream.cs | 127 + crypto/src/util/zlib/ZInputStream.cs | 193 + crypto/src/util/zlib/ZOutputStream.cs | 229 + crypto/src/util/zlib/ZStream.cs | 214 + crypto/src/x509/AttributeCertificateHolder.cs | 442 + crypto/src/x509/AttributeCertificateIssuer.cs | 199 + crypto/src/x509/IX509AttributeCertificate.cs | 57 + crypto/src/x509/IX509Extension.cs | 27 + crypto/src/x509/PEMParser.cs | 94 + crypto/src/x509/PrincipalUtil.cs | 70 + crypto/src/x509/SubjectPublicKeyInfoFactory.cs | 187 + crypto/src/x509/X509AttrCertParser.cs | 173 + crypto/src/x509/X509Attribute.cs | 76 + crypto/src/x509/X509CertPairParser.cs | 95 + crypto/src/x509/X509Certificate.cs | 595 ++ crypto/src/x509/X509CertificatePair.cs | 123 + crypto/src/x509/X509CertificateParser.cs | 183 + crypto/src/x509/X509Crl.cs | 403 + crypto/src/x509/X509CrlEntry.cs | 201 + crypto/src/x509/X509CrlParser.cs | 195 + crypto/src/x509/X509ExtensionBase.cs | 82 + crypto/src/x509/X509KeyUsage.cs | 59 + crypto/src/x509/X509SignatureUtil.cs | 128 + crypto/src/x509/X509Utilities.cs | 187 + crypto/src/x509/X509V1CertificateGenerator.cs | 205 + crypto/src/x509/X509V2AttributeCertificate.cs | 255 + .../x509/X509V2AttributeCertificateGenerator.cs | 180 + crypto/src/x509/X509V2CRLGenerator.cs | 261 + crypto/src/x509/X509V3CertificateGenerator.cs | 346 + .../extension/AuthorityKeyIdentifierStructure.cs | 102 + .../extension/SubjectKeyIdentifierStructure.cs | 49 + crypto/src/x509/extension/X509ExtensionUtil.cs | 89 + crypto/src/x509/store/IX509Selector.cs | 15 + crypto/src/x509/store/IX509Store.cs | 11 + crypto/src/x509/store/IX509StoreParameters.cs | 8 + crypto/src/x509/store/NoSuchStoreException.cs | 28 + crypto/src/x509/store/X509AttrCertStoreSelector.cs | 376 + crypto/src/x509/store/X509CertPairStoreSelector.cs | 92 + crypto/src/x509/store/X509CertStoreSelector.cs | 337 + crypto/src/x509/store/X509CollectionStore.cs | 51 + .../x509/store/X509CollectionStoreParameters.cs | 60 + crypto/src/x509/store/X509CrlStoreSelector.cs | 283 + crypto/src/x509/store/X509StoreException.cs | 28 + crypto/src/x509/store/X509StoreFactory.cs | 62 + crypto/test/data/PKITS/README.txt | 3 + .../certs/AllCertificatesNoPoliciesTest2EE.crt | Bin 0 -> 627 bytes .../certs/AllCertificatesSamePoliciesTest10EE.crt | Bin 0 -> 670 bytes .../certs/AllCertificatesSamePoliciesTest13EE.crt | Bin 0 -> 687 bytes .../certs/AllCertificatesanyPolicyTest11EE.crt | Bin 0 -> 643 bytes crypto/test/data/PKITS/certs/AnyPolicyTest14EE.crt | Bin 0 -> 632 bytes .../data/PKITS/certs/BadCRLIssuerNameCACert.crt | Bin 0 -> 640 bytes .../data/PKITS/certs/BadCRLSignatureCACert.crt | Bin 0 -> 638 bytes crypto/test/data/PKITS/certs/BadSignedCACert.crt | Bin 0 -> 631 bytes .../data/PKITS/certs/BadnotAfterDateCACert.crt | Bin 0 -> 638 bytes .../data/PKITS/certs/BadnotBeforeDateCACert.crt | Bin 0 -> 639 bytes .../certs/BasicSelfIssuedCRLSigningKeyCACert.crt | Bin 0 -> 654 bytes .../certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt | Bin 0 -> 797 bytes .../PKITS/certs/BasicSelfIssuedNewKeyCACert.crt | Bin 0 -> 646 bytes .../BasicSelfIssuedNewKeyOldWithNewCACert.crt | Bin 0 -> 662 bytes .../PKITS/certs/BasicSelfIssuedOldKeyCACert.crt | Bin 0 -> 646 bytes .../BasicSelfIssuedOldKeyNewWithOldCACert.crt | Bin 0 -> 789 bytes .../PKITS/certs/CPSPointerQualifierTest20EE.crt | Bin 0 -> 701 bytes crypto/test/data/PKITS/certs/DSACACert.crt | Bin 0 -> 906 bytes .../PKITS/certs/DSAParametersInheritedCACert.crt | Bin 0 -> 536 bytes .../data/PKITS/certs/DifferentPoliciesTest12EE.crt | Bin 0 -> 643 bytes .../data/PKITS/certs/DifferentPoliciesTest3EE.crt | Bin 0 -> 645 bytes .../data/PKITS/certs/DifferentPoliciesTest4EE.crt | Bin 0 -> 638 bytes .../data/PKITS/certs/DifferentPoliciesTest5EE.crt | Bin 0 -> 646 bytes .../data/PKITS/certs/DifferentPoliciesTest7EE.crt | Bin 0 -> 672 bytes .../data/PKITS/certs/DifferentPoliciesTest8EE.crt | Bin 0 -> 670 bytes .../data/PKITS/certs/DifferentPoliciesTest9EE.crt | Bin 0 -> 660 bytes .../certs/GeneralizedTimeCRLnextUpdateCACert.crt | Bin 0 -> 649 bytes crypto/test/data/PKITS/certs/GoodCACert.crt | Bin 0 -> 625 bytes crypto/test/data/PKITS/certs/GoodsubCACert.crt | Bin 0 -> 639 bytes .../certs/GoodsubCAPanyPolicyMapping1to2CACert.crt | Bin 0 -> 697 bytes .../PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt | Bin 0 -> 659 bytes .../PKITS/certs/InvalidBadCRLSignatureTest4EE.crt | Bin 0 -> 655 bytes .../InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt | Bin 0 -> 687 bytes .../InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt | Bin 0 -> 687 bytes .../InvalidBasicSelfIssuedNewWithOldTest5EE.crt | Bin 0 -> 676 bytes .../InvalidBasicSelfIssuedOldWithNewTest2EE.crt | Bin 0 -> 676 bytes .../data/PKITS/certs/InvalidCASignatureTest2EE.crt | Bin 0 -> 628 bytes .../PKITS/certs/InvalidCAnotAfterDateTest5EE.crt | Bin 0 -> 654 bytes .../PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt | Bin 0 -> 656 bytes .../certs/InvalidDNSnameConstraintsTest31EE.crt | Bin 0 -> 710 bytes .../certs/InvalidDNSnameConstraintsTest33EE.crt | Bin 0 -> 699 bytes .../certs/InvalidDNSnameConstraintsTest38EE.crt | Bin 0 -> 698 bytes .../InvalidDNandRFC822nameConstraintsTest28EE.crt | Bin 0 -> 778 bytes .../InvalidDNandRFC822nameConstraintsTest29EE.crt | Bin 0 -> 780 bytes .../certs/InvalidDNnameConstraintsTest10EE.crt | Bin 0 -> 715 bytes .../certs/InvalidDNnameConstraintsTest12EE.crt | Bin 0 -> 720 bytes .../certs/InvalidDNnameConstraintsTest13EE.crt | Bin 0 -> 720 bytes .../certs/InvalidDNnameConstraintsTest15EE.crt | Bin 0 -> 690 bytes .../certs/InvalidDNnameConstraintsTest16EE.crt | Bin 0 -> 690 bytes .../certs/InvalidDNnameConstraintsTest17EE.crt | Bin 0 -> 690 bytes .../certs/InvalidDNnameConstraintsTest20EE.crt | Bin 0 -> 633 bytes .../certs/InvalidDNnameConstraintsTest2EE.crt | Bin 0 -> 685 bytes .../certs/InvalidDNnameConstraintsTest3EE.crt | Bin 0 -> 833 bytes .../certs/InvalidDNnameConstraintsTest7EE.crt | Bin 0 -> 685 bytes .../certs/InvalidDNnameConstraintsTest8EE.crt | Bin 0 -> 685 bytes .../certs/InvalidDNnameConstraintsTest9EE.crt | Bin 0 -> 685 bytes .../PKITS/certs/InvalidDSASignatureTest6EE.crt | Bin 0 -> 827 bytes .../data/PKITS/certs/InvalidEESignatureTest3EE.crt | Bin 0 -> 622 bytes .../PKITS/certs/InvalidEEnotAfterDateTest6EE.crt | Bin 0 -> 641 bytes .../PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt | Bin 0 -> 642 bytes .../certs/InvalidIDPwithindirectCRLTest23EE.crt | Bin 0 -> 654 bytes .../certs/InvalidIDPwithindirectCRLTest26EE.crt | Bin 0 -> 743 bytes .../certs/InvalidLongSerialNumberTest18EE.crt | Bin 0 -> 677 bytes .../certs/InvalidMappingFromanyPolicyTest7EE.crt | Bin 0 -> 665 bytes .../certs/InvalidMappingToanyPolicyTest8EE.crt | Bin 0 -> 655 bytes .../data/PKITS/certs/InvalidMissingCRLTest1EE.crt | Bin 0 -> 638 bytes .../InvalidMissingbasicConstraintsTest1EE.crt | Bin 0 -> 669 bytes .../certs/InvalidNameChainingOrderTest2EE.crt | Bin 0 -> 728 bytes .../PKITS/certs/InvalidNameChainingTest1EE.crt | Bin 0 -> 643 bytes .../certs/InvalidNegativeSerialNumberTest15EE.crt | Bin 0 -> 666 bytes .../certs/InvalidOldCRLnextUpdateTest11EE.crt | Bin 0 -> 658 bytes .../PKITS/certs/InvalidPolicyMappingTest10EE.crt | Bin 0 -> 667 bytes .../PKITS/certs/InvalidPolicyMappingTest2EE.crt | Bin 0 -> 647 bytes .../PKITS/certs/InvalidPolicyMappingTest4EE.crt | Bin 0 -> 657 bytes .../certs/InvalidRFC822nameConstraintsTest22EE.crt | Bin 0 -> 711 bytes .../certs/InvalidRFC822nameConstraintsTest24EE.crt | Bin 0 -> 722 bytes .../certs/InvalidRFC822nameConstraintsTest26EE.crt | Bin 0 -> 711 bytes .../data/PKITS/certs/InvalidRevokedCATest2EE.crt | Bin 0 -> 638 bytes .../data/PKITS/certs/InvalidRevokedEETest3EE.crt | Bin 0 -> 632 bytes .../InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt | Bin 0 -> 648 bytes .../InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt | Bin 0 -> 673 bytes ...validSelfIssuedinhibitPolicyMappingTest10EE.crt | Bin 0 -> 681 bytes ...validSelfIssuedinhibitPolicyMappingTest11EE.crt | Bin 0 -> 681 bytes ...nvalidSelfIssuedinhibitPolicyMappingTest8EE.crt | Bin 0 -> 683 bytes ...nvalidSelfIssuedinhibitPolicyMappingTest9EE.crt | Bin 0 -> 683 bytes .../InvalidSelfIssuedpathLenConstraintTest16EE.crt | Bin 0 -> 673 bytes ...validSelfIssuedrequireExplicitPolicyTest7EE.crt | Bin 0 -> 654 bytes ...validSelfIssuedrequireExplicitPolicyTest8EE.crt | Bin 0 -> 654 bytes ...nvalidSeparateCertificateandCRLKeysTest20EE.crt | Bin 0 -> 689 bytes ...nvalidSeparateCertificateandCRLKeysTest21EE.crt | Bin 0 -> 689 bytes .../certs/InvalidURInameConstraintsTest35EE.crt | Bin 0 -> 716 bytes .../certs/InvalidURInameConstraintsTest37EE.crt | Bin 0 -> 716 bytes .../InvalidUnknownCRLEntryExtensionTest8EE.crt | Bin 0 -> 675 bytes .../certs/InvalidUnknownCRLExtensionTest10EE.crt | Bin 0 -> 664 bytes .../certs/InvalidUnknownCRLExtensionTest9EE.crt | Bin 0 -> 663 bytes ...dUnknownCriticalCertificateExtensionTest2EE.crt | Bin 0 -> 683 bytes .../data/PKITS/certs/InvalidWrongCRLTest6EE.crt | Bin 0 -> 639 bytes .../data/PKITS/certs/InvalidcAFalseTest2EE.crt | Bin 0 -> 663 bytes .../data/PKITS/certs/InvalidcAFalseTest3EE.crt | Bin 0 -> 667 bytes .../data/PKITS/certs/InvalidcRLIssuerTest27EE.crt | Bin 0 -> 723 bytes .../data/PKITS/certs/InvalidcRLIssuerTest31EE.crt | Bin 0 -> 855 bytes .../data/PKITS/certs/InvalidcRLIssuerTest32EE.crt | Bin 0 -> 855 bytes .../data/PKITS/certs/InvalidcRLIssuerTest34EE.crt | Bin 0 -> 768 bytes .../data/PKITS/certs/InvalidcRLIssuerTest35EE.crt | Bin 0 -> 847 bytes .../InvaliddeltaCRLIndicatorNoBaseTest1EE.crt | Bin 0 -> 671 bytes .../data/PKITS/certs/InvaliddeltaCRLTest10EE.crt | Bin 0 -> 813 bytes .../data/PKITS/certs/InvaliddeltaCRLTest3EE.crt | Bin 0 -> 812 bytes .../data/PKITS/certs/InvaliddeltaCRLTest4EE.crt | Bin 0 -> 812 bytes .../data/PKITS/certs/InvaliddeltaCRLTest6EE.crt | Bin 0 -> 812 bytes .../data/PKITS/certs/InvaliddeltaCRLTest9EE.crt | Bin 0 -> 812 bytes .../certs/InvaliddistributionPointTest2EE.crt | Bin 0 -> 793 bytes .../certs/InvaliddistributionPointTest3EE.crt | Bin 0 -> 793 bytes .../certs/InvaliddistributionPointTest6EE.crt | Bin 0 -> 713 bytes .../certs/InvaliddistributionPointTest8EE.crt | Bin 0 -> 752 bytes .../certs/InvaliddistributionPointTest9EE.crt | Bin 0 -> 656 bytes .../PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt | Bin 0 -> 648 bytes .../PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt | Bin 0 -> 652 bytes .../PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt | Bin 0 -> 654 bytes .../PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt | Bin 0 -> 655 bytes .../certs/InvalidinhibitPolicyMappingTest1EE.crt | Bin 0 -> 679 bytes .../certs/InvalidinhibitPolicyMappingTest3EE.crt | Bin 0 -> 672 bytes .../certs/InvalidinhibitPolicyMappingTest5EE.crt | Bin 0 -> 671 bytes .../certs/InvalidinhibitPolicyMappingTest6EE.crt | Bin 0 -> 676 bytes .../InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt | Bin 0 -> 683 bytes ...alidkeyUsageCriticalkeyCertSignFalseTest1EE.crt | Bin 0 -> 691 bytes ...validkeyUsageNotCriticalcRLSignFalseTest5EE.crt | Bin 0 -> 691 bytes ...dkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt | Bin 0 -> 692 bytes .../InvalidonlyContainsAttributeCertsTest14EE.crt | Bin 0 -> 674 bytes .../certs/InvalidonlyContainsCACertsTest12EE.crt | Bin 0 -> 660 bytes .../certs/InvalidonlyContainsUserCertsTest11EE.crt | Bin 0 -> 681 bytes .../PKITS/certs/InvalidonlySomeReasonsTest15EE.crt | Bin 0 -> 653 bytes .../PKITS/certs/InvalidonlySomeReasonsTest16EE.crt | Bin 0 -> 653 bytes .../PKITS/certs/InvalidonlySomeReasonsTest17EE.crt | Bin 0 -> 653 bytes .../PKITS/certs/InvalidonlySomeReasonsTest20EE.crt | Bin 0 -> 872 bytes .../PKITS/certs/InvalidonlySomeReasonsTest21EE.crt | Bin 0 -> 872 bytes .../certs/InvalidpathLenConstraintTest10EE.crt | Bin 0 -> 682 bytes .../certs/InvalidpathLenConstraintTest11EE.crt | Bin 0 -> 669 bytes .../certs/InvalidpathLenConstraintTest12EE.crt | Bin 0 -> 686 bytes .../certs/InvalidpathLenConstraintTest5EE.crt | Bin 0 -> 659 bytes .../certs/InvalidpathLenConstraintTest6EE.crt | Bin 0 -> 676 bytes .../certs/InvalidpathLenConstraintTest9EE.crt | Bin 0 -> 664 bytes .../certs/Invalidpre2000CRLnextUpdateTest12EE.crt | Bin 0 -> 666 bytes .../Invalidpre2000UTCEEnotAfterDateTest7EE.crt | Bin 0 -> 655 bytes .../certs/InvalidrequireExplicitPolicyTest3EE.crt | Bin 0 -> 648 bytes .../certs/InvalidrequireExplicitPolicyTest5EE.crt | Bin 0 -> 654 bytes .../data/PKITS/certs/LongSerialNumberCACert.crt | Bin 0 -> 639 bytes crypto/test/data/PKITS/certs/Mapping1to2CACert.crt | Bin 0 -> 689 bytes .../PKITS/certs/MappingFromanyPolicyCACert.crt | Bin 0 -> 690 bytes .../data/PKITS/certs/MappingToanyPolicyCACert.crt | Bin 0 -> 694 bytes .../PKITS/certs/MissingbasicConstraintsCACert.crt | Bin 0 -> 628 bytes .../test/data/PKITS/certs/NameOrderingCACert.crt | Bin 0 -> 709 bytes .../PKITS/certs/NegativeSerialNumberCACert.crt | Bin 0 -> 643 bytes crypto/test/data/PKITS/certs/NoCRLCACert.crt | Bin 0 -> 627 bytes crypto/test/data/PKITS/certs/NoPoliciesCACert.crt | Bin 0 -> 607 bytes .../certs/NoissuingDistributionPointCACert.crt | Bin 0 -> 648 bytes .../data/PKITS/certs/OldCRLnextUpdateCACert.crt | Bin 0 -> 639 bytes .../PKITS/certs/OverlappingPoliciesTest6EE.crt | Bin 0 -> 677 bytes .../test/data/PKITS/certs/P12Mapping1to3CACert.crt | Bin 0 -> 707 bytes .../data/PKITS/certs/P12Mapping1to3subCACert.crt | Bin 0 -> 729 bytes .../PKITS/certs/P12Mapping1to3subsubCACert.crt | Bin 0 -> 709 bytes .../data/PKITS/certs/P1Mapping1to234CACert.crt | Bin 0 -> 746 bytes .../data/PKITS/certs/P1Mapping1to234subCACert.crt | Bin 0 -> 731 bytes .../PKITS/certs/P1anyPolicyMapping1to2CACert.crt | Bin 0 -> 1058 bytes .../PKITS/certs/PanyPolicyMapping1to2CACert.crt | Bin 0 -> 694 bytes .../test/data/PKITS/certs/PoliciesP1234CACert.crt | Bin 0 -> 693 bytes .../PKITS/certs/PoliciesP1234subCAP123Cert.crt | Bin 0 -> 677 bytes .../certs/PoliciesP1234subsubCAP123P12Cert.crt | Bin 0 -> 676 bytes .../test/data/PKITS/certs/PoliciesP123CACert.crt | Bin 0 -> 678 bytes .../data/PKITS/certs/PoliciesP123subCAP12Cert.crt | Bin 0 -> 660 bytes .../PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt | Bin 0 -> 655 bytes .../PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt | Bin 0 -> 655 bytes .../certs/PoliciesP123subsubsubCAP12P2P1Cert.crt | Bin 0 -> 665 bytes crypto/test/data/PKITS/certs/PoliciesP12CACert.crt | Bin 0 -> 663 bytes .../data/PKITS/certs/PoliciesP12subCAP1Cert.crt | Bin 0 -> 641 bytes .../PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt | Bin 0 -> 651 bytes .../test/data/PKITS/certs/PoliciesP2subCA2Cert.crt | Bin 0 -> 647 bytes .../test/data/PKITS/certs/PoliciesP2subCACert.crt | Bin 0 -> 630 bytes crypto/test/data/PKITS/certs/PoliciesP3CACert.crt | Bin 0 -> 648 bytes .../certs/RFC3280MandatoryAttributeTypesCACert.crt | Bin 0 -> 709 bytes .../certs/RFC3280OptionalAttributeTypesCACert.crt | Bin 0 -> 721 bytes crypto/test/data/PKITS/certs/RevokedsubCACert.crt | Bin 0 -> 626 bytes ...lloverfromPrintableStringtoUTF8StringCACert.crt | Bin 0 -> 664 bytes ...arateCertificateandCRLKeysCA2CRLSigningCert.crt | Bin 0 -> 638 bytes ...ficateandCRLKeysCA2CertificateSigningCACert.crt | Bin 0 -> 655 bytes ...SeparateCertificateandCRLKeysCRLSigningCert.crt | Bin 0 -> 638 bytes ...rtificateandCRLKeysCertificateSigningCACert.crt | Bin 0 -> 655 bytes .../PKITS/certs/TrustAnchorRootCertificate.crt | Bin 0 -> 572 bytes crypto/test/data/PKITS/certs/TwoCRLsCACert.crt | Bin 0 -> 629 bytes crypto/test/data/PKITS/certs/UIDCACert.crt | Bin 0 -> 629 bytes .../certs/UTF8StringCaseInsensitiveMatchCACert.crt | Bin 0 -> 654 bytes .../PKITS/certs/UTF8StringEncodedNamesCACert.crt | Bin 0 -> 631 bytes .../PKITS/certs/UnknownCRLEntryExtensionCACert.crt | Bin 0 -> 648 bytes .../data/PKITS/certs/UnknownCRLExtensionCACert.crt | Bin 0 -> 642 bytes .../PKITS/certs/UserNoticeQualifierTest15EE.crt | Bin 0 -> 755 bytes .../PKITS/certs/UserNoticeQualifierTest16EE.crt | Bin 0 -> 874 bytes .../PKITS/certs/UserNoticeQualifierTest17EE.crt | Bin 0 -> 743 bytes .../PKITS/certs/UserNoticeQualifierTest18EE.crt | Bin 0 -> 969 bytes .../PKITS/certs/UserNoticeQualifierTest19EE.crt | Bin 0 -> 992 bytes .../ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt | Bin 0 -> 685 bytes .../ValidBasicSelfIssuedNewWithOldTest3EE.crt | Bin 0 -> 674 bytes .../ValidBasicSelfIssuedNewWithOldTest4EE.crt | Bin 0 -> 674 bytes .../ValidBasicSelfIssuedOldWithNewTest1EE.crt | Bin 0 -> 674 bytes .../PKITS/certs/ValidCertificatePathTest1EE.crt | Bin 0 -> 622 bytes .../certs/ValidDNSnameConstraintsTest30EE.crt | Bin 0 -> 705 bytes .../certs/ValidDNSnameConstraintsTest32EE.crt | Bin 0 -> 705 bytes .../ValidDNandRFC822nameConstraintsTest27EE.crt | Bin 0 -> 773 bytes .../PKITS/certs/ValidDNnameConstraintsTest11EE.crt | Bin 0 -> 714 bytes .../PKITS/certs/ValidDNnameConstraintsTest14EE.crt | Bin 0 -> 660 bytes .../PKITS/certs/ValidDNnameConstraintsTest18EE.crt | Bin 0 -> 661 bytes .../PKITS/certs/ValidDNnameConstraintsTest19EE.crt | Bin 0 -> 685 bytes .../PKITS/certs/ValidDNnameConstraintsTest1EE.crt | Bin 0 -> 684 bytes .../PKITS/certs/ValidDNnameConstraintsTest4EE.crt | Bin 0 -> 744 bytes .../PKITS/certs/ValidDNnameConstraintsTest5EE.crt | Bin 0 -> 829 bytes .../PKITS/certs/ValidDNnameConstraintsTest6EE.crt | Bin 0 -> 684 bytes .../certs/ValidDSAParameterInheritanceTest5EE.crt | Bin 0 -> 566 bytes .../data/PKITS/certs/ValidDSASignaturesTest4EE.crt | Bin 0 -> 826 bytes .../ValidGeneralizedTimeCRLnextUpdateTest13EE.crt | Bin 0 -> 678 bytes .../ValidGeneralizedTimenotAfterDateTest8EE.crt | Bin 0 -> 654 bytes .../ValidGeneralizedTimenotBeforeDateTest4EE.crt | Bin 0 -> 655 bytes .../certs/ValidIDPwithindirectCRLTest22EE.crt | Bin 0 -> 652 bytes .../certs/ValidIDPwithindirectCRLTest24EE.crt | Bin 0 -> 740 bytes .../certs/ValidIDPwithindirectCRLTest25EE.crt | Bin 0 -> 740 bytes .../PKITS/certs/ValidLongSerialNumberTest16EE.crt | Bin 0 -> 675 bytes .../PKITS/certs/ValidLongSerialNumberTest17EE.crt | Bin 0 -> 675 bytes .../ValidNameChainingCapitalizationTest5EE.crt | Bin 0 -> 651 bytes .../certs/ValidNameChainingWhitespaceTest3EE.crt | Bin 0 -> 652 bytes .../certs/ValidNameChainingWhitespaceTest4EE.crt | Bin 0 -> 653 bytes .../test/data/PKITS/certs/ValidNameUIDsTest6EE.crt | Bin 0 -> 630 bytes .../certs/ValidNegativeSerialNumberTest14EE.crt | Bin 0 -> 665 bytes .../ValidNoissuingDistributionPointTest10EE.crt | Bin 0 -> 793 bytes .../PKITS/certs/ValidPolicyMappingTest11EE.crt | Bin 0 -> 665 bytes .../PKITS/certs/ValidPolicyMappingTest12EE.crt | Bin 0 -> 1068 bytes .../PKITS/certs/ValidPolicyMappingTest13EE.crt | Bin 0 -> 658 bytes .../PKITS/certs/ValidPolicyMappingTest14EE.crt | Bin 0 -> 658 bytes .../data/PKITS/certs/ValidPolicyMappingTest1EE.crt | Bin 0 -> 645 bytes .../data/PKITS/certs/ValidPolicyMappingTest3EE.crt | Bin 0 -> 655 bytes .../data/PKITS/certs/ValidPolicyMappingTest5EE.crt | Bin 0 -> 653 bytes .../data/PKITS/certs/ValidPolicyMappingTest6EE.crt | Bin 0 -> 653 bytes .../data/PKITS/certs/ValidPolicyMappingTest9EE.crt | Bin 0 -> 656 bytes .../ValidRFC3280MandatoryAttributeTypesTest7EE.crt | Bin 0 -> 740 bytes .../ValidRFC3280OptionalAttributeTypesTest8EE.crt | Bin 0 -> 751 bytes .../certs/ValidRFC822nameConstraintsTest21EE.crt | Bin 0 -> 720 bytes .../certs/ValidRFC822nameConstraintsTest23EE.crt | Bin 0 -> 709 bytes .../certs/ValidRFC822nameConstraintsTest25EE.crt | Bin 0 -> 720 bytes ...overfromPrintableStringtoUTF8StringTest10EE.crt | Bin 0 -> 694 bytes .../ValidSelfIssuedinhibitAnyPolicyTest7EE.crt | Bin 0 -> 668 bytes .../ValidSelfIssuedinhibitAnyPolicyTest9EE.crt | Bin 0 -> 668 bytes .../ValidSelfIssuedinhibitPolicyMappingTest7EE.crt | Bin 0 -> 678 bytes .../ValidSelfIssuedpathLenConstraintTest15EE.crt | Bin 0 -> 667 bytes .../ValidSelfIssuedpathLenConstraintTest17EE.crt | Bin 0 -> 670 bytes ...ValidSelfIssuedrequireExplicitPolicyTest6EE.crt | Bin 0 -> 649 bytes .../ValidSeparateCertificateandCRLKeysTest19EE.crt | Bin 0 -> 687 bytes .../test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt | Bin 0 -> 635 bytes .../certs/ValidURInameConstraintsTest34EE.crt | Bin 0 -> 723 bytes .../certs/ValidURInameConstraintsTest36EE.crt | Bin 0 -> 726 bytes ...ValidUTF8StringCaseInsensitiveMatchTest11EE.crt | Bin 0 -> 691 bytes .../certs/ValidUTF8StringEncodedNamesTest9EE.crt | Bin 0 -> 653 bytes ...knownNotCriticalCertificateExtensionTest1EE.crt | Bin 0 -> 681 bytes .../ValidbasicConstraintsNotCriticalTest4EE.crt | Bin 0 -> 677 bytes .../data/PKITS/certs/ValidcRLIssuerTest28EE.crt | Bin 0 -> 873 bytes .../data/PKITS/certs/ValidcRLIssuerTest29EE.crt | Bin 0 -> 788 bytes .../data/PKITS/certs/ValidcRLIssuerTest30EE.crt | Bin 0 -> 873 bytes .../data/PKITS/certs/ValidcRLIssuerTest33EE.crt | Bin 0 -> 853 bytes .../test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt | Bin 0 -> 810 bytes .../test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt | Bin 0 -> 810 bytes .../test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt | Bin 0 -> 810 bytes .../test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt | Bin 0 -> 810 bytes .../PKITS/certs/ValiddistributionPointTest1EE.crt | Bin 0 -> 791 bytes .../PKITS/certs/ValiddistributionPointTest4EE.crt | Bin 0 -> 711 bytes .../PKITS/certs/ValiddistributionPointTest5EE.crt | Bin 0 -> 711 bytes .../PKITS/certs/ValiddistributionPointTest7EE.crt | Bin 0 -> 791 bytes .../PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt | Bin 0 -> 660 bytes .../certs/ValidinhibitPolicyMappingTest2EE.crt | Bin 0 -> 667 bytes .../certs/ValidinhibitPolicyMappingTest4EE.crt | Bin 0 -> 670 bytes .../certs/ValidkeyUsageNotCriticalTest3EE.crt | Bin 0 -> 661 bytes .../certs/ValidonlyContainsCACertsTest13EE.crt | Bin 0 -> 675 bytes .../PKITS/certs/ValidonlySomeReasonsTest18EE.crt | Bin 0 -> 759 bytes .../PKITS/certs/ValidonlySomeReasonsTest19EE.crt | Bin 0 -> 870 bytes .../PKITS/certs/ValidpathLenConstraintTest13EE.crt | Bin 0 -> 667 bytes .../PKITS/certs/ValidpathLenConstraintTest14EE.crt | Bin 0 -> 684 bytes .../PKITS/certs/ValidpathLenConstraintTest7EE.crt | Bin 0 -> 654 bytes .../PKITS/certs/ValidpathLenConstraintTest8EE.crt | Bin 0 -> 671 bytes .../certs/Validpre2000UTCnotBeforeDateTest3EE.crt | Bin 0 -> 649 bytes .../certs/ValidrequireExplicitPolicyTest1EE.crt | Bin 0 -> 647 bytes .../certs/ValidrequireExplicitPolicyTest2EE.crt | Bin 0 -> 646 bytes .../certs/ValidrequireExplicitPolicyTest4EE.crt | Bin 0 -> 671 bytes crypto/test/data/PKITS/certs/WrongCRLCACert.crt | Bin 0 -> 630 bytes crypto/test/data/PKITS/certs/anyPolicyCACert.crt | Bin 0 -> 640 bytes .../basicConstraintsCriticalcAFalseCACert.crt | Bin 0 -> 652 bytes .../certs/basicConstraintsNotCriticalCACert.crt | Bin 0 -> 647 bytes .../basicConstraintsNotCriticalcAFalseCACert.crt | Bin 0 -> 653 bytes crypto/test/data/PKITS/certs/deltaCRLCA1Cert.crt | Bin 0 -> 630 bytes crypto/test/data/PKITS/certs/deltaCRLCA2Cert.crt | Bin 0 -> 630 bytes crypto/test/data/PKITS/certs/deltaCRLCA3Cert.crt | Bin 0 -> 630 bytes .../PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt | Bin 0 -> 646 bytes .../data/PKITS/certs/distributionPoint1CACert.crt | Bin 0 -> 639 bytes .../data/PKITS/certs/distributionPoint2CACert.crt | Bin 0 -> 639 bytes .../test/data/PKITS/certs/indirectCRLCA1Cert.crt | Bin 0 -> 633 bytes .../test/data/PKITS/certs/indirectCRLCA2Cert.crt | Bin 0 -> 633 bytes .../test/data/PKITS/certs/indirectCRLCA3Cert.crt | Bin 0 -> 633 bytes .../PKITS/certs/indirectCRLCA3cRLIssuerCert.crt | Bin 0 -> 734 bytes .../test/data/PKITS/certs/indirectCRLCA4Cert.crt | Bin 0 -> 633 bytes .../PKITS/certs/indirectCRLCA4cRLIssuerCert.crt | Bin 0 -> 861 bytes .../test/data/PKITS/certs/indirectCRLCA5Cert.crt | Bin 0 -> 633 bytes .../test/data/PKITS/certs/indirectCRLCA6Cert.crt | Bin 0 -> 633 bytes .../data/PKITS/certs/inhibitAnyPolicy0CACert.crt | Bin 0 -> 669 bytes .../data/PKITS/certs/inhibitAnyPolicy1CACert.crt | Bin 0 -> 669 bytes .../certs/inhibitAnyPolicy1SelfIssuedCACert.crt | Bin 0 -> 646 bytes .../inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt | Bin 0 -> 648 bytes .../PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt | Bin 0 -> 644 bytes .../PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt | Bin 0 -> 644 bytes .../PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt | Bin 0 -> 670 bytes .../PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt | Bin 0 -> 651 bytes .../data/PKITS/certs/inhibitAnyPolicy5CACert.crt | Bin 0 -> 669 bytes .../PKITS/certs/inhibitAnyPolicy5subCACert.crt | Bin 0 -> 666 bytes .../PKITS/certs/inhibitAnyPolicy5subsubCACert.crt | Bin 0 -> 655 bytes .../data/PKITS/certs/inhibitAnyPolicyTest3EE.crt | Bin 0 -> 650 bytes .../PKITS/certs/inhibitPolicyMapping0CACert.crt | Bin 0 -> 664 bytes .../PKITS/certs/inhibitPolicyMapping0subCACert.crt | Bin 0 -> 699 bytes .../PKITS/certs/inhibitPolicyMapping1P12CACert.crt | Bin 0 -> 682 bytes .../certs/inhibitPolicyMapping1P12subCACert.crt | Bin 0 -> 747 bytes .../inhibitPolicyMapping1P12subCAIPM5Cert.crt | Bin 0 -> 702 bytes .../certs/inhibitPolicyMapping1P12subsubCACert.crt | Bin 0 -> 727 bytes .../inhibitPolicyMapping1P12subsubCAIPM5Cert.crt | Bin 0 -> 735 bytes .../PKITS/certs/inhibitPolicyMapping1P1CACert.crt | Bin 0 -> 667 bytes .../inhibitPolicyMapping1P1SelfIssuedCACert.crt | Bin 0 -> 660 bytes .../inhibitPolicyMapping1P1SelfIssuedsubCACert.crt | Bin 0 -> 708 bytes .../certs/inhibitPolicyMapping1P1subCACert.crt | Bin 0 -> 705 bytes .../certs/inhibitPolicyMapping1P1subsubCACert.crt | Bin 0 -> 711 bytes .../PKITS/certs/inhibitPolicyMapping5CACert.crt | Bin 0 -> 664 bytes .../PKITS/certs/inhibitPolicyMapping5subCACert.crt | Bin 0 -> 676 bytes .../certs/inhibitPolicyMapping5subsubCACert.crt | Bin 0 -> 663 bytes .../certs/inhibitPolicyMapping5subsubsubCACert.crt | Bin 0 -> 711 bytes .../certs/keyUsageCriticalcRLSignFalseCACert.crt | Bin 0 -> 652 bytes .../keyUsageCriticalkeyCertSignFalseCACert.crt | Bin 0 -> 656 bytes .../data/PKITS/certs/keyUsageNotCriticalCACert.crt | Bin 0 -> 639 bytes .../keyUsageNotCriticalcRLSignFalseCACert.crt | Bin 0 -> 653 bytes .../keyUsageNotCriticalkeyCertSignFalseCACert.crt | Bin 0 -> 657 bytes .../data/PKITS/certs/nameConstraintsDN1CACert.crt | Bin 0 -> 733 bytes .../certs/nameConstraintsDN1SelfIssuedCACert.crt | Bin 0 -> 650 bytes .../PKITS/certs/nameConstraintsDN1subCA1Cert.crt | Bin 0 -> 803 bytes .../PKITS/certs/nameConstraintsDN1subCA2Cert.crt | Bin 0 -> 775 bytes .../PKITS/certs/nameConstraintsDN1subCA3Cert.crt | Bin 0 -> 724 bytes .../data/PKITS/certs/nameConstraintsDN2CACert.crt | Bin 0 -> 814 bytes .../data/PKITS/certs/nameConstraintsDN3CACert.crt | Bin 0 -> 732 bytes .../PKITS/certs/nameConstraintsDN3subCA1Cert.crt | Bin 0 -> 746 bytes .../PKITS/certs/nameConstraintsDN3subCA2Cert.crt | Bin 0 -> 719 bytes .../data/PKITS/certs/nameConstraintsDN4CACert.crt | Bin 0 -> 812 bytes .../data/PKITS/certs/nameConstraintsDN5CACert.crt | Bin 0 -> 842 bytes .../data/PKITS/certs/nameConstraintsDNS1CACert.crt | Bin 0 -> 683 bytes .../data/PKITS/certs/nameConstraintsDNS2CACert.crt | Bin 0 -> 686 bytes .../PKITS/certs/nameConstraintsRFC822CA1Cert.crt | Bin 0 -> 687 bytes .../PKITS/certs/nameConstraintsRFC822CA2Cert.crt | Bin 0 -> 686 bytes .../PKITS/certs/nameConstraintsRFC822CA3Cert.crt | Bin 0 -> 686 bytes .../data/PKITS/certs/nameConstraintsURI1CACert.crt | Bin 0 -> 684 bytes .../data/PKITS/certs/nameConstraintsURI2CACert.crt | Bin 0 -> 686 bytes .../certs/onlyContainsAttributeCertsCACert.crt | Bin 0 -> 647 bytes .../data/PKITS/certs/onlyContainsCACertsCACert.crt | Bin 0 -> 640 bytes .../PKITS/certs/onlyContainsUserCertsCACert.crt | Bin 0 -> 642 bytes .../data/PKITS/certs/onlySomeReasonsCA1Cert.crt | Bin 0 -> 637 bytes .../data/PKITS/certs/onlySomeReasonsCA2Cert.crt | Bin 0 -> 637 bytes .../data/PKITS/certs/onlySomeReasonsCA3Cert.crt | Bin 0 -> 637 bytes .../data/PKITS/certs/onlySomeReasonsCA4Cert.crt | Bin 0 -> 637 bytes .../data/PKITS/certs/pathLenConstraint0CACert.crt | Bin 0 -> 642 bytes .../certs/pathLenConstraint0SelfIssuedCACert.crt | Bin 0 -> 648 bytes .../PKITS/certs/pathLenConstraint0subCA2Cert.crt | Bin 0 -> 652 bytes .../PKITS/certs/pathLenConstraint0subCACert.crt | Bin 0 -> 651 bytes .../data/PKITS/certs/pathLenConstraint1CACert.crt | Bin 0 -> 642 bytes .../certs/pathLenConstraint1SelfIssuedCACert.crt | Bin 0 -> 648 bytes .../pathLenConstraint1SelfIssuedsubCACert.crt | Bin 0 -> 654 bytes .../PKITS/certs/pathLenConstraint1subCACert.crt | Bin 0 -> 651 bytes .../data/PKITS/certs/pathLenConstraint6CACert.crt | Bin 0 -> 642 bytes .../PKITS/certs/pathLenConstraint6subCA0Cert.crt | Bin 0 -> 655 bytes .../PKITS/certs/pathLenConstraint6subCA1Cert.crt | Bin 0 -> 655 bytes .../PKITS/certs/pathLenConstraint6subCA4Cert.crt | Bin 0 -> 655 bytes .../certs/pathLenConstraint6subsubCA00Cert.crt | Bin 0 -> 663 bytes .../certs/pathLenConstraint6subsubCA11Cert.crt | Bin 0 -> 663 bytes .../certs/pathLenConstraint6subsubCA41Cert.crt | Bin 0 -> 663 bytes .../certs/pathLenConstraint6subsubsubCA11XCert.crt | Bin 0 -> 668 bytes .../certs/pathLenConstraint6subsubsubCA41XCert.crt | Bin 0 -> 668 bytes .../PKITS/certs/pre2000CRLnextUpdateCACert.crt | Bin 0 -> 643 bytes .../PKITS/certs/requireExplicitPolicy0CACert.crt | Bin 0 -> 662 bytes .../certs/requireExplicitPolicy0subCACert.crt | Bin 0 -> 659 bytes .../certs/requireExplicitPolicy0subsubCACert.crt | Bin 0 -> 665 bytes .../requireExplicitPolicy0subsubsubCACert.crt | Bin 0 -> 671 bytes .../PKITS/certs/requireExplicitPolicy10CACert.crt | Bin 0 -> 663 bytes .../certs/requireExplicitPolicy10subCACert.crt | Bin 0 -> 661 bytes .../certs/requireExplicitPolicy10subsubCACert.crt | Bin 0 -> 667 bytes .../requireExplicitPolicy10subsubsubCACert.crt | Bin 0 -> 673 bytes .../PKITS/certs/requireExplicitPolicy2CACert.crt | Bin 0 -> 662 bytes .../requireExplicitPolicy2SelfIssuedCACert.crt | Bin 0 -> 656 bytes .../requireExplicitPolicy2SelfIssuedsubCACert.crt | Bin 0 -> 662 bytes .../certs/requireExplicitPolicy2subCACert.crt | Bin 0 -> 659 bytes .../PKITS/certs/requireExplicitPolicy4CACert.crt | Bin 0 -> 662 bytes .../certs/requireExplicitPolicy4subCACert.crt | Bin 0 -> 659 bytes .../certs/requireExplicitPolicy4subsubCACert.crt | Bin 0 -> 665 bytes .../requireExplicitPolicy4subsubsubCACert.crt | Bin 0 -> 671 bytes .../PKITS/certs/requireExplicitPolicy5CACert.crt | Bin 0 -> 662 bytes .../certs/requireExplicitPolicy5subCACert.crt | Bin 0 -> 659 bytes .../certs/requireExplicitPolicy5subsubCACert.crt | Bin 0 -> 665 bytes .../requireExplicitPolicy5subsubsubCACert.crt | Bin 0 -> 671 bytes .../PKITS/certs/requireExplicitPolicy7CACert.crt | Bin 0 -> 662 bytes .../certs/requireExplicitPolicy7subCARE2Cert.crt | Bin 0 -> 681 bytes .../requireExplicitPolicy7subsubCARE2RE4Cert.crt | Bin 0 -> 693 bytes ...requireExplicitPolicy7subsubsubCARE2RE4Cert.crt | Bin 0 -> 683 bytes .../test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl | Bin 0 -> 330 bytes .../test/data/PKITS/crls/BadCRLSignatureCACRL.crl | Bin 0 -> 325 bytes crypto/test/data/PKITS/crls/BadSignedCACRL.crl | Bin 0 -> 318 bytes .../test/data/PKITS/crls/BadnotAfterDateCACRL.crl | Bin 0 -> 325 bytes .../test/data/PKITS/crls/BadnotBeforeDateCACRL.crl | Bin 0 -> 326 bytes .../crls/BasicSelfIssuedCRLSigningKeyCACRL.crl | Bin 0 -> 377 bytes .../BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl | Bin 0 -> 479 bytes .../data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl | Bin 0 -> 369 bytes .../data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl | Bin 0 -> 369 bytes .../BasicSelfIssuedOldKeySelfIssuedCertCRL.crl | Bin 0 -> 462 bytes crypto/test/data/PKITS/crls/DSACACRL.crl | Bin 0 -> 219 bytes .../PKITS/crls/DSAParametersInheritedCACRL.crl | Bin 0 -> 241 bytes .../crls/GeneralizedTimeCRLnextUpdateCACRL.crl | Bin 0 -> 338 bytes crypto/test/data/PKITS/crls/GoodCACRL.crl | Bin 0 -> 382 bytes crypto/test/data/PKITS/crls/GoodsubCACRL.crl | Bin 0 -> 315 bytes .../crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl | Bin 0 -> 339 bytes .../test/data/PKITS/crls/LongSerialNumberCACRL.crl | Bin 0 -> 381 bytes crypto/test/data/PKITS/crls/Mapping1to2CACRL.crl | Bin 0 -> 320 bytes .../data/PKITS/crls/MappingFromanyPolicyCACRL.crl | Bin 0 -> 330 bytes .../data/PKITS/crls/MappingToanyPolicyCACRL.crl | Bin 0 -> 328 bytes .../PKITS/crls/MissingbasicConstraintsCACRL.crl | Bin 0 -> 332 bytes crypto/test/data/PKITS/crls/NameOrderCACRL.crl | Bin 0 -> 396 bytes .../data/PKITS/crls/NegativeSerialNumberCACRL.crl | Bin 0 -> 366 bytes crypto/test/data/PKITS/crls/NoPoliciesCACRL.crl | Bin 0 -> 319 bytes .../PKITS/crls/NoissuingDistributionPointCACRL.crl | Bin 0 -> 335 bytes .../test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl | Bin 0 -> 326 bytes .../test/data/PKITS/crls/P12Mapping1to3CACRL.crl | Bin 0 -> 324 bytes .../data/PKITS/crls/P12Mapping1to3subCACRL.crl | Bin 0 -> 327 bytes .../data/PKITS/crls/P12Mapping1to3subsubCACRL.crl | Bin 0 -> 330 bytes .../test/data/PKITS/crls/P1Mapping1to234CACRL.crl | Bin 0 -> 325 bytes .../data/PKITS/crls/P1Mapping1to234subCACRL.crl | Bin 0 -> 328 bytes .../PKITS/crls/P1anyPolicyMapping1to2CACRL.crl | Bin 0 -> 332 bytes .../data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl | Bin 0 -> 331 bytes crypto/test/data/PKITS/crls/PoliciesP1234CACRL.crl | Bin 0 -> 322 bytes .../data/PKITS/crls/PoliciesP1234subCAP123CRL.crl | Bin 0 -> 329 bytes .../PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl | Bin 0 -> 335 bytes crypto/test/data/PKITS/crls/PoliciesP123CACRL.crl | Bin 0 -> 321 bytes .../data/PKITS/crls/PoliciesP123subCAP12CRL.crl | Bin 0 -> 327 bytes .../PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl | Bin 0 -> 332 bytes .../PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl | Bin 0 -> 332 bytes .../crls/PoliciesP123subsubsubCAP12P2P1CRL.crl | Bin 0 -> 337 bytes crypto/test/data/PKITS/crls/PoliciesP12CACRL.crl | Bin 0 -> 320 bytes .../test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl | Bin 0 -> 325 bytes .../data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl | Bin 0 -> 330 bytes .../test/data/PKITS/crls/PoliciesP2subCA2CRL.crl | Bin 0 -> 323 bytes crypto/test/data/PKITS/crls/PoliciesP2subCACRL.crl | Bin 0 -> 322 bytes crypto/test/data/PKITS/crls/PoliciesP3CACRL.crl | Bin 0 -> 319 bytes .../crls/RFC3280MandatoryAttributeTypesCACRL.crl | Bin 0 -> 396 bytes .../crls/RFC3280OptionalAttributeTypesCACRL.crl | Bin 0 -> 408 bytes crypto/test/data/PKITS/crls/RevokedsubCACRL.crl | Bin 0 -> 318 bytes ...olloverfromPrintableStringtoUTF8StringCACRL.crl | Bin 0 -> 351 bytes .../crls/SeparateCertificateandCRLKeysCA2CRL.crl | Bin 0 -> 342 bytes .../crls/SeparateCertificateandCRLKeysCRL.crl | Bin 0 -> 378 bytes crypto/test/data/PKITS/crls/TrustAnchorRootCRL.crl | Bin 0 -> 353 bytes crypto/test/data/PKITS/crls/TwoCRLsCABadCRL.crl | Bin 0 -> 364 bytes crypto/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl | Bin 0 -> 316 bytes crypto/test/data/PKITS/crls/UIDCACRL.crl | Bin 0 -> 311 bytes .../crls/UTF8StringCaseInsensitiveMatchCACRL.crl | Bin 0 -> 341 bytes .../PKITS/crls/UTF8StringEncodedNamesCACRL.crl | Bin 0 -> 318 bytes .../PKITS/crls/UnknownCRLEntryExtensionCACRL.crl | Bin 0 -> 392 bytes .../data/PKITS/crls/UnknownCRLExtensionCACRL.crl | Bin 0 -> 386 bytes crypto/test/data/PKITS/crls/WrongCRLCACRL.crl | Bin 0 -> 353 bytes crypto/test/data/PKITS/crls/anyPolicyCACRL.crl | Bin 0 -> 317 bytes .../crls/basicConstraintsCriticalcAFalseCACRL.crl | Bin 0 -> 342 bytes .../crls/basicConstraintsNotCriticalCACRL.crl | Bin 0 -> 337 bytes .../basicConstraintsNotCriticalcAFalseCACRL.crl | Bin 0 -> 346 bytes crypto/test/data/PKITS/crls/deltaCRLCA1CRL.crl | Bin 0 -> 509 bytes .../test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl | Bin 0 -> 472 bytes crypto/test/data/PKITS/crls/deltaCRLCA2CRL.crl | Bin 0 -> 441 bytes .../test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl | Bin 0 -> 368 bytes crypto/test/data/PKITS/crls/deltaCRLCA3CRL.crl | Bin 0 -> 404 bytes .../test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl | Bin 0 -> 332 bytes .../PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl | Bin 0 -> 348 bytes .../data/PKITS/crls/distributionPoint1CACRL.crl | Bin 0 -> 501 bytes .../data/PKITS/crls/distributionPoint2CACRL.crl | Bin 0 -> 419 bytes crypto/test/data/PKITS/crls/indirectCRLCA1CRL.crl | Bin 0 -> 373 bytes crypto/test/data/PKITS/crls/indirectCRLCA3CRL.crl | Bin 0 -> 427 bytes .../data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl | Bin 0 -> 481 bytes .../data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl | Bin 0 -> 481 bytes crypto/test/data/PKITS/crls/indirectCRLCA5CRL.crl | Bin 0 -> 1408 bytes .../data/PKITS/crls/inhibitAnyPolicy0CACRL.crl | Bin 0 -> 325 bytes .../data/PKITS/crls/inhibitAnyPolicy1CACRL.crl | Bin 0 -> 325 bytes .../data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl | Bin 0 -> 329 bytes .../data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl | Bin 0 -> 329 bytes .../PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl | Bin 0 -> 332 bytes .../PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl | Bin 0 -> 332 bytes .../data/PKITS/crls/inhibitAnyPolicy5CACRL.crl | Bin 0 -> 325 bytes .../data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl | Bin 0 -> 328 bytes .../PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl | Bin 0 -> 331 bytes .../data/PKITS/crls/inhibitPolicyMapping0CACRL.crl | Bin 0 -> 329 bytes .../PKITS/crls/inhibitPolicyMapping0subCACRL.crl | Bin 0 -> 332 bytes .../PKITS/crls/inhibitPolicyMapping1P12CACRL.crl | Bin 0 -> 333 bytes .../crls/inhibitPolicyMapping1P12subCACRL.crl | Bin 0 -> 336 bytes .../crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl | Bin 0 -> 340 bytes .../crls/inhibitPolicyMapping1P12subsubCACRL.crl | Bin 0 -> 339 bytes .../inhibitPolicyMapping1P12subsubCAIPM5CRL.crl | Bin 0 -> 343 bytes .../PKITS/crls/inhibitPolicyMapping1P1CACRL.crl | Bin 0 -> 332 bytes .../PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl | Bin 0 -> 335 bytes .../crls/inhibitPolicyMapping1P1subsubCACRL.crl | Bin 0 -> 338 bytes .../data/PKITS/crls/inhibitPolicyMapping5CACRL.crl | Bin 0 -> 329 bytes .../PKITS/crls/inhibitPolicyMapping5subCACRL.crl | Bin 0 -> 332 bytes .../crls/inhibitPolicyMapping5subsubCACRL.crl | Bin 0 -> 335 bytes .../crls/inhibitPolicyMapping5subsubsubCACRL.crl | Bin 0 -> 338 bytes .../crls/keyUsageCriticalcRLSignFalseCACRL.crl | Bin 0 -> 339 bytes .../crls/keyUsageCriticalkeyCertSignFalseCACRL.crl | Bin 0 -> 343 bytes .../data/PKITS/crls/keyUsageNotCriticalCACRL.crl | Bin 0 -> 329 bytes .../crls/keyUsageNotCriticalcRLSignFalseCACRL.crl | Bin 0 -> 343 bytes .../keyUsageNotCriticalkeyCertSignFalseCACRL.crl | Bin 0 -> 347 bytes .../data/PKITS/crls/nameConstraintsDN1CACRL.crl | Bin 0 -> 327 bytes .../PKITS/crls/nameConstraintsDN1subCA1CRL.crl | Bin 0 -> 359 bytes .../PKITS/crls/nameConstraintsDN1subCA2CRL.crl | Bin 0 -> 359 bytes .../PKITS/crls/nameConstraintsDN1subCA3CRL.crl | Bin 0 -> 359 bytes .../data/PKITS/crls/nameConstraintsDN2CACRL.crl | Bin 0 -> 327 bytes .../data/PKITS/crls/nameConstraintsDN3CACRL.crl | Bin 0 -> 327 bytes .../PKITS/crls/nameConstraintsDN3subCA1CRL.crl | Bin 0 -> 331 bytes .../PKITS/crls/nameConstraintsDN3subCA2CRL.crl | Bin 0 -> 331 bytes .../data/PKITS/crls/nameConstraintsDN4CACRL.crl | Bin 0 -> 327 bytes .../data/PKITS/crls/nameConstraintsDN5CACRL.crl | Bin 0 -> 327 bytes .../data/PKITS/crls/nameConstraintsDNS1CACRL.crl | Bin 0 -> 328 bytes .../data/PKITS/crls/nameConstraintsDNS2CACRL.crl | Bin 0 -> 328 bytes .../PKITS/crls/nameConstraintsRFC822CA1CRL.crl | Bin 0 -> 331 bytes .../PKITS/crls/nameConstraintsRFC822CA2CRL.crl | Bin 0 -> 331 bytes .../PKITS/crls/nameConstraintsRFC822CA3CRL.crl | Bin 0 -> 331 bytes .../data/PKITS/crls/nameConstraintsURI1CACRL.crl | Bin 0 -> 328 bytes .../data/PKITS/crls/nameConstraintsURI2CACRL.crl | Bin 0 -> 328 bytes .../PKITS/crls/onlyContainsAttributeCertsCACRL.crl | Bin 0 -> 351 bytes .../data/PKITS/crls/onlyContainsCACertsCACRL.crl | Bin 0 -> 344 bytes .../data/PKITS/crls/onlyContainsUserCertsCACRL.crl | Bin 0 -> 346 bytes .../PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl | Bin 0 -> 378 bytes .../crls/onlySomeReasonsCA1otherreasonsCRL.crl | Bin 0 -> 379 bytes .../data/PKITS/crls/onlySomeReasonsCA2CRL1.crl | Bin 0 -> 342 bytes .../data/PKITS/crls/onlySomeReasonsCA2CRL2.crl | Bin 0 -> 342 bytes .../PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl | Bin 0 -> 438 bytes .../crls/onlySomeReasonsCA3otherreasonsCRL.crl | Bin 0 -> 439 bytes .../PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl | Bin 0 -> 475 bytes .../crls/onlySomeReasonsCA4otherreasonsCRL.crl | Bin 0 -> 476 bytes .../data/PKITS/crls/pathLenConstraint0CACRL.crl | Bin 0 -> 326 bytes .../PKITS/crls/pathLenConstraint0subCA2CRL.crl | Bin 0 -> 330 bytes .../data/PKITS/crls/pathLenConstraint0subCACRL.crl | Bin 0 -> 329 bytes .../data/PKITS/crls/pathLenConstraint1CACRL.crl | Bin 0 -> 326 bytes .../data/PKITS/crls/pathLenConstraint1subCACRL.crl | Bin 0 -> 329 bytes .../data/PKITS/crls/pathLenConstraint6CACRL.crl | Bin 0 -> 326 bytes .../PKITS/crls/pathLenConstraint6subCA0CRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/pathLenConstraint6subCA1CRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/pathLenConstraint6subCA4CRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/pathLenConstraint6subsubCA00CRL.crl | Bin 0 -> 334 bytes .../PKITS/crls/pathLenConstraint6subsubCA11CRL.crl | Bin 0 -> 334 bytes .../PKITS/crls/pathLenConstraint6subsubCA41CRL.crl | Bin 0 -> 334 bytes .../crls/pathLenConstraint6subsubsubCA11XCRL.crl | Bin 0 -> 338 bytes .../crls/pathLenConstraint6subsubsubCA41XCRL.crl | Bin 0 -> 338 bytes .../data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/requireExplicitPolicy0CACRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/requireExplicitPolicy0subCACRL.crl | Bin 0 -> 333 bytes .../crls/requireExplicitPolicy0subsubCACRL.crl | Bin 0 -> 336 bytes .../crls/requireExplicitPolicy0subsubsubCACRL.crl | Bin 0 -> 339 bytes .../PKITS/crls/requireExplicitPolicy10CACRL.crl | Bin 0 -> 331 bytes .../PKITS/crls/requireExplicitPolicy10subCACRL.crl | Bin 0 -> 334 bytes .../crls/requireExplicitPolicy10subsubCACRL.crl | Bin 0 -> 337 bytes .../crls/requireExplicitPolicy10subsubsubCACRL.crl | Bin 0 -> 340 bytes .../PKITS/crls/requireExplicitPolicy2CACRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/requireExplicitPolicy2subCACRL.crl | Bin 0 -> 333 bytes .../PKITS/crls/requireExplicitPolicy4CACRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/requireExplicitPolicy4subCACRL.crl | Bin 0 -> 333 bytes .../crls/requireExplicitPolicy4subsubCACRL.crl | Bin 0 -> 336 bytes .../crls/requireExplicitPolicy4subsubsubCACRL.crl | Bin 0 -> 339 bytes .../PKITS/crls/requireExplicitPolicy5CACRL.crl | Bin 0 -> 330 bytes .../PKITS/crls/requireExplicitPolicy5subCACRL.crl | Bin 0 -> 333 bytes .../crls/requireExplicitPolicy5subsubCACRL.crl | Bin 0 -> 336 bytes .../crls/requireExplicitPolicy5subsubsubCACRL.crl | Bin 0 -> 339 bytes .../PKITS/crls/requireExplicitPolicy7CACRL.crl | Bin 0 -> 330 bytes .../crls/requireExplicitPolicy7subCARE2CRL.crl | Bin 0 -> 336 bytes .../requireExplicitPolicy7subsubCARE2RE4CRL.crl | Bin 0 -> 342 bytes .../requireExplicitPolicy7subsubsubCARE2RE4CRL.crl | Bin 0 -> 345 bytes crypto/test/data/asn1/masterlist-content.data | Bin 0 -> 1748 bytes crypto/test/data/cms/sigs/PSSSignData.data | 1 + crypto/test/data/cms/sigs/PSSSignDataSHA1.sig | Bin 0 -> 3345 bytes crypto/test/data/cms/sigs/PSSSignDataSHA1Enc.sig | Bin 0 -> 3371 bytes crypto/test/data/cms/sigs/PSSSignDataSHA256.sig | Bin 0 -> 3417 bytes crypto/test/data/cms/sigs/PSSSignDataSHA256Enc.sig | Bin 0 -> 3443 bytes crypto/test/data/cms/sigs/PSSSignDataSHA512.sig | Bin 0 -> 3450 bytes crypto/test/data/cms/sigs/PSSSignDataSHA512Enc.sig | Bin 0 -> 3476 bytes crypto/test/data/cms/sigs/counterSig.p7m | Bin 0 -> 5647 bytes crypto/test/data/hc256/hc128/ecrypt_HC-128.txt | 2337 ++++ .../data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt | 2337 ++++ .../data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt | 2783 +++++ .../data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt | 2783 +++++ .../data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt | 3257 ++++++ crypto/test/data/keys/README.txt | 4 + .../test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key | Bin 0 -> 677 bytes .../test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key | Bin 0 -> 677 bytes .../test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key | Bin 0 -> 677 bytes .../test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key | Bin 0 -> 677 bytes .../test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key | Bin 0 -> 677 bytes .../test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key | Bin 0 -> 677 bytes .../keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key | Bin 0 -> 678 bytes .../data/keys/pbes1/pbe_WithSHA1And128BitRC4.key | Bin 0 -> 673 bytes .../pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key | Bin 0 -> 678 bytes .../pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key | Bin 0 -> 678 bytes .../keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key | Bin 0 -> 678 bytes .../data/keys/pbes1/pbe_WithSHA1And40BitRC4.key | Bin 0 -> 673 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-cbc.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-cfb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-cfb1.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-cfb8.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-ecb.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-128-ofb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-cbc.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-cfb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-cfb1.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-cfb8.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-ecb.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-192-ofb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-cbc.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-cfb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-cfb1.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-cfb8.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-ecb.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes-256-ofb.key | Bin 0 -> 718 bytes crypto/test/data/keys/pbes2/pbes2.aes128.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes192.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.aes256.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.bf-cbc.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.bf.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.blowfish.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.cast-cbc.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.cast.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.cast5-cbc.key | Bin 0 -> 715 bytes crypto/test/data/keys/pbes2/pbes2.des-cbc.key | Bin 0 -> 711 bytes crypto/test/data/keys/pbes2/pbes2.des-cfb.key | Bin 0 -> 706 bytes crypto/test/data/keys/pbes2/pbes2.des-cfb1.key | Bin 0 -> 706 bytes crypto/test/data/keys/pbes2/pbes2.des-cfb8.key | Bin 0 -> 706 bytes crypto/test/data/keys/pbes2/pbes2.des-ecb.key | Bin 0 -> 711 bytes crypto/test/data/keys/pbes2/pbes2.des-ede.key | Bin 0 -> 711 bytes crypto/test/data/keys/pbes2/pbes2.des-ede3-cbc.key | Bin 0 -> 714 bytes crypto/test/data/keys/pbes2/pbes2.des-ofb.key | Bin 0 -> 706 bytes crypto/test/data/keys/pbes2/pbes2.des.key | Bin 0 -> 711 bytes crypto/test/data/keys/pbes2/pbes2.des3.key | Bin 0 -> 714 bytes crypto/test/data/keys/pbes2/pbes2.rc2-40-cbc.key | Bin 0 -> 723 bytes crypto/test/data/keys/pbes2/pbes2.rc2-64-cbc.key | Bin 0 -> 722 bytes crypto/test/data/keys/pbes2/pbes2.rc2-cbc.key | Bin 0 -> 722 bytes crypto/test/data/keys/pbes2/pbes2.rc2.key | Bin 0 -> 722 bytes crypto/test/data/openpgp/dsa/README.txt | 36 + crypto/test/data/openpgp/dsa/keys/DSA-1024-160.pub | Bin 0 -> 534 bytes crypto/test/data/openpgp/dsa/keys/DSA-1024-160.sec | Bin 0 -> 597 bytes .../test/data/openpgp/dsa/keys/DSA-15360-512.pub | Bin 0 -> 6043 bytes .../test/data/openpgp/dsa/keys/DSA-15360-512.sec | Bin 0 -> 6150 bytes crypto/test/data/openpgp/dsa/keys/DSA-2048-224.pub | Bin 0 -> 941 bytes crypto/test/data/openpgp/dsa/keys/DSA-2048-224.sec | Bin 0 -> 1012 bytes crypto/test/data/openpgp/dsa/keys/DSA-3072-256.pub | Bin 0 -> 1337 bytes crypto/test/data/openpgp/dsa/keys/DSA-3072-256.sec | Bin 0 -> 1412 bytes crypto/test/data/openpgp/dsa/keys/DSA-7680-384.pub | Bin 0 -> 3113 bytes crypto/test/data/openpgp/dsa/keys/DSA-7680-384.sec | Bin 0 -> 3204 bytes .../data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg | 1 + .../data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg | Bin 0 -> 121 bytes .../data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg | Bin 0 -> 123 bytes .../data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg | Bin 0 -> 122 bytes .../data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg | Bin 0 -> 122 bytes .../data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg | Bin 0 -> 216 bytes .../data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg | Bin 0 -> 141 bytes .../data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg | Bin 0 -> 150 bytes .../data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg | Bin 0 -> 184 bytes crypto/test/data/openssl/README.txt | 8 + .../data/openssl/dsa/openssl_dsa_aes128_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes128_cfb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes128_ecb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes128_ofb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes192_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes192_cfb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes192_ecb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes192_ofb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes256_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes256_cfb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes256_ecb.pem | 23 + .../data/openssl/dsa/openssl_dsa_aes256_ofb.pem | 23 + .../data/openssl/dsa/openssl_dsa_blowfish_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_blowfish_cfb.pem | 23 + .../data/openssl/dsa/openssl_dsa_blowfish_ecb.pem | 23 + .../data/openssl/dsa/openssl_dsa_blowfish_ofb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des1_cbc.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des1_cfb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des1_ecb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des1_ofb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des2_cbc.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des2_cfb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des2_ecb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des2_ofb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des3_cbc.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des3_cfb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des3_ecb.pem | 23 + .../test/data/openssl/dsa/openssl_dsa_des3_ofb.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem | 23 + .../data/openssl/dsa/openssl_dsa_unencrypted.pem | 20 + crypto/test/data/openssl/eckey.pem | 9 + crypto/test/data/openssl/enckey.pem | 30 + crypto/test/data/openssl/pkcs7.pem | 54 + .../test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem | 28 + .../data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem | 30 + crypto/test/data/openssl/pkcs8test.pem | 175 + .../data/openssl/rsa/openssl_rsa_aes128_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes128_cfb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes128_ecb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes128_ofb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes192_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes192_cfb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes192_ecb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes192_ofb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes256_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes256_cfb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes256_ecb.pem | 30 + .../data/openssl/rsa/openssl_rsa_aes256_ofb.pem | 30 + .../data/openssl/rsa/openssl_rsa_blowfish_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_blowfish_cfb.pem | 30 + .../data/openssl/rsa/openssl_rsa_blowfish_ecb.pem | 30 + .../data/openssl/rsa/openssl_rsa_blowfish_ofb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des1_cbc.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des1_cfb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des1_ecb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des1_ofb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des2_cbc.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des2_cfb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des2_ecb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des2_ofb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des3_cbc.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des3_cfb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des3_ecb.pem | 30 + .../test/data/openssl/rsa/openssl_rsa_des3_ofb.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem | 30 + .../data/openssl/rsa/openssl_rsa_unencrypted.pem | 27 + crypto/test/data/openssl/test.pem | 133 + crypto/test/data/rfc4134/3.1.bin | Bin 0 -> 55 bytes crypto/test/data/rfc4134/3.2.bin | 1 + crypto/test/data/rfc4134/4.1.bin | Bin 0 -> 923 bytes crypto/test/data/rfc4134/4.10.bin | Bin 0 -> 2051 bytes crypto/test/data/rfc4134/4.11.bin | Bin 0 -> 1676 bytes crypto/test/data/rfc4134/4.2.bin | Bin 0 -> 854 bytes crypto/test/data/rfc4134/4.3.bin | Bin 0 -> 891 bytes crypto/test/data/rfc4134/4.4.bin | Bin 0 -> 2833 bytes crypto/test/data/rfc4134/4.5.bin | Bin 0 -> 1359 bytes crypto/test/data/rfc4134/4.6.bin | Bin 0 -> 1467 bytes crypto/test/data/rfc4134/4.7.bin | Bin 0 -> 920 bytes crypto/test/data/rfc4134/4.8.eml | 39 + crypto/test/data/rfc4134/4.9.eml | 28 + crypto/test/data/rfc4134/5.1.bin | Bin 0 -> 290 bytes crypto/test/data/rfc4134/5.2.bin | Bin 0 -> 361 bytes crypto/test/data/rfc4134/5.3.eml | 19 + crypto/test/data/rfc4134/6.0.bin | Bin 0 -> 96 bytes crypto/test/data/rfc4134/7.1.bin | Bin 0 -> 89 bytes crypto/test/data/rfc4134/7.2.bin | Bin 0 -> 152 bytes .../data/rfc4134/AliceDSSSignByCarlNoInherit.cer | Bin 0 -> 736 bytes crypto/test/data/rfc4134/AlicePrivDSSSign.pri | Bin 0 -> 335 bytes crypto/test/data/rfc4134/AlicePrivRSASign.pri | Bin 0 -> 634 bytes crypto/test/data/rfc4134/AliceRSASignByCarl.cer | Bin 0 -> 560 bytes crypto/test/data/rfc4134/BobPrivRSAEncrypt.pri | Bin 0 -> 649 bytes crypto/test/data/rfc4134/BobRSASignByCarl.cer | Bin 0 -> 555 bytes crypto/test/data/rfc4134/CarlDSSCRLEmpty.crl | Bin 0 -> 111 bytes crypto/test/data/rfc4134/CarlDSSCRLForAll.crl | Bin 0 -> 219 bytes crypto/test/data/rfc4134/CarlDSSCRLForCarl.crl | Bin 0 -> 134 bytes crypto/test/data/rfc4134/CarlDSSSelf.cer | Bin 0 -> 671 bytes crypto/test/data/rfc4134/CarlPrivDSSSign.pri | Bin 0 -> 334 bytes crypto/test/data/rfc4134/CarlPrivRSASign.pri | Bin 0 -> 634 bytes crypto/test/data/rfc4134/CarlRSACRLEmpty.crl | Bin 0 -> 202 bytes crypto/test/data/rfc4134/CarlRSACRLForAll.crl | Bin 0 -> 311 bytes crypto/test/data/rfc4134/CarlRSACRLForCarl.crl | Bin 0 -> 239 bytes crypto/test/data/rfc4134/CarlRSASelf.cer | Bin 0 -> 495 bytes .../data/rfc4134/DianeDSSSignByCarlInherit.cer | Bin 0 -> 444 bytes crypto/test/data/rfc4134/DianePrivDSSSign.pri | Bin 0 -> 335 bytes .../test/data/rfc4134/DianePrivRSASignEncrypt.pri | Bin 0 -> 635 bytes crypto/test/data/rfc4134/DianeRSASignByCarl.cer | Bin 0 -> 560 bytes crypto/test/data/rfc4134/ExContent.bin | 1 + crypto/test/data/rfc4134/rfc4134.txt | 7619 +++++++++++++ crypto/test/data/rsa3/self-testcase-A.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-A.pem | 52 + crypto/test/data/rsa3/self-testcase-B.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-B.pem | 52 + crypto/test/data/rsa3/self-testcase-C.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-C.pem | 52 + crypto/test/data/rsa3/self-testcase-D.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-D.pem | 52 + crypto/test/data/rsa3/self-testcase-E.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-E.pem | 52 + crypto/test/data/rsa3/self-testcase-F.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-F.pem | 52 + crypto/test/data/rsa3/self-testcase-G.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-G.pem | 52 + crypto/test/data/rsa3/self-testcase-H.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-H.pem | 52 + crypto/test/data/rsa3/self-testcase-I.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-I.pem | 52 + crypto/test/data/rsa3/self-testcase-J.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-J.pem | 52 + crypto/test/data/rsa3/self-testcase-L.p12 | Bin 0 -> 2742 bytes crypto/test/data/rsa3/self-testcase-L.pem | 52 + crypto/test/data/rsa3/testcases.README | Bin 0 -> 14352 bytes crypto/test/data/scrypt/TestVectors.txt | 20 + crypto/test/data/tls/keystores/client_store.dsa | Bin 0 -> 2035 bytes crypto/test/data/tls/keystores/client_store.rsa | Bin 0 -> 1947 bytes crypto/test/data/tls/keystores/server_store.dsa | Bin 0 -> 2035 bytes crypto/test/data/tls/keystores/server_store.rsa | Bin 0 -> 1947 bytes crypto/test/lib/nunit.core.dll | Bin 0 -> 90112 bytes crypto/test/lib/nunit.core.interfaces.dll | Bin 0 -> 40960 bytes crypto/test/lib/nunit.framework.dll | Bin 0 -> 81920 bytes .../test/src/asn1/test/ASN1SequenceParserTest.cs | 359 + crypto/test/src/asn1/test/ASN1UnitTest.cs | 88 + .../test/AdditionalInformationSyntaxUnitTest.cs | 77 + .../test/src/asn1/test/AdmissionSyntaxUnitTest.cs | 99 + crypto/test/src/asn1/test/AdmissionsUnitTest.cs | 90 + crypto/test/src/asn1/test/AllTests.cs | 32 + .../test/src/asn1/test/AttributeTableUnitTest.cs | 151 + crypto/test/src/asn1/test/BiometricDataUnitTest.cs | 133 + .../test/src/asn1/test/BitStringConstantTester.cs | 25 + crypto/test/src/asn1/test/BitStringTest.cs | 82 + crypto/test/src/asn1/test/CMSTest.cs | 306 + crypto/test/src/asn1/test/CertHashUnitTest.cs | 93 + crypto/test/src/asn1/test/CertificateTest.cs | 395 + .../asn1/test/CommitmentTypeIndicationUnitTest.cs | 107 + .../asn1/test/CommitmentTypeQualifierUnitTest.cs | 107 + crypto/test/src/asn1/test/ContentHintsUnitTest.cs | 93 + crypto/test/src/asn1/test/CscaMasterListTest.cs | 57 + .../src/asn1/test/DERApplicationSpecificTest.cs | 88 + crypto/test/src/asn1/test/DERUTF8StringTest.cs | 113 + crypto/test/src/asn1/test/DataGroupHashUnitTest.cs | 106 + .../src/asn1/test/DeclarationOfMajorityUnitTest.cs | 97 + .../src/asn1/test/EncryptedPrivateKeyInfoTest.cs | 152 + crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs | 94 + crypto/test/src/asn1/test/EssCertIDv2UnitTest.cs | 46 + crypto/test/src/asn1/test/GeneralNameTest.cs | 116 + crypto/test/src/asn1/test/GeneralizedTimeTest.cs | 193 + crypto/test/src/asn1/test/GenerationTest.cs | 325 + crypto/test/src/asn1/test/InputStreamTest.cs | 85 + .../src/asn1/test/Iso4217CurrencyCodeUnitTest.cs | 156 + .../src/asn1/test/IssuingDistributionPointTest.cs | 133 + crypto/test/src/asn1/test/KeyUsageTest.cs | 49 + .../src/asn1/test/LDSSecurityObjectUnitTest.cs | 208 + crypto/test/src/asn1/test/MiscTest.cs | 100 + crypto/test/src/asn1/test/MonetaryLimitUnitTest.cs | 93 + crypto/test/src/asn1/test/MonetaryValueUnitTest.cs | 99 + .../test/src/asn1/test/NameOrPseudonymUnitTest.cs | 114 + .../test/src/asn1/test/NamingAuthorityUnitTest.cs | 106 + crypto/test/src/asn1/test/NetscapeCertTypeTest.cs | 45 + crypto/test/src/asn1/test/OCSPTest.cs | 183 + crypto/test/src/asn1/test/OIDTest.cs | 149 + crypto/test/src/asn1/test/OctetStringTest.cs | 186 + crypto/test/src/asn1/test/OtherCertIDUnitTest.cs | 100 + .../asn1/test/OtherSigningCertificateUnitTest.cs | 94 + crypto/test/src/asn1/test/PKCS10Test.cs | 95 + crypto/test/src/asn1/test/PKCS12Test.cs | 210 + crypto/test/src/asn1/test/PKIFailureInfoTest.cs | 76 + crypto/test/src/asn1/test/ParseTest.cs | 303 + crypto/test/src/asn1/test/ParsingTest.cs | 104 + crypto/test/src/asn1/test/PersonalDataUnitTest.cs | 127 + .../src/asn1/test/ProcurationSyntaxUnitTest.cs | 111 + .../test/src/asn1/test/ProfessionInfoUnitTest.cs | 121 + crypto/test/src/asn1/test/QCStatementUnitTest.cs | 108 + crypto/test/src/asn1/test/ReasonFlagsTest.cs | 46 + crypto/test/src/asn1/test/RegressionTest.cs | 85 + .../src/asn1/test/RequestedCertificateUnitTest.cs | 117 + crypto/test/src/asn1/test/RestrictionUnitTest.cs | 78 + crypto/test/src/asn1/test/SMIMETest.cs | 90 + .../src/asn1/test/SemanticsInformationUnitTest.cs | 138 + crypto/test/src/asn1/test/SetTest.cs | 117 + .../test/src/asn1/test/SignerLocationUnitTest.cs | 195 + crypto/test/src/asn1/test/StringTest.cs | 105 + .../test/src/asn1/test/SubjectKeyIdentifierTest.cs | 61 + crypto/test/src/asn1/test/TagTest.cs | 115 + crypto/test/src/asn1/test/TargetInformationTest.cs | 58 + crypto/test/src/asn1/test/TimeTest.cs | 28 + .../src/asn1/test/TypeOfBiometricDataUnitTest.cs | 152 + crypto/test/src/asn1/test/UTCTimeTest.cs | 122 + crypto/test/src/asn1/test/X509ExtensionsTest.cs | 117 + crypto/test/src/asn1/test/X509NameTest.cs | 674 ++ crypto/test/src/asn1/test/X9Test.cs | 181 + crypto/test/src/cms/test/AllTests.cs | 35 + .../src/cms/test/AuthenticatedDataStreamTest.cs | 113 + crypto/test/src/cms/test/AuthenticatedDataTest.cs | 320 + crypto/test/src/cms/test/CMSSampleMessages.cs | 147 + crypto/test/src/cms/test/CMSTestUtil.cs | 480 + .../test/src/cms/test/CompressedDataStreamTest.cs | 116 + crypto/test/src/cms/test/CompressedDataTest.cs | 117 + .../test/src/cms/test/EnvelopedDataStreamTest.cs | 537 + crypto/test/src/cms/test/EnvelopedDataTest.cs | 866 ++ crypto/test/src/cms/test/MiscDataStreamTest.cs | 221 + crypto/test/src/cms/test/Rfc4134Test.cs | 344 + crypto/test/src/cms/test/SignedDataStreamTest.cs | 1215 +++ crypto/test/src/cms/test/SignedDataTest.cs | 1480 +++ crypto/test/src/crypto/examples/DESExample.cs | 396 + crypto/test/src/crypto/io/test/AllTests.cs | 27 + crypto/test/src/crypto/io/test/CipherStreamTest.cs | 166 + crypto/test/src/crypto/test/AESFastTest.cs | 168 + crypto/test/src/crypto/test/AESLightTest.cs | 168 + crypto/test/src/crypto/test/AESTest.cs | 178 + crypto/test/src/crypto/test/AESWrapTest.cs | 214 + crypto/test/src/crypto/test/AllTests.cs | 47 + .../src/crypto/test/BlockCipherMonteCarloTest.cs | 83 + .../test/src/crypto/test/BlockCipherVectorTest.cs | 75 + crypto/test/src/crypto/test/BlowfishTest.cs | 55 + crypto/test/src/crypto/test/CAST6Test.cs | 57 + crypto/test/src/crypto/test/CCMTest.cs | 268 + crypto/test/src/crypto/test/CMacTest.cs | 286 + crypto/test/src/crypto/test/CTSTest.cs | 192 + crypto/test/src/crypto/test/CamelliaLightTest.cs | 80 + crypto/test/src/crypto/test/CamelliaTest.cs | 80 + crypto/test/src/crypto/test/Cast5Test.cs | 49 + crypto/test/src/crypto/test/CipherTest.cs | 117 + crypto/test/src/crypto/test/DESTest.cs | 214 + crypto/test/src/crypto/test/DESedeTest.cs | 187 + crypto/test/src/crypto/test/DHKEKGeneratorTest.cs | 79 + crypto/test/src/crypto/test/DHTest.cs | 403 + crypto/test/src/crypto/test/DSATest.cs | 615 ++ .../test/src/crypto/test/DigestRandomNumberTest.cs | 163 + crypto/test/src/crypto/test/DigestTest.cs | 143 + crypto/test/src/crypto/test/EAXTest.cs | 352 + .../test/src/crypto/test/ECDHKEKGeneratorTest.cs | 80 + crypto/test/src/crypto/test/ECGOST3410Test.cs | 335 + crypto/test/src/crypto/test/ECIESTest.cs | 246 + crypto/test/src/crypto/test/ECNRTest.cs | 115 + crypto/test/src/crypto/test/ECTest.cs | 919 ++ crypto/test/src/crypto/test/ElGamalTest.cs | 278 + crypto/test/src/crypto/test/EqualsHashCodeTest.cs | 262 + crypto/test/src/crypto/test/GCMTest.cs | 589 + crypto/test/src/crypto/test/GOST28147MacTest.cs | 105 + crypto/test/src/crypto/test/GOST28147Test.cs | 334 + crypto/test/src/crypto/test/GOST3410Test.cs | 1604 +++ crypto/test/src/crypto/test/GOST3411DigestTest.cs | 79 + crypto/test/src/crypto/test/GcmReorderTest.cs | 362 + crypto/test/src/crypto/test/HCFamilyTest.cs | 192 + crypto/test/src/crypto/test/HCFamilyVecTest.cs | 184 + crypto/test/src/crypto/test/IDEATest.cs | 57 + crypto/test/src/crypto/test/ISAACTest.cs | 196 + crypto/test/src/crypto/test/ISO9796Test.cs | 961 ++ crypto/test/src/crypto/test/ISO9797Alg3MacTest.cs | 99 + crypto/test/src/crypto/test/KDF1GeneratorTest.cs | 103 + crypto/test/src/crypto/test/KDF2GeneratorTest.cs | 115 + crypto/test/src/crypto/test/MD2DigestTest.cs | 204 + crypto/test/src/crypto/test/MD4DigestTest.cs | 176 + crypto/test/src/crypto/test/MD5DigestTest.cs | 175 + crypto/test/src/crypto/test/MD5HMacTest.cs | 91 + crypto/test/src/crypto/test/MGF1GeneratorTest.cs | 103 + crypto/test/src/crypto/test/MacTest.cs | 214 + crypto/test/src/crypto/test/ModeTest.cs | 108 + crypto/test/src/crypto/test/NaccacheSternTest.cs | 354 + crypto/test/src/crypto/test/NoekeonTest.cs | 59 + crypto/test/src/crypto/test/NullTest.cs | 88 + crypto/test/src/crypto/test/OAEPTest.cs | 798 ++ crypto/test/src/crypto/test/OCBTest.cs | 261 + crypto/test/src/crypto/test/PSSBlindTest.cs | 399 + crypto/test/src/crypto/test/PSSTest.cs | 338 + crypto/test/src/crypto/test/PaddingTest.cs | 171 + crypto/test/src/crypto/test/Pkcs12Test.cs | 101 + crypto/test/src/crypto/test/Pkcs5Test.cs | 243 + crypto/test/src/crypto/test/RC2Test.cs | 58 + crypto/test/src/crypto/test/RC2WrapTest.cs | 123 + crypto/test/src/crypto/test/RC4Test.cs | 59 + crypto/test/src/crypto/test/RC5Test.cs | 201 + crypto/test/src/crypto/test/RC6Test.cs | 54 + crypto/test/src/crypto/test/RFC3211WrapTest.cs | 216 + crypto/test/src/crypto/test/RSABlindedTest.cs | 449 + crypto/test/src/crypto/test/RegressionTest.cs | 126 + crypto/test/src/crypto/test/RijndaelTest.cs | 135 + crypto/test/src/crypto/test/RipeMD128DigestTest.cs | 135 + crypto/test/src/crypto/test/RipeMD128HMacTest.cs | 100 + crypto/test/src/crypto/test/RipeMD160DigestTest.cs | 135 + crypto/test/src/crypto/test/RipeMD160HMacTest.cs | 102 + crypto/test/src/crypto/test/RipeMD256DigestTest.cs | 104 + crypto/test/src/crypto/test/RipeMD320DigestTest.cs | 105 + crypto/test/src/crypto/test/RsaTest.cs | 596 ++ crypto/test/src/crypto/test/SCryptTest.cs | 103 + crypto/test/src/crypto/test/SEEDTest.cs | 65 + crypto/test/src/crypto/test/SHA1DigestTest.cs | 151 + crypto/test/src/crypto/test/SHA1HMacTest.cs | 93 + crypto/test/src/crypto/test/SHA224DigestTest.cs | 200 + crypto/test/src/crypto/test/SHA224HMacTest.cs | 122 + crypto/test/src/crypto/test/SHA256DigestTest.cs | 205 + crypto/test/src/crypto/test/SHA256HMacTest.cs | 122 + crypto/test/src/crypto/test/SHA384DigestTest.cs | 203 + crypto/test/src/crypto/test/SHA384HMacTest.cs | 122 + crypto/test/src/crypto/test/SHA3DigestTest.cs | 374 + crypto/test/src/crypto/test/SHA512DigestTest.cs | 165 + crypto/test/src/crypto/test/SHA512HMacTest.cs | 123 + .../test/src/crypto/test/SHA512t224DigestTest.cs | 62 + .../test/src/crypto/test/SHA512t256DigestTest.cs | 62 + crypto/test/src/crypto/test/SRP6Test.cs | 300 + crypto/test/src/crypto/test/Salsa20Test.cs | 261 + crypto/test/src/crypto/test/SerpentTest.cs | 119 + crypto/test/src/crypto/test/ShortenedDigestTest.cs | 98 + crypto/test/src/crypto/test/SipHashTest.cs | 76 + crypto/test/src/crypto/test/SkipjackTest.cs | 46 + .../test/src/crypto/test/StreamCipherVectorTest.cs | 68 + crypto/test/src/crypto/test/TEATest.cs | 59 + crypto/test/src/crypto/test/TigerDigestTest.cs | 140 + crypto/test/src/crypto/test/TwofishTest.cs | 54 + crypto/test/src/crypto/test/VMPCKSA3Test.cs | 112 + crypto/test/src/crypto/test/VMPCMacTest.cs | 68 + crypto/test/src/crypto/test/VMPCTest.cs | 112 + crypto/test/src/crypto/test/WhirlpoolDigestTest.cs | 147 + crypto/test/src/crypto/test/XTEATest.cs | 59 + crypto/test/src/math/ec/test/AllTests.cs | 27 + .../src/math/ec/test/ECPointPerformanceTest.cs | 73 + crypto/test/src/math/ec/test/ECPointTest.cs | 451 + crypto/test/src/math/ec/test/F2mProofer.cs | 201 + crypto/test/src/math/ec/test/TnafTest.cs | 158 + crypto/test/src/math/test/AllTests.cs | 27 + crypto/test/src/math/test/BigIntegerTest.cs | 1048 ++ crypto/test/src/ocsp/test/AllTests.cs | 29 + crypto/test/src/ocsp/test/OCSPTest.cs | 852 ++ crypto/test/src/ocsp/test/OCSPTestUtil.cs | 147 + .../test/src/openpgp/examples/ByteArrayHandler.cs | 195 + .../openpgp/examples/ClearSignedFileProcessor.cs | 375 + .../openpgp/examples/DetachedSignatureProcessor.cs | 167 + .../src/openpgp/examples/DirectKeySignature.cs | 140 + .../openpgp/examples/DsaElGamalKeyRingGenerator.cs | 134 + .../src/openpgp/examples/KeyBasedFileProcessor.cs | 259 + .../openpgp/examples/KeyBasedLargeFileProcessor.cs | 267 + .../test/src/openpgp/examples/PbeFileProcessor.cs | 183 + .../src/openpgp/examples/PgpExampleUtilities.cs | 123 + .../test/src/openpgp/examples/PublicKeyRingDump.cs | 98 + .../src/openpgp/examples/RsaKeyRingGenerator.cs | 115 + .../src/openpgp/examples/SignedFileProcessor.cs | 188 + crypto/test/src/openpgp/examples/test/AllTests.cs | 403 + crypto/test/src/openpgp/test/DSA2Test.cs | 237 + crypto/test/src/openpgp/test/PGPArmoredTest.cs | 265 + .../openpgp/test/PGPClearSignedSignatureTest.cs | 445 + crypto/test/src/openpgp/test/PGPCompressionTest.cs | 117 + crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs | 492 + crypto/test/src/openpgp/test/PGPDSATest.cs | 597 ++ crypto/test/src/openpgp/test/PGPPBETest.cs | 384 + crypto/test/src/openpgp/test/PGPPacketTest.cs | 80 + crypto/test/src/openpgp/test/PGPRSATest.cs | 1235 +++ crypto/test/src/openpgp/test/PGPSignatureTest.cs | 761 ++ crypto/test/src/openpgp/test/PgpKeyRingTest.cs | 2163 ++++ crypto/test/src/openpgp/test/PgpMarkerTest.cs | 102 + crypto/test/src/openpgp/test/RegressionTest.cs | 34 + crypto/test/src/openssl/test/AllTests.cs | 133 + crypto/test/src/openssl/test/ReaderTest.cs | 380 + crypto/test/src/openssl/test/WriterTest.cs | 185 + crypto/test/src/pkcs/examples/PKCS12Example.cs | 386 + .../src/pkcs/test/EncryptedPrivateKeyInfoTest.cs | 92 + crypto/test/src/pkcs/test/PKCS10Test.cs | 88 + crypto/test/src/pkcs/test/PKCS12StoreTest.cs | 921 ++ crypto/test/src/security/test/SecureRandomTest.cs | 150 + crypto/test/src/security/test/TestDigestUtil.cs | 63 + crypto/test/src/security/test/TestDotNetUtil.cs | 88 + crypto/test/src/security/test/TestEncodings.cs | 188 + crypto/test/src/security/test/TestParameterUtil.cs | 74 + crypto/test/src/security/test/TestSignerUtil.cs | 180 + crypto/test/src/test/AESSICTest.cs | 147 + crypto/test/src/test/AESTest.cs | 363 + crypto/test/src/test/AttrCertSelectorTest.cs | 214 + crypto/test/src/test/AttrCertTest.cs | 621 ++ crypto/test/src/test/BaseBlockCipherTest.cs | 146 + crypto/test/src/test/BlockCipherTest.cs | 978 ++ crypto/test/src/test/CMacTest.cs | 276 + crypto/test/src/test/CRL5Test.cs | 257 + crypto/test/src/test/CamelliaTest.cs | 204 + crypto/test/src/test/CertPathBuilderTest.cs | 163 + crypto/test/src/test/CertPathTest.cs | 359 + crypto/test/src/test/CertPathValidatorTest.cs | 304 + crypto/test/src/test/CertTest.cs | 2544 +++++ crypto/test/src/test/CipherStreamTest.cs | 449 + crypto/test/src/test/DESedeTest.cs | 298 + crypto/test/src/test/DHTest.cs | 650 ++ crypto/test/src/test/DSATest.cs | 888 ++ crypto/test/src/test/DigestTest.cs | 175 + crypto/test/src/test/ECDSA5Test.cs | 300 + crypto/test/src/test/ECEncodingTest.cs | 243 + crypto/test/src/test/ECNRTest.cs | 204 + crypto/test/src/test/ElGamalTest.cs | 334 + .../test/src/test/EncryptedPrivateKeyInfoTest.cs | 154 + crypto/test/src/test/FIPSDESTest.cs | 205 + crypto/test/src/test/GOST28147Test.cs | 245 + crypto/test/src/test/GOST3410Test.cs | 383 + crypto/test/src/test/HMacTest.cs | 189 + crypto/test/src/test/IESTest.cs | 245 + crypto/test/src/test/MacTest.cs | 216 + crypto/test/src/test/MqvTest.cs | 99 + crypto/test/src/test/NamedCurveTest.cs | 394 + crypto/test/src/test/NistCertPathTest.cs | 5192 +++++++++ crypto/test/src/test/NoekeonTest.cs | 157 + crypto/test/src/test/PBETest.cs | 527 + crypto/test/src/test/PEMData.cs | 117 + crypto/test/src/test/PKCS10CertRequestTest.cs | 470 + crypto/test/src/test/PSSTest.cs | 253 + crypto/test/src/test/PkixNameConstraintsTest.cs | 433 + crypto/test/src/test/PkixPolicyMappingTest.cs | 419 + crypto/test/src/test/PkixTest.cs | 248 + crypto/test/src/test/RSATest.cs | 685 ++ crypto/test/src/test/RegressionTest.cs | 80 + crypto/test/src/test/SEEDTest.cs | 190 + crypto/test/src/test/SigTest.cs | 378 + crypto/test/src/test/TestUtilities.cs | 264 + crypto/test/src/test/WrapTest.cs | 94 + crypto/test/src/test/X509CertificatePairTest.cs | 149 + crypto/test/src/test/X509StoreTest.cs | 335 + crypto/test/src/test/nist/NistCertPathTest.cs | 847 ++ crypto/test/src/test/rsa3/RSA3CertTest.cs | 127 + crypto/test/src/tsp/test/AllTests.cs | 32 + crypto/test/src/tsp/test/GenTimeAccuracyTest.cs | 116 + crypto/test/src/tsp/test/ParseTest.cs | 396 + crypto/test/src/tsp/test/TSPTest.cs | 548 + crypto/test/src/tsp/test/TSPTestUtil.cs | 200 + crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs | 145 + crypto/test/src/util/io/pem/test/AllTests.cs | 77 + crypto/test/src/util/net/test/IPAddressTest.cs | 61 + crypto/test/src/util/test/FixedSecureRandom.cs | 64 + crypto/test/src/util/test/ITest.cs | 17 + crypto/test/src/util/test/ITestResult.cs | 13 + crypto/test/src/util/test/NumberParsing.cs | 40 + crypto/test/src/util/test/SimpleTest.cs | 164 + crypto/test/src/util/test/SimpleTestResult.cs | 91 + crypto/test/src/util/test/TestFailedException.cs | 24 + crypto/test/src/util/test/UncloseableStream.cs | 22 + crypto/test/src/x509/test/TestCertificateGen.cs | 715 ++ crypto/testcfg.nunit | 6 + csharp.mds | 20 + csharp.sln | 29 + 2279 files changed, 281992 insertions(+) create mode 100644 FxCop/CustomDictionary.xml create mode 100644 crypto-test/App.ico create mode 100644 crypto-test/CryptoTest.cs create mode 100644 crypto-test/crypto-test.csproj create mode 100644 crypto-test/crypto-test.mdp create mode 100644 crypto/Contributors.html create mode 100644 crypto/License.html create mode 100644 crypto/NBuild.build create mode 100644 crypto/Readme.html create mode 100644 crypto/bzip2/src/BZip2Constants.cs create mode 100644 crypto/bzip2/src/CBZip2InputStream.cs create mode 100644 crypto/bzip2/src/CBZip2OutputStream.cs create mode 100644 crypto/bzip2/src/CRC.cs create mode 100644 crypto/checklist.txt create mode 100644 crypto/crypto.csproj create mode 100644 crypto/crypto.mdp create mode 100644 crypto/src/AssemblyInfo.cs create mode 100644 crypto/src/asn1/ASN1Generator.cs create mode 100644 crypto/src/asn1/ASN1OctetStringParser.cs create mode 100644 crypto/src/asn1/ASN1SequenceParser.cs create mode 100644 crypto/src/asn1/ASN1SetParser.cs create mode 100644 crypto/src/asn1/ASN1StreamParser.cs create mode 100644 crypto/src/asn1/ASN1TaggedObjectParser.cs create mode 100644 crypto/src/asn1/Asn1Encodable.cs create mode 100644 crypto/src/asn1/Asn1EncodableVector.cs create mode 100644 crypto/src/asn1/Asn1Exception.cs create mode 100644 crypto/src/asn1/Asn1InputStream.cs create mode 100644 crypto/src/asn1/Asn1Null.cs create mode 100644 crypto/src/asn1/Asn1Object.cs create mode 100644 crypto/src/asn1/Asn1OctetString.cs create mode 100644 crypto/src/asn1/Asn1OutputStream.cs create mode 100644 crypto/src/asn1/Asn1ParsingException.cs create mode 100644 crypto/src/asn1/Asn1Sequence.cs create mode 100644 crypto/src/asn1/Asn1Set.cs create mode 100644 crypto/src/asn1/Asn1TaggedObject.cs create mode 100644 crypto/src/asn1/Asn1Tags.cs create mode 100644 crypto/src/asn1/BERGenerator.cs create mode 100644 crypto/src/asn1/BEROctetStringGenerator.cs create mode 100644 crypto/src/asn1/BEROctetStringParser.cs create mode 100644 crypto/src/asn1/BERSequenceGenerator.cs create mode 100644 crypto/src/asn1/BERSequenceParser.cs create mode 100644 crypto/src/asn1/BERSetGenerator.cs create mode 100644 crypto/src/asn1/BERSetParser.cs create mode 100644 crypto/src/asn1/BERTaggedObjectParser.cs create mode 100644 crypto/src/asn1/BerApplicationSpecific.cs create mode 100644 crypto/src/asn1/BerApplicationSpecificParser.cs create mode 100644 crypto/src/asn1/BerNull.cs create mode 100644 crypto/src/asn1/BerOctetString.cs create mode 100644 crypto/src/asn1/BerOutputStream.cs create mode 100644 crypto/src/asn1/BerSequence.cs create mode 100644 crypto/src/asn1/BerSet.cs create mode 100644 crypto/src/asn1/BerTaggedObject.cs create mode 100644 crypto/src/asn1/ConstructedOctetStream.cs create mode 100644 crypto/src/asn1/DERExternal.cs create mode 100644 crypto/src/asn1/DERExternalParser.cs create mode 100644 crypto/src/asn1/DERGenerator.cs create mode 100644 crypto/src/asn1/DEROctetStringParser.cs create mode 100644 crypto/src/asn1/DERSequenceGenerator.cs create mode 100644 crypto/src/asn1/DERSequenceParser.cs create mode 100644 crypto/src/asn1/DERSetGenerator.cs create mode 100644 crypto/src/asn1/DERSetParser.cs create mode 100644 crypto/src/asn1/DefiniteLengthInputStream.cs create mode 100644 crypto/src/asn1/DerApplicationSpecific.cs create mode 100644 crypto/src/asn1/DerBMPString.cs create mode 100644 crypto/src/asn1/DerBitString.cs create mode 100644 crypto/src/asn1/DerBoolean.cs create mode 100644 crypto/src/asn1/DerEnumerated.cs create mode 100644 crypto/src/asn1/DerGeneralString.cs create mode 100644 crypto/src/asn1/DerGeneralizedTime.cs create mode 100644 crypto/src/asn1/DerIA5String.cs create mode 100644 crypto/src/asn1/DerInteger.cs create mode 100644 crypto/src/asn1/DerNull.cs create mode 100644 crypto/src/asn1/DerNumericString.cs create mode 100644 crypto/src/asn1/DerObjectIdentifier.cs create mode 100644 crypto/src/asn1/DerOctetString.cs create mode 100644 crypto/src/asn1/DerOutputStream.cs create mode 100644 crypto/src/asn1/DerPrintableString.cs create mode 100644 crypto/src/asn1/DerSequence.cs create mode 100644 crypto/src/asn1/DerSet.cs create mode 100644 crypto/src/asn1/DerStringBase.cs create mode 100644 crypto/src/asn1/DerT61String.cs create mode 100644 crypto/src/asn1/DerTaggedObject.cs create mode 100644 crypto/src/asn1/DerUTCTime.cs create mode 100644 crypto/src/asn1/DerUTF8String.cs create mode 100644 crypto/src/asn1/DerUniversalString.cs create mode 100644 crypto/src/asn1/DerUnknownTag.cs create mode 100644 crypto/src/asn1/DerVisibleString.cs create mode 100644 crypto/src/asn1/IAsn1ApplicationSpecificParser.cs create mode 100644 crypto/src/asn1/IAsn1Choice.cs create mode 100644 crypto/src/asn1/IAsn1Convertible.cs create mode 100644 crypto/src/asn1/IAsn1String.cs create mode 100644 crypto/src/asn1/IndefiniteLengthInputStream.cs create mode 100644 crypto/src/asn1/LazyASN1InputStream.cs create mode 100644 crypto/src/asn1/LazyDERSequence.cs create mode 100644 crypto/src/asn1/LazyDERSet.cs create mode 100644 crypto/src/asn1/LimitedInputStream.cs create mode 100644 crypto/src/asn1/OidTokenizer.cs create mode 100644 crypto/src/asn1/bc/BCObjectIdentifiers.cs create mode 100644 crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs create mode 100644 crypto/src/asn1/cmp/CertConfirmContent.cs create mode 100644 crypto/src/asn1/cmp/CertOrEncCert.cs create mode 100644 crypto/src/asn1/cmp/CertRepMessage.cs create mode 100644 crypto/src/asn1/cmp/CertResponse.cs create mode 100644 crypto/src/asn1/cmp/CertStatus.cs create mode 100644 crypto/src/asn1/cmp/CertifiedKeyPair.cs create mode 100644 crypto/src/asn1/cmp/Challenge.cs create mode 100644 crypto/src/asn1/cmp/CmpCertificate.cs create mode 100644 crypto/src/asn1/cmp/CmpObjectIdentifiers.cs create mode 100644 crypto/src/asn1/cmp/CrlAnnContent.cs create mode 100644 crypto/src/asn1/cmp/ErrorMsgContent.cs create mode 100644 crypto/src/asn1/cmp/GenMsgContent.cs create mode 100644 crypto/src/asn1/cmp/GenRepContent.cs create mode 100644 crypto/src/asn1/cmp/InfoTypeAndValue.cs create mode 100644 crypto/src/asn1/cmp/KeyRecRepContent.cs create mode 100644 crypto/src/asn1/cmp/OobCertHash.cs create mode 100644 crypto/src/asn1/cmp/PKIBody.cs create mode 100644 crypto/src/asn1/cmp/PKIConfirmContent.cs create mode 100644 crypto/src/asn1/cmp/PKIFailureInfo.cs create mode 100644 crypto/src/asn1/cmp/PKIFreeText.cs create mode 100644 crypto/src/asn1/cmp/PKIHeader.cs create mode 100644 crypto/src/asn1/cmp/PKIHeaderBuilder.cs create mode 100644 crypto/src/asn1/cmp/PKIMessage.cs create mode 100644 crypto/src/asn1/cmp/PKIMessages.cs create mode 100644 crypto/src/asn1/cmp/PKIStatus.cs create mode 100644 crypto/src/asn1/cmp/PKIStatusInfo.cs create mode 100644 crypto/src/asn1/cmp/PbmParameter.cs create mode 100644 crypto/src/asn1/cmp/PollRepContent.cs create mode 100644 crypto/src/asn1/cmp/PollReqContent.cs create mode 100644 crypto/src/asn1/cmp/PopoDecKeyChallContent.cs create mode 100644 crypto/src/asn1/cmp/PopoDecKeyRespContent.cs create mode 100644 crypto/src/asn1/cmp/ProtectedPart.cs create mode 100644 crypto/src/asn1/cmp/RevAnnContent.cs create mode 100644 crypto/src/asn1/cmp/RevDetails.cs create mode 100644 crypto/src/asn1/cmp/RevRepContent.cs create mode 100644 crypto/src/asn1/cmp/RevRepContentBuilder.cs create mode 100644 crypto/src/asn1/cmp/RevReqContent.cs create mode 100644 crypto/src/asn1/cms/Attribute.cs create mode 100644 crypto/src/asn1/cms/AttributeTable.cs create mode 100644 crypto/src/asn1/cms/Attributes.cs create mode 100644 crypto/src/asn1/cms/AuthEnvelopedData.cs create mode 100644 crypto/src/asn1/cms/AuthEnvelopedDataParser.cs create mode 100644 crypto/src/asn1/cms/AuthenticatedData.cs create mode 100644 crypto/src/asn1/cms/AuthenticatedDataParser.cs create mode 100644 crypto/src/asn1/cms/CMSAttributes.cs create mode 100644 crypto/src/asn1/cms/CMSObjectIdentifiers.cs create mode 100644 crypto/src/asn1/cms/CompressedData.cs create mode 100644 crypto/src/asn1/cms/CompressedDataParser.cs create mode 100644 crypto/src/asn1/cms/ContentInfo.cs create mode 100644 crypto/src/asn1/cms/ContentInfoParser.cs create mode 100644 crypto/src/asn1/cms/EncryptedContentInfo.cs create mode 100644 crypto/src/asn1/cms/EncryptedContentInfoParser.cs create mode 100644 crypto/src/asn1/cms/EncryptedData.cs create mode 100644 crypto/src/asn1/cms/EnvelopedData.cs create mode 100644 crypto/src/asn1/cms/EnvelopedDataParser.cs create mode 100644 crypto/src/asn1/cms/Evidence.cs create mode 100644 crypto/src/asn1/cms/IssuerAndSerialNumber.cs create mode 100644 crypto/src/asn1/cms/KEKIdentifier.cs create mode 100644 crypto/src/asn1/cms/KEKRecipientInfo.cs create mode 100644 crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs create mode 100644 crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs create mode 100644 crypto/src/asn1/cms/KeyTransRecipientInfo.cs create mode 100644 crypto/src/asn1/cms/MetaData.cs create mode 100644 crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs create mode 100644 crypto/src/asn1/cms/OriginatorInfo.cs create mode 100644 crypto/src/asn1/cms/OriginatorPublicKey.cs create mode 100644 crypto/src/asn1/cms/OtherKeyAttribute.cs create mode 100644 crypto/src/asn1/cms/OtherRecipientInfo.cs create mode 100644 crypto/src/asn1/cms/OtherRevocationInfoFormat.cs create mode 100644 crypto/src/asn1/cms/PasswordRecipientInfo.cs create mode 100644 crypto/src/asn1/cms/RecipientEncryptedKey.cs create mode 100644 crypto/src/asn1/cms/RecipientIdentifier.cs create mode 100644 crypto/src/asn1/cms/RecipientInfo.cs create mode 100644 crypto/src/asn1/cms/RecipientKeyIdentifier.cs create mode 100644 crypto/src/asn1/cms/SCVPReqRes.cs create mode 100644 crypto/src/asn1/cms/SignedData.cs create mode 100644 crypto/src/asn1/cms/SignedDataParser.cs create mode 100644 crypto/src/asn1/cms/SignerIdentifier.cs create mode 100644 crypto/src/asn1/cms/SignerInfo.cs create mode 100644 crypto/src/asn1/cms/Time.cs create mode 100644 crypto/src/asn1/cms/TimeStampAndCRL.cs create mode 100644 crypto/src/asn1/cms/TimeStampTokenEvidence.cs create mode 100644 crypto/src/asn1/cms/TimeStampedData.cs create mode 100644 crypto/src/asn1/cms/TimeStampedDataParser.cs create mode 100644 crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs create mode 100644 crypto/src/asn1/crmf/AttributeTypeAndValue.cs create mode 100644 crypto/src/asn1/crmf/CertId.cs create mode 100644 crypto/src/asn1/crmf/CertReqMessages.cs create mode 100644 crypto/src/asn1/crmf/CertReqMsg.cs create mode 100644 crypto/src/asn1/crmf/CertRequest.cs create mode 100644 crypto/src/asn1/crmf/CertTemplate.cs create mode 100644 crypto/src/asn1/crmf/CertTemplateBuilder.cs create mode 100644 crypto/src/asn1/crmf/Controls.cs create mode 100644 crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs create mode 100644 crypto/src/asn1/crmf/EncKeyWithID.cs create mode 100644 crypto/src/asn1/crmf/EncryptedKey.cs create mode 100644 crypto/src/asn1/crmf/EncryptedValue.cs create mode 100644 crypto/src/asn1/crmf/OptionalValidity.cs create mode 100644 crypto/src/asn1/crmf/PKIArchiveOptions.cs create mode 100644 crypto/src/asn1/crmf/PKIPublicationInfo.cs create mode 100644 crypto/src/asn1/crmf/PKMacValue.cs create mode 100644 crypto/src/asn1/crmf/PopoPrivKey.cs create mode 100644 crypto/src/asn1/crmf/PopoSigningKey.cs create mode 100644 crypto/src/asn1/crmf/PopoSigningKeyInput.cs create mode 100644 crypto/src/asn1/crmf/ProofOfPossession.cs create mode 100644 crypto/src/asn1/crmf/SinglePubInfo.cs create mode 100644 crypto/src/asn1/crmf/SubsequentMessage.cs create mode 100644 crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs create mode 100644 crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs create mode 100644 crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs create mode 100644 crypto/src/asn1/cryptopro/GOST28147Parameters.cs create mode 100644 crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs create mode 100644 crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs create mode 100644 crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs create mode 100644 crypto/src/asn1/eac/EACObjectIdentifiers.cs create mode 100644 crypto/src/asn1/esf/CertificateValues.cs create mode 100644 crypto/src/asn1/esf/CommitmentTypeIdentifier.cs create mode 100644 crypto/src/asn1/esf/CommitmentTypeIndication.cs create mode 100644 crypto/src/asn1/esf/CommitmentTypeQualifier.cs create mode 100644 crypto/src/asn1/esf/CompleteCertificateRefs.cs create mode 100644 crypto/src/asn1/esf/CompleteRevocationRefs.cs create mode 100644 crypto/src/asn1/esf/CrlIdentifier.cs create mode 100644 crypto/src/asn1/esf/CrlListID.cs create mode 100644 crypto/src/asn1/esf/CrlOcspRef.cs create mode 100644 crypto/src/asn1/esf/CrlValidatedID.cs create mode 100644 crypto/src/asn1/esf/ESFAttributes.cs create mode 100644 crypto/src/asn1/esf/OcspIdentifier.cs create mode 100644 crypto/src/asn1/esf/OcspListID.cs create mode 100644 crypto/src/asn1/esf/OcspResponsesID.cs create mode 100644 crypto/src/asn1/esf/OtherCertID.cs create mode 100644 crypto/src/asn1/esf/OtherHash.cs create mode 100644 crypto/src/asn1/esf/OtherHashAlgAndValue.cs create mode 100644 crypto/src/asn1/esf/OtherRevRefs.cs create mode 100644 crypto/src/asn1/esf/OtherRevVals.cs create mode 100644 crypto/src/asn1/esf/OtherSigningCertificate.cs create mode 100644 crypto/src/asn1/esf/RevocationValues.cs create mode 100644 crypto/src/asn1/esf/SigPolicyQualifierInfo.cs create mode 100644 crypto/src/asn1/esf/SignaturePolicyId.cs create mode 100644 crypto/src/asn1/esf/SignaturePolicyIdentifier.cs create mode 100644 crypto/src/asn1/esf/SignerAttribute.cs create mode 100644 crypto/src/asn1/esf/SignerLocation.cs create mode 100644 crypto/src/asn1/ess/ContentHints.cs create mode 100644 crypto/src/asn1/ess/ContentIdentifier.cs create mode 100644 crypto/src/asn1/ess/ESSCertID.cs create mode 100644 crypto/src/asn1/ess/ESSCertIDv2.cs create mode 100644 crypto/src/asn1/ess/OtherCertID.cs create mode 100644 crypto/src/asn1/ess/OtherSigningCertificate.cs create mode 100644 crypto/src/asn1/ess/SigningCertificate.cs create mode 100644 crypto/src/asn1/ess/SigningCertificateV2.cs create mode 100644 crypto/src/asn1/gnu/GNUObjectIdentifiers.cs create mode 100644 crypto/src/asn1/iana/IANAObjectIdentifiers.cs create mode 100644 crypto/src/asn1/icao/CscaMasterList.cs create mode 100644 crypto/src/asn1/icao/DataGroupHash.cs create mode 100644 crypto/src/asn1/icao/ICAOObjectIdentifiers.cs create mode 100644 crypto/src/asn1/icao/LDSSecurityObject.cs create mode 100644 crypto/src/asn1/icao/LDSVersionInfo.cs create mode 100644 crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs create mode 100644 crypto/src/asn1/isismtt/ocsp/CertHash.cs create mode 100644 crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs create mode 100644 crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs create mode 100644 crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs create mode 100644 crypto/src/asn1/isismtt/x509/Admissions.cs create mode 100644 crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs create mode 100644 crypto/src/asn1/isismtt/x509/MonetaryLimit.cs create mode 100644 crypto/src/asn1/isismtt/x509/NamingAuthority.cs create mode 100644 crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs create mode 100644 crypto/src/asn1/isismtt/x509/ProfessionInfo.cs create mode 100644 crypto/src/asn1/isismtt/x509/Restriction.cs create mode 100644 crypto/src/asn1/kisa/KISAObjectIdentifiers.cs create mode 100644 crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs create mode 100644 crypto/src/asn1/misc/CAST5CBCParameters.cs create mode 100644 crypto/src/asn1/misc/IDEACBCPar.cs create mode 100644 crypto/src/asn1/misc/MiscObjectIdentifiers.cs create mode 100644 crypto/src/asn1/misc/NetscapeCertType.cs create mode 100644 crypto/src/asn1/misc/NetscapeRevocationURL.cs create mode 100644 crypto/src/asn1/misc/VerisignCzagExtension.cs create mode 100644 crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs create mode 100644 crypto/src/asn1/nist/NISTNamedCurves.cs create mode 100644 crypto/src/asn1/nist/NISTObjectIdentifiers.cs create mode 100644 crypto/src/asn1/ntt/NTTObjectIdentifiers.cs create mode 100644 crypto/src/asn1/ocsp/BasicOCSPResponse.cs create mode 100644 crypto/src/asn1/ocsp/CertID.cs create mode 100644 crypto/src/asn1/ocsp/CertStatus.cs create mode 100644 crypto/src/asn1/ocsp/CrlID.cs create mode 100644 crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs create mode 100644 crypto/src/asn1/ocsp/OCSPRequest.cs create mode 100644 crypto/src/asn1/ocsp/OCSPResponse.cs create mode 100644 crypto/src/asn1/ocsp/OCSPResponseStatus.cs create mode 100644 crypto/src/asn1/ocsp/Request.cs create mode 100644 crypto/src/asn1/ocsp/ResponderID.cs create mode 100644 crypto/src/asn1/ocsp/ResponseBytes.cs create mode 100644 crypto/src/asn1/ocsp/ResponseData.cs create mode 100644 crypto/src/asn1/ocsp/RevokedInfo.cs create mode 100644 crypto/src/asn1/ocsp/ServiceLocator.cs create mode 100644 crypto/src/asn1/ocsp/Signature.cs create mode 100644 crypto/src/asn1/ocsp/SingleResponse.cs create mode 100644 crypto/src/asn1/ocsp/TBSRequest.cs create mode 100644 crypto/src/asn1/oiw/ElGamalParameter.cs create mode 100644 crypto/src/asn1/oiw/OIWObjectIdentifiers.cs create mode 100644 crypto/src/asn1/pkcs/Attribute.cs create mode 100644 crypto/src/asn1/pkcs/AuthenticatedSafe.cs create mode 100644 crypto/src/asn1/pkcs/CertBag.cs create mode 100644 crypto/src/asn1/pkcs/CertificationRequest.cs create mode 100644 crypto/src/asn1/pkcs/CertificationRequestInfo.cs create mode 100644 crypto/src/asn1/pkcs/ContentInfo.cs create mode 100644 crypto/src/asn1/pkcs/DHParameter.cs create mode 100644 crypto/src/asn1/pkcs/EncryptedData.cs create mode 100644 crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs create mode 100644 crypto/src/asn1/pkcs/EncryptionScheme.cs create mode 100644 crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs create mode 100644 crypto/src/asn1/pkcs/KeyDerivationFunc.cs create mode 100644 crypto/src/asn1/pkcs/MacData.cs create mode 100644 crypto/src/asn1/pkcs/PBEParameter.cs create mode 100644 crypto/src/asn1/pkcs/PBES2Parameters.cs create mode 100644 crypto/src/asn1/pkcs/PBKDF2Params.cs create mode 100644 crypto/src/asn1/pkcs/PKCS12PBEParams.cs create mode 100644 crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs create mode 100644 crypto/src/asn1/pkcs/Pfx.cs create mode 100644 crypto/src/asn1/pkcs/PrivateKeyInfo.cs create mode 100644 crypto/src/asn1/pkcs/RC2CBCParameter.cs create mode 100644 crypto/src/asn1/pkcs/RSAESOAEPparams.cs create mode 100644 crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs create mode 100644 crypto/src/asn1/pkcs/RSASSAPSSparams.cs create mode 100644 crypto/src/asn1/pkcs/SafeBag.cs create mode 100644 crypto/src/asn1/pkcs/SignedData.cs create mode 100644 crypto/src/asn1/pkcs/SignerInfo.cs create mode 100644 crypto/src/asn1/sec/ECPrivateKeyStructure.cs create mode 100644 crypto/src/asn1/sec/SECNamedCurves.cs create mode 100644 crypto/src/asn1/sec/SECObjectIdentifiers.cs create mode 100644 crypto/src/asn1/smime/SMIMEAttributes.cs create mode 100644 crypto/src/asn1/smime/SMIMECapabilities.cs create mode 100644 crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs create mode 100644 crypto/src/asn1/smime/SMIMECapability.cs create mode 100644 crypto/src/asn1/smime/SMIMECapabilityVector.cs create mode 100644 crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs create mode 100644 crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs create mode 100644 crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs create mode 100644 crypto/src/asn1/tsp/Accuracy.cs create mode 100644 crypto/src/asn1/tsp/MessageImprint.cs create mode 100644 crypto/src/asn1/tsp/TSTInfo.cs create mode 100644 crypto/src/asn1/tsp/TimeStampReq.cs create mode 100644 crypto/src/asn1/tsp/TimeStampResp.cs create mode 100644 crypto/src/asn1/util/Asn1Dump.cs create mode 100644 crypto/src/asn1/util/Dump.cs create mode 100644 crypto/src/asn1/util/FilterStream.cs create mode 100644 crypto/src/asn1/x500/DirectoryString.cs create mode 100644 crypto/src/asn1/x509/AccessDescription.cs create mode 100644 crypto/src/asn1/x509/AlgorithmIdentifier.cs create mode 100644 crypto/src/asn1/x509/AttCertIssuer.cs create mode 100644 crypto/src/asn1/x509/AttCertValidityPeriod.cs create mode 100644 crypto/src/asn1/x509/Attribute.cs create mode 100644 crypto/src/asn1/x509/AttributeCertificate.cs create mode 100644 crypto/src/asn1/x509/AttributeCertificateInfo.cs create mode 100644 crypto/src/asn1/x509/AttributeTable.cs create mode 100644 crypto/src/asn1/x509/AuthorityInformationAccess.cs create mode 100644 crypto/src/asn1/x509/AuthorityKeyIdentifier.cs create mode 100644 crypto/src/asn1/x509/BasicConstraints.cs create mode 100644 crypto/src/asn1/x509/CRLDistPoint.cs create mode 100644 crypto/src/asn1/x509/CRLNumber.cs create mode 100644 crypto/src/asn1/x509/CRLReason.cs create mode 100644 crypto/src/asn1/x509/CertPolicyId.cs create mode 100644 crypto/src/asn1/x509/CertificateList.cs create mode 100644 crypto/src/asn1/x509/CertificatePair.cs create mode 100644 crypto/src/asn1/x509/CertificatePolicies.cs create mode 100644 crypto/src/asn1/x509/DSAParameter.cs create mode 100644 crypto/src/asn1/x509/DigestInfo.cs create mode 100644 crypto/src/asn1/x509/DisplayText.cs create mode 100644 crypto/src/asn1/x509/DistributionPoint.cs create mode 100644 crypto/src/asn1/x509/DistributionPointName.cs create mode 100644 crypto/src/asn1/x509/ExtendedKeyUsage.cs create mode 100644 crypto/src/asn1/x509/GeneralName.cs create mode 100644 crypto/src/asn1/x509/GeneralNames.cs create mode 100644 crypto/src/asn1/x509/GeneralSubtree.cs create mode 100644 crypto/src/asn1/x509/Holder.cs create mode 100644 crypto/src/asn1/x509/IetfAttrSyntax.cs create mode 100644 crypto/src/asn1/x509/IssuerSerial.cs create mode 100644 crypto/src/asn1/x509/IssuingDistributionPoint.cs create mode 100644 crypto/src/asn1/x509/KeyPurposeId.cs create mode 100644 crypto/src/asn1/x509/KeyUsage.cs create mode 100644 crypto/src/asn1/x509/NameConstraints.cs create mode 100644 crypto/src/asn1/x509/NoticeReference.cs create mode 100644 crypto/src/asn1/x509/ObjectDigestInfo.cs create mode 100644 crypto/src/asn1/x509/PolicyInformation.cs create mode 100644 crypto/src/asn1/x509/PolicyMappings.cs create mode 100644 crypto/src/asn1/x509/PolicyQualifierId.cs create mode 100644 crypto/src/asn1/x509/PolicyQualifierInfo.cs create mode 100644 crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs create mode 100644 crypto/src/asn1/x509/RSAPublicKeyStructure.cs create mode 100644 crypto/src/asn1/x509/ReasonFlags.cs create mode 100644 crypto/src/asn1/x509/RoleSyntax.cs create mode 100644 crypto/src/asn1/x509/SubjectDirectoryAttributes.cs create mode 100644 crypto/src/asn1/x509/SubjectKeyIdentifier.cs create mode 100644 crypto/src/asn1/x509/SubjectPublicKeyInfo.cs create mode 100644 crypto/src/asn1/x509/TBSCertList.cs create mode 100644 crypto/src/asn1/x509/TBSCertificateStructure.cs create mode 100644 crypto/src/asn1/x509/Target.cs create mode 100644 crypto/src/asn1/x509/TargetInformation.cs create mode 100644 crypto/src/asn1/x509/Targets.cs create mode 100644 crypto/src/asn1/x509/Time.cs create mode 100644 crypto/src/asn1/x509/UserNotice.cs create mode 100644 crypto/src/asn1/x509/V1TBSCertificateGenerator.cs create mode 100644 crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs create mode 100644 crypto/src/asn1/x509/V2Form.cs create mode 100644 crypto/src/asn1/x509/V2TBSCertListGenerator.cs create mode 100644 crypto/src/asn1/x509/V3TBSCertificateGenerator.cs create mode 100644 crypto/src/asn1/x509/X509Attributes.cs create mode 100644 crypto/src/asn1/x509/X509CertificateStructure.cs create mode 100644 crypto/src/asn1/x509/X509DefaultEntryConverter.cs create mode 100644 crypto/src/asn1/x509/X509Extension.cs create mode 100644 crypto/src/asn1/x509/X509Extensions.cs create mode 100644 crypto/src/asn1/x509/X509ExtensionsGenerator.cs create mode 100644 crypto/src/asn1/x509/X509Name.cs create mode 100644 crypto/src/asn1/x509/X509NameEntryConverter.cs create mode 100644 crypto/src/asn1/x509/X509NameTokenizer.cs create mode 100644 crypto/src/asn1/x509/X509ObjectIdentifiers.cs create mode 100644 crypto/src/asn1/x509/qualified/BiometricData.cs create mode 100644 crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs create mode 100644 crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs create mode 100644 crypto/src/asn1/x509/qualified/MonetaryValue.cs create mode 100644 crypto/src/asn1/x509/qualified/QCStatement.cs create mode 100644 crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs create mode 100644 crypto/src/asn1/x509/qualified/SemanticsInformation.cs create mode 100644 crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs create mode 100644 crypto/src/asn1/x509/sigi/NameOrPseudonym.cs create mode 100644 crypto/src/asn1/x509/sigi/PersonalData.cs create mode 100644 crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs create mode 100644 crypto/src/asn1/x9/DHDomainParameters.cs create mode 100644 crypto/src/asn1/x9/DHPublicKey.cs create mode 100644 crypto/src/asn1/x9/DHValidationParms.cs create mode 100644 crypto/src/asn1/x9/KeySpecificInfo.cs create mode 100644 crypto/src/asn1/x9/OtherInfo.cs create mode 100644 crypto/src/asn1/x9/X962NamedCurves.cs create mode 100644 crypto/src/asn1/x9/X962Parameters.cs create mode 100644 crypto/src/asn1/x9/X9Curve.cs create mode 100644 crypto/src/asn1/x9/X9ECParameters.cs create mode 100644 crypto/src/asn1/x9/X9ECParametersHolder.cs create mode 100644 crypto/src/asn1/x9/X9ECPoint.cs create mode 100644 crypto/src/asn1/x9/X9FieldElement.cs create mode 100644 crypto/src/asn1/x9/X9FieldID.cs create mode 100644 crypto/src/asn1/x9/X9IntegerConverter.cs create mode 100644 crypto/src/asn1/x9/X9ObjectIdentifiers.cs create mode 100644 crypto/src/bcpg/ArmoredInputStream.cs create mode 100644 crypto/src/bcpg/ArmoredOutputStream.cs create mode 100644 crypto/src/bcpg/BcpgInputStream.cs create mode 100644 crypto/src/bcpg/BcpgObject.cs create mode 100644 crypto/src/bcpg/BcpgOutputStream.cs create mode 100644 crypto/src/bcpg/CompressedDataPacket.cs create mode 100644 crypto/src/bcpg/CompressionAlgorithmTags.cs create mode 100644 crypto/src/bcpg/ContainedPacket.cs create mode 100644 crypto/src/bcpg/Crc24.cs create mode 100644 crypto/src/bcpg/DsaPublicBcpgKey.cs create mode 100644 crypto/src/bcpg/DsaSecretBcpgKey.cs create mode 100644 crypto/src/bcpg/ElGamalPublicBcpgKey.cs create mode 100644 crypto/src/bcpg/ElGamalSecretBcpgKey.cs create mode 100644 crypto/src/bcpg/ExperimentalPacket.cs create mode 100644 crypto/src/bcpg/HashAlgorithmTags.cs create mode 100644 crypto/src/bcpg/IBcpgKey.cs create mode 100644 crypto/src/bcpg/InputStreamPacket.cs create mode 100644 crypto/src/bcpg/LiteralDataPacket.cs create mode 100644 crypto/src/bcpg/MPInteger.cs create mode 100644 crypto/src/bcpg/MarkerPacket.cs create mode 100644 crypto/src/bcpg/ModDetectionCodePacket.cs create mode 100644 crypto/src/bcpg/OnePassSignaturePacket.cs create mode 100644 crypto/src/bcpg/OutputStreamPacket.cs create mode 100644 crypto/src/bcpg/Packet.cs create mode 100644 crypto/src/bcpg/PacketTags.cs create mode 100644 crypto/src/bcpg/PublicKeyAlgorithmTags.cs create mode 100644 crypto/src/bcpg/PublicKeyEncSessionPacket.cs create mode 100644 crypto/src/bcpg/PublicKeyPacket.cs create mode 100644 crypto/src/bcpg/PublicSubkeyPacket.cs create mode 100644 crypto/src/bcpg/RsaPublicBcpgKey.cs create mode 100644 crypto/src/bcpg/RsaSecretBcpgKey.cs create mode 100644 crypto/src/bcpg/S2k.cs create mode 100644 crypto/src/bcpg/SecretKeyPacket.cs create mode 100644 crypto/src/bcpg/SecretSubkeyPacket.cs create mode 100644 crypto/src/bcpg/SignaturePacket.cs create mode 100644 crypto/src/bcpg/SignatureSubpacket.cs create mode 100644 crypto/src/bcpg/SignatureSubpacketTags.cs create mode 100644 crypto/src/bcpg/SignatureSubpacketsReader.cs create mode 100644 crypto/src/bcpg/SymmetricEncDataPacket.cs create mode 100644 crypto/src/bcpg/SymmetricEncIntegrityPacket.cs create mode 100644 crypto/src/bcpg/SymmetricKeyAlgorithmTags.cs create mode 100644 crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs create mode 100644 crypto/src/bcpg/TrustPacket.cs create mode 100644 crypto/src/bcpg/UserAttributePacket.cs create mode 100644 crypto/src/bcpg/UserAttributeSubpacket.cs create mode 100644 crypto/src/bcpg/UserAttributeSubpacketTags.cs create mode 100644 crypto/src/bcpg/UserAttributeSubpacketsReader.cs create mode 100644 crypto/src/bcpg/UserIdPacket.cs create mode 100644 crypto/src/bcpg/attr/ImageAttrib.cs create mode 100644 crypto/src/bcpg/sig/EmbeddedSignature.cs create mode 100644 crypto/src/bcpg/sig/Exportable.cs create mode 100644 crypto/src/bcpg/sig/IssuerKeyId.cs create mode 100644 crypto/src/bcpg/sig/KeyExpirationTime.cs create mode 100644 crypto/src/bcpg/sig/KeyFlags.cs create mode 100644 crypto/src/bcpg/sig/NotationData.cs create mode 100644 crypto/src/bcpg/sig/PreferredAlgorithms.cs create mode 100644 crypto/src/bcpg/sig/PrimaryUserId.cs create mode 100644 crypto/src/bcpg/sig/Revocable.cs create mode 100644 crypto/src/bcpg/sig/RevocationKey.cs create mode 100644 crypto/src/bcpg/sig/RevocationKeyTags.cs create mode 100644 crypto/src/bcpg/sig/RevocationReason.cs create mode 100644 crypto/src/bcpg/sig/RevocationReasonTags.cs create mode 100644 crypto/src/bcpg/sig/SignatureCreationTime.cs create mode 100644 crypto/src/bcpg/sig/SignatureExpirationTime.cs create mode 100644 crypto/src/bcpg/sig/SignerUserId.cs create mode 100644 crypto/src/bcpg/sig/TrustSignature.cs create mode 100644 crypto/src/cms/BaseDigestCalculator.cs create mode 100644 crypto/src/cms/CMSAttributeTableGenerationException.cs create mode 100644 crypto/src/cms/CMSAttributeTableGenerator.cs create mode 100644 crypto/src/cms/CMSAuthEnvelopedData.cs create mode 100644 crypto/src/cms/CMSAuthEnvelopedGenerator.cs create mode 100644 crypto/src/cms/CMSAuthenticatedData.cs create mode 100644 crypto/src/cms/CMSAuthenticatedDataGenerator.cs create mode 100644 crypto/src/cms/CMSAuthenticatedDataParser.cs create mode 100644 crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs create mode 100644 crypto/src/cms/CMSAuthenticatedGenerator.cs create mode 100644 crypto/src/cms/CMSCompressedData.cs create mode 100644 crypto/src/cms/CMSCompressedDataGenerator.cs create mode 100644 crypto/src/cms/CMSCompressedDataParser.cs create mode 100644 crypto/src/cms/CMSCompressedDataStreamGenerator.cs create mode 100644 crypto/src/cms/CMSContentInfoParser.cs create mode 100644 crypto/src/cms/CMSEnvelopedData.cs create mode 100644 crypto/src/cms/CMSEnvelopedDataGenerator.cs create mode 100644 crypto/src/cms/CMSEnvelopedDataParser.cs create mode 100644 crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs create mode 100644 crypto/src/cms/CMSEnvelopedGenerator.cs create mode 100644 crypto/src/cms/CMSEnvelopedHelper.cs create mode 100644 crypto/src/cms/CMSException.cs create mode 100644 crypto/src/cms/CMSPBEKey.cs create mode 100644 crypto/src/cms/CMSProcessable.cs create mode 100644 crypto/src/cms/CMSProcessableByteArray.cs create mode 100644 crypto/src/cms/CMSProcessableFile.cs create mode 100644 crypto/src/cms/CMSProcessableInputStream.cs create mode 100644 crypto/src/cms/CMSReadable.cs create mode 100644 crypto/src/cms/CMSSecureReadable.cs create mode 100644 crypto/src/cms/CMSSignedData.cs create mode 100644 crypto/src/cms/CMSSignedDataGenerator.cs create mode 100644 crypto/src/cms/CMSSignedDataParser.cs create mode 100644 crypto/src/cms/CMSSignedDataStreamGenerator.cs create mode 100644 crypto/src/cms/CMSSignedGenerator.cs create mode 100644 crypto/src/cms/CMSSignedHelper.cs create mode 100644 crypto/src/cms/CMSStreamException.cs create mode 100644 crypto/src/cms/CMSTypedStream.cs create mode 100644 crypto/src/cms/CMSUtils.cs create mode 100644 crypto/src/cms/CounterSignatureDigestCalculator.cs create mode 100644 crypto/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs create mode 100644 crypto/src/cms/DefaultSignedAttributeTableGenerator.cs create mode 100644 crypto/src/cms/DigOutputStream.cs create mode 100644 crypto/src/cms/IDigestCalculator.cs create mode 100644 crypto/src/cms/KEKRecipientInfoGenerator.cs create mode 100644 crypto/src/cms/KEKRecipientInformation.cs create mode 100644 crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs create mode 100644 crypto/src/cms/KeyAgreeRecipientInformation.cs create mode 100644 crypto/src/cms/KeyTransRecipientInfoGenerator.cs create mode 100644 crypto/src/cms/KeyTransRecipientInformation.cs create mode 100644 crypto/src/cms/MacOutputStream.cs create mode 100644 crypto/src/cms/NullOutputStream.cs create mode 100644 crypto/src/cms/OriginatorId.cs create mode 100644 crypto/src/cms/OriginatorInfoGenerator.cs create mode 100644 crypto/src/cms/OriginatorInformation.cs create mode 100644 crypto/src/cms/PKCS5Scheme2PBEKey.cs create mode 100644 crypto/src/cms/PKCS5Scheme2UTF8PBEKey.cs create mode 100644 crypto/src/cms/PasswordRecipientInfoGenerator.cs create mode 100644 crypto/src/cms/PasswordRecipientInformation.cs create mode 100644 crypto/src/cms/RecipientId.cs create mode 100644 crypto/src/cms/RecipientInfoGenerator.cs create mode 100644 crypto/src/cms/RecipientInformation.cs create mode 100644 crypto/src/cms/RecipientInformationStore.cs create mode 100644 crypto/src/cms/SigOutputStream.cs create mode 100644 crypto/src/cms/SignerId.cs create mode 100644 crypto/src/cms/SignerInfoGenerator.cs create mode 100644 crypto/src/cms/SignerInformation.cs create mode 100644 crypto/src/cms/SignerInformationStore.cs create mode 100644 crypto/src/cms/SimpleAttributeTableGenerator.cs create mode 100644 crypto/src/crypto/AsymmetricCipherKeyPair.cs create mode 100644 crypto/src/crypto/AsymmetricKeyParameter.cs create mode 100644 crypto/src/crypto/BufferedAeadBlockCipher.cs create mode 100644 crypto/src/crypto/BufferedAsymmetricBlockCipher.cs create mode 100644 crypto/src/crypto/BufferedBlockCipher.cs create mode 100644 crypto/src/crypto/BufferedCipherBase.cs create mode 100644 crypto/src/crypto/BufferedIesCipher.cs create mode 100644 crypto/src/crypto/BufferedStreamCipher.cs create mode 100644 crypto/src/crypto/CipherKeyGenerator.cs create mode 100644 crypto/src/crypto/CryptoException.cs create mode 100644 crypto/src/crypto/DataLengthException.cs create mode 100644 crypto/src/crypto/IAsymmetricBlockCipher.cs create mode 100644 crypto/src/crypto/IAsymmetricCipherKeyPairGenerator.cs create mode 100644 crypto/src/crypto/IBasicAgreement.cs create mode 100644 crypto/src/crypto/IBlockCipher.cs create mode 100644 crypto/src/crypto/IBufferedCipher.cs create mode 100644 crypto/src/crypto/ICipherParameters.cs create mode 100644 crypto/src/crypto/IDSA.cs create mode 100644 crypto/src/crypto/IDerivationFunction.cs create mode 100644 crypto/src/crypto/IDerivationParameters.cs create mode 100644 crypto/src/crypto/IDigest.cs create mode 100644 crypto/src/crypto/IMac.cs create mode 100644 crypto/src/crypto/ISigner.cs create mode 100644 crypto/src/crypto/ISignerWithRecovery.cs create mode 100644 crypto/src/crypto/IStreamCipher.cs create mode 100644 crypto/src/crypto/IWrapper.cs create mode 100644 crypto/src/crypto/InvalidCipherTextException.cs create mode 100644 crypto/src/crypto/KeyGenerationParameters.cs create mode 100644 crypto/src/crypto/MaxBytesExceededException.cs create mode 100644 crypto/src/crypto/PbeParametersGenerator.cs create mode 100644 crypto/src/crypto/StreamBlockCipher.cs create mode 100644 crypto/src/crypto/agreement/DHAgreement.cs create mode 100644 crypto/src/crypto/agreement/DHBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/ECDHBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/ECDHCBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/ECMqvBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs create mode 100644 crypto/src/crypto/agreement/kdf/DHKdfParameters.cs create mode 100644 crypto/src/crypto/agreement/kdf/DHKekGenerator.cs create mode 100644 crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs create mode 100644 crypto/src/crypto/agreement/srp/SRP6Client.cs create mode 100644 crypto/src/crypto/agreement/srp/SRP6Server.cs create mode 100644 crypto/src/crypto/agreement/srp/SRP6Utilities.cs create mode 100644 crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs create mode 100644 crypto/src/crypto/digests/GOST3411Digest.cs create mode 100644 crypto/src/crypto/digests/GeneralDigest.cs create mode 100644 crypto/src/crypto/digests/LongDigest.cs create mode 100644 crypto/src/crypto/digests/MD2Digest.cs create mode 100644 crypto/src/crypto/digests/MD4Digest.cs create mode 100644 crypto/src/crypto/digests/MD5Digest.cs create mode 100644 crypto/src/crypto/digests/NullDigest.cs create mode 100644 crypto/src/crypto/digests/RipeMD128Digest.cs create mode 100644 crypto/src/crypto/digests/RipeMD160Digest.cs create mode 100644 crypto/src/crypto/digests/RipeMD256Digest.cs create mode 100644 crypto/src/crypto/digests/RipeMD320Digest.cs create mode 100644 crypto/src/crypto/digests/SHA3Digest.cs create mode 100644 crypto/src/crypto/digests/Sha1Digest.cs create mode 100644 crypto/src/crypto/digests/Sha224Digest.cs create mode 100644 crypto/src/crypto/digests/Sha256Digest.cs create mode 100644 crypto/src/crypto/digests/Sha384Digest.cs create mode 100644 crypto/src/crypto/digests/Sha512Digest.cs create mode 100644 crypto/src/crypto/digests/Sha512tDigest.cs create mode 100644 crypto/src/crypto/digests/ShortenedDigest.cs create mode 100644 crypto/src/crypto/digests/TigerDigest.cs create mode 100644 crypto/src/crypto/digests/WhirlpoolDigest.cs create mode 100644 crypto/src/crypto/encodings/ISO9796d1Encoding.cs create mode 100644 crypto/src/crypto/encodings/OaepEncoding.cs create mode 100644 crypto/src/crypto/encodings/Pkcs1Encoding.cs create mode 100644 crypto/src/crypto/engines/AesEngine.cs create mode 100644 crypto/src/crypto/engines/AesFastEngine.cs create mode 100644 crypto/src/crypto/engines/AesLightEngine.cs create mode 100644 crypto/src/crypto/engines/AesWrapEngine.cs create mode 100644 crypto/src/crypto/engines/BlowfishEngine.cs create mode 100644 crypto/src/crypto/engines/CamelliaEngine.cs create mode 100644 crypto/src/crypto/engines/CamelliaLightEngine.cs create mode 100644 crypto/src/crypto/engines/CamelliaWrapEngine.cs create mode 100644 crypto/src/crypto/engines/Cast5Engine.cs create mode 100644 crypto/src/crypto/engines/Cast6Engine.cs create mode 100644 crypto/src/crypto/engines/DesEdeEngine.cs create mode 100644 crypto/src/crypto/engines/DesEdeWrapEngine.cs create mode 100644 crypto/src/crypto/engines/DesEngine.cs create mode 100644 crypto/src/crypto/engines/ElGamalEngine.cs create mode 100644 crypto/src/crypto/engines/GOST28147Engine.cs create mode 100644 crypto/src/crypto/engines/HC128Engine.cs create mode 100644 crypto/src/crypto/engines/HC256Engine.cs create mode 100644 crypto/src/crypto/engines/ISAACEngine.cs create mode 100644 crypto/src/crypto/engines/IdeaEngine.cs create mode 100644 crypto/src/crypto/engines/IesEngine.cs create mode 100644 crypto/src/crypto/engines/NaccacheSternEngine.cs create mode 100644 crypto/src/crypto/engines/NoekeonEngine.cs create mode 100644 crypto/src/crypto/engines/NullEngine.cs create mode 100644 crypto/src/crypto/engines/RC2Engine.cs create mode 100644 crypto/src/crypto/engines/RC2WrapEngine.cs create mode 100644 crypto/src/crypto/engines/RC4Engine.cs create mode 100644 crypto/src/crypto/engines/RC532Engine.cs create mode 100644 crypto/src/crypto/engines/RC564Engine.cs create mode 100644 crypto/src/crypto/engines/RC6Engine.cs create mode 100644 crypto/src/crypto/engines/RFC3211WrapEngine.cs create mode 100644 crypto/src/crypto/engines/RFC3394WrapEngine.cs create mode 100644 crypto/src/crypto/engines/RSABlindedEngine.cs create mode 100644 crypto/src/crypto/engines/RSABlindingEngine.cs create mode 100644 crypto/src/crypto/engines/RSACoreEngine.cs create mode 100644 crypto/src/crypto/engines/RijndaelEngine.cs create mode 100644 crypto/src/crypto/engines/RsaEngine.cs create mode 100644 crypto/src/crypto/engines/SEEDEngine.cs create mode 100644 crypto/src/crypto/engines/SEEDWrapEngine.cs create mode 100644 crypto/src/crypto/engines/Salsa20Engine.cs create mode 100644 crypto/src/crypto/engines/SerpentEngine.cs create mode 100644 crypto/src/crypto/engines/SkipjackEngine.cs create mode 100644 crypto/src/crypto/engines/TEAEngine.cs create mode 100644 crypto/src/crypto/engines/TwofishEngine.cs create mode 100644 crypto/src/crypto/engines/VMPCEngine.cs create mode 100644 crypto/src/crypto/engines/VMPCKSA3Engine.cs create mode 100644 crypto/src/crypto/engines/XTEAEngine.cs create mode 100644 crypto/src/crypto/generators/BaseKdfBytesGenerator.cs create mode 100644 crypto/src/crypto/generators/DHBasicKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/DHKeyGeneratorHelper.cs create mode 100644 crypto/src/crypto/generators/DHKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/DHParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/DHParametersHelper.cs create mode 100644 crypto/src/crypto/generators/DesEdeKeyGenerator.cs create mode 100644 crypto/src/crypto/generators/DesKeyGenerator.cs create mode 100644 crypto/src/crypto/generators/DsaKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/DsaParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/ECKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/ElGamalKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/ElGamalParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/GOST3410KeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/GOST3410ParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/Kdf1BytesGenerator.cs create mode 100644 crypto/src/crypto/generators/Kdf2BytesGenerator.cs create mode 100644 crypto/src/crypto/generators/Mgf1BytesGenerator.cs create mode 100644 crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/OpenSSLPBEParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs create mode 100644 crypto/src/crypto/generators/RSABlindingFactorGenerator.cs create mode 100644 crypto/src/crypto/generators/RsaKeyPairGenerator.cs create mode 100644 crypto/src/crypto/generators/SCrypt.cs create mode 100644 crypto/src/crypto/io/CipherStream.cs create mode 100644 crypto/src/crypto/io/DigestStream.cs create mode 100644 crypto/src/crypto/io/MacStream.cs create mode 100644 crypto/src/crypto/io/SignerStream.cs create mode 100644 crypto/src/crypto/macs/CMac.cs create mode 100644 crypto/src/crypto/macs/CbcBlockCipherMac.cs create mode 100644 crypto/src/crypto/macs/CfbBlockCipherMac.cs create mode 100644 crypto/src/crypto/macs/GOST28147Mac.cs create mode 100644 crypto/src/crypto/macs/HMac.cs create mode 100644 crypto/src/crypto/macs/ISO9797Alg3Mac.cs create mode 100644 crypto/src/crypto/macs/SipHash.cs create mode 100644 crypto/src/crypto/macs/VMPCMac.cs create mode 100644 crypto/src/crypto/modes/CbcBlockCipher.cs create mode 100644 crypto/src/crypto/modes/CcmBlockCipher.cs create mode 100644 crypto/src/crypto/modes/CfbBlockCipher.cs create mode 100644 crypto/src/crypto/modes/CtsBlockCipher.cs create mode 100644 crypto/src/crypto/modes/EAXBlockCipher.cs create mode 100644 crypto/src/crypto/modes/GCMBlockCipher.cs create mode 100644 crypto/src/crypto/modes/GOFBBlockCipher.cs create mode 100644 crypto/src/crypto/modes/IAeadBlockCipher.cs create mode 100644 crypto/src/crypto/modes/OCBBlockCipher.cs create mode 100644 crypto/src/crypto/modes/OfbBlockCipher.cs create mode 100644 crypto/src/crypto/modes/OpenPgpCfbBlockCipher.cs create mode 100644 crypto/src/crypto/modes/SicBlockCipher.cs create mode 100644 crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs create mode 100644 crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs create mode 100644 crypto/src/crypto/modes/gcm/GcmUtilities.cs create mode 100644 crypto/src/crypto/modes/gcm/IGcmExponentiator.cs create mode 100644 crypto/src/crypto/modes/gcm/IGcmMultiplier.cs create mode 100644 crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs create mode 100644 crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs create mode 100644 crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs create mode 100644 crypto/src/crypto/paddings/BlockCipherPadding.cs create mode 100644 crypto/src/crypto/paddings/ISO10126d2Padding.cs create mode 100644 crypto/src/crypto/paddings/ISO7816d4Padding.cs create mode 100644 crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs create mode 100644 crypto/src/crypto/paddings/Pkcs7Padding.cs create mode 100644 crypto/src/crypto/paddings/TbcPadding.cs create mode 100644 crypto/src/crypto/paddings/X923Padding.cs create mode 100644 crypto/src/crypto/paddings/ZeroBytePadding.cs create mode 100644 crypto/src/crypto/parameters/AEADParameters.cs create mode 100644 crypto/src/crypto/parameters/CcmParameters.cs create mode 100644 crypto/src/crypto/parameters/DHKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/DHKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DHParameters.cs create mode 100644 crypto/src/crypto/parameters/DHPrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DHPublicKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DHValidationParameters.cs create mode 100644 crypto/src/crypto/parameters/DSAParameterGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/DesEdeParameters.cs create mode 100644 crypto/src/crypto/parameters/DesParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaPrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaPublicKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/DsaValidationParameters.cs create mode 100644 crypto/src/crypto/parameters/ECDomainParameters.cs create mode 100644 crypto/src/crypto/parameters/ECKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/ECKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ECPrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ECPublicKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ElGamalKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/ElGamalKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ElGamalParameters.cs create mode 100644 crypto/src/crypto/parameters/ElGamalPrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ElGamalPublicKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410KeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410KeyParameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410Parameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410PrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410PublicKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/GOST3410ValidationParameters.cs create mode 100644 crypto/src/crypto/parameters/ISO18033KDFParameters.cs create mode 100644 crypto/src/crypto/parameters/IesParameters.cs create mode 100644 crypto/src/crypto/parameters/IesWithCipherParameters.cs create mode 100644 crypto/src/crypto/parameters/KdfParameters.cs create mode 100644 crypto/src/crypto/parameters/KeyParameter.cs create mode 100644 crypto/src/crypto/parameters/MgfParameters.cs create mode 100644 crypto/src/crypto/parameters/MqvPrivateParameters.cs create mode 100644 crypto/src/crypto/parameters/MqvPublicParameters.cs create mode 100644 crypto/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/NaccacheSternKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/ParametersWithIV.cs create mode 100644 crypto/src/crypto/parameters/ParametersWithRandom.cs create mode 100644 crypto/src/crypto/parameters/ParametersWithSBox.cs create mode 100644 crypto/src/crypto/parameters/ParametersWithSalt.cs create mode 100644 crypto/src/crypto/parameters/RC2Parameters.cs create mode 100644 crypto/src/crypto/parameters/RC5Parameters.cs create mode 100644 crypto/src/crypto/parameters/RSABlindingParameters.cs create mode 100644 crypto/src/crypto/parameters/RsaKeyGenerationParameters.cs create mode 100644 crypto/src/crypto/parameters/RsaKeyParameters.cs create mode 100644 crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs create mode 100644 crypto/src/crypto/prng/CryptoApiRandomGenerator.cs create mode 100644 crypto/src/crypto/prng/DigestRandomGenerator.cs create mode 100644 crypto/src/crypto/prng/IRandomGenerator.cs create mode 100644 crypto/src/crypto/prng/ReversedWindowGenerator.cs create mode 100644 crypto/src/crypto/prng/ThreadedSeedGenerator.cs create mode 100644 crypto/src/crypto/prng/VMPCRandomGenerator.cs create mode 100644 crypto/src/crypto/signers/DsaDigestSigner.cs create mode 100644 crypto/src/crypto/signers/DsaSigner.cs create mode 100644 crypto/src/crypto/signers/ECDsaSigner.cs create mode 100644 crypto/src/crypto/signers/ECGOST3410Signer.cs create mode 100644 crypto/src/crypto/signers/ECNRSigner.cs create mode 100644 crypto/src/crypto/signers/GOST3410DigestSigner.cs create mode 100644 crypto/src/crypto/signers/GOST3410Signer.cs create mode 100644 crypto/src/crypto/signers/GenericSigner.cs create mode 100644 crypto/src/crypto/signers/Iso9796d2PssSigner.cs create mode 100644 crypto/src/crypto/signers/Iso9796d2Signer.cs create mode 100644 crypto/src/crypto/signers/PssSigner.cs create mode 100644 crypto/src/crypto/signers/RsaDigestSigner.cs create mode 100644 crypto/src/crypto/tls/AlertDescription.cs create mode 100644 crypto/src/crypto/tls/AlertLevel.cs create mode 100644 crypto/src/crypto/tls/AlwaysValidVerifyer.cs create mode 100644 crypto/src/crypto/tls/ByteQueue.cs create mode 100644 crypto/src/crypto/tls/Certificate.cs create mode 100644 crypto/src/crypto/tls/CertificateRequest.cs create mode 100644 crypto/src/crypto/tls/CipherSuite.cs create mode 100644 crypto/src/crypto/tls/ClientCertificateType.cs create mode 100644 crypto/src/crypto/tls/CombinedHash.cs create mode 100644 crypto/src/crypto/tls/CompressionMethod.cs create mode 100644 crypto/src/crypto/tls/ContentType.cs create mode 100644 crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs create mode 100644 crypto/src/crypto/tls/DefaultTlsCipherFactory.cs create mode 100644 crypto/src/crypto/tls/DefaultTlsClient.cs create mode 100644 crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs create mode 100644 crypto/src/crypto/tls/DigestAlgorithm.cs create mode 100644 crypto/src/crypto/tls/ECCurveType.cs create mode 100644 crypto/src/crypto/tls/ECPointFormat.cs create mode 100644 crypto/src/crypto/tls/EncryptionAlgorithm.cs create mode 100644 crypto/src/crypto/tls/ExtensionType.cs create mode 100644 crypto/src/crypto/tls/HandshakeType.cs create mode 100644 crypto/src/crypto/tls/ICertificateVerifyer.cs create mode 100644 crypto/src/crypto/tls/KeyExchangeAlgorithm.cs create mode 100644 crypto/src/crypto/tls/LegacyTlsAuthentication.cs create mode 100644 crypto/src/crypto/tls/LegacyTlsClient.cs create mode 100644 crypto/src/crypto/tls/NamedCurve.cs create mode 100644 crypto/src/crypto/tls/PskTlsClient.cs create mode 100644 crypto/src/crypto/tls/RecordStream.cs create mode 100644 crypto/src/crypto/tls/SecurityParameters.cs create mode 100644 crypto/src/crypto/tls/SrpTlsClient.cs create mode 100644 crypto/src/crypto/tls/Ssl3Mac.cs create mode 100644 crypto/src/crypto/tls/TlsAgreementCredentials.cs create mode 100644 crypto/src/crypto/tls/TlsAuthentication.cs create mode 100644 crypto/src/crypto/tls/TlsBlockCipher.cs create mode 100644 crypto/src/crypto/tls/TlsCipher.cs create mode 100644 crypto/src/crypto/tls/TlsCipherFactory.cs create mode 100644 crypto/src/crypto/tls/TlsClient.cs create mode 100644 crypto/src/crypto/tls/TlsClientContext.cs create mode 100644 crypto/src/crypto/tls/TlsClientContextImpl.cs create mode 100644 crypto/src/crypto/tls/TlsCompression.cs create mode 100644 crypto/src/crypto/tls/TlsCredentials.cs create mode 100644 crypto/src/crypto/tls/TlsDHKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsDHUtilities.cs create mode 100644 crypto/src/crypto/tls/TlsDeflateCompression.cs create mode 100644 crypto/src/crypto/tls/TlsDheKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsDsaSigner.cs create mode 100644 crypto/src/crypto/tls/TlsDssSigner.cs create mode 100644 crypto/src/crypto/tls/TlsECDHKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsECDheKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsECDsaSigner.cs create mode 100644 crypto/src/crypto/tls/TlsException.cs create mode 100644 crypto/src/crypto/tls/TlsFatalAlert.cs create mode 100644 crypto/src/crypto/tls/TlsKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsMac.cs create mode 100644 crypto/src/crypto/tls/TlsNullCipher.cs create mode 100644 crypto/src/crypto/tls/TlsNullCompression.cs create mode 100644 crypto/src/crypto/tls/TlsProtocolHandler.cs create mode 100644 crypto/src/crypto/tls/TlsPskIdentity.cs create mode 100644 crypto/src/crypto/tls/TlsPskKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsRsaKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsRsaSigner.cs create mode 100644 crypto/src/crypto/tls/TlsRsaUtilities.cs create mode 100644 crypto/src/crypto/tls/TlsSigner.cs create mode 100644 crypto/src/crypto/tls/TlsSignerCredentials.cs create mode 100644 crypto/src/crypto/tls/TlsSrpKeyExchange.cs create mode 100644 crypto/src/crypto/tls/TlsStream.cs create mode 100644 crypto/src/crypto/tls/TlsStreamCipher.cs create mode 100644 crypto/src/crypto/tls/TlsUtilities.cs create mode 100644 crypto/src/crypto/util/Pack.cs create mode 100644 crypto/src/math/BigInteger.cs create mode 100644 crypto/src/math/ec/ECAlgorithms.cs create mode 100644 crypto/src/math/ec/ECCurve.cs create mode 100644 crypto/src/math/ec/ECFieldElement.cs create mode 100644 crypto/src/math/ec/ECPoint.cs create mode 100644 crypto/src/math/ec/IntArray.cs create mode 100644 crypto/src/math/ec/abc/SimpleBigDecimal.cs create mode 100644 crypto/src/math/ec/abc/Tnaf.cs create mode 100644 crypto/src/math/ec/abc/ZTauElement.cs create mode 100644 crypto/src/math/ec/multiplier/ECMultiplier.cs create mode 100644 crypto/src/math/ec/multiplier/FpNafMultiplier.cs create mode 100644 crypto/src/math/ec/multiplier/PreCompInfo.cs create mode 100644 crypto/src/math/ec/multiplier/ReferenceMultiplier.cs create mode 100644 crypto/src/math/ec/multiplier/WNafMultiplier.cs create mode 100644 crypto/src/math/ec/multiplier/WNafPreCompInfo.cs create mode 100644 crypto/src/math/ec/multiplier/WTauNafMultiplier.cs create mode 100644 crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs create mode 100644 crypto/src/ocsp/BasicOCSPResp.cs create mode 100644 crypto/src/ocsp/BasicOCSPRespGenerator.cs create mode 100644 crypto/src/ocsp/CertificateID.cs create mode 100644 crypto/src/ocsp/CertificateStatus.cs create mode 100644 crypto/src/ocsp/OCSPException.cs create mode 100644 crypto/src/ocsp/OCSPReq.cs create mode 100644 crypto/src/ocsp/OCSPReqGenerator.cs create mode 100644 crypto/src/ocsp/OCSPResp.cs create mode 100644 crypto/src/ocsp/OCSPRespGenerator.cs create mode 100644 crypto/src/ocsp/OCSPRespStatus.cs create mode 100644 crypto/src/ocsp/OCSPUtil.cs create mode 100644 crypto/src/ocsp/Req.cs create mode 100644 crypto/src/ocsp/RespData.cs create mode 100644 crypto/src/ocsp/RespID.cs create mode 100644 crypto/src/ocsp/RevokedStatus.cs create mode 100644 crypto/src/ocsp/SingleResp.cs create mode 100644 crypto/src/ocsp/UnknownStatus.cs create mode 100644 crypto/src/openpgp/IStreamGenerator.cs create mode 100644 crypto/src/openpgp/PGPKeyRing.cs create mode 100644 crypto/src/openpgp/PGPObject.cs create mode 100644 crypto/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs create mode 100644 crypto/src/openpgp/PgpCompressedData.cs create mode 100644 crypto/src/openpgp/PgpCompressedDataGenerator.cs create mode 100644 crypto/src/openpgp/PgpDataValidationException.cs create mode 100644 crypto/src/openpgp/PgpEncryptedData.cs create mode 100644 crypto/src/openpgp/PgpEncryptedDataGenerator.cs create mode 100644 crypto/src/openpgp/PgpEncryptedDataList.cs create mode 100644 crypto/src/openpgp/PgpException.cs create mode 100644 crypto/src/openpgp/PgpExperimental.cs create mode 100644 crypto/src/openpgp/PgpKeyFlags.cs create mode 100644 crypto/src/openpgp/PgpKeyPair.cs create mode 100644 crypto/src/openpgp/PgpKeyRingGenerator.cs create mode 100644 crypto/src/openpgp/PgpKeyValidationException.cs create mode 100644 crypto/src/openpgp/PgpLiteralData.cs create mode 100644 crypto/src/openpgp/PgpLiteralDataGenerator.cs create mode 100644 crypto/src/openpgp/PgpMarker.cs create mode 100644 crypto/src/openpgp/PgpObjectFactory.cs create mode 100644 crypto/src/openpgp/PgpOnePassSignature.cs create mode 100644 crypto/src/openpgp/PgpOnePassSignatureList.cs create mode 100644 crypto/src/openpgp/PgpPbeEncryptedData.cs create mode 100644 crypto/src/openpgp/PgpPrivateKey.cs create mode 100644 crypto/src/openpgp/PgpPublicKey.cs create mode 100644 crypto/src/openpgp/PgpPublicKeyEncryptedData.cs create mode 100644 crypto/src/openpgp/PgpPublicKeyRing.cs create mode 100644 crypto/src/openpgp/PgpPublicKeyRingBundle.cs create mode 100644 crypto/src/openpgp/PgpSecretKey.cs create mode 100644 crypto/src/openpgp/PgpSecretKeyRing.cs create mode 100644 crypto/src/openpgp/PgpSecretKeyRingBundle.cs create mode 100644 crypto/src/openpgp/PgpSignature.cs create mode 100644 crypto/src/openpgp/PgpSignatureGenerator.cs create mode 100644 crypto/src/openpgp/PgpSignatureList.cs create mode 100644 crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs create mode 100644 crypto/src/openpgp/PgpSignatureSubpacketVector.cs create mode 100644 crypto/src/openpgp/PgpUserAttributeSubpacketVector.cs create mode 100644 crypto/src/openpgp/PgpUtilities.cs create mode 100644 crypto/src/openpgp/PgpV3SignatureGenerator.cs create mode 100644 crypto/src/openpgp/WrappedGeneratorStream.cs create mode 100644 crypto/src/openssl/EncryptionException.cs create mode 100644 crypto/src/openssl/IPasswordFinder.cs create mode 100644 crypto/src/openssl/MiscPemGenerator.cs create mode 100644 crypto/src/openssl/PEMException.cs create mode 100644 crypto/src/openssl/PEMReader.cs create mode 100644 crypto/src/openssl/PEMUtilities.cs create mode 100644 crypto/src/openssl/PEMWriter.cs create mode 100644 crypto/src/openssl/PasswordException.cs create mode 100644 crypto/src/openssl/Pkcs8Generator.cs create mode 100644 crypto/src/pkcs/AsymmetricKeyEntry.cs create mode 100644 crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs create mode 100644 crypto/src/pkcs/PKCS12StoreBuilder.cs create mode 100644 crypto/src/pkcs/Pkcs10CertificationRequest.cs create mode 100644 crypto/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs create mode 100644 crypto/src/pkcs/Pkcs12Entry.cs create mode 100644 crypto/src/pkcs/Pkcs12Store.cs create mode 100644 crypto/src/pkcs/Pkcs12Utilities.cs create mode 100644 crypto/src/pkcs/PrivateKeyInfoFactory.cs create mode 100644 crypto/src/pkcs/X509CertificateEntry.cs create mode 100644 crypto/src/pkix/CertStatus.cs create mode 100644 crypto/src/pkix/PkixAttrCertChecker.cs create mode 100644 crypto/src/pkix/PkixAttrCertPathBuilder.cs create mode 100644 crypto/src/pkix/PkixAttrCertPathValidator.cs create mode 100644 crypto/src/pkix/PkixBuilderParameters.cs create mode 100644 crypto/src/pkix/PkixCertPath.cs create mode 100644 crypto/src/pkix/PkixCertPathBuilder.cs create mode 100644 crypto/src/pkix/PkixCertPathBuilderException.cs create mode 100644 crypto/src/pkix/PkixCertPathBuilderResult.cs create mode 100644 crypto/src/pkix/PkixCertPathChecker.cs create mode 100644 crypto/src/pkix/PkixCertPathValidator.cs create mode 100644 crypto/src/pkix/PkixCertPathValidatorException.cs create mode 100644 crypto/src/pkix/PkixCertPathValidatorResult.cs create mode 100644 crypto/src/pkix/PkixCertPathValidatorUtilities.cs create mode 100644 crypto/src/pkix/PkixCrlUtilities.cs create mode 100644 crypto/src/pkix/PkixNameConstraintValidator.cs create mode 100644 crypto/src/pkix/PkixNameConstraintValidatorException.cs create mode 100644 crypto/src/pkix/PkixParameters.cs create mode 100644 crypto/src/pkix/PkixPolicyNode.cs create mode 100644 crypto/src/pkix/ReasonsMask.cs create mode 100644 crypto/src/pkix/Rfc3280CertPathUtilities.cs create mode 100644 crypto/src/pkix/Rfc3281CertPathUtilities.cs create mode 100644 crypto/src/pkix/TrustAnchor.cs create mode 100644 crypto/src/security/AgreementUtilities.cs create mode 100644 crypto/src/security/CipherUtilities.cs create mode 100644 crypto/src/security/DigestUtilities.cs create mode 100644 crypto/src/security/DotNetUtilities.cs create mode 100644 crypto/src/security/GeneralSecurityException.cs create mode 100644 crypto/src/security/GeneratorUtilities.cs create mode 100644 crypto/src/security/InvalidKeyException.cs create mode 100644 crypto/src/security/InvalidParameterException.cs create mode 100644 crypto/src/security/KeyException.cs create mode 100644 crypto/src/security/MacUtilities.cs create mode 100644 crypto/src/security/NoSuchAlgorithmException.cs create mode 100644 crypto/src/security/ParameterUtilities.cs create mode 100644 crypto/src/security/PbeUtilities.cs create mode 100644 crypto/src/security/PrivateKeyFactory.cs create mode 100644 crypto/src/security/PublicKeyFactory.cs create mode 100644 crypto/src/security/SecureRandom.cs create mode 100644 crypto/src/security/SecurityUtilityException.cs create mode 100644 crypto/src/security/SignatureException.cs create mode 100644 crypto/src/security/SignerUtilities.cs create mode 100644 crypto/src/security/WrapperUtilities.cs create mode 100644 crypto/src/security/cert/CertificateEncodingException.cs create mode 100644 crypto/src/security/cert/CertificateException.cs create mode 100644 crypto/src/security/cert/CertificateExpiredException.cs create mode 100644 crypto/src/security/cert/CertificateNotYetValidException.cs create mode 100644 crypto/src/security/cert/CertificateParsingException.cs create mode 100644 crypto/src/security/cert/CrlException.cs create mode 100644 crypto/src/tsp/GenTimeAccuracy.cs create mode 100644 crypto/src/tsp/TSPAlgorithms.cs create mode 100644 crypto/src/tsp/TSPException.cs create mode 100644 crypto/src/tsp/TSPUtil.cs create mode 100644 crypto/src/tsp/TSPValidationException.cs create mode 100644 crypto/src/tsp/TimeStampRequest.cs create mode 100644 crypto/src/tsp/TimeStampRequestGenerator.cs create mode 100644 crypto/src/tsp/TimeStampResponse.cs create mode 100644 crypto/src/tsp/TimeStampResponseGenerator.cs create mode 100644 crypto/src/tsp/TimeStampToken.cs create mode 100644 crypto/src/tsp/TimeStampTokenGenerator.cs create mode 100644 crypto/src/tsp/TimeStampTokenInfo.cs create mode 100644 crypto/src/util/Arrays.cs create mode 100644 crypto/src/util/BigIntegers.cs create mode 100644 crypto/src/util/Enums.cs create mode 100644 crypto/src/util/Platform.cs create mode 100644 crypto/src/util/Strings.cs create mode 100644 crypto/src/util/collections/CollectionUtilities.cs create mode 100644 crypto/src/util/collections/EmptyEnumerable.cs create mode 100644 crypto/src/util/collections/EnumerableProxy.cs create mode 100644 crypto/src/util/collections/HashSet.cs create mode 100644 crypto/src/util/collections/ISet.cs create mode 100644 crypto/src/util/collections/LinkedDictionary.cs create mode 100644 crypto/src/util/collections/UnmodifiableDictionary.cs create mode 100644 crypto/src/util/collections/UnmodifiableDictionaryProxy.cs create mode 100644 crypto/src/util/collections/UnmodifiableList.cs create mode 100644 crypto/src/util/collections/UnmodifiableListProxy.cs create mode 100644 crypto/src/util/collections/UnmodifiableSet.cs create mode 100644 crypto/src/util/collections/UnmodifiableSetProxy.cs create mode 100644 crypto/src/util/date/DateTimeObject.cs create mode 100644 crypto/src/util/date/DateTimeUtilities.cs create mode 100644 crypto/src/util/encoders/Base64.cs create mode 100644 crypto/src/util/encoders/Base64Encoder.cs create mode 100644 crypto/src/util/encoders/BufferedDecoder.cs create mode 100644 crypto/src/util/encoders/BufferedEncoder.cs create mode 100644 crypto/src/util/encoders/Hex.cs create mode 100644 crypto/src/util/encoders/HexEncoder.cs create mode 100644 crypto/src/util/encoders/HexTranslator.cs create mode 100644 crypto/src/util/encoders/IEncoder.cs create mode 100644 crypto/src/util/encoders/Translator.cs create mode 100644 crypto/src/util/encoders/UrlBase64.cs create mode 100644 crypto/src/util/encoders/UrlBase64Encoder.cs create mode 100644 crypto/src/util/io/BaseInputStream.cs create mode 100644 crypto/src/util/io/BaseOutputStream.cs create mode 100644 crypto/src/util/io/PushbackStream.cs create mode 100644 crypto/src/util/io/StreamOverflowException.cs create mode 100644 crypto/src/util/io/Streams.cs create mode 100644 crypto/src/util/io/TeeInputStream.cs create mode 100644 crypto/src/util/io/TeeOutputStream.cs create mode 100644 crypto/src/util/io/pem/PemGenerationException.cs create mode 100644 crypto/src/util/io/pem/PemHeader.cs create mode 100644 crypto/src/util/io/pem/PemObject.cs create mode 100644 crypto/src/util/io/pem/PemObjectGenerator.cs create mode 100644 crypto/src/util/io/pem/PemObjectParser.cs create mode 100644 crypto/src/util/io/pem/PemReader.cs create mode 100644 crypto/src/util/io/pem/PemWriter.cs create mode 100644 crypto/src/util/net/IPAddress.cs create mode 100644 crypto/src/util/zlib/Adler32.cs create mode 100644 crypto/src/util/zlib/Deflate.cs create mode 100644 crypto/src/util/zlib/InfBlocks.cs create mode 100644 crypto/src/util/zlib/InfCodes.cs create mode 100644 crypto/src/util/zlib/InfTree.cs create mode 100644 crypto/src/util/zlib/Inflate.cs create mode 100644 crypto/src/util/zlib/JZlib.cs create mode 100644 crypto/src/util/zlib/StaticTree.cs create mode 100644 crypto/src/util/zlib/Tree.cs create mode 100644 crypto/src/util/zlib/ZDeflaterOutputStream.cs create mode 100644 crypto/src/util/zlib/ZInflaterInputStream.cs create mode 100644 crypto/src/util/zlib/ZInputStream.cs create mode 100644 crypto/src/util/zlib/ZOutputStream.cs create mode 100644 crypto/src/util/zlib/ZStream.cs create mode 100644 crypto/src/x509/AttributeCertificateHolder.cs create mode 100644 crypto/src/x509/AttributeCertificateIssuer.cs create mode 100644 crypto/src/x509/IX509AttributeCertificate.cs create mode 100644 crypto/src/x509/IX509Extension.cs create mode 100644 crypto/src/x509/PEMParser.cs create mode 100644 crypto/src/x509/PrincipalUtil.cs create mode 100644 crypto/src/x509/SubjectPublicKeyInfoFactory.cs create mode 100644 crypto/src/x509/X509AttrCertParser.cs create mode 100644 crypto/src/x509/X509Attribute.cs create mode 100644 crypto/src/x509/X509CertPairParser.cs create mode 100644 crypto/src/x509/X509Certificate.cs create mode 100644 crypto/src/x509/X509CertificatePair.cs create mode 100644 crypto/src/x509/X509CertificateParser.cs create mode 100644 crypto/src/x509/X509Crl.cs create mode 100644 crypto/src/x509/X509CrlEntry.cs create mode 100644 crypto/src/x509/X509CrlParser.cs create mode 100644 crypto/src/x509/X509ExtensionBase.cs create mode 100644 crypto/src/x509/X509KeyUsage.cs create mode 100644 crypto/src/x509/X509SignatureUtil.cs create mode 100644 crypto/src/x509/X509Utilities.cs create mode 100644 crypto/src/x509/X509V1CertificateGenerator.cs create mode 100644 crypto/src/x509/X509V2AttributeCertificate.cs create mode 100644 crypto/src/x509/X509V2AttributeCertificateGenerator.cs create mode 100644 crypto/src/x509/X509V2CRLGenerator.cs create mode 100644 crypto/src/x509/X509V3CertificateGenerator.cs create mode 100644 crypto/src/x509/extension/AuthorityKeyIdentifierStructure.cs create mode 100644 crypto/src/x509/extension/SubjectKeyIdentifierStructure.cs create mode 100644 crypto/src/x509/extension/X509ExtensionUtil.cs create mode 100644 crypto/src/x509/store/IX509Selector.cs create mode 100644 crypto/src/x509/store/IX509Store.cs create mode 100644 crypto/src/x509/store/IX509StoreParameters.cs create mode 100644 crypto/src/x509/store/NoSuchStoreException.cs create mode 100644 crypto/src/x509/store/X509AttrCertStoreSelector.cs create mode 100644 crypto/src/x509/store/X509CertPairStoreSelector.cs create mode 100644 crypto/src/x509/store/X509CertStoreSelector.cs create mode 100644 crypto/src/x509/store/X509CollectionStore.cs create mode 100644 crypto/src/x509/store/X509CollectionStoreParameters.cs create mode 100644 crypto/src/x509/store/X509CrlStoreSelector.cs create mode 100644 crypto/src/x509/store/X509StoreException.cs create mode 100644 crypto/src/x509/store/X509StoreFactory.cs create mode 100644 crypto/test/data/PKITS/README.txt create mode 100644 crypto/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/AnyPolicyTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BadCRLSignatureCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BadSignedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BadnotAfterDateCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BadnotBeforeDateCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt create mode 100644 crypto/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt create mode 100644 crypto/test/data/PKITS/certs/DSACACert.crt create mode 100644 crypto/test/data/PKITS/certs/DSAParametersInheritedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt create mode 100644 crypto/test/data/PKITS/certs/GoodCACert.crt create mode 100644 crypto/test/data/PKITS/certs/GoodsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/LongSerialNumberCACert.crt create mode 100644 crypto/test/data/PKITS/certs/Mapping1to2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/MappingToanyPolicyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt create mode 100644 crypto/test/data/PKITS/certs/NameOrderingCACert.crt create mode 100644 crypto/test/data/PKITS/certs/NegativeSerialNumberCACert.crt create mode 100644 crypto/test/data/PKITS/certs/NoCRLCACert.crt create mode 100644 crypto/test/data/PKITS/certs/NoPoliciesCACert.crt create mode 100644 crypto/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt create mode 100644 crypto/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt create mode 100644 crypto/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/P12Mapping1to3CACert.crt create mode 100644 crypto/test/data/PKITS/certs/P12Mapping1to3subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/P1Mapping1to234CACert.crt create mode 100644 crypto/test/data/PKITS/certs/P1Mapping1to234subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP1234CACert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP123CACert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP12CACert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP2subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/PoliciesP3CACert.crt create mode 100644 crypto/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt create mode 100644 crypto/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt create mode 100644 crypto/test/data/PKITS/certs/RevokedsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt create mode 100644 crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt create mode 100644 crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt create mode 100644 crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt create mode 100644 crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt create mode 100644 crypto/test/data/PKITS/certs/TrustAnchorRootCertificate.crt create mode 100644 crypto/test/data/PKITS/certs/TwoCRLsCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UIDCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt create mode 100644 crypto/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt create mode 100644 crypto/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt create mode 100644 crypto/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt create mode 100644 crypto/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt create mode 100644 crypto/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt create mode 100644 crypto/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt create mode 100644 crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt create mode 100644 crypto/test/data/PKITS/certs/WrongCRLCACert.crt create mode 100644 crypto/test/data/PKITS/certs/anyPolicyCACert.crt create mode 100644 crypto/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt create mode 100644 crypto/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/deltaCRLCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/deltaCRLCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/deltaCRLCA3Cert.crt create mode 100644 crypto/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/distributionPoint1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/distributionPoint2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA3Cert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA4Cert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA5Cert.crt create mode 100644 crypto/test/data/PKITS/certs/indirectCRLCA6Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt create mode 100644 crypto/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN3CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN4CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDN5CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsURI1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/nameConstraintsURI2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt create mode 100644 crypto/test/data/PKITS/certs/onlyContainsCACertsCACert.crt create mode 100644 crypto/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt create mode 100644 crypto/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt create mode 100644 crypto/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint0CACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint0subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint1CACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint1subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6CACert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt create mode 100644 crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt create mode 100644 crypto/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt create mode 100644 crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt create mode 100644 crypto/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BadCRLSignatureCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BadSignedCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BadnotAfterDateCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl create mode 100644 crypto/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl create mode 100644 crypto/test/data/PKITS/crls/DSACACRL.crl create mode 100644 crypto/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/GoodCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/GoodsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/LongSerialNumberCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/Mapping1to2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/NameOrderCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/NoPoliciesCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P12Mapping1to3CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P1Mapping1to234CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP1234CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP123CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP12CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP2subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/PoliciesP3CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/RevokedsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl create mode 100644 crypto/test/data/PKITS/crls/TrustAnchorRootCRL.crl create mode 100644 crypto/test/data/PKITS/crls/TwoCRLsCABadCRL.crl create mode 100644 crypto/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl create mode 100644 crypto/test/data/PKITS/crls/UIDCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/WrongCRLCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/anyPolicyCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA3CRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl create mode 100644 crypto/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/distributionPoint1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/distributionPoint2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/indirectCRLCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/indirectCRLCA3CRL.crl create mode 100644 crypto/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl create mode 100644 crypto/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl create mode 100644 crypto/test/data/PKITS/crls/indirectCRLCA5CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl create mode 100644 crypto/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint0CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint1CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl create mode 100644 crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl create mode 100644 crypto/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl create mode 100644 crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl create mode 100644 crypto/test/data/asn1/masterlist-content.data create mode 100644 crypto/test/data/cms/sigs/PSSSignData.data create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA1.sig create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA1Enc.sig create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA256.sig create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA256Enc.sig create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA512.sig create mode 100644 crypto/test/data/cms/sigs/PSSSignDataSHA512Enc.sig create mode 100644 crypto/test/data/cms/sigs/counterSig.p7m create mode 100644 crypto/test/data/hc256/hc128/ecrypt_HC-128.txt create mode 100644 crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt create mode 100644 crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt create mode 100644 crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt create mode 100644 crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt create mode 100644 crypto/test/data/keys/README.txt create mode 100644 crypto/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key create mode 100644 crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-cfb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-cfb1.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-cfb8.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-ecb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-128-ofb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-cfb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-cfb1.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-cfb8.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-ecb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-192-ofb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-cfb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-cfb1.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-cfb8.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-ecb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes-256-ofb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes128.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes192.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.aes256.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.bf-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.bf.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.blowfish.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.cast-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.cast.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.cast5-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-cfb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-cfb1.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-cfb8.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-ecb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-ede.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-ede3-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des-ofb.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.des3.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.rc2-40-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.rc2-64-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.rc2-cbc.key create mode 100644 crypto/test/data/keys/pbes2/pbes2.rc2.key create mode 100644 crypto/test/data/openpgp/dsa/README.txt create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-1024-160.pub create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-1024-160.sec create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-15360-512.pub create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-15360-512.sec create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-2048-224.pub create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-2048-224.sec create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-3072-256.pub create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-3072-256.sec create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-7680-384.pub create mode 100644 crypto/test/data/openpgp/dsa/keys/DSA-7680-384.sec create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg create mode 100644 crypto/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg create mode 100644 crypto/test/data/openssl/README.txt create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem create mode 100644 crypto/test/data/openssl/dsa/openssl_dsa_unencrypted.pem create mode 100644 crypto/test/data/openssl/eckey.pem create mode 100644 crypto/test/data/openssl/enckey.pem create mode 100644 crypto/test/data/openssl/pkcs7.pem create mode 100644 crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem create mode 100644 crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem create mode 100644 crypto/test/data/openssl/pkcs8test.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem create mode 100644 crypto/test/data/openssl/rsa/openssl_rsa_unencrypted.pem create mode 100644 crypto/test/data/openssl/test.pem create mode 100644 crypto/test/data/rfc4134/3.1.bin create mode 100644 crypto/test/data/rfc4134/3.2.bin create mode 100644 crypto/test/data/rfc4134/4.1.bin create mode 100644 crypto/test/data/rfc4134/4.10.bin create mode 100644 crypto/test/data/rfc4134/4.11.bin create mode 100644 crypto/test/data/rfc4134/4.2.bin create mode 100644 crypto/test/data/rfc4134/4.3.bin create mode 100644 crypto/test/data/rfc4134/4.4.bin create mode 100644 crypto/test/data/rfc4134/4.5.bin create mode 100644 crypto/test/data/rfc4134/4.6.bin create mode 100644 crypto/test/data/rfc4134/4.7.bin create mode 100644 crypto/test/data/rfc4134/4.8.eml create mode 100644 crypto/test/data/rfc4134/4.9.eml create mode 100644 crypto/test/data/rfc4134/5.1.bin create mode 100644 crypto/test/data/rfc4134/5.2.bin create mode 100644 crypto/test/data/rfc4134/5.3.eml create mode 100644 crypto/test/data/rfc4134/6.0.bin create mode 100644 crypto/test/data/rfc4134/7.1.bin create mode 100644 crypto/test/data/rfc4134/7.2.bin create mode 100644 crypto/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer create mode 100644 crypto/test/data/rfc4134/AlicePrivDSSSign.pri create mode 100644 crypto/test/data/rfc4134/AlicePrivRSASign.pri create mode 100644 crypto/test/data/rfc4134/AliceRSASignByCarl.cer create mode 100644 crypto/test/data/rfc4134/BobPrivRSAEncrypt.pri create mode 100644 crypto/test/data/rfc4134/BobRSASignByCarl.cer create mode 100644 crypto/test/data/rfc4134/CarlDSSCRLEmpty.crl create mode 100644 crypto/test/data/rfc4134/CarlDSSCRLForAll.crl create mode 100644 crypto/test/data/rfc4134/CarlDSSCRLForCarl.crl create mode 100644 crypto/test/data/rfc4134/CarlDSSSelf.cer create mode 100644 crypto/test/data/rfc4134/CarlPrivDSSSign.pri create mode 100644 crypto/test/data/rfc4134/CarlPrivRSASign.pri create mode 100644 crypto/test/data/rfc4134/CarlRSACRLEmpty.crl create mode 100644 crypto/test/data/rfc4134/CarlRSACRLForAll.crl create mode 100644 crypto/test/data/rfc4134/CarlRSACRLForCarl.crl create mode 100644 crypto/test/data/rfc4134/CarlRSASelf.cer create mode 100644 crypto/test/data/rfc4134/DianeDSSSignByCarlInherit.cer create mode 100644 crypto/test/data/rfc4134/DianePrivDSSSign.pri create mode 100644 crypto/test/data/rfc4134/DianePrivRSASignEncrypt.pri create mode 100644 crypto/test/data/rfc4134/DianeRSASignByCarl.cer create mode 100644 crypto/test/data/rfc4134/ExContent.bin create mode 100644 crypto/test/data/rfc4134/rfc4134.txt create mode 100644 crypto/test/data/rsa3/self-testcase-A.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-A.pem create mode 100644 crypto/test/data/rsa3/self-testcase-B.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-B.pem create mode 100644 crypto/test/data/rsa3/self-testcase-C.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-C.pem create mode 100644 crypto/test/data/rsa3/self-testcase-D.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-D.pem create mode 100644 crypto/test/data/rsa3/self-testcase-E.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-E.pem create mode 100644 crypto/test/data/rsa3/self-testcase-F.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-F.pem create mode 100644 crypto/test/data/rsa3/self-testcase-G.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-G.pem create mode 100644 crypto/test/data/rsa3/self-testcase-H.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-H.pem create mode 100644 crypto/test/data/rsa3/self-testcase-I.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-I.pem create mode 100644 crypto/test/data/rsa3/self-testcase-J.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-J.pem create mode 100644 crypto/test/data/rsa3/self-testcase-L.p12 create mode 100644 crypto/test/data/rsa3/self-testcase-L.pem create mode 100644 crypto/test/data/rsa3/testcases.README create mode 100644 crypto/test/data/scrypt/TestVectors.txt create mode 100644 crypto/test/data/tls/keystores/client_store.dsa create mode 100644 crypto/test/data/tls/keystores/client_store.rsa create mode 100644 crypto/test/data/tls/keystores/server_store.dsa create mode 100644 crypto/test/data/tls/keystores/server_store.rsa create mode 100644 crypto/test/lib/nunit.core.dll create mode 100644 crypto/test/lib/nunit.core.interfaces.dll create mode 100644 crypto/test/lib/nunit.framework.dll create mode 100644 crypto/test/src/asn1/test/ASN1SequenceParserTest.cs create mode 100644 crypto/test/src/asn1/test/ASN1UnitTest.cs create mode 100644 crypto/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs create mode 100644 crypto/test/src/asn1/test/AdmissionSyntaxUnitTest.cs create mode 100644 crypto/test/src/asn1/test/AdmissionsUnitTest.cs create mode 100644 crypto/test/src/asn1/test/AllTests.cs create mode 100644 crypto/test/src/asn1/test/AttributeTableUnitTest.cs create mode 100644 crypto/test/src/asn1/test/BiometricDataUnitTest.cs create mode 100644 crypto/test/src/asn1/test/BitStringConstantTester.cs create mode 100644 crypto/test/src/asn1/test/BitStringTest.cs create mode 100644 crypto/test/src/asn1/test/CMSTest.cs create mode 100644 crypto/test/src/asn1/test/CertHashUnitTest.cs create mode 100644 crypto/test/src/asn1/test/CertificateTest.cs create mode 100644 crypto/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs create mode 100644 crypto/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs create mode 100644 crypto/test/src/asn1/test/ContentHintsUnitTest.cs create mode 100644 crypto/test/src/asn1/test/CscaMasterListTest.cs create mode 100644 crypto/test/src/asn1/test/DERApplicationSpecificTest.cs create mode 100644 crypto/test/src/asn1/test/DERUTF8StringTest.cs create mode 100644 crypto/test/src/asn1/test/DataGroupHashUnitTest.cs create mode 100644 crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs create mode 100644 crypto/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs create mode 100644 crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs create mode 100644 crypto/test/src/asn1/test/EssCertIDv2UnitTest.cs create mode 100644 crypto/test/src/asn1/test/GeneralNameTest.cs create mode 100644 crypto/test/src/asn1/test/GeneralizedTimeTest.cs create mode 100644 crypto/test/src/asn1/test/GenerationTest.cs create mode 100644 crypto/test/src/asn1/test/InputStreamTest.cs create mode 100644 crypto/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs create mode 100644 crypto/test/src/asn1/test/IssuingDistributionPointTest.cs create mode 100644 crypto/test/src/asn1/test/KeyUsageTest.cs create mode 100644 crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs create mode 100644 crypto/test/src/asn1/test/MiscTest.cs create mode 100644 crypto/test/src/asn1/test/MonetaryLimitUnitTest.cs create mode 100644 crypto/test/src/asn1/test/MonetaryValueUnitTest.cs create mode 100644 crypto/test/src/asn1/test/NameOrPseudonymUnitTest.cs create mode 100644 crypto/test/src/asn1/test/NamingAuthorityUnitTest.cs create mode 100644 crypto/test/src/asn1/test/NetscapeCertTypeTest.cs create mode 100644 crypto/test/src/asn1/test/OCSPTest.cs create mode 100644 crypto/test/src/asn1/test/OIDTest.cs create mode 100644 crypto/test/src/asn1/test/OctetStringTest.cs create mode 100644 crypto/test/src/asn1/test/OtherCertIDUnitTest.cs create mode 100644 crypto/test/src/asn1/test/OtherSigningCertificateUnitTest.cs create mode 100644 crypto/test/src/asn1/test/PKCS10Test.cs create mode 100644 crypto/test/src/asn1/test/PKCS12Test.cs create mode 100644 crypto/test/src/asn1/test/PKIFailureInfoTest.cs create mode 100644 crypto/test/src/asn1/test/ParseTest.cs create mode 100644 crypto/test/src/asn1/test/ParsingTest.cs create mode 100644 crypto/test/src/asn1/test/PersonalDataUnitTest.cs create mode 100644 crypto/test/src/asn1/test/ProcurationSyntaxUnitTest.cs create mode 100644 crypto/test/src/asn1/test/ProfessionInfoUnitTest.cs create mode 100644 crypto/test/src/asn1/test/QCStatementUnitTest.cs create mode 100644 crypto/test/src/asn1/test/ReasonFlagsTest.cs create mode 100644 crypto/test/src/asn1/test/RegressionTest.cs create mode 100644 crypto/test/src/asn1/test/RequestedCertificateUnitTest.cs create mode 100644 crypto/test/src/asn1/test/RestrictionUnitTest.cs create mode 100644 crypto/test/src/asn1/test/SMIMETest.cs create mode 100644 crypto/test/src/asn1/test/SemanticsInformationUnitTest.cs create mode 100644 crypto/test/src/asn1/test/SetTest.cs create mode 100644 crypto/test/src/asn1/test/SignerLocationUnitTest.cs create mode 100644 crypto/test/src/asn1/test/StringTest.cs create mode 100644 crypto/test/src/asn1/test/SubjectKeyIdentifierTest.cs create mode 100644 crypto/test/src/asn1/test/TagTest.cs create mode 100644 crypto/test/src/asn1/test/TargetInformationTest.cs create mode 100644 crypto/test/src/asn1/test/TimeTest.cs create mode 100644 crypto/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs create mode 100644 crypto/test/src/asn1/test/UTCTimeTest.cs create mode 100644 crypto/test/src/asn1/test/X509ExtensionsTest.cs create mode 100644 crypto/test/src/asn1/test/X509NameTest.cs create mode 100644 crypto/test/src/asn1/test/X9Test.cs create mode 100644 crypto/test/src/cms/test/AllTests.cs create mode 100644 crypto/test/src/cms/test/AuthenticatedDataStreamTest.cs create mode 100644 crypto/test/src/cms/test/AuthenticatedDataTest.cs create mode 100644 crypto/test/src/cms/test/CMSSampleMessages.cs create mode 100644 crypto/test/src/cms/test/CMSTestUtil.cs create mode 100644 crypto/test/src/cms/test/CompressedDataStreamTest.cs create mode 100644 crypto/test/src/cms/test/CompressedDataTest.cs create mode 100644 crypto/test/src/cms/test/EnvelopedDataStreamTest.cs create mode 100644 crypto/test/src/cms/test/EnvelopedDataTest.cs create mode 100644 crypto/test/src/cms/test/MiscDataStreamTest.cs create mode 100644 crypto/test/src/cms/test/Rfc4134Test.cs create mode 100644 crypto/test/src/cms/test/SignedDataStreamTest.cs create mode 100644 crypto/test/src/cms/test/SignedDataTest.cs create mode 100644 crypto/test/src/crypto/examples/DESExample.cs create mode 100644 crypto/test/src/crypto/io/test/AllTests.cs create mode 100644 crypto/test/src/crypto/io/test/CipherStreamTest.cs create mode 100644 crypto/test/src/crypto/test/AESFastTest.cs create mode 100644 crypto/test/src/crypto/test/AESLightTest.cs create mode 100644 crypto/test/src/crypto/test/AESTest.cs create mode 100644 crypto/test/src/crypto/test/AESWrapTest.cs create mode 100644 crypto/test/src/crypto/test/AllTests.cs create mode 100644 crypto/test/src/crypto/test/BlockCipherMonteCarloTest.cs create mode 100644 crypto/test/src/crypto/test/BlockCipherVectorTest.cs create mode 100644 crypto/test/src/crypto/test/BlowfishTest.cs create mode 100644 crypto/test/src/crypto/test/CAST6Test.cs create mode 100644 crypto/test/src/crypto/test/CCMTest.cs create mode 100644 crypto/test/src/crypto/test/CMacTest.cs create mode 100644 crypto/test/src/crypto/test/CTSTest.cs create mode 100644 crypto/test/src/crypto/test/CamelliaLightTest.cs create mode 100644 crypto/test/src/crypto/test/CamelliaTest.cs create mode 100644 crypto/test/src/crypto/test/Cast5Test.cs create mode 100644 crypto/test/src/crypto/test/CipherTest.cs create mode 100644 crypto/test/src/crypto/test/DESTest.cs create mode 100644 crypto/test/src/crypto/test/DESedeTest.cs create mode 100644 crypto/test/src/crypto/test/DHKEKGeneratorTest.cs create mode 100644 crypto/test/src/crypto/test/DHTest.cs create mode 100644 crypto/test/src/crypto/test/DSATest.cs create mode 100644 crypto/test/src/crypto/test/DigestRandomNumberTest.cs create mode 100644 crypto/test/src/crypto/test/DigestTest.cs create mode 100644 crypto/test/src/crypto/test/EAXTest.cs create mode 100644 crypto/test/src/crypto/test/ECDHKEKGeneratorTest.cs create mode 100644 crypto/test/src/crypto/test/ECGOST3410Test.cs create mode 100644 crypto/test/src/crypto/test/ECIESTest.cs create mode 100644 crypto/test/src/crypto/test/ECNRTest.cs create mode 100644 crypto/test/src/crypto/test/ECTest.cs create mode 100644 crypto/test/src/crypto/test/ElGamalTest.cs create mode 100644 crypto/test/src/crypto/test/EqualsHashCodeTest.cs create mode 100644 crypto/test/src/crypto/test/GCMTest.cs create mode 100644 crypto/test/src/crypto/test/GOST28147MacTest.cs create mode 100644 crypto/test/src/crypto/test/GOST28147Test.cs create mode 100644 crypto/test/src/crypto/test/GOST3410Test.cs create mode 100644 crypto/test/src/crypto/test/GOST3411DigestTest.cs create mode 100644 crypto/test/src/crypto/test/GcmReorderTest.cs create mode 100644 crypto/test/src/crypto/test/HCFamilyTest.cs create mode 100644 crypto/test/src/crypto/test/HCFamilyVecTest.cs create mode 100644 crypto/test/src/crypto/test/IDEATest.cs create mode 100644 crypto/test/src/crypto/test/ISAACTest.cs create mode 100644 crypto/test/src/crypto/test/ISO9796Test.cs create mode 100644 crypto/test/src/crypto/test/ISO9797Alg3MacTest.cs create mode 100644 crypto/test/src/crypto/test/KDF1GeneratorTest.cs create mode 100644 crypto/test/src/crypto/test/KDF2GeneratorTest.cs create mode 100644 crypto/test/src/crypto/test/MD2DigestTest.cs create mode 100644 crypto/test/src/crypto/test/MD4DigestTest.cs create mode 100644 crypto/test/src/crypto/test/MD5DigestTest.cs create mode 100644 crypto/test/src/crypto/test/MD5HMacTest.cs create mode 100644 crypto/test/src/crypto/test/MGF1GeneratorTest.cs create mode 100644 crypto/test/src/crypto/test/MacTest.cs create mode 100644 crypto/test/src/crypto/test/ModeTest.cs create mode 100644 crypto/test/src/crypto/test/NaccacheSternTest.cs create mode 100644 crypto/test/src/crypto/test/NoekeonTest.cs create mode 100644 crypto/test/src/crypto/test/NullTest.cs create mode 100644 crypto/test/src/crypto/test/OAEPTest.cs create mode 100644 crypto/test/src/crypto/test/OCBTest.cs create mode 100644 crypto/test/src/crypto/test/PSSBlindTest.cs create mode 100644 crypto/test/src/crypto/test/PSSTest.cs create mode 100644 crypto/test/src/crypto/test/PaddingTest.cs create mode 100644 crypto/test/src/crypto/test/Pkcs12Test.cs create mode 100644 crypto/test/src/crypto/test/Pkcs5Test.cs create mode 100644 crypto/test/src/crypto/test/RC2Test.cs create mode 100644 crypto/test/src/crypto/test/RC2WrapTest.cs create mode 100644 crypto/test/src/crypto/test/RC4Test.cs create mode 100644 crypto/test/src/crypto/test/RC5Test.cs create mode 100644 crypto/test/src/crypto/test/RC6Test.cs create mode 100644 crypto/test/src/crypto/test/RFC3211WrapTest.cs create mode 100644 crypto/test/src/crypto/test/RSABlindedTest.cs create mode 100644 crypto/test/src/crypto/test/RegressionTest.cs create mode 100644 crypto/test/src/crypto/test/RijndaelTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD128DigestTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD128HMacTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD160DigestTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD160HMacTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD256DigestTest.cs create mode 100644 crypto/test/src/crypto/test/RipeMD320DigestTest.cs create mode 100644 crypto/test/src/crypto/test/RsaTest.cs create mode 100644 crypto/test/src/crypto/test/SCryptTest.cs create mode 100644 crypto/test/src/crypto/test/SEEDTest.cs create mode 100644 crypto/test/src/crypto/test/SHA1DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA1HMacTest.cs create mode 100644 crypto/test/src/crypto/test/SHA224DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA224HMacTest.cs create mode 100644 crypto/test/src/crypto/test/SHA256DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA256HMacTest.cs create mode 100644 crypto/test/src/crypto/test/SHA384DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA384HMacTest.cs create mode 100644 crypto/test/src/crypto/test/SHA3DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA512DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA512HMacTest.cs create mode 100644 crypto/test/src/crypto/test/SHA512t224DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SHA512t256DigestTest.cs create mode 100644 crypto/test/src/crypto/test/SRP6Test.cs create mode 100644 crypto/test/src/crypto/test/Salsa20Test.cs create mode 100644 crypto/test/src/crypto/test/SerpentTest.cs create mode 100644 crypto/test/src/crypto/test/ShortenedDigestTest.cs create mode 100644 crypto/test/src/crypto/test/SipHashTest.cs create mode 100644 crypto/test/src/crypto/test/SkipjackTest.cs create mode 100644 crypto/test/src/crypto/test/StreamCipherVectorTest.cs create mode 100644 crypto/test/src/crypto/test/TEATest.cs create mode 100644 crypto/test/src/crypto/test/TigerDigestTest.cs create mode 100644 crypto/test/src/crypto/test/TwofishTest.cs create mode 100644 crypto/test/src/crypto/test/VMPCKSA3Test.cs create mode 100644 crypto/test/src/crypto/test/VMPCMacTest.cs create mode 100644 crypto/test/src/crypto/test/VMPCTest.cs create mode 100644 crypto/test/src/crypto/test/WhirlpoolDigestTest.cs create mode 100644 crypto/test/src/crypto/test/XTEATest.cs create mode 100644 crypto/test/src/math/ec/test/AllTests.cs create mode 100644 crypto/test/src/math/ec/test/ECPointPerformanceTest.cs create mode 100644 crypto/test/src/math/ec/test/ECPointTest.cs create mode 100644 crypto/test/src/math/ec/test/F2mProofer.cs create mode 100644 crypto/test/src/math/ec/test/TnafTest.cs create mode 100644 crypto/test/src/math/test/AllTests.cs create mode 100644 crypto/test/src/math/test/BigIntegerTest.cs create mode 100644 crypto/test/src/ocsp/test/AllTests.cs create mode 100644 crypto/test/src/ocsp/test/OCSPTest.cs create mode 100644 crypto/test/src/ocsp/test/OCSPTestUtil.cs create mode 100644 crypto/test/src/openpgp/examples/ByteArrayHandler.cs create mode 100644 crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/DetachedSignatureProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/DirectKeySignature.cs create mode 100644 crypto/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs create mode 100644 crypto/test/src/openpgp/examples/KeyBasedFileProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/PbeFileProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/PgpExampleUtilities.cs create mode 100644 crypto/test/src/openpgp/examples/PublicKeyRingDump.cs create mode 100644 crypto/test/src/openpgp/examples/RsaKeyRingGenerator.cs create mode 100644 crypto/test/src/openpgp/examples/SignedFileProcessor.cs create mode 100644 crypto/test/src/openpgp/examples/test/AllTests.cs create mode 100644 crypto/test/src/openpgp/test/DSA2Test.cs create mode 100644 crypto/test/src/openpgp/test/PGPArmoredTest.cs create mode 100644 crypto/test/src/openpgp/test/PGPClearSignedSignatureTest.cs create mode 100644 crypto/test/src/openpgp/test/PGPCompressionTest.cs create mode 100644 crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs create mode 100644 crypto/test/src/openpgp/test/PGPDSATest.cs create mode 100644 crypto/test/src/openpgp/test/PGPPBETest.cs create mode 100644 crypto/test/src/openpgp/test/PGPPacketTest.cs create mode 100644 crypto/test/src/openpgp/test/PGPRSATest.cs create mode 100644 crypto/test/src/openpgp/test/PGPSignatureTest.cs create mode 100644 crypto/test/src/openpgp/test/PgpKeyRingTest.cs create mode 100644 crypto/test/src/openpgp/test/PgpMarkerTest.cs create mode 100644 crypto/test/src/openpgp/test/RegressionTest.cs create mode 100644 crypto/test/src/openssl/test/AllTests.cs create mode 100644 crypto/test/src/openssl/test/ReaderTest.cs create mode 100644 crypto/test/src/openssl/test/WriterTest.cs create mode 100644 crypto/test/src/pkcs/examples/PKCS12Example.cs create mode 100644 crypto/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs create mode 100644 crypto/test/src/pkcs/test/PKCS10Test.cs create mode 100644 crypto/test/src/pkcs/test/PKCS12StoreTest.cs create mode 100644 crypto/test/src/security/test/SecureRandomTest.cs create mode 100644 crypto/test/src/security/test/TestDigestUtil.cs create mode 100644 crypto/test/src/security/test/TestDotNetUtil.cs create mode 100644 crypto/test/src/security/test/TestEncodings.cs create mode 100644 crypto/test/src/security/test/TestParameterUtil.cs create mode 100644 crypto/test/src/security/test/TestSignerUtil.cs create mode 100644 crypto/test/src/test/AESSICTest.cs create mode 100644 crypto/test/src/test/AESTest.cs create mode 100644 crypto/test/src/test/AttrCertSelectorTest.cs create mode 100644 crypto/test/src/test/AttrCertTest.cs create mode 100644 crypto/test/src/test/BaseBlockCipherTest.cs create mode 100644 crypto/test/src/test/BlockCipherTest.cs create mode 100644 crypto/test/src/test/CMacTest.cs create mode 100644 crypto/test/src/test/CRL5Test.cs create mode 100644 crypto/test/src/test/CamelliaTest.cs create mode 100644 crypto/test/src/test/CertPathBuilderTest.cs create mode 100644 crypto/test/src/test/CertPathTest.cs create mode 100644 crypto/test/src/test/CertPathValidatorTest.cs create mode 100644 crypto/test/src/test/CertTest.cs create mode 100644 crypto/test/src/test/CipherStreamTest.cs create mode 100644 crypto/test/src/test/DESedeTest.cs create mode 100644 crypto/test/src/test/DHTest.cs create mode 100644 crypto/test/src/test/DSATest.cs create mode 100644 crypto/test/src/test/DigestTest.cs create mode 100644 crypto/test/src/test/ECDSA5Test.cs create mode 100644 crypto/test/src/test/ECEncodingTest.cs create mode 100644 crypto/test/src/test/ECNRTest.cs create mode 100644 crypto/test/src/test/ElGamalTest.cs create mode 100644 crypto/test/src/test/EncryptedPrivateKeyInfoTest.cs create mode 100644 crypto/test/src/test/FIPSDESTest.cs create mode 100644 crypto/test/src/test/GOST28147Test.cs create mode 100644 crypto/test/src/test/GOST3410Test.cs create mode 100644 crypto/test/src/test/HMacTest.cs create mode 100644 crypto/test/src/test/IESTest.cs create mode 100644 crypto/test/src/test/MacTest.cs create mode 100644 crypto/test/src/test/MqvTest.cs create mode 100644 crypto/test/src/test/NamedCurveTest.cs create mode 100644 crypto/test/src/test/NistCertPathTest.cs create mode 100644 crypto/test/src/test/NoekeonTest.cs create mode 100644 crypto/test/src/test/PBETest.cs create mode 100644 crypto/test/src/test/PEMData.cs create mode 100644 crypto/test/src/test/PKCS10CertRequestTest.cs create mode 100644 crypto/test/src/test/PSSTest.cs create mode 100644 crypto/test/src/test/PkixNameConstraintsTest.cs create mode 100644 crypto/test/src/test/PkixPolicyMappingTest.cs create mode 100644 crypto/test/src/test/PkixTest.cs create mode 100644 crypto/test/src/test/RSATest.cs create mode 100644 crypto/test/src/test/RegressionTest.cs create mode 100644 crypto/test/src/test/SEEDTest.cs create mode 100644 crypto/test/src/test/SigTest.cs create mode 100644 crypto/test/src/test/TestUtilities.cs create mode 100644 crypto/test/src/test/WrapTest.cs create mode 100644 crypto/test/src/test/X509CertificatePairTest.cs create mode 100644 crypto/test/src/test/X509StoreTest.cs create mode 100644 crypto/test/src/test/nist/NistCertPathTest.cs create mode 100644 crypto/test/src/test/rsa3/RSA3CertTest.cs create mode 100644 crypto/test/src/tsp/test/AllTests.cs create mode 100644 crypto/test/src/tsp/test/GenTimeAccuracyTest.cs create mode 100644 crypto/test/src/tsp/test/ParseTest.cs create mode 100644 crypto/test/src/tsp/test/TSPTest.cs create mode 100644 crypto/test/src/tsp/test/TSPTestUtil.cs create mode 100644 crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs create mode 100644 crypto/test/src/util/io/pem/test/AllTests.cs create mode 100644 crypto/test/src/util/net/test/IPAddressTest.cs create mode 100644 crypto/test/src/util/test/FixedSecureRandom.cs create mode 100644 crypto/test/src/util/test/ITest.cs create mode 100644 crypto/test/src/util/test/ITestResult.cs create mode 100644 crypto/test/src/util/test/NumberParsing.cs create mode 100644 crypto/test/src/util/test/SimpleTest.cs create mode 100644 crypto/test/src/util/test/SimpleTestResult.cs create mode 100644 crypto/test/src/util/test/TestFailedException.cs create mode 100644 crypto/test/src/util/test/UncloseableStream.cs create mode 100644 crypto/test/src/x509/test/TestCertificateGen.cs create mode 100644 crypto/testcfg.nunit create mode 100644 csharp.mds create mode 100644 csharp.sln diff --git a/FxCop/CustomDictionary.xml b/FxCop/CustomDictionary.xml new file mode 100644 index 000000000..7f9080348 --- /dev/null +++ b/FxCop/CustomDictionary.xml @@ -0,0 +1,119 @@ + + + + + Pgp + Pbe + Rsa + Dsa + Gamal + Aes + a + b + x + X + C + y + k + Y + p + q + P + n + m + e + g + d + r + s + t + v + str + tokenizer + oid + Bcpg + Sqrt + Pkcs + Asn1 + Ber + Der + priv + Videotex + Subpacket + Subpackets + unhashed + Twofish + Paddings + dP + dQ + Tbc + Tpb + Gnb + Kdf + Diffie + Hellman + Ede + Cbc + Cfb + Cts + Ofb + Sha + Oaep + ies + mgf + Naccache + ccm + gcd + Alg + Oids + Params + Pkix + Pki + Etsi + Trus + Nist + Ecb + Cbc + Cfb + Ofb + Smime + Unotice + Cps + Tbs + spki + Crl + Oiw + Icao + Esf + Cmp + Pka + Crc + Infos + Ori + o + datagroup + gost + param + req + resp + tsa + tst + + + + + El + ECDH + ECDHC + ECNR + Fp + F2m + sBox + cL + Gn + Pp + Tp + Qt + + + \ No newline at end of file diff --git a/crypto-test/App.ico b/crypto-test/App.ico new file mode 100644 index 000000000..3a5525fd7 Binary files /dev/null and b/crypto-test/App.ico differ diff --git a/crypto-test/CryptoTest.cs b/crypto-test/CryptoTest.cs new file mode 100644 index 000000000..1f6973e28 --- /dev/null +++ b/crypto-test/CryptoTest.cs @@ -0,0 +1,51 @@ +using System; + +namespace crypto_test +{ + public class CryptoTest + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + DateTime before = DateTime.Now; + + try + { + Org.BouncyCastle.Asn1.Tests.RegressionTest.Main(args); + //Org.BouncyCastle.Bcpg.OpenPgp.Tests.Dsa2Test.? + Org.BouncyCastle.Bcpg.OpenPgp.Tests.RegressionTest.Main(args); + Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests.AllTests.Main(args); + Org.BouncyCastle.Cms.Tests.AllTests.Main(args); + Org.BouncyCastle.Crypto.Tests.RegressionTest.Main(args); + Org.BouncyCastle.Crypto.IO.Tests.AllTests.Main(args); + Org.BouncyCastle.Math.Tests.AllTests.Main(args); + Org.BouncyCastle.Math.EC.Tests.AllTests.Main(args); + Org.BouncyCastle.Ocsp.Tests.AllTests.Main(args); + //Org.BouncyCastle.Pkcs.Tests.? + Org.BouncyCastle.Pkcs.Tests.EncryptedPrivateKeyInfoTest.Main(args); + Org.BouncyCastle.Pkcs.Tests.Pkcs10Test.Main(args); + Org.BouncyCastle.Pkcs.Tests.Pkcs12StoreTest.Main(args); + //Org.BouncyCastle.OpenSsl.Tests.? + Org.BouncyCastle.OpenSsl.Tests.ReaderTest.Main(args); + Org.BouncyCastle.OpenSsl.Tests.WriterTest.Main(args); + //Org.BouncyCastle.Security.Tests.? + Org.BouncyCastle.Tests.RegressionTest.Main(args); + Org.BouncyCastle.Tsp.Tests.AllTests.Main(args); + //Org.BouncyCastle.X509.Tests.? + } + catch (Exception e) + { + Console.WriteLine("Tests failed with exception: " + e.Message); + Console.WriteLine(e.StackTrace); + } + + DateTime after = DateTime.Now; + long elapsedTicks = after.Ticks - before.Ticks; + + Console.WriteLine("Done in {0}ms.", elapsedTicks / TimeSpan.TicksPerMillisecond); + } + } +} diff --git a/crypto-test/crypto-test.csproj b/crypto-test/crypto-test.csproj new file mode 100644 index 000000000..9bb4cdbb9 --- /dev/null +++ b/crypto-test/crypto-test.csproj @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crypto-test/crypto-test.mdp b/crypto-test/crypto-test.mdp new file mode 100644 index 000000000..a9c3a30ba --- /dev/null +++ b/crypto-test/crypto-test.mdp @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/crypto/Contributors.html b/crypto/Contributors.html new file mode 100644 index 000000000..b37af312f --- /dev/null +++ b/crypto/Contributors.html @@ -0,0 +1,116 @@ + + + + + Contributors + + +

The Bouncy Castle Cryptographic C#® API

+

Contributors:

+

The following people have contributed to the C# Bouncy Castle Cryptography + Package.

+

Thanks, may your castles never deflate!

+ + + diff --git a/crypto/License.html b/crypto/License.html new file mode 100644 index 000000000..7213058e7 --- /dev/null +++ b/crypto/License.html @@ -0,0 +1,39 @@ + + + + + License + + +

The Bouncy Castle Cryptographic C#® API

+

License:

+The Bouncy Castle License
+Copyright (c) 2000-2013 The Legion Of The Bouncy Castle +(http://www.bouncycastle.org)
+Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sub license, 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.
+
+
+ + diff --git a/crypto/NBuild.build b/crypto/NBuild.build new file mode 100644 index 000000000..9c4488c38 --- /dev/null +++ b/crypto/NBuild.build @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Include extended algorithm set (IDEA) + + + + + + Compile targets will be signed using keyfile ../BouncyCastle.snk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crypto/Readme.html b/crypto/Readme.html new file mode 100644 index 000000000..2660d4ac3 --- /dev/null +++ b/crypto/Readme.html @@ -0,0 +1,455 @@ + + + + Notes + + + +

The Bouncy Castle Cryptographic + C# API

+

Contents:
+

+
    +
  1. The Bouncy + Castle Cryptographic C# API +
      +
    1. +
        +
      1. + Contents: +
      2. + License & Contributors: +
      3. + Features: +
      4. + How To Build. +
      5. + The Source: +
      6. + Documentation: +
      7. + For first time users. +
      8. + Notes: +
          +
        1. + Release 1.7 +
        2. + Release 1.6.1 +
        3. + Release 1.6 +
        4. + Release 1.5 +
        5. + Release 1.4 +
        6. + Release 1.3 +
        7. + Release 1.2 +
        8. + Release 1.1 +
        9. + Release 1.0 +
        10. + Tuesday Febuary 1, 2005 +
        11. + Sunday December 12, 2004
        12. +
        +
      9. + Trademarks. +
      10. +
+
+
+

License & Contributors:

+ See License & Contributors + files.
+  
+
+
+

Features:

+ +
+

Porting notes from the old ASN.1 library For the most part code using the + old subset of ASN.1 classes should be easy to transfer, providing the following + changes are made: +

+ +
+
+

How To Build.

+

+ The BC C# API uses NAnt (http://nant.sourceforge.net) + to provide a platform independent build environment (suggested version NAnt 0.90). + There is also a solution file for Visual Studio, and for MonoDevelop. The API works + with .NET Framework 1.1 and above. It has been successfully built and tested with Mono + versions from 1.1.13 onwards. The source code can be built for .NET Compact Framework 1.0 + by setting the compilation flag NETCF_1_0, or .NET Compact Framework 2.0 by setting NETCF_2_0, + or Silverlight 2 by setting SILVERLIGHT. +

+ Using a command prompt (DOS window), cd into the 'crypto' folder of this + distribution.
+
+ Use,
+ +

+ Output:
+
+     The compiled API can be found in the 'api/bin/release' & + 'api/bin/debug' directories.
+     The compiled tests can be found in the 'test/bin' directory + (by default a debug build is used for testing).
+

+


+

+

The Source:

+ Source code can be found in the 'src'directory.
+
+
+

Documentation:

+

There is limited documentation available at the moment. Some of the source + contains XML comments, but this is a work in progress. We will be working to + improve this now that 1.0 is out the door.

+

+


+

+

For first time users.

+  Java heritage,
+
+ The Bouncy Castle C# API is a port of the Bouncy Castle Java APIs. + Approximately %80 of the functionality in the Java build has now been ported. + For the most part, the naming conventions of the .NET platform have been + adopted. The C# API is constantly kept uptodate with bug fixes and new test + cases from the Java build (and vice versa sometimes), thus benefitting from the + large user base and real-world use the Java version has seen.
+
+ Please consider.
+
+ The Bouncy Castle C# API is a library of transformations that when combined + properly will enable developers to create standard conforming cryptographic + systems. In order to use this API you must have some knowledge of how to build + cryptographic systems, namely what transformations to use and the when, where + and why of their use.
+ Developing good cryptographic systems takes practice and understanding.
+
+ There are many resources available online and in book shops; please use those + to your advantage.
+
+
+

Notes:

+

Release 1.7, Thursday April 7, 2011

+
Additional Features and Functionality
+ +
Additional Notes
+ +

Release 1.6.1, Monday February 8, 2010

+ +

Release 1.6, Thursday February 4, 2010

+
Defects Fixed
+ +
Security Advisory
+ +
Additional Features and Functionality
+ +
Additional Notes
+ +

Release 1.5, Tuesday August 18, 2009

+
Defects Fixed
+ +
Security Advisory
+ +
Additional Features and Functionality
+ +
Additional Notes
+ +

Release 1.4, Thursday August 8, 2008

+
Defects Fixed
+ +
Additional Features and Functionality
+ +
Additional Notes
+ +

Release 1.3, Saturday December 8, 2007

+

+ ASN.1 stream parsing now handles definite length encodings efficiently.
+ Buffering in the streaming CMS has been reworked. Throughput is now usually higher and the behaviour is more predictable.
+ BcpgInputStream now handles data blocks in the 2**31->2**32-1 range.
+ Some confusion over the parameters J and L in connection with Diffie-Hellman has been resolved.
+ Added CryptoApiRandomGenerator, a wrapper for RNGCryptoServiceProvider.
+ Added VMPC stream cipher, VMPCMAC and a VMPC-based implementation of IRandomGenerator.
+ Added support in OpenPGP for fetching keyrings by case-insensitive user ID [#BMA-8].
+ Fixed a vulnerability of CMS signatures that do not use signed attributes (Bleichenbacher RSA forgery).
+ Fixed a bug causing second and later encrypted objects to be ignored in KeyBasedFileProcessor example.
+ Fixed case-sensitivity issue with deletion from a PKCS#12 file.
+ Fixed problem overwriting entities in a PKCS#12 file.
+ Fixed PgpUtilities.MakeKeyFromPassPhrase for 8-bit characters [#BMA-13].
+ Fixed duplicate certificate problem in Pkcs12Store.Save [#BMA-12].
+ Fixed NAnt build under Mono [#BMA-10].
+ Fixed BigInteger.ModPow for negative exponents [#BMA-7].
+

+

Release 1.2, Thursday July 5, 2007

+

+ Source now builds on .NET Compact Framework 1.0 (compilation flag NETCF_1_0).
+ Release assembly now signed with a strong name.
+ Added CCM and EAX block cipher modes.
+ Added Noekeon block cipher.
+ Added HC-128, HC-256, and ISAAC stream ciphers.
+ Added RIPEMD160withECDSA signature algorithm.
+ Added support for notation data signature subpackets to OpenPGP.
+ Added support for parsing of experimental signatures to OpenPGP.
+ Added the complete set of SEC-2 EC curves.
+ Added support for implicit tagging to DerApplicationSpecific.
+ Added remaining ASN.1 structures from RFC 3126 to Asn1.Esf namespace.
+ Performance of ECDSA improved.
+ Performance of ASN.1 stream parsing improved.
+ Fixed default private key length for Diffie-Hellman parameters.
+ Fixed DerT61String to correctly support 8-bit characters.
+ Fixed duplicate attribute problem in Pkcs12Store.Save.
+ Fixed a problem writing public keys in OpenPGP [#BMA-5].
+

+

Release 1.1, Friday May 4, 2007

+

+ Added support for writing DSA private keys, and more encodings, in OpenSsl + (PemReader/PemWriter).
+ Removed SharpZipLib dependency.
+ Added RSA blinded signature classes.
+ Added Asn1.IsisMtt namespace (ISIS-MTT ASN.1 classes).
+ Added SEED block cipher engine.
+ Added Salsa20 stream cipher engine.
+ Performance optimisations for F2m elliptic curves.
+ Fixed OpenPGP bug decrypting files with multiple types of encryption on the + session key.
+

+

Release 1.0, Thursday January 18, + 2007

+

+ Implementations of CMS, OCSP, OpenPGP, and TSP.
+ Elliptic Curves (F2m and Fp).
+ A basic TLS client.
+ PEM file reading and writing.
+ Symmetric key algorithms: Camellia, GOST28147, NaccacheStern, and TEA/XTEA.
+ Symmetric key modes: GOFB and OpenPGPCFB.
+ Symmetric key paddings: ISO7816d4.
+ Asymmetric key algorithms: RSA blinding.
+ Digests: GOST3411 and Whirlpool.
+ Macs: GOST28147 and ISO9797 Alg 3.
+ Signer mechanisms: ECDSA, ECGOST3410, and GOST3410.
+ ...and many more features, bug fixes, and performance improvements.
+

+

Tuesday Febuary 1, 2005

+

This is the second beta release of the Bouncy Castle API C# implementation.
+ Reliability improvement to ASN1InputStream.
+ The OID entries in SignerUtilities for RSA signature algorithms for SHA-256,
+ SHA-384, and SHA-512 were pointing creating the wrong signature objects.

+

Sunday December 12, 2004

+ This is the first beta release of the Bouncy Castle Cryptographic API C# + implementation.
+ The Legion of the Bouncy Castle would like to extend their thanks to all those + who contributed to this API during the alpha stages of its development.
+ Keep up the good work folks.
+ Please send any questions or bug reports to + dev-crypto-csharp@bouncycastle.org
+
+
+

Trademarks.
+

+ C#, .NET, and MSDN are Registered Trademarks of Microsoft. + Microsoft.com
+ Java is a Registered Trademark of Sun Microsystems. Sun + Microsystems
+
+
+
2007 Legion of the Bouncy Castle
+
+ + diff --git a/crypto/bzip2/src/BZip2Constants.cs b/crypto/bzip2/src/BZip2Constants.cs new file mode 100644 index 000000000..4a5442d8b --- /dev/null +++ b/crypto/bzip2/src/BZip2Constants.cs @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This package is based on the work done by Keiron Liddle, Aftex Software + * to whom the Ant project is very grateful for his + * great code. + */ + +using System; + +namespace Org.BouncyCastle.Apache.Bzip2 +{ + /** + * Base class for both the compress and decompress classes. + * Holds common arrays, and static data. + * + * @author Keiron Liddle + */ + public class BZip2Constants { + + public const int baseBlockSize = 100000; + public const int MAX_ALPHA_SIZE = 258; + public const int MAX_CODE_LEN = 23; + public const int RUNA = 0; + public const int RUNB = 1; + public const int N_GROUPS = 6; + public const int G_SIZE = 50; + public const int N_ITERS = 4; + public const int MAX_SELECTORS = (2 + (900000 / G_SIZE)); + public const int NUM_OVERSHOOT_BYTES = 20; + + public static readonly int[] rNums = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + }; + } +} \ No newline at end of file diff --git a/crypto/bzip2/src/CBZip2InputStream.cs b/crypto/bzip2/src/CBZip2InputStream.cs new file mode 100644 index 000000000..7efb3b3ab --- /dev/null +++ b/crypto/bzip2/src/CBZip2InputStream.cs @@ -0,0 +1,919 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This package is based on the work done by Keiron Liddle, Aftex Software + * to whom the Ant project is very grateful for his + * great code. + */ + +using System; +using System.IO; + +namespace Org.BouncyCastle.Apache.Bzip2 +{ + /** + * An input stream that decompresses from the BZip2 format (with the file + * header chars) to be read as any other stream. + * + * @author Keiron Liddle + * + * NB: note this class has been modified to read the leading BZ from the + * start of the BZIP2 stream to make it compatible with other PGP programs. + */ + public class CBZip2InputStream : Stream + { + private static void Cadvise() { + //System.out.Println("CRC Error"); + //throw new CCoruptionError(); + } + +// private static void BadBGLengths() { +// Cadvise(); +// } +// +// private static void BitStreamEOF() { +// Cadvise(); +// } + + private static void CompressedStreamEOF() { + Cadvise(); + } + + private void MakeMaps() { + int i; + nInUse = 0; + for (i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char) i; + unseqToSeq[i] = (char) nInUse; + nInUse++; + } + } + } + + /* + index of the last char in the block, so + the block size == last + 1. + */ + private int last; + + /* + index in zptr[] of original string after sorting. + */ + private int origPtr; + + /* + always: in the range 0 .. 9. + The current block size is 100000 * this number. + */ + private int blockSize100k; + + private bool blockRandomised; + + private int bsBuff; + private int bsLive; + private CRC mCrc = new CRC(); + + private bool[] inUse = new bool[256]; + private int nInUse; + + private char[] seqToUnseq = new char[256]; + private char[] unseqToSeq = new char[256]; + + private char[] selector = new char[BZip2Constants.MAX_SELECTORS]; + private char[] selectorMtf = new char[BZip2Constants.MAX_SELECTORS]; + + private int[] tt; + private char[] ll8; + + /* + freq table collected to save a pass over the data + during decompression. + */ + private int[] unzftab = new int[256]; + + private int[][] limit = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + private int[][] basev = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + private int[][] perm = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + private int[] minLens = new int[BZip2Constants.N_GROUPS]; + + private Stream bsStream; + + private bool streamEnd = false; + + private int currentChar = -1; + + private const int START_BLOCK_STATE = 1; + private const int RAND_PART_A_STATE = 2; + private const int RAND_PART_B_STATE = 3; + private const int RAND_PART_C_STATE = 4; + private const int NO_RAND_PART_A_STATE = 5; + private const int NO_RAND_PART_B_STATE = 6; + private const int NO_RAND_PART_C_STATE = 7; + + private int currentState = START_BLOCK_STATE; + + private int storedBlockCRC, storedCombinedCRC; + private int computedBlockCRC, computedCombinedCRC; + + int i2, count, chPrev, ch2; + int i, tPos; + int rNToGo = 0; + int rTPos = 0; + int j2; + char z; + + public CBZip2InputStream(Stream zStream) { + ll8 = null; + tt = null; + BsSetStream(zStream); + Initialize(); + InitBlock(); + SetupBlock(); + } + + internal static int[][] InitIntArray(int n1, int n2) { + int[][] a = new int[n1][]; + for (int k = 0; k < n1; ++k) { + a[k] = new int[n2]; + } + return a; + } + + internal static char[][] InitCharArray(int n1, int n2) { + char[][] a = new char[n1][]; + for (int k = 0; k < n1; ++k) { + a[k] = new char[n2]; + } + return a; + } + + public override int ReadByte() { + if (streamEnd) { + return -1; + } else { + int retChar = currentChar; + switch (currentState) { + case START_BLOCK_STATE: + break; + case RAND_PART_A_STATE: + break; + case RAND_PART_B_STATE: + SetupRandPartB(); + break; + case RAND_PART_C_STATE: + SetupRandPartC(); + break; + case NO_RAND_PART_A_STATE: + break; + case NO_RAND_PART_B_STATE: + SetupNoRandPartB(); + break; + case NO_RAND_PART_C_STATE: + SetupNoRandPartC(); + break; + default: + break; + } + return retChar; + } + } + + private void Initialize() { + char magic3, magic4; + magic3 = BsGetUChar(); + magic4 = BsGetUChar(); + if (magic3 != 'B' && magic4 != 'Z') + { + throw new IOException("Not a BZIP2 marked stream"); + } + magic3 = BsGetUChar(); + magic4 = BsGetUChar(); + if (magic3 != 'h' || magic4 < '1' || magic4 > '9') { + BsFinishedWithStream(); + streamEnd = true; + return; + } + + SetDecompressStructureSizes(magic4 - '0'); + computedCombinedCRC = 0; + } + + private void InitBlock() { + char magic1, magic2, magic3, magic4; + char magic5, magic6; + magic1 = BsGetUChar(); + magic2 = BsGetUChar(); + magic3 = BsGetUChar(); + magic4 = BsGetUChar(); + magic5 = BsGetUChar(); + magic6 = BsGetUChar(); + if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 + && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) { + Complete(); + return; + } + + if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 + || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) { + BadBlockHeader(); + streamEnd = true; + return; + } + + storedBlockCRC = BsGetInt32(); + + if (BsR(1) == 1) { + blockRandomised = true; + } else { + blockRandomised = false; + } + + // currBlockNo++; + GetAndMoveToFrontDecode(); + + mCrc.InitialiseCRC(); + currentState = START_BLOCK_STATE; + } + + private void EndBlock() { + computedBlockCRC = mCrc.GetFinalCRC(); + /* A bad CRC is considered a fatal error. */ + if (storedBlockCRC != computedBlockCRC) { + CrcError(); + } + + computedCombinedCRC = (computedCombinedCRC << 1) + | (int)(((uint)computedCombinedCRC) >> 31); + computedCombinedCRC ^= computedBlockCRC; + } + + private void Complete() { + storedCombinedCRC = BsGetInt32(); + if (storedCombinedCRC != computedCombinedCRC) { + CrcError(); + } + + BsFinishedWithStream(); + streamEnd = true; + } + + private static void BlockOverrun() { + Cadvise(); + } + + private static void BadBlockHeader() { + Cadvise(); + } + + private static void CrcError() { + Cadvise(); + } + + private void BsFinishedWithStream() { + try { + if (this.bsStream != null) { + this.bsStream.Close(); + this.bsStream = null; + } + } catch { + //ignore + } + } + + private void BsSetStream(Stream f) { + bsStream = f; + bsLive = 0; + bsBuff = 0; + } + + private int BsR(int n) { + int v; + while (bsLive < n) { + int zzi; + char thech = '\0'; + try { + thech = (char) bsStream.ReadByte(); + } catch (IOException) { + CompressedStreamEOF(); + } + if (thech == '\uffff') { + CompressedStreamEOF(); + } + zzi = thech; + bsBuff = (bsBuff << 8) | (zzi & 0xff); + bsLive += 8; + } + + v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1); + bsLive -= n; + return v; + } + + private char BsGetUChar() { + return (char) BsR(8); + } + + private int BsGetint() { + int u = 0; + u = (u << 8) | BsR(8); + u = (u << 8) | BsR(8); + u = (u << 8) | BsR(8); + u = (u << 8) | BsR(8); + return u; + } + + private int BsGetIntVS(int numBits) { + return (int) BsR(numBits); + } + + private int BsGetInt32() { + return (int) BsGetint(); + } + + private void HbCreateDecodeTables(int[] limit, int[] basev, + int[] perm, char[] length, + int minLen, int maxLen, int alphaSize) { + int pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) { + for (j = 0; j < alphaSize; j++) { + if (length[j] == i) { + perm[pp] = j; + pp++; + } + } + } + + for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++) { + basev[i] = 0; + } + for (i = 0; i < alphaSize; i++) { + basev[length[i] + 1]++; + } + + for (i = 1; i < BZip2Constants.MAX_CODE_LEN; i++) { + basev[i] += basev[i - 1]; + } + + for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++) { + limit[i] = 0; + } + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (basev[i + 1] - basev[i]); + limit[i] = vec - 1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) { + basev[i] = ((limit[i - 1] + 1) << 1) - basev[i]; + } + } + + private void RecvDecodingTables() { + char[][] len = InitCharArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + int i, j, t, nGroups, nSelectors, alphaSize; + int minLen, maxLen; + bool[] inUse16 = new bool[16]; + + /* Receive the mapping table */ + for (i = 0; i < 16; i++) { + if (BsR(1) == 1) { + inUse16[i] = true; + } else { + inUse16[i] = false; + } + } + + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i < 16; i++) { + if (inUse16[i]) { + for (j = 0; j < 16; j++) { + if (BsR(1) == 1) { + inUse[i * 16 + j] = true; + } + } + } + } + + MakeMaps(); + alphaSize = nInUse + 2; + + /* Now the selectors */ + nGroups = BsR(3); + nSelectors = BsR(15); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (BsR(1) == 1) { + j++; + } + selectorMtf[i] = (char) j; + } + + /* Undo the MTF values for the selectors. */ + { + char[] pos = new char[BZip2Constants.N_GROUPS]; + char tmp, v; + for (v = '\0'; v < nGroups; v++) { + pos[v] = v; + } + + for (i = 0; i < nSelectors; i++) { + v = selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { + pos[v] = pos[v - 1]; + v--; + } + pos[0] = tmp; + selector[i] = tmp; + } + } + + /* Now the coding tables */ + for (t = 0; t < nGroups; t++) { + int curr = BsR(5); + for (i = 0; i < alphaSize; i++) { + while (BsR(1) == 1) { + if (BsR(1) == 0) { + curr++; + } else { + curr--; + } + } + len[t][i] = (char) curr; + } + } + + /* Create the Huffman decoding tables */ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + HbCreateDecodeTables(limit[t], basev[t], perm[t], len[t], minLen, + maxLen, alphaSize); + minLens[t] = minLen; + } + } + + private void GetAndMoveToFrontDecode() { + char[] yy = new char[256]; + int i, j, nextSym, limitLast; + int EOB, groupNo, groupPos; + + limitLast = BZip2Constants.baseBlockSize * blockSize100k; + origPtr = BsGetIntVS(24); + + RecvDecodingTables(); + EOB = nInUse + 1; + groupNo = -1; + groupPos = 0; + + /* + Setting up the unzftab entries here is not strictly + necessary, but it does save having to do it later + in a separate pass, and so saves a block's worth of + cache misses. + */ + for (i = 0; i <= 255; i++) { + unzftab[i] = 0; + } + + for (i = 0; i <= 255; i++) { + yy[i] = (char) i; + } + + last = -1; + + { + int zt, zn, zvec, zj; + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.G_SIZE; + } + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + { + { + while (bsLive < 1) { + int zzi; + char thech = '\0'; + try { + thech = (char) bsStream.ReadByte(); + } catch (IOException) { + CompressedStreamEOF(); + } + if (thech == '\uffff') { + CompressedStreamEOF(); + } + zzi = thech; + bsBuff = (bsBuff << 8) | (zzi & 0xff); + bsLive += 8; + } + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + } + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - basev[zt][zn]]; + } + + while (true) { + + if (nextSym == EOB) { + break; + } + + if (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB) { + char ch; + int s = -1; + int N = 1; + do { + if (nextSym == BZip2Constants.RUNA) { + s = s + (0 + 1) * N; + } else if (nextSym == BZip2Constants.RUNB) { + s = s + (1 + 1) * N; + } + N = N * 2; + { + int zt, zn, zvec, zj; + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.G_SIZE; + } + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + { + { + while (bsLive < 1) { + int zzi; + char thech = '\0'; + try { + thech = (char) bsStream.ReadByte(); + } catch (IOException) { + CompressedStreamEOF(); + } + if (thech == '\uffff') { + CompressedStreamEOF(); + } + zzi = thech; + bsBuff = (bsBuff << 8) | (zzi & 0xff); + bsLive += 8; + } + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + } + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - basev[zt][zn]]; + } + } while (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB); + + s++; + ch = seqToUnseq[yy[0]]; + unzftab[ch] += s; + + while (s > 0) { + last++; + ll8[last] = ch; + s--; + } + + if (last >= limitLast) { + BlockOverrun(); + } + continue; + } else { + char tmp; + last++; + if (last >= limitLast) { + BlockOverrun(); + } + + tmp = yy[nextSym - 1]; + unzftab[seqToUnseq[tmp]]++; + ll8[last] = seqToUnseq[tmp]; + + /* + This loop is hammered during decompression, + hence the unrolling. + + for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1]; + */ + + j = nextSym - 1; + for (; j > 3; j -= 4) { + yy[j] = yy[j - 1]; + yy[j - 1] = yy[j - 2]; + yy[j - 2] = yy[j - 3]; + yy[j - 3] = yy[j - 4]; + } + for (; j > 0; j--) { + yy[j] = yy[j - 1]; + } + + yy[0] = tmp; + { + int zt, zn, zvec, zj; + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.G_SIZE; + } + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + { + { + while (bsLive < 1) { + int zzi; + char thech = '\0'; + try { + thech = (char) bsStream.ReadByte(); + } catch (IOException) { + CompressedStreamEOF(); + } + zzi = thech; + bsBuff = (bsBuff << 8) | (zzi & 0xff); + bsLive += 8; + } + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + } + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - basev[zt][zn]]; + } + continue; + } + } + } + + private void SetupBlock() { + int[] cftab = new int[257]; + char ch; + + cftab[0] = 0; + for (i = 1; i <= 256; i++) { + cftab[i] = unzftab[i - 1]; + } + for (i = 1; i <= 256; i++) { + cftab[i] += cftab[i - 1]; + } + + for (i = 0; i <= last; i++) { + ch = (char) ll8[i]; + tt[cftab[ch]] = i; + cftab[ch]++; + } + cftab = null; + + tPos = tt[origPtr]; + + count = 0; + i2 = 0; + ch2 = 256; /* not a char and not EOF */ + + if (blockRandomised) { + rNToGo = 0; + rTPos = 0; + SetupRandPartA(); + } else { + SetupNoRandPartA(); + } + } + + private void SetupRandPartA() { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.rNums[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + ch2 ^= (int) ((rNToGo == 1) ? 1 : 0); + i2++; + + currentChar = ch2; + currentState = RAND_PART_B_STATE; + mCrc.UpdateCRC(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + private void SetupNoRandPartA() { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + i2++; + + currentChar = ch2; + currentState = NO_RAND_PART_B_STATE; + mCrc.UpdateCRC(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + private void SetupRandPartB() { + if (ch2 != chPrev) { + currentState = RAND_PART_A_STATE; + count = 1; + SetupRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.rNums[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + z ^= (char)((rNToGo == 1) ? 1 : 0); + j2 = 0; + currentState = RAND_PART_C_STATE; + SetupRandPartC(); + } else { + currentState = RAND_PART_A_STATE; + SetupRandPartA(); + } + } + } + + private void SetupRandPartC() { + if (j2 < (int) z) { + currentChar = ch2; + mCrc.UpdateCRC(ch2); + j2++; + } else { + currentState = RAND_PART_A_STATE; + i2++; + count = 0; + SetupRandPartA(); + } + } + + private void SetupNoRandPartB() { + if (ch2 != chPrev) { + currentState = NO_RAND_PART_A_STATE; + count = 1; + SetupNoRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + currentState = NO_RAND_PART_C_STATE; + j2 = 0; + SetupNoRandPartC(); + } else { + currentState = NO_RAND_PART_A_STATE; + SetupNoRandPartA(); + } + } + } + + private void SetupNoRandPartC() { + if (j2 < (int) z) { + currentChar = ch2; + mCrc.UpdateCRC(ch2); + j2++; + } else { + currentState = NO_RAND_PART_A_STATE; + i2++; + count = 0; + SetupNoRandPartA(); + } + } + + private void SetDecompressStructureSizes(int newSize100k) { + if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k + && blockSize100k <= 9)) { + // throw new IOException("Invalid block size"); + } + + blockSize100k = newSize100k; + + if (newSize100k == 0) { + return; + } + + int n = BZip2Constants.baseBlockSize * newSize100k; + ll8 = new char[n]; + tt = new int[n]; + } + + public override void Flush() { + } + + public override int Read(byte[] buffer, int offset, int count) { + int c = -1; + int k; + for (k = 0; k < count; ++k) { + c = ReadByte(); + if (c == -1) + break; + buffer[k + offset] = (byte)c; + } + return k; + } + + public override long Seek(long offset, SeekOrigin origin) { + return 0; + } + + public override void SetLength(long value) { + } + + public override void Write(byte[] buffer, int offset, int count) { + } + + public override bool CanRead { + get { + return true; + } + } + + public override bool CanSeek { + get { + return false; + } + } + + public override bool CanWrite { + get { + return false; + } + } + + public override long Length { + get { + return 0; + } + } + + public override long Position { + get { + return 0; + } + set { + } + } + } +} \ No newline at end of file diff --git a/crypto/bzip2/src/CBZip2OutputStream.cs b/crypto/bzip2/src/CBZip2OutputStream.cs new file mode 100644 index 000000000..bf43a6a6c --- /dev/null +++ b/crypto/bzip2/src/CBZip2OutputStream.cs @@ -0,0 +1,1691 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This package is based on the work done by Keiron Liddle, Aftex Software + * to whom the Ant project is very grateful for his + * great code. + */ + +using System; +using System.IO; + +namespace Org.BouncyCastle.Apache.Bzip2 +{ + /** + * An output stream that compresses into the BZip2 format (with the file + * header chars) into another stream. + * + * @author Keiron Liddle + * + * TODO: Update to BZip2 1.0.1 + * NB: note this class has been modified to add a leading BZ to the + * start of the BZIP2 stream to make it compatible with other PGP programs. + */ + public class CBZip2OutputStream : Stream + { + protected const int SETMASK = (1 << 21); + protected const int CLEARMASK = (~SETMASK); + protected const int GREATER_ICOST = 15; + protected const int LESSER_ICOST = 0; + protected const int SMALL_THRESH = 20; + protected const int DEPTH_THRESH = 10; + + /* + If you are ever unlucky/improbable enough + to get a stack overflow whilst sorting, + increase the following constant and try + again. In practice I have never seen the + stack go above 27 elems, so the following + limit seems very generous. + */ + protected const int QSORT_STACK_SIZE = 1000; + private bool finished; + + private static void Panic() { + //System.out.Println("panic"); + //throw new CError(); + } + + private void MakeMaps() { + int i; + nInUse = 0; + for (i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char) i; + unseqToSeq[i] = (char) nInUse; + nInUse++; + } + } + } + + protected static void HbMakeCodeLengths(char[] len, int[] freq, + int alphaSize, int maxLen) { + /* + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + */ + int nNodes, nHeap, n1, n2, i, j, k; + bool tooLong; + + int[] heap = new int[BZip2Constants.MAX_ALPHA_SIZE + 2]; + int[] weight = new int[BZip2Constants.MAX_ALPHA_SIZE * 2]; + int[] parent = new int[BZip2Constants.MAX_ALPHA_SIZE * 2]; + + for (i = 0; i < alphaSize; i++) { + weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + } + + while (true) { + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + { + int zz, tmp; + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + } + if (!(nHeap < (BZip2Constants.MAX_ALPHA_SIZE + 2))) { + Panic(); + } + + while (nHeap > 1) { + n1 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + { + int zz = 0, yy = 0, tmp = 0; + zz = 1; + tmp = heap[zz]; + while (true) { + yy = zz << 1; + if (yy > nHeap) { + break; + } + if (yy < nHeap + && weight[heap[yy + 1]] < weight[heap[yy]]) { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + } + n2 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + { + int zz = 0, yy = 0, tmp = 0; + zz = 1; + tmp = heap[zz]; + while (true) { + yy = zz << 1; + if (yy > nHeap) { + break; + } + if (yy < nHeap + && weight[heap[yy + 1]] < weight[heap[yy]]) { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + } + nNodes++; + parent[n1] = parent[n2] = nNodes; + + weight[nNodes] = (int)((uint)((weight[n1] & 0xffffff00) + + (weight[n2] & 0xffffff00)) + | (uint)(1 + (((weight[n1] & 0x000000ff) > + (weight[n2] & 0x000000ff)) ? + (weight[n1] & 0x000000ff) : + (weight[n2] & 0x000000ff)))); + + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + { + int zz = 0, tmp = 0; + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + } + if (!(nNodes < (BZip2Constants.MAX_ALPHA_SIZE * 2))) { + Panic(); + } + + tooLong = false; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { + k = parent[k]; + j++; + } + len[i - 1] = (char) j; + if (j > maxLen) { + tooLong = true; + } + } + + if (!tooLong) { + break; + } + + for (i = 1; i < alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } + } + + /* + index of the last char in the block, so + the block size == last + 1. + */ + int last; + + /* + index in zptr[] of original string after sorting. + */ + int origPtr; + + /* + always: in the range 0 .. 9. + The current block size is 100000 * this number. + */ + int blockSize100k; + + bool blockRandomised; + + int bytesOut; + int bsBuff; + int bsLive; + CRC mCrc = new CRC(); + + private bool[] inUse = new bool[256]; + private int nInUse; + + private char[] seqToUnseq = new char[256]; + private char[] unseqToSeq = new char[256]; + + private char[] selector = new char[BZip2Constants.MAX_SELECTORS]; + private char[] selectorMtf = new char[BZip2Constants.MAX_SELECTORS]; + + private char[] block; + private int[] quadrant; + private int[] zptr; + private short[] szptr; + private int[] ftab; + + private int nMTF; + + private int[] mtfFreq = new int[BZip2Constants.MAX_ALPHA_SIZE]; + + /* + * Used when sorting. If too many long comparisons + * happen, we stop sorting, randomise the block + * slightly, and try again. + */ + private int workFactor; + private int workDone; + private int workLimit; + private bool firstAttempt; + private int nBlocksRandomised; + + private int currentChar = -1; + private int runLength = 0; + + public CBZip2OutputStream(Stream inStream) : this(inStream, 9) { + } + + public CBZip2OutputStream(Stream inStream, int inBlockSize) + { + block = null; + quadrant = null; + zptr = null; + ftab = null; + + inStream.WriteByte((byte)'B'); + inStream.WriteByte((byte)'Z'); + + BsSetStream(inStream); + + workFactor = 50; + if (inBlockSize > 9) { + inBlockSize = 9; + } + if (inBlockSize < 1) { + inBlockSize = 1; + } + blockSize100k = inBlockSize; + AllocateCompressStructures(); + Initialize(); + InitBlock(); + } + + /** + * + * modified by Oliver Merkel, 010128 + * + */ + public override void WriteByte(byte bv) { + int b = (256 + bv) % 256; + if (currentChar != -1) { + if (currentChar == b) { + runLength++; + if (runLength > 254) { + WriteRun(); + currentChar = -1; + runLength = 0; + } + } else { + WriteRun(); + runLength = 1; + currentChar = b; + } + } else { + currentChar = b; + runLength++; + } + } + + private void WriteRun() { + if (last < allowableBlockSize) { + inUse[currentChar] = true; + for (int i = 0; i < runLength; i++) { + mCrc.UpdateCRC((char) currentChar); + } + switch (runLength) { + case 1: + last++; + block[last + 1] = (char) currentChar; + break; + case 2: + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + break; + case 3: + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + break; + default: + inUse[runLength - 4] = true; + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) currentChar; + last++; + block[last + 1] = (char) (runLength - 4); + break; + } + } else { + EndBlock(); + InitBlock(); + WriteRun(); + } + } + + bool closed = false; + +// protected void Finalize() { +// Close(); +// } + + public override void Close() { + if (closed) { + return; + } + + Finish(); + + closed = true; + base.Close(); + bsStream.Close(); + } + + public void Finish() { + if (finished) { + return; + } + + if (runLength > 0) { + WriteRun(); + } + currentChar = -1; + EndBlock(); + EndCompression(); + finished = true; + Flush(); + } + + public override void Flush() { + bsStream.Flush(); + } + + private int blockCRC, combinedCRC; + + private void Initialize() { + bytesOut = 0; + nBlocksRandomised = 0; + + /* Write `magic' bytes h indicating file-format == huffmanised, + followed by a digit indicating blockSize100k. + */ + BsPutUChar('h'); + BsPutUChar('0' + blockSize100k); + + combinedCRC = 0; + } + + private int allowableBlockSize; + + private void InitBlock() { + // blockNo++; + mCrc.InitialiseCRC(); + last = -1; + // ch = 0; + + for (int i = 0; i < 256; i++) { + inUse[i] = false; + } + + /* 20 is just a paranoia constant */ + allowableBlockSize = BZip2Constants.baseBlockSize * blockSize100k - 20; + } + + private void EndBlock() { + blockCRC = mCrc.GetFinalCRC(); + combinedCRC = (combinedCRC << 1) | (int)(((uint)combinedCRC) >> 31); + combinedCRC ^= blockCRC; + + /* sort the block and establish posn of original string */ + DoReversibleTransformation(); + + /* + A 6-byte block header, the value chosen arbitrarily + as 0x314159265359 :-). A 32 bit value does not really + give a strong enough guarantee that the value will not + appear by chance in the compressed datastream. Worst-case + probability of this event, for a 900k block, is about + 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. + For a compressed file of size 100Gb -- about 100000 blocks -- + only a 48-bit marker will do. NB: normal compression/ + decompression do *not* rely on these statistical properties. + They are only important when trying to recover blocks from + damaged files. + */ + BsPutUChar(0x31); + BsPutUChar(0x41); + BsPutUChar(0x59); + BsPutUChar(0x26); + BsPutUChar(0x53); + BsPutUChar(0x59); + + /* Now the block's CRC, so it is in a known place. */ + BsPutint(blockCRC); + + /* Now a single bit indicating randomisation. */ + if (blockRandomised) { + BsW(1, 1); + nBlocksRandomised++; + } else { + BsW(1, 0); + } + + /* Finally, block's contents proper. */ + MoveToFrontCodeAndSend(); + } + + private void EndCompression() { + /* + Now another magic 48-bit number, 0x177245385090, to + indicate the end of the last block. (Sqrt(pi), if + you want to know. I did want to use e, but it contains + too much repetition -- 27 18 28 18 28 46 -- for me + to feel statistically comfortable. Call me paranoid.) + */ + BsPutUChar(0x17); + BsPutUChar(0x72); + BsPutUChar(0x45); + BsPutUChar(0x38); + BsPutUChar(0x50); + BsPutUChar(0x90); + + BsPutint(combinedCRC); + + BsFinishedWithStream(); + } + + private void HbAssignCodes(int[] code, char[] length, int minLen, + int maxLen, int alphaSize) { + int n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) { + if (length[i] == n) { + code[i] = vec; + vec++; + } + }; + vec <<= 1; + } + } + + private void BsSetStream(Stream f) { + bsStream = f; + bsLive = 0; + bsBuff = 0; + bytesOut = 0; + } + + private void BsFinishedWithStream() { + while (bsLive > 0) { + int ch = (bsBuff >> 24); + try { + bsStream.WriteByte((byte)ch); // write 8-bit + } catch (IOException e) { + throw e; + } + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + } + + private void BsW(int n, int v) { + while (bsLive >= 8) { + int ch = (bsBuff >> 24); + try { + bsStream.WriteByte((byte)ch); // write 8-bit + } catch (IOException e) { + throw e; + } + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + bsBuff |= (v << (32 - bsLive - n)); + bsLive += n; + } + + private void BsPutUChar(int c) { + BsW(8, c); + } + + private void BsPutint(int u) { + BsW(8, (u >> 24) & 0xff); + BsW(8, (u >> 16) & 0xff); + BsW(8, (u >> 8) & 0xff); + BsW(8, u & 0xff); + } + + private void BsPutIntVS(int numBits, int c) { + BsW(numBits, c); + } + + private void SendMTFValues() { + char[][] len = CBZip2InputStream.InitCharArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + + int v, t, i, j, gs, ge, totc, bt, bc, iter; + int nSelectors = 0, alphaSize, minLen, maxLen, selCtr; + int nGroups; + + alphaSize = nInUse + 2; + for (t = 0; t < BZip2Constants.N_GROUPS; t++) { + for (v = 0; v < alphaSize; v++) { + len[t][v] = (char) GREATER_ICOST; + } + } + + /* Decide how many coding tables to use */ + if (nMTF <= 0) { + Panic(); + } + + if (nMTF < 200) { + nGroups = 2; + } else if (nMTF < 600) { + nGroups = 3; + } else if (nMTF < 1200) { + nGroups = 4; + } else if (nMTF < 2400) { + nGroups = 5; + } else { + nGroups = 6; + } + + /* Generate an initial set of coding tables */ { + int nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs - 1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize - 1) { + ge++; + aFreq += mtfFreq[ge]; + } + + if (ge > gs && nPart != nGroups && nPart != 1 + && ((nGroups - nPart) % 2 == 1)) { + aFreq -= mtfFreq[ge]; + ge--; + } + + for (v = 0; v < alphaSize; v++) { + if (v >= gs && v <= ge) { + len[nPart - 1][v] = (char) LESSER_ICOST; + } else { + len[nPart - 1][v] = (char) GREATER_ICOST; + } + } + + nPart--; + gs = ge + 1; + remF -= aFreq; + } + } + + int[][] rfreq = CBZip2InputStream.InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + int[] fave = new int[BZip2Constants.N_GROUPS]; + short[] cost = new short[BZip2Constants.N_GROUPS]; + /* + Iterate up to N_ITERS times to improve the tables. + */ + for (iter = 0; iter < BZip2Constants.N_ITERS; iter++) { + for (t = 0; t < nGroups; t++) { + fave[t] = 0; + } + + for (t = 0; t < nGroups; t++) { + for (v = 0; v < alphaSize; v++) { + rfreq[t][v] = 0; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (true) { + + /* Set group start & end marks. */ + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.G_SIZE - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + /* + Calculate the cost of this group as coded + by each of the coding tables. + */ + for (t = 0; t < nGroups; t++) { + cost[t] = 0; + } + + if (nGroups == 6) { + short cost0, cost1, cost2, cost3, cost4, cost5; + cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0; + for (i = gs; i <= ge; i++) { + short icv = szptr[i]; + cost0 += (short)len[0][icv]; + cost1 += (short)len[1][icv]; + cost2 += (short)len[2][icv]; + cost3 += (short)len[3][icv]; + cost4 += (short)len[4][icv]; + cost5 += (short)len[5][icv]; + } + cost[0] = cost0; + cost[1] = cost1; + cost[2] = cost2; + cost[3] = cost3; + cost[4] = cost4; + cost[5] = cost5; + } else { + for (i = gs; i <= ge; i++) { + short icv = szptr[i]; + for (t = 0; t < nGroups; t++) { + cost[t] += (short)len[t][icv]; + } + } + } + + /* + Find the coding table which is best for this group, + and record its identity in the selector table. + */ + bc = 999999999; + bt = -1; + for (t = 0; t < nGroups; t++) { + if (cost[t] < bc) { + bc = cost[t]; + bt = t; + } + }; + totc += bc; + fave[bt]++; + selector[nSelectors] = (char) bt; + nSelectors++; + + /* + Increment the symbol frequencies for the selected table. + */ + for (i = gs; i <= ge; i++) { + rfreq[bt][szptr[i]]++; + } + + gs = ge + 1; + } + + /* + Recompute the tables based on the accumulated frequencies. + */ + for (t = 0; t < nGroups; t++) { + HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20); + } + } + + rfreq = null; + fave = null; + cost = null; + + if (!(nGroups < 8)) { + Panic(); + } + if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.G_SIZE)))) { + Panic(); + } + + + /* Compute MTF values for the selectors. */ + { + char[] pos = new char[BZip2Constants.N_GROUPS]; + char ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) { + pos[i] = (char) i; + } + for (i = 0; i < nSelectors; i++) { + ll_i = selector[i]; + j = 0; + tmp = pos[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + } + pos[0] = tmp; + selectorMtf[i] = (char) j; + } + } + + int[][] code = CBZip2InputStream.InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE); + + /* Assign actual codes for the tables. */ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + if (maxLen > 20) { + Panic(); + } + if (minLen < 1) { + Panic(); + } + HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize); + } + + /* Transmit the mapping table. */ + { + bool[] inUse16 = new bool[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = false; + for (j = 0; j < 16; j++) { + if (inUse[i * 16 + j]) { + inUse16[i] = true; + } + } + } + + for (i = 0; i < 16; i++) { + if (inUse16[i]) { + BsW(1, 1); + } else { + BsW(1, 0); + } + } + + for (i = 0; i < 16; i++) { + if (inUse16[i]) { + for (j = 0; j < 16; j++) { + if (inUse[i * 16 + j]) { + BsW(1, 1); + } else { + BsW(1, 0); + } + } + } + } + + } + + /* Now the selectors. */ + BsW(3, nGroups); + BsW(15, nSelectors); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < selectorMtf[i]; j++) { + BsW(1, 1); + } + BsW(1, 0); + } + + /* Now the coding tables. */ + for (t = 0; t < nGroups; t++) { + int curr = len[t][0]; + BsW(5, curr); + for (i = 0; i < alphaSize; i++) { + while (curr < len[t][i]) { + BsW(2, 2); + curr++; /* 10 */ + } + while (curr > len[t][i]) { + BsW(2, 3); + curr--; /* 11 */ + } + BsW(1, 0); + } + } + + /* And finally, the block data proper */ + selCtr = 0; + gs = 0; + while (true) { + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.G_SIZE - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + for (i = gs; i <= ge; i++) { + BsW(len[selector[selCtr]][szptr[i]], + code[selector[selCtr]][szptr[i]]); + } + + gs = ge + 1; + selCtr++; + } + if (!(selCtr == nSelectors)) { + Panic(); + } + } + + private void MoveToFrontCodeAndSend() { + BsPutIntVS(24, origPtr); + GenerateMTFValues(); + SendMTFValues(); + } + + private Stream bsStream; + + private void SimpleSort(int lo, int hi, int d) { + int i, j, h, bigN, hp; + int v; + + bigN = hi - lo + 1; + if (bigN < 2) { + return; + } + + hp = 0; + while (incs[hp] < bigN) { + hp++; + } + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (true) { + /* copy 1 */ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU(zptr[j - h] + d, v + d)) { + zptr[j] = zptr[j - h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /* copy 2 */ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU(zptr[j - h] + d, v + d)) { + zptr[j] = zptr[j - h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /* copy 3 */ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU(zptr[j - h] + d, v + d)) { + zptr[j] = zptr[j - h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + if (workDone > workLimit && firstAttempt) { + return; + } + } + } + } + + private void Vswap(int p1, int p2, int n) { + int temp = 0; + while (n > 0) { + temp = zptr[p1]; + zptr[p1] = zptr[p2]; + zptr[p2] = temp; + p1++; + p2++; + n--; + } + } + + private char Med3(char a, char b, char c) { + char t; + if (a > b) { + t = a; + a = b; + b = t; + } + if (b > c) { + t = b; + b = c; + c = t; + } + if (a > b) { + b = a; + } + return b; + } + + internal class StackElem { + internal int ll; + internal int hh; + internal int dd; + } + + private void QSort3(int loSt, int hiSt, int dSt) { + int unLo, unHi, ltLo, gtHi, med, n, m; + int sp, lo, hi, d; + StackElem[] stack = new StackElem[QSORT_STACK_SIZE]; + for (int count = 0; count < QSORT_STACK_SIZE; count++) { + stack[count] = new StackElem(); + } + + sp = 0; + + stack[sp].ll = loSt; + stack[sp].hh = hiSt; + stack[sp].dd = dSt; + sp++; + + while (sp > 0) { + if (sp >= QSORT_STACK_SIZE) { + Panic(); + } + + sp--; + lo = stack[sp].ll; + hi = stack[sp].hh; + d = stack[sp].dd; + + if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) { + SimpleSort(lo, hi, d); + if (workDone > workLimit && firstAttempt) { + return; + } + continue; + } + + med = Med3(block[zptr[lo] + d + 1], + block[zptr[hi ] + d + 1], + block[zptr[(lo + hi) >> 1] + d + 1]); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (true) { + while (true) { + if (unLo > unHi) { + break; + } + n = ((int) block[zptr[unLo] + d + 1]) - med; + if (n == 0) { + int temp = 0; + temp = zptr[unLo]; + zptr[unLo] = zptr[ltLo]; + zptr[ltLo] = temp; + ltLo++; + unLo++; + continue; + }; + if (n > 0) { + break; + } + unLo++; + } + while (true) { + if (unLo > unHi) { + break; + } + n = ((int) block[zptr[unHi] + d + 1]) - med; + if (n == 0) { + int temp = 0; + temp = zptr[unHi]; + zptr[unHi] = zptr[gtHi]; + zptr[gtHi] = temp; + gtHi--; + unHi--; + continue; + }; + if (n < 0) { + break; + } + unHi--; + } + if (unLo > unHi) { + break; + } + int tempx = zptr[unLo]; + zptr[unLo] = zptr[unHi]; + zptr[unHi] = tempx; + unLo++; + unHi--; + } + + if (gtHi < ltLo) { + stack[sp].ll = lo; + stack[sp].hh = hi; + stack[sp].dd = d + 1; + sp++; + continue; + } + + n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo) : (unLo - ltLo); + Vswap(lo, unLo - n, n); + m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi) : (gtHi - unHi); + Vswap(unLo, hi - m + 1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + stack[sp].ll = lo; + stack[sp].hh = n; + stack[sp].dd = d; + sp++; + + stack[sp].ll = n + 1; + stack[sp].hh = m - 1; + stack[sp].dd = d + 1; + sp++; + + stack[sp].ll = m; + stack[sp].hh = hi; + stack[sp].dd = d; + sp++; + } + } + + private void MainSort() { + int i, j, ss, sb; + int[] runningOrder = new int[256]; + int[] copy = new int[256]; + bool[] bigDone = new bool[256]; + int c1, c2; + int numQSorted; + + /* + In the various block-sized structures, live data runs + from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First, + set up the overshoot area for block. + */ + + // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" ); + for (i = 0; i < BZip2Constants.NUM_OVERSHOOT_BYTES; i++) { + block[last + i + 2] = block[(i % (last + 1)) + 1]; + } + for (i = 0; i <= last + BZip2Constants.NUM_OVERSHOOT_BYTES; i++) { + quadrant[i] = 0; + } + + block[0] = (char) (block[last + 1]); + + if (last < 4000) { + /* + Use SimpleSort(), since the full sorting mechanism + has quite a large constant overhead. + */ + for (i = 0; i <= last; i++) { + zptr[i] = i; + } + firstAttempt = false; + workDone = workLimit = 0; + SimpleSort(0, last, 0); + } else { + numQSorted = 0; + for (i = 0; i <= 255; i++) { + bigDone[i] = false; + } + + for (i = 0; i <= 65536; i++) { + ftab[i] = 0; + } + + c1 = block[0]; + for (i = 0; i <= last; i++) { + c2 = block[i + 1]; + ftab[(c1 << 8) + c2]++; + c1 = c2; + } + + for (i = 1; i <= 65536; i++) { + ftab[i] += ftab[i - 1]; + } + + c1 = block[1]; + for (i = 0; i < last; i++) { + c2 = block[i + 2]; + j = (c1 << 8) + c2; + c1 = c2; + ftab[j]--; + zptr[ftab[j]] = i; + } + + j = ((block[last + 1]) << 8) + (block[1]); + ftab[j]--; + zptr[ftab[j]] = last; + + /* + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + */ + + for (i = 0; i <= 255; i++) { + runningOrder[i] = i; + } + + { + int vv; + int h = 1; + do { + h = 3 * h + 1; + } + while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ((ftab[((runningOrder[j - h]) + 1) << 8] + - ftab[(runningOrder[j - h]) << 8]) > + (ftab[((vv) + 1) << 8] - ftab[(vv) << 8])) { + runningOrder[j] = runningOrder[j - h]; + j = j - h; + if (j <= (h - 1)) { + break; + } + } + runningOrder[j] = vv; + } + } while (h != 1); + } + + /* + The main sorting loop. + */ + for (i = 0; i <= 255; i++) { + + /* + Process big buckets, starting with the least full. + */ + ss = runningOrder[i]; + + /* + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j]. Hopefully + previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + */ + for (j = 0; j <= 255; j++) { + sb = (ss << 8) + j; + if (!((ftab[sb] & SETMASK) == SETMASK)) { + int lo = ftab[sb] & CLEARMASK; + int hi = (ftab[sb + 1] & CLEARMASK) - 1; + if (hi > lo) { + QSort3(lo, hi, 2); + numQSorted += (hi - lo + 1); + if (workDone > workLimit && firstAttempt) { + return; + } + } + ftab[sb] |= SETMASK; + } + } + + /* + The ss big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + */ + bigDone[ss] = true; + + if (i < 255) { + int bbStart = ftab[ss << 8] & CLEARMASK; + int bbSize = (ftab[(ss + 1) << 8] & CLEARMASK) - bbStart; + int shifts = 0; + + while ((bbSize >> shifts) > 65534) { + shifts++; + } + + for (j = 0; j < bbSize; j++) { + int a2update = zptr[bbStart + j]; + int qVal = (j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZip2Constants.NUM_OVERSHOOT_BYTES) { + quadrant[a2update + last + 1] = qVal; + } + } + + if (!(((bbSize - 1) >> shifts) <= 65535)) { + Panic(); + } + } + + /* + Now scan this big bucket so as to synthesise the + sorted order for small buckets [t, ss] for all t != ss. + */ + for (j = 0; j <= 255; j++) { + copy[j] = ftab[(j << 8) + ss] & CLEARMASK; + } + + for (j = ftab[ss << 8] & CLEARMASK; + j < (ftab[(ss + 1) << 8] & CLEARMASK); j++) { + c1 = block[zptr[j]]; + if (!bigDone[c1]) { + zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1; + copy[c1]++; + } + } + + for (j = 0; j <= 255; j++) { + ftab[(j << 8) + ss] |= SETMASK; + } + } + } + } + + private void RandomiseBlock() { + int i; + int rNToGo = 0; + int rTPos = 0; + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i <= last; i++) { + if (rNToGo == 0) { + rNToGo = (char) BZip2Constants.rNums[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + block[i + 1] ^= (char)((rNToGo == 1) ? 1 : 0); + // handle 16 bit signed numbers + block[i + 1] &= (char)0xFF; + + inUse[block[i + 1]] = true; + } + } + + private void DoReversibleTransformation() { + int i; + + workLimit = workFactor * last; + workDone = 0; + blockRandomised = false; + firstAttempt = true; + + MainSort(); + + if (workDone > workLimit && firstAttempt) { + RandomiseBlock(); + workLimit = workDone = 0; + blockRandomised = true; + firstAttempt = false; + MainSort(); + } + + origPtr = -1; + for (i = 0; i <= last; i++) { + if (zptr[i] == 0) { + origPtr = i; + break; + } + }; + + if (origPtr == -1) { + Panic(); + } + } + + private bool FullGtU(int i1, int i2) { + int k; + char c1, c2; + int s1, s2; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + i1++; + i2++; + + k = last + 1; + + do { + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return (s1 > s2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return (s1 > s2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return (s1 > s2); + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return (c1 > c2); + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return (s1 > s2); + } + i1++; + i2++; + + if (i1 > last) { + i1 -= last; + i1--; + }; + if (i2 > last) { + i2 -= last; + i2--; + }; + + k -= 4; + workDone++; + } while (k >= 0); + + return false; + } + + /* + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. + */ + private int[] incs = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + + private void AllocateCompressStructures() { + int n = BZip2Constants.baseBlockSize * blockSize100k; + block = new char[(n + 1 + BZip2Constants.NUM_OVERSHOOT_BYTES)]; + quadrant = new int[(n + BZip2Constants.NUM_OVERSHOOT_BYTES)]; + zptr = new int[n]; + ftab = new int[65537]; + + if (block == null || quadrant == null || zptr == null + || ftab == null) { + //int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537; + //compressOutOfMemory ( totalDraw, n ); + } + + /* + The back end needs a place to store the MTF values + whilst it calculates the coding tables. We could + put them in the zptr array. However, these values + will fit in a short, so we overlay szptr at the + start of zptr, in the hope of reducing the number + of cache misses induced by the multiple traversals + of the MTF values when calculating coding tables. + Seems to improve compression speed by about 1%. + */ + // szptr = zptr; + + + szptr = new short[2 * n]; + } + + private void GenerateMTFValues() { + char[] yy = new char[256]; + int i, j; + char tmp; + char tmp2; + int zPend; + int wr; + int EOB; + + MakeMaps(); + EOB = nInUse + 1; + + for (i = 0; i <= EOB; i++) { + mtfFreq[i] = 0; + } + + wr = 0; + zPend = 0; + for (i = 0; i < nInUse; i++) { + yy[i] = (char) i; + } + + + for (i = 0; i <= last; i++) { + char ll_i; + + ll_i = unseqToSeq[block[zptr[i]]]; + + j = 0; + tmp = yy[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = yy[j]; + yy[j] = tmp2; + }; + yy[0] = tmp; + + if (j == 0) { + zPend++; + } else { + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short) BZip2Constants.RUNA; + wr++; + mtfFreq[BZip2Constants.RUNA]++; + break; + case 1: + szptr[wr] = (short) BZip2Constants.RUNB; + wr++; + mtfFreq[BZip2Constants.RUNB]++; + break; + }; + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + szptr[wr] = (short) (j + 1); + wr++; + mtfFreq[j + 1]++; + } + } + + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short) BZip2Constants.RUNA; + wr++; + mtfFreq[BZip2Constants.RUNA]++; + break; + case 1: + szptr[wr] = (short) BZip2Constants.RUNB; + wr++; + mtfFreq[BZip2Constants.RUNB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + } + + szptr[wr] = (short) EOB; + wr++; + mtfFreq[EOB]++; + + nMTF = wr; + } + + public override int Read(byte[] buffer, int offset, int count) { + return 0; + } + + public override long Seek(long offset, SeekOrigin origin) { + return 0; + } + + public override void SetLength(long value) { + } + + public override void Write(byte[] buffer, int offset, int count) { + for (int k = 0; k < count; ++k) { + WriteByte(buffer[k + offset]); + } + } + + public override bool CanRead { + get { + return false; + } + } + + public override bool CanSeek { + get { + return false; + } + } + + public override bool CanWrite { + get { + return true; + } + } + + public override long Length { + get { + return 0; + } + } + + public override long Position { + get { + return 0; + } + set { + } + } + } +} \ No newline at end of file diff --git a/crypto/bzip2/src/CRC.cs b/crypto/bzip2/src/CRC.cs new file mode 100644 index 000000000..278a9f336 --- /dev/null +++ b/crypto/bzip2/src/CRC.cs @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This package is based on the work done by Keiron Liddle), Aftex Software + * to whom the Ant project is very grateful for his + * great code. + */ + +using System; + +namespace Org.BouncyCastle.Apache.Bzip2 +{ + /** + * A simple class the hold and calculate the CRC for sanity checking + * of the data. + * + * @author Keiron Liddle + */ + internal class CRC + { + public static readonly int[] crc32Table = { + unchecked((int)0x00000000), unchecked((int)0x04c11db7), unchecked((int)0x09823b6e), unchecked((int)0x0d4326d9), + unchecked((int)0x130476dc), unchecked((int)0x17c56b6b), unchecked((int)0x1a864db2), unchecked((int)0x1e475005), + unchecked((int)0x2608edb8), unchecked((int)0x22c9f00f), unchecked((int)0x2f8ad6d6), unchecked((int)0x2b4bcb61), + unchecked((int)0x350c9b64), unchecked((int)0x31cd86d3), unchecked((int)0x3c8ea00a), unchecked((int)0x384fbdbd), + unchecked((int)0x4c11db70), unchecked((int)0x48d0c6c7), unchecked((int)0x4593e01e), unchecked((int)0x4152fda9), + unchecked((int)0x5f15adac), unchecked((int)0x5bd4b01b), unchecked((int)0x569796c2), unchecked((int)0x52568b75), + unchecked((int)0x6a1936c8), unchecked((int)0x6ed82b7f), unchecked((int)0x639b0da6), unchecked((int)0x675a1011), + unchecked((int)0x791d4014), unchecked((int)0x7ddc5da3), unchecked((int)0x709f7b7a), unchecked((int)0x745e66cd), + unchecked((int)0x9823b6e0), unchecked((int)0x9ce2ab57), unchecked((int)0x91a18d8e), unchecked((int)0x95609039), + unchecked((int)0x8b27c03c), unchecked((int)0x8fe6dd8b), unchecked((int)0x82a5fb52), unchecked((int)0x8664e6e5), + unchecked((int)0xbe2b5b58), unchecked((int)0xbaea46ef), unchecked((int)0xb7a96036), unchecked((int)0xb3687d81), + unchecked((int)0xad2f2d84), unchecked((int)0xa9ee3033), unchecked((int)0xa4ad16ea), unchecked((int)0xa06c0b5d), + unchecked((int)0xd4326d90), unchecked((int)0xd0f37027), unchecked((int)0xddb056fe), unchecked((int)0xd9714b49), + unchecked((int)0xc7361b4c), unchecked((int)0xc3f706fb), unchecked((int)0xceb42022), unchecked((int)0xca753d95), + unchecked((int)0xf23a8028), unchecked((int)0xf6fb9d9f), unchecked((int)0xfbb8bb46), unchecked((int)0xff79a6f1), + unchecked((int)0xe13ef6f4), unchecked((int)0xe5ffeb43), unchecked((int)0xe8bccd9a), unchecked((int)0xec7dd02d), + unchecked((int)0x34867077), unchecked((int)0x30476dc0), unchecked((int)0x3d044b19), unchecked((int)0x39c556ae), + unchecked((int)0x278206ab), unchecked((int)0x23431b1c), unchecked((int)0x2e003dc5), unchecked((int)0x2ac12072), + unchecked((int)0x128e9dcf), unchecked((int)0x164f8078), unchecked((int)0x1b0ca6a1), unchecked((int)0x1fcdbb16), + unchecked((int)0x018aeb13), unchecked((int)0x054bf6a4), unchecked((int)0x0808d07d), unchecked((int)0x0cc9cdca), + unchecked((int)0x7897ab07), unchecked((int)0x7c56b6b0), unchecked((int)0x71159069), unchecked((int)0x75d48dde), + unchecked((int)0x6b93dddb), unchecked((int)0x6f52c06c), unchecked((int)0x6211e6b5), unchecked((int)0x66d0fb02), + unchecked((int)0x5e9f46bf), unchecked((int)0x5a5e5b08), unchecked((int)0x571d7dd1), unchecked((int)0x53dc6066), + unchecked((int)0x4d9b3063), unchecked((int)0x495a2dd4), unchecked((int)0x44190b0d), unchecked((int)0x40d816ba), + unchecked((int)0xaca5c697), unchecked((int)0xa864db20), unchecked((int)0xa527fdf9), unchecked((int)0xa1e6e04e), + unchecked((int)0xbfa1b04b), unchecked((int)0xbb60adfc), unchecked((int)0xb6238b25), unchecked((int)0xb2e29692), + unchecked((int)0x8aad2b2f), unchecked((int)0x8e6c3698), unchecked((int)0x832f1041), unchecked((int)0x87ee0df6), + unchecked((int)0x99a95df3), unchecked((int)0x9d684044), unchecked((int)0x902b669d), unchecked((int)0x94ea7b2a), + unchecked((int)0xe0b41de7), unchecked((int)0xe4750050), unchecked((int)0xe9362689), unchecked((int)0xedf73b3e), + unchecked((int)0xf3b06b3b), unchecked((int)0xf771768c), unchecked((int)0xfa325055), unchecked((int)0xfef34de2), + unchecked((int)0xc6bcf05f), unchecked((int)0xc27dede8), unchecked((int)0xcf3ecb31), unchecked((int)0xcbffd686), + unchecked((int)0xd5b88683), unchecked((int)0xd1799b34), unchecked((int)0xdc3abded), unchecked((int)0xd8fba05a), + unchecked((int)0x690ce0ee), unchecked((int)0x6dcdfd59), unchecked((int)0x608edb80), unchecked((int)0x644fc637), + unchecked((int)0x7a089632), unchecked((int)0x7ec98b85), unchecked((int)0x738aad5c), unchecked((int)0x774bb0eb), + unchecked((int)0x4f040d56), unchecked((int)0x4bc510e1), unchecked((int)0x46863638), unchecked((int)0x42472b8f), + unchecked((int)0x5c007b8a), unchecked((int)0x58c1663d), unchecked((int)0x558240e4), unchecked((int)0x51435d53), + unchecked((int)0x251d3b9e), unchecked((int)0x21dc2629), unchecked((int)0x2c9f00f0), unchecked((int)0x285e1d47), + unchecked((int)0x36194d42), unchecked((int)0x32d850f5), unchecked((int)0x3f9b762c), unchecked((int)0x3b5a6b9b), + unchecked((int)0x0315d626), unchecked((int)0x07d4cb91), unchecked((int)0x0a97ed48), unchecked((int)0x0e56f0ff), + unchecked((int)0x1011a0fa), unchecked((int)0x14d0bd4d), unchecked((int)0x19939b94), unchecked((int)0x1d528623), + unchecked((int)0xf12f560e), unchecked((int)0xf5ee4bb9), unchecked((int)0xf8ad6d60), unchecked((int)0xfc6c70d7), + unchecked((int)0xe22b20d2), unchecked((int)0xe6ea3d65), unchecked((int)0xeba91bbc), unchecked((int)0xef68060b), + unchecked((int)0xd727bbb6), unchecked((int)0xd3e6a601), unchecked((int)0xdea580d8), unchecked((int)0xda649d6f), + unchecked((int)0xc423cd6a), unchecked((int)0xc0e2d0dd), unchecked((int)0xcda1f604), unchecked((int)0xc960ebb3), + unchecked((int)0xbd3e8d7e), unchecked((int)0xb9ff90c9), unchecked((int)0xb4bcb610), unchecked((int)0xb07daba7), + unchecked((int)0xae3afba2), unchecked((int)0xaafbe615), unchecked((int)0xa7b8c0cc), unchecked((int)0xa379dd7b), + unchecked((int)0x9b3660c6), unchecked((int)0x9ff77d71), unchecked((int)0x92b45ba8), unchecked((int)0x9675461f), + unchecked((int)0x8832161a), unchecked((int)0x8cf30bad), unchecked((int)0x81b02d74), unchecked((int)0x857130c3), + unchecked((int)0x5d8a9099), unchecked((int)0x594b8d2e), unchecked((int)0x5408abf7), unchecked((int)0x50c9b640), + unchecked((int)0x4e8ee645), unchecked((int)0x4a4ffbf2), unchecked((int)0x470cdd2b), unchecked((int)0x43cdc09c), + unchecked((int)0x7b827d21), unchecked((int)0x7f436096), unchecked((int)0x7200464f), unchecked((int)0x76c15bf8), + unchecked((int)0x68860bfd), unchecked((int)0x6c47164a), unchecked((int)0x61043093), unchecked((int)0x65c52d24), + unchecked((int)0x119b4be9), unchecked((int)0x155a565e), unchecked((int)0x18197087), unchecked((int)0x1cd86d30), + unchecked((int)0x029f3d35), unchecked((int)0x065e2082), unchecked((int)0x0b1d065b), unchecked((int)0x0fdc1bec), + unchecked((int)0x3793a651), unchecked((int)0x3352bbe6), unchecked((int)0x3e119d3f), unchecked((int)0x3ad08088), + unchecked((int)0x2497d08d), unchecked((int)0x2056cd3a), unchecked((int)0x2d15ebe3), unchecked((int)0x29d4f654), + unchecked((int)0xc5a92679), unchecked((int)0xc1683bce), unchecked((int)0xcc2b1d17), unchecked((int)0xc8ea00a0), + unchecked((int)0xd6ad50a5), unchecked((int)0xd26c4d12), unchecked((int)0xdf2f6bcb), unchecked((int)0xdbee767c), + unchecked((int)0xe3a1cbc1), unchecked((int)0xe760d676), unchecked((int)0xea23f0af), unchecked((int)0xeee2ed18), + unchecked((int)0xf0a5bd1d), unchecked((int)0xf464a0aa), unchecked((int)0xf9278673), unchecked((int)0xfde69bc4), + unchecked((int)0x89b8fd09), unchecked((int)0x8d79e0be), unchecked((int)0x803ac667), unchecked((int)0x84fbdbd0), + unchecked((int)0x9abc8bd5), unchecked((int)0x9e7d9662), unchecked((int)0x933eb0bb), unchecked((int)0x97ffad0c), + unchecked((int)0xafb010b1), unchecked((int)0xab710d06), unchecked((int)0xa6322bdf), unchecked((int)0xa2f33668), + unchecked((int)0xbcb4666d), unchecked((int)0xb8757bda), unchecked((int)0xb5365d03), unchecked((int)0xb1f740b4) + }; + + public CRC() { + InitialiseCRC(); + } + + internal void InitialiseCRC() { + globalCrc = unchecked((int)0xffffffff); + } + + internal int GetFinalCRC() { + return ~globalCrc; + } + + internal int GetGlobalCRC() { + return globalCrc; + } + + internal void SetGlobalCRC(int newCrc) { + globalCrc = newCrc; + } + + internal void UpdateCRC(int inCh) { + int temp = (globalCrc >> 24) ^ inCh; + if (temp < 0) { + temp = 256 + temp; + } + globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp]; + } + + internal int globalCrc; + } +} \ No newline at end of file diff --git a/crypto/checklist.txt b/crypto/checklist.txt new file mode 100644 index 000000000..39b8fc4af --- /dev/null +++ b/crypto/checklist.txt @@ -0,0 +1,16 @@ +----------------- +Release Checklist +----------------- + +- Update to latest from CVS +- Run 'nant -t:net-1.1 clean test' +- Run 'nant -t:netcf-1.0 clean compile-release' +- Edit AssemblyInfo.cs: Change version and check copyright +- Edit NBuild.build: Change version +- Edit License.html: Check copyright +- Edit Readme.html: Add release notes +- Commit changes to CVS +- Tag CVS HEAD with "release-${version}" +- Place BouncyCastle.snk in parent directory +- Run 'nant -t:net-1.1 clean dist' + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj new file mode 100644 index 000000000..76c91ae2b --- /dev/null +++ b/crypto/crypto.csproj @@ -0,0 +1,10628 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crypto/crypto.mdp b/crypto/crypto.mdp new file mode 100644 index 000000000..8152a40a9 --- /dev/null +++ b/crypto/crypto.mdp @@ -0,0 +1,2310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs new file mode 100644 index 000000000..4e85daa95 --- /dev/null +++ b/crypto/src/AssemblyInfo.cs @@ -0,0 +1,81 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +//using System.Security.Permissions; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +#if INCLUDE_IDEA +[assembly: AssemblyTitle("BouncyCastle.CryptoExt")] +[assembly: AssemblyDescription("Bouncy Castle Cryptography API (Extended)")] +#else +[assembly: AssemblyTitle("BouncyCastle.Crypto")] +[assembly: AssemblyDescription("Bouncy Castle Cryptography API")] +#endif +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Legion of the Bouncy Castle")] +[assembly: AssemblyProduct("Bouncy Castle for .NET")] +[assembly: AssemblyCopyright("Copyright (C) 2000-2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.7.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +#if STRONG_NAME +[assembly: AssemblyKeyFile(@"../BouncyCastle.snk")] +#else +[assembly: AssemblyKeyFile("")] +#endif +[assembly: AssemblyKeyName("")] + +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] + +// Start with no permissions +//[assembly: PermissionSet(SecurityAction.RequestOptional, Unrestricted=false)] +//...and explicitly add those we need + +// see Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabledProperty +//[assembly: EnvironmentPermission(SecurityAction.RequestOptional, Read="Org.BouncyCastle.Pkcs1.Strict")] + diff --git a/crypto/src/asn1/ASN1Generator.cs b/crypto/src/asn1/ASN1Generator.cs new file mode 100644 index 000000000..e56051736 --- /dev/null +++ b/crypto/src/asn1/ASN1Generator.cs @@ -0,0 +1,27 @@ +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class Asn1Generator + { + private Stream _out; + + protected Asn1Generator( + Stream outStream) + { + _out = outStream; + } + + protected Stream Out + { + get { return _out; } + } + + public abstract void AddObject(Asn1Encodable obj); + + public abstract Stream GetRawOutputStream(); + + public abstract void Close(); + } +} diff --git a/crypto/src/asn1/ASN1OctetStringParser.cs b/crypto/src/asn1/ASN1OctetStringParser.cs new file mode 100644 index 000000000..5815aa42f --- /dev/null +++ b/crypto/src/asn1/ASN1OctetStringParser.cs @@ -0,0 +1,10 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public interface Asn1OctetStringParser + : IAsn1Convertible + { + Stream GetOctetStream(); + } +} diff --git a/crypto/src/asn1/ASN1SequenceParser.cs b/crypto/src/asn1/ASN1SequenceParser.cs new file mode 100644 index 000000000..9e88ac788 --- /dev/null +++ b/crypto/src/asn1/ASN1SequenceParser.cs @@ -0,0 +1,8 @@ +namespace Org.BouncyCastle.Asn1 +{ + public interface Asn1SequenceParser + : IAsn1Convertible + { + IAsn1Convertible ReadObject(); + } +} diff --git a/crypto/src/asn1/ASN1SetParser.cs b/crypto/src/asn1/ASN1SetParser.cs new file mode 100644 index 000000000..d1b9c64e2 --- /dev/null +++ b/crypto/src/asn1/ASN1SetParser.cs @@ -0,0 +1,8 @@ +namespace Org.BouncyCastle.Asn1 +{ + public interface Asn1SetParser + : IAsn1Convertible + { + IAsn1Convertible ReadObject(); + } +} diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs new file mode 100644 index 000000000..a5e6e3164 --- /dev/null +++ b/crypto/src/asn1/ASN1StreamParser.cs @@ -0,0 +1,235 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class Asn1StreamParser + { + private readonly Stream _in; + private readonly int _limit; + + private readonly byte[][] tmpBuffers; + + public Asn1StreamParser( + Stream inStream) + : this(inStream, Asn1InputStream.FindLimit(inStream)) + { + } + + public Asn1StreamParser( + Stream inStream, + int limit) + { + if (!inStream.CanRead) + throw new ArgumentException("Expected stream to be readable", "inStream"); + + this._in = inStream; + this._limit = limit; + this.tmpBuffers = new byte[16][]; + } + + public Asn1StreamParser( + byte[] encoding) + : this(new MemoryStream(encoding, false), encoding.Length) + { + } + + internal IAsn1Convertible ReadIndef(int tagValue) + { + // Note: INDEF => CONSTRUCTED + + // TODO There are other tags that may be constructed (e.g. BIT_STRING) + switch (tagValue) + { + case Asn1Tags.External: + return new DerExternalParser(this); + case Asn1Tags.OctetString: + return new BerOctetStringParser(this); + case Asn1Tags.Sequence: + return new BerSequenceParser(this); + case Asn1Tags.Set: + return new BerSetParser(this); + default: + throw new Asn1Exception("unknown BER object encountered: 0x" + tagValue.ToString("X")); + } + } + + internal IAsn1Convertible ReadImplicit(bool constructed, int tag) + { + if (_in is IndefiniteLengthInputStream) + { + if (!constructed) + throw new IOException("indefinite length primitive encoding encountered"); + + return ReadIndef(tag); + } + + if (constructed) + { + switch (tag) + { + case Asn1Tags.Set: + return new DerSetParser(this); + case Asn1Tags.Sequence: + return new DerSequenceParser(this); + case Asn1Tags.OctetString: + return new BerOctetStringParser(this); + } + } + else + { + switch (tag) + { + case Asn1Tags.Set: + throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)"); + case Asn1Tags.Sequence: + throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)"); + case Asn1Tags.OctetString: + return new DerOctetStringParser((DefiniteLengthInputStream)_in); + } + } + + throw new Asn1Exception("implicit tagging not implemented"); + } + + internal Asn1Object ReadTaggedObject(bool constructed, int tag) + { + if (!constructed) + { + // Note: !CONSTRUCTED => IMPLICIT + DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in; + return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray())); + } + + Asn1EncodableVector v = ReadVector(); + + if (_in is IndefiniteLengthInputStream) + { + return v.Count == 1 + ? new BerTaggedObject(true, tag, v[0]) + : new BerTaggedObject(false, tag, BerSequence.FromVector(v)); + } + + return v.Count == 1 + ? new DerTaggedObject(true, tag, v[0]) + : new DerTaggedObject(false, tag, DerSequence.FromVector(v)); + } + + public virtual IAsn1Convertible ReadObject() + { + int tag = _in.ReadByte(); + 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); + + bool isConstructed = (tag & Asn1Tags.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 & Asn1Tags.Application) != 0) + { + return new BerApplicationSpecificParser(tagNo, sp); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new BerTaggedObjectParser(true, tagNo, sp); + } + + return sp.ReadIndef(tagNo); + } + else + { + DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length); + + if ((tag & Asn1Tags.Application) != 0) + { + return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray()); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new BerTaggedObjectParser(isConstructed, tagNo, new Asn1StreamParser(defIn)); + } + + if (isConstructed) + { + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) + { + case Asn1Tags.OctetString: + // + // yes, people actually do this... + // + return new BerOctetStringParser(new Asn1StreamParser(defIn)); + case Asn1Tags.Sequence: + return new DerSequenceParser(new Asn1StreamParser(defIn)); + case Asn1Tags.Set: + return new DerSetParser(new Asn1StreamParser(defIn)); + case Asn1Tags.External: + return new DerExternalParser(new Asn1StreamParser(defIn)); + default: + // TODO Add DerUnknownTagParser class? + return new DerUnknownTag(true, tagNo, defIn.ToArray()); + } + } + + // Some primitive encodings can be handled by parsers too... + switch (tagNo) + { + case Asn1Tags.OctetString: + return new DerOctetStringParser(defIn); + } + + try + { + return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); + } + catch (ArgumentException e) + { + throw new Asn1Exception("corrupted stream detected", e); + } + } + } + + private void Set00Check( + bool enabled) + { + if (_in is IndefiniteLengthInputStream) + { + ((IndefiniteLengthInputStream) _in).SetEofOn00(enabled); + } + } + + internal Asn1EncodableVector ReadVector() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + IAsn1Convertible obj; + while ((obj = ReadObject()) != null) + { + v.Add(obj.ToAsn1Object()); + } + + return v; + } + } +} diff --git a/crypto/src/asn1/ASN1TaggedObjectParser.cs b/crypto/src/asn1/ASN1TaggedObjectParser.cs new file mode 100644 index 000000000..32327a269 --- /dev/null +++ b/crypto/src/asn1/ASN1TaggedObjectParser.cs @@ -0,0 +1,10 @@ +namespace Org.BouncyCastle.Asn1 +{ + public interface Asn1TaggedObjectParser + : IAsn1Convertible + { + int TagNo { get; } + + IAsn1Convertible GetObjectParser(int tag, bool isExplicit); + } +} diff --git a/crypto/src/asn1/Asn1Encodable.cs b/crypto/src/asn1/Asn1Encodable.cs new file mode 100644 index 000000000..e3dd9a14c --- /dev/null +++ b/crypto/src/asn1/Asn1Encodable.cs @@ -0,0 +1,78 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class Asn1Encodable + : IAsn1Convertible + { + public const string Der = "DER"; + public const string Ber = "BER"; + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + Asn1OutputStream aOut = new Asn1OutputStream(bOut); + + aOut.WriteObject(this); + + return bOut.ToArray(); + } + + public byte[] GetEncoded( + string encoding) + { + if (encoding.Equals(Der)) + { + MemoryStream bOut = new MemoryStream(); + DerOutputStream dOut = new DerOutputStream(bOut); + + dOut.WriteObject(this); + + return bOut.ToArray(); + } + + return GetEncoded(); + } + + /** + * Return the DER encoding of the object, null if the DER encoding can not be made. + * + * @return a DER byte array, null otherwise. + */ + public byte[] GetDerEncoded() + { + try + { + return GetEncoded(Der); + } + catch (IOException) + { + return null; + } + } + + public sealed override int GetHashCode() + { + return ToAsn1Object().CallAsn1GetHashCode(); + } + + public sealed override bool Equals( + object obj) + { + if (obj == this) + return true; + + IAsn1Convertible other = obj as IAsn1Convertible; + + if (other == null) + return false; + + Asn1Object o1 = ToAsn1Object(); + Asn1Object o2 = other.ToAsn1Object(); + + return o1 == o2 || o1.CallAsn1Equals(o2); + } + + public abstract Asn1Object ToAsn1Object(); + } +} diff --git a/crypto/src/asn1/Asn1EncodableVector.cs b/crypto/src/asn1/Asn1EncodableVector.cs new file mode 100644 index 000000000..49532fe57 --- /dev/null +++ b/crypto/src/asn1/Asn1EncodableVector.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class Asn1EncodableVector + : IEnumerable + { + private IList v = Platform.CreateArrayList(); + + public static Asn1EncodableVector FromEnumerable( + IEnumerable e) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + foreach (Asn1Encodable obj in e) + { + v.Add(obj); + } + return v; + } + +// public Asn1EncodableVector() +// { +// } + + public Asn1EncodableVector( + params Asn1Encodable[] v) + { + Add(v); + } + +// public void Add( +// Asn1Encodable obj) +// { +// v.Add(obj); +// } + + public void Add( + params Asn1Encodable[] objs) + { + foreach (Asn1Encodable obj in objs) + { + v.Add(obj); + } + } + + public void AddOptional( + params Asn1Encodable[] objs) + { + if (objs != null) + { + foreach (Asn1Encodable obj in objs) + { + if (obj != null) + { + v.Add(obj); + } + } + } + } + + public Asn1Encodable this[ + int index] + { + get { return (Asn1Encodable) v[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public Asn1Encodable Get( + int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return v.Count; } + } + + public int Count + { + get { return v.Count; } + } + + public IEnumerator GetEnumerator() + { + return v.GetEnumerator(); + } + } +} diff --git a/crypto/src/asn1/Asn1Exception.cs b/crypto/src/asn1/Asn1Exception.cs new file mode 100644 index 000000000..806cc95d5 --- /dev/null +++ b/crypto/src/asn1/Asn1Exception.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class Asn1Exception + : IOException + { + public Asn1Exception() + : base() + { + } + + public Asn1Exception( + string message) + : base(message) + { + } + + public Asn1Exception( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs new file mode 100644 index 000000000..a72049b56 --- /dev/null +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -0,0 +1,368 @@ +using System; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * 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 + : FilterStream + { + private readonly int limit; + + private readonly byte[][] tmpBuffers; + + internal static int FindLimit(Stream input) + { + if (input is LimitedInputStream) + { + return ((LimitedInputStream)input).GetRemaining(); + } + else if (input is MemoryStream) + { + MemoryStream mem = (MemoryStream)input; + return (int)(mem.Length - mem.Position); + } + + return int.MaxValue; + } + + public Asn1InputStream( + Stream inputStream) + : this(inputStream, FindLimit(inputStream)) + { + } + + /** + * 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( + Stream inputStream, + int limit) + : base(inputStream) + { + this.limit = limit; + this.tmpBuffers = new byte[16][]; + } + + /** + * 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 MemoryStream(input, false), input.Length) + { + } + + /** + * build an object given its tag and the number of bytes to construct it from. + */ + private Asn1Object BuildObject( + int tag, + int tagNo, + int length) + { + bool isConstructed = (tag & Asn1Tags.Constructed) != 0; + + DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length); + + if ((tag & Asn1Tags.Application) != 0) + { + return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray()); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo); + } + + if (isConstructed) + { + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) + { + case Asn1Tags.OctetString: + // + // yes, people actually do this... + // + return new BerOctetString(BuildDerEncodableVector(defIn)); + case Asn1Tags.Sequence: + return CreateDerSequence(defIn); + case Asn1Tags.Set: + return CreateDerSet(defIn); + case Asn1Tags.External: + return new DerExternal(BuildDerEncodableVector(defIn)); + default: + return new DerUnknownTag(true, tagNo, defIn.ToArray()); + } + } + + return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); + } + + internal Asn1EncodableVector BuildEncodableVector() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + Asn1Object o; + while ((o = ReadObject()) != null) + { + v.Add(o); + } + + return v; + } + + internal virtual Asn1EncodableVector BuildDerEncodableVector( + DefiniteLengthInputStream dIn) + { + return new Asn1InputStream(dIn).BuildEncodableVector(); + } + + internal virtual DerSequence CreateDerSequence( + DefiniteLengthInputStream dIn) + { + return DerSequence.FromVector(BuildDerEncodableVector(dIn)); + } + + internal virtual DerSet CreateDerSet( + DefiniteLengthInputStream dIn) + { + return DerSet.FromVector(BuildDerEncodableVector(dIn), false); + } + + public Asn1Object ReadObject() + { + int tag = ReadByte(); + if (tag <= 0) + { + if (tag == 0) + throw new IOException("unexpected end-of-contents marker"); + + return null; + } + + // + // calculate tag number + // + int tagNo = ReadTagNumber(this.s, tag); + + bool isConstructed = (tag & Asn1Tags.Constructed) != 0; + + // + // calculate length + // + int length = ReadLength(this.s, limit); + + if (length < 0) // indefinite length method + { + if (!isConstructed) + throw new IOException("indefinite length primitive encoding encountered"); + + IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit); + Asn1StreamParser sp = new Asn1StreamParser(indIn, limit); + + if ((tag & Asn1Tags.Application) != 0) + { + return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object(); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object(); + } + + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) + { + case Asn1Tags.OctetString: + return new BerOctetStringParser(sp).ToAsn1Object(); + case Asn1Tags.Sequence: + return new BerSequenceParser(sp).ToAsn1Object(); + case Asn1Tags.Set: + return new BerSetParser(sp).ToAsn1Object(); + case Asn1Tags.External: + return new DerExternalParser(sp).ToAsn1Object(); + default: + throw new IOException("unknown BER object encountered"); + } + } + else + { + try + { + return BuildObject(tag, tagNo, length); + } + catch (ArgumentException e) + { + throw new Asn1Exception("corrupted stream detected", e); + } + } + } + + internal static int ReadTagNumber( + Stream s, + int tag) + { + 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.ReadByte(); + + // 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.ReadByte(); + } + + if (b < 0) + throw new EndOfStreamException("EOF found inside tag value."); + + tagNo |= (b & 0x7f); + } + + return tagNo; + } + + internal static int ReadLength( + Stream s, + int limit) + { + int length = s.ReadByte(); + if (length < 0) + throw new EndOfStreamException("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.ReadByte(); + + if (next < 0) + throw new EndOfStreamException("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; + } + + internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers) + { + int len = defIn.GetRemaining(); + if (len >= tmpBuffers.Length) + { + return defIn.ToArray(); + } + + byte[] buf = tmpBuffers[len]; + if (buf == null) + { + buf = tmpBuffers[len] = new byte[len]; + } + + defIn.ReadAllIntoByteArray(buf); + + return buf; + } + + internal static Asn1Object CreatePrimitiveDerObject( + int tagNo, + DefiniteLengthInputStream defIn, + byte[][] tmpBuffers) + { + switch (tagNo) + { + case Asn1Tags.Boolean: + return new DerBoolean(GetBuffer(defIn, tmpBuffers)); + case Asn1Tags.Enumerated: + return new DerEnumerated(GetBuffer(defIn, tmpBuffers)); + case Asn1Tags.ObjectIdentifier: + return DerObjectIdentifier.FromOctetString(GetBuffer(defIn, tmpBuffers)); + } + + byte[] bytes = defIn.ToArray(); + + switch (tagNo) + { + case Asn1Tags.BitString: + return DerBitString.FromAsn1Octets(bytes); + case Asn1Tags.BmpString: + return new DerBmpString(bytes); + case Asn1Tags.GeneralizedTime: + return new DerGeneralizedTime(bytes); + case Asn1Tags.GeneralString: + return new DerGeneralString(bytes); + case Asn1Tags.IA5String: + return new DerIA5String(bytes); + case Asn1Tags.Integer: + return new DerInteger(bytes); + case Asn1Tags.Null: + return DerNull.Instance; // actual content is ignored (enforce 0 length?) + case Asn1Tags.NumericString: + return new DerNumericString(bytes); + case Asn1Tags.OctetString: + return new DerOctetString(bytes); + case Asn1Tags.PrintableString: + return new DerPrintableString(bytes); + case Asn1Tags.T61String: + return new DerT61String(bytes); + case Asn1Tags.UniversalString: + return new DerUniversalString(bytes); + case Asn1Tags.UtcTime: + return new DerUtcTime(bytes); + case Asn1Tags.Utf8String: + return new DerUtf8String(bytes); + case Asn1Tags.VisibleString: + return new DerVisibleString(bytes); + default: + return new DerUnknownTag(false, tagNo, bytes); + } + } + } +} diff --git a/crypto/src/asn1/Asn1Null.cs b/crypto/src/asn1/Asn1Null.cs new file mode 100644 index 000000000..d54019f67 --- /dev/null +++ b/crypto/src/asn1/Asn1Null.cs @@ -0,0 +1,18 @@ +namespace Org.BouncyCastle.Asn1 +{ + /** + * A Null object. + */ + public abstract class Asn1Null + : Asn1Object + { + internal Asn1Null() + { + } + + public override string ToString() + { + return "NULL"; + } + } +} diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs new file mode 100644 index 000000000..08bd599c1 --- /dev/null +++ b/crypto/src/asn1/Asn1Object.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class Asn1Object + : Asn1Encodable + { + /// Create a base ASN.1 object from a byte array. + /// The byte array to parse. + /// The base ASN.1 object represented by the byte array. + /// If there is a problem parsing the data. + public static Asn1Object FromByteArray( + byte[] data) + { + try + { + return new Asn1InputStream(data).ReadObject(); + } + catch (InvalidCastException) + { + throw new IOException("cannot recognise object in stream"); + } + } + + /// Read a base ASN.1 object from a stream. + /// The stream to parse. + /// The base ASN.1 object represented by the byte array. + /// If there is a problem parsing the data. + public static Asn1Object FromStream( + Stream inStr) + { + try + { + return new Asn1InputStream(inStr).ReadObject(); + } + catch (InvalidCastException) + { + throw new IOException("cannot recognise object in stream"); + } + } + + public sealed override Asn1Object ToAsn1Object() + { + return this; + } + + internal abstract void Encode(DerOutputStream derOut); + + protected abstract bool Asn1Equals(Asn1Object asn1Object); + protected abstract int Asn1GetHashCode(); + + internal bool CallAsn1Equals(Asn1Object obj) + { + return Asn1Equals(obj); + } + + internal int CallAsn1GetHashCode() + { + return Asn1GetHashCode(); + } + } +} diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs new file mode 100644 index 000000000..9c738a8f2 --- /dev/null +++ b/crypto/src/asn1/Asn1OctetString.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class Asn1OctetString + : Asn1Object, Asn1OctetStringParser + { + internal byte[] str; + + /** + * return an Octet string from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static Asn1OctetString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is Asn1OctetString) + { + return GetInstance(o); + } + + return BerOctetString.FromSequence(Asn1Sequence.GetInstance(o)); + } + + /** + * return an Octet string from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static Asn1OctetString GetInstance(object obj) + { + if (obj == null || obj is Asn1OctetString) + { + return (Asn1OctetString)obj; + } + + // TODO: this needs to be deleted in V2 + if (obj is Asn1TaggedObject) + return GetInstance(((Asn1TaggedObject)obj).GetObject()); + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * @param string the octets making up the octet string. + */ + internal Asn1OctetString( + byte[] str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + internal Asn1OctetString( + Asn1Encodable obj) + { + try + { + this.str = obj.GetEncoded(Asn1Encodable.Der); + } + catch (IOException e) + { + throw new ArgumentException("Error processing object : " + e.ToString()); + } + } + + public Stream GetOctetStream() + { + return new MemoryStream(str, false); + } + + public Asn1OctetStringParser Parser + { + get { return this; } + } + + public virtual byte[] GetOctets() + { + return str; + } + + protected override int Asn1GetHashCode() + { + return Arrays.GetHashCode(GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerOctetString other = asn1Object as DerOctetString; + + if (other == null) + return false; + + return Arrays.AreEqual(GetOctets(), other.GetOctets()); + } + + public override string ToString() + { + return "#" + Hex.ToHexString(str); + } + } +} diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs new file mode 100644 index 000000000..39c8b1e5e --- /dev/null +++ b/crypto/src/asn1/Asn1OutputStream.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class Asn1OutputStream + : DerOutputStream + { + public Asn1OutputStream(Stream os) : base(os) + { + } + + [Obsolete("Use version taking an Asn1Encodable arg instead")] + public override void WriteObject( + object obj) + { + if (obj == null) + { + WriteNull(); + } + else if (obj is Asn1Object) + { + ((Asn1Object)obj).Encode(this); + } + else if (obj is Asn1Encodable) + { + ((Asn1Encodable)obj).ToAsn1Object().Encode(this); + } + else + { + throw new IOException("object not Asn1Encodable"); + } + } + } +} diff --git a/crypto/src/asn1/Asn1ParsingException.cs b/crypto/src/asn1/Asn1ParsingException.cs new file mode 100644 index 000000000..40e5da480 --- /dev/null +++ b/crypto/src/asn1/Asn1ParsingException.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class Asn1ParsingException + : InvalidOperationException + { + public Asn1ParsingException() + : base() + { + } + + public Asn1ParsingException( + string message) + : base(message) + { + } + + public Asn1ParsingException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs new file mode 100644 index 000000000..5f9ea4460 --- /dev/null +++ b/crypto/src/asn1/Asn1Sequence.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class Asn1Sequence + : Asn1Object, IEnumerable + { + private readonly IList seq; + + /** + * return an Asn1Sequence from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static Asn1Sequence GetInstance( + object obj) + { + if (obj == null || obj is Asn1Sequence) + { + return (Asn1Sequence)obj; + } + else if (obj is Asn1SequenceParser) + { + return Asn1Sequence.GetInstance(((Asn1SequenceParser)obj).ToAsn1Object()); + } + else if (obj is byte[]) + { + try + { + return Asn1Sequence.GetInstance(FromByteArray((byte[])obj)); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message); + } + } + else if (obj is Asn1Encodable) + { + Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object(); + + if (primitive is Asn1Sequence) + { + return (Asn1Sequence)primitive; + } + } + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + /** + * 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 should + * be using this method. + * + * @param obj the tagged object. + * @param explicitly true if the object is meant to be explicitly tagged, + * false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static Asn1Sequence GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + Asn1Object inner = obj.GetObject(); + + if (explicitly) + { + if (!obj.IsExplicit()) + throw new ArgumentException("object implicit - explicit expected."); + + return (Asn1Sequence) inner; + } + + // + // 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 is BerTaggedObject) + { + return new BerSequence(inner); + } + + return new DerSequence(inner); + } + + if (inner is Asn1Sequence) + { + return (Asn1Sequence) inner; + } + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + protected internal Asn1Sequence( + int capacity) + { + seq = Platform.CreateArrayList(capacity); + } + + public virtual IEnumerator GetEnumerator() + { + return seq.GetEnumerator(); + } + + [Obsolete("Use GetEnumerator() instead")] + public IEnumerator GetObjects() + { + return GetEnumerator(); + } + + private class Asn1SequenceParserImpl + : Asn1SequenceParser + { + private readonly Asn1Sequence outer; + private readonly int max; + private int index; + + public Asn1SequenceParserImpl( + Asn1Sequence outer) + { + this.outer = outer; + this.max = outer.Count; + } + + public IAsn1Convertible ReadObject() + { + if (index == max) + return null; + + Asn1Encodable obj = outer[index++]; + + if (obj is Asn1Sequence) + return ((Asn1Sequence)obj).Parser; + + if (obj is Asn1Set) + return ((Asn1Set)obj).Parser; + + // NB: Asn1OctetString implements Asn1OctetStringParser directly +// if (obj is Asn1OctetString) +// return ((Asn1OctetString)obj).Parser; + + return obj; + } + + public Asn1Object ToAsn1Object() + { + return outer; + } + } + + public virtual Asn1SequenceParser Parser + { + get { return new Asn1SequenceParserImpl(this); } + } + + /** + * 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 virtual Asn1Encodable this[int index] + { + get { return (Asn1Encodable) seq[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public Asn1Encodable GetObjectAt( + int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return Count; } + } + + public virtual int Count + { + get { return seq.Count; } + } + + protected override int Asn1GetHashCode() + { + int hc = Count; + + foreach (object o in this) + { + hc *= 17; + if (o == null) + { + hc ^= DerNull.Instance.GetHashCode(); + } + else + { + hc ^= o.GetHashCode(); + } + } + + return hc; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + Asn1Sequence other = asn1Object as Asn1Sequence; + + if (other == null) + return false; + + if (Count != other.Count) + return false; + + IEnumerator s1 = GetEnumerator(); + IEnumerator s2 = other.GetEnumerator(); + + while (s1.MoveNext() && s2.MoveNext()) + { + Asn1Object o1 = GetCurrent(s1).ToAsn1Object(); + Asn1Object o2 = GetCurrent(s2).ToAsn1Object(); + + if (!o1.Equals(o2)) + return false; + } + + return true; + } + + private Asn1Encodable GetCurrent(IEnumerator e) + { + Asn1Encodable encObj = (Asn1Encodable)e.Current; + + // unfortunately null was allowed as a substitute for DER null + if (encObj == null) + return DerNull.Instance; + + return encObj; + } + + protected internal void AddObject( + Asn1Encodable obj) + { + seq.Add(obj); + } + + public override string ToString() + { + return CollectionUtilities.ToString(seq); + } + } +} diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs new file mode 100644 index 000000000..2e77ca2a9 --- /dev/null +++ b/crypto/src/asn1/Asn1Set.cs @@ -0,0 +1,351 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1 +{ + abstract public class Asn1Set + : Asn1Object, IEnumerable + { + private readonly IList _set; + + /** + * return an ASN1Set from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static Asn1Set GetInstance( + object obj) + { + if (obj == null || obj is Asn1Set) + { + return (Asn1Set)obj; + } + else if (obj is Asn1SetParser) + { + return Asn1Set.GetInstance(((Asn1SetParser)obj).ToAsn1Object()); + } + else if (obj is byte[]) + { + try + { + return Asn1Set.GetInstance(FromByteArray((byte[])obj)); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct set from byte[]: " + e.Message); + } + } + else if (obj is Asn1Encodable) + { + Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object(); + + if (primitive is Asn1Set) + { + return (Asn1Set)primitive; + } + } + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + /** + * 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 should + * be using this method. + * + * @param obj the tagged object. + * @param explicitly true if the object is meant to be explicitly tagged + * false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static Asn1Set GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + Asn1Object inner = obj.GetObject(); + + if (explicitly) + { + if (!obj.IsExplicit()) + throw new ArgumentException("object implicit - explicit expected."); + + return (Asn1Set) inner; + } + + // + // constructed object which appears to be explicitly tagged + // and it's really implicit means we have to add the + // surrounding sequence. + // + if (obj.IsExplicit()) + { + return new DerSet(inner); + } + + if (inner is Asn1Set) + { + return (Asn1Set) inner; + } + + // + // in this case the parser returns a sequence, convert it + // into a set. + // + if (inner is Asn1Sequence) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + Asn1Sequence s = (Asn1Sequence) inner; + + foreach (Asn1Encodable ae in s) + { + v.Add(ae); + } + + // TODO Should be able to construct set directly from sequence? + return new DerSet(v, false); + } + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + protected internal Asn1Set( + int capacity) + { + _set = Platform.CreateArrayList(capacity); + } + + public virtual IEnumerator GetEnumerator() + { + return _set.GetEnumerator(); + } + + [Obsolete("Use GetEnumerator() instead")] + public IEnumerator GetObjects() + { + return GetEnumerator(); + } + + /** + * 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 virtual Asn1Encodable this[int index] + { + get { return (Asn1Encodable) _set[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public Asn1Encodable GetObjectAt( + int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return Count; } + } + + public virtual int Count + { + get { return _set.Count; } + } + + public virtual Asn1Encodable[] ToArray() + { + Asn1Encodable[] values = new Asn1Encodable[this.Count]; + for (int i = 0; i < this.Count; ++i) + { + values[i] = this[i]; + } + return values; + } + + private class Asn1SetParserImpl + : Asn1SetParser + { + private readonly Asn1Set outer; + private readonly int max; + private int index; + + public Asn1SetParserImpl( + Asn1Set outer) + { + this.outer = outer; + this.max = outer.Count; + } + + public IAsn1Convertible ReadObject() + { + if (index == max) + return null; + + Asn1Encodable obj = outer[index++]; + if (obj is Asn1Sequence) + return ((Asn1Sequence)obj).Parser; + + if (obj is Asn1Set) + return ((Asn1Set)obj).Parser; + + // NB: Asn1OctetString implements Asn1OctetStringParser directly +// if (obj is Asn1OctetString) +// return ((Asn1OctetString)obj).Parser; + + return obj; + } + + public virtual Asn1Object ToAsn1Object() + { + return outer; + } + } + + public Asn1SetParser Parser + { + get { return new Asn1SetParserImpl(this); } + } + + protected override int Asn1GetHashCode() + { + int hc = Count; + + foreach (object o in this) + { + hc *= 17; + if (o == null) + { + hc ^= DerNull.Instance.GetHashCode(); + } + else + { + hc ^= o.GetHashCode(); + } + } + + return hc; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + Asn1Set other = asn1Object as Asn1Set; + + if (other == null) + return false; + + if (Count != other.Count) + { + return false; + } + + IEnumerator s1 = GetEnumerator(); + IEnumerator s2 = other.GetEnumerator(); + + while (s1.MoveNext() && s2.MoveNext()) + { + Asn1Object o1 = GetCurrent(s1).ToAsn1Object(); + Asn1Object o2 = GetCurrent(s2).ToAsn1Object(); + + if (!o1.Equals(o2)) + return false; + } + + return true; + } + + private Asn1Encodable GetCurrent(IEnumerator e) + { + Asn1Encodable encObj = (Asn1Encodable)e.Current; + + // 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 bool LessThanOrEqual( + byte[] a, + byte[] b) + { + int len = System.Math.Min(a.Length, b.Length); + for (int i = 0; i != len; ++i) + { + if (a[i] != b[i]) + { + return a[i] < b[i]; + } + } + return len == a.Length; + } + + protected internal void Sort() + { + if (_set.Count > 1) + { + bool swapped = true; + int lastSwap = _set.Count - 1; + + while (swapped) + { + int index = 0; + int swapIndex = 0; + byte[] a = ((Asn1Encodable) _set[0]).GetEncoded(); + + swapped = false; + + while (index != lastSwap) + { + byte[] b = ((Asn1Encodable) _set[index + 1]).GetEncoded(); + + if (LessThanOrEqual(a, b)) + { + a = b; + } + else + { + object o = _set[index]; + _set[index] = _set[index + 1]; + _set[index + 1] = o; + + swapped = true; + swapIndex = index; + } + + index++; + } + + lastSwap = swapIndex; + } + } + } + + protected internal void AddObject( + Asn1Encodable obj) + { + _set.Add(obj); + } + + public override string ToString() + { + return CollectionUtilities.ToString(_set); + } + } +} diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs new file mode 100644 index 000000000..2e480738a --- /dev/null +++ b/crypto/src/asn1/Asn1TaggedObject.cs @@ -0,0 +1,178 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * 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 + : Asn1Object, Asn1TaggedObjectParser + { + internal int tagNo; +// internal bool empty; + internal bool explicitly = true; + internal Asn1Encodable obj; + + static public Asn1TaggedObject GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + if (explicitly) + { + return (Asn1TaggedObject) obj.GetObject(); + } + + throw new ArgumentException("implicitly tagged tagged object"); + } + + static public Asn1TaggedObject GetInstance( + object obj) + { + if (obj == null || obj is Asn1TaggedObject) + { + return (Asn1TaggedObject) obj; + } + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + /** + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + protected Asn1TaggedObject( + int tagNo, + Asn1Encodable obj) + { + this.explicitly = true; + this.tagNo = tagNo; + this.obj = obj; + } + + /** + * @param explicitly true if the object is explicitly tagged. + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + protected Asn1TaggedObject( + bool explicitly, + int tagNo, + Asn1Encodable obj) + { + // IAsn1Choice marker interface 'insists' on explicit tagging + this.explicitly = explicitly || (obj is IAsn1Choice); + this.tagNo = tagNo; + this.obj = obj; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + Asn1TaggedObject other = asn1Object as Asn1TaggedObject; + + if (other == null) + return false; + + return this.tagNo == other.tagNo +// && this.empty == other.empty + && this.explicitly == other.explicitly // TODO Should this be part of equality? + && Platform.Equals(GetObject(), other.GetObject()); + } + + protected override int Asn1GetHashCode() + { + int code = tagNo.GetHashCode(); + + // 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... +// code ^= explicitly.GetHashCode(); + + if (obj != null) + { + code ^= obj.GetHashCode(); + } + + return code; + } + + public int TagNo + { + get { return tagNo; } + } + + /** + * return whether or not the object may be explicitly tagged. + *

+ * 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 bool IsExplicit() + { + return explicitly; + } + + public bool IsEmpty() + { + return false; //empty; + } + + /** + * return whatever was following the tag. + *

+ * 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 Asn1Object GetObject() + { + if (obj != null) + { + return obj.ToAsn1Object(); + } + + 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 IAsn1Convertible GetObjectParser( + int tag, + bool isExplicit) + { + switch (tag) + { + case Asn1Tags.Set: + return Asn1Set.GetInstance(this, isExplicit).Parser; + case Asn1Tags.Sequence: + return Asn1Sequence.GetInstance(this, isExplicit).Parser; + case Asn1Tags.OctetString: + return Asn1OctetString.GetInstance(this, isExplicit).Parser; + } + + if (isExplicit) + { + return GetObject(); + } + + throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag); + } + + public override string ToString() + { + return "[" + tagNo + "]" + obj; + } + } +} diff --git a/crypto/src/asn1/Asn1Tags.cs b/crypto/src/asn1/Asn1Tags.cs new file mode 100644 index 000000000..32ac6bc6c --- /dev/null +++ b/crypto/src/asn1/Asn1Tags.cs @@ -0,0 +1,36 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class Asn1Tags + { + public const int Boolean = 0x01; + public const int Integer = 0x02; + public const int BitString = 0x03; + public const int OctetString = 0x04; + public const int Null = 0x05; + public const int ObjectIdentifier = 0x06; + public const int External = 0x08; + public const int Enumerated = 0x0a; + public const int Sequence = 0x10; + public const int SequenceOf = 0x10; // for completeness + public const int Set = 0x11; + public const int SetOf = 0x11; // for completeness + + public const int NumericString = 0x12; + public const int PrintableString = 0x13; + public const int T61String = 0x14; + public const int VideotexString = 0x15; + public const int IA5String = 0x16; + public const int UtcTime = 0x17; + public const int GeneralizedTime = 0x18; + public const int GraphicString = 0x19; + public const int VisibleString = 0x1a; + public const int GeneralString = 0x1b; + public const int UniversalString = 0x1c; + public const int BmpString = 0x1e; + public const int Utf8String = 0x0c; + + public const int Constructed = 0x20; + public const int Application = 0x40; + public const int Tagged = 0x80; + } +} diff --git a/crypto/src/asn1/BERGenerator.cs b/crypto/src/asn1/BERGenerator.cs new file mode 100644 index 000000000..271572c02 --- /dev/null +++ b/crypto/src/asn1/BERGenerator.cs @@ -0,0 +1,102 @@ +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerGenerator + : Asn1Generator + { + private bool _tagged = false; + private bool _isExplicit; + private int _tagNo; + + protected BerGenerator( + Stream outStream) + : base(outStream) + { + } + + public BerGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream) + { + _tagged = true; + _isExplicit = isExplicit; + _tagNo = tagNo; + } + + public override void AddObject( + Asn1Encodable obj) + { + new BerOutputStream(Out).WriteObject(obj); + } + + public override Stream GetRawOutputStream() + { + return Out; + } + + public override void Close() + { + WriteBerEnd(); + } + + private void WriteHdr( + int tag) + { + Out.WriteByte((byte) tag); + Out.WriteByte(0x80); + } + + protected void WriteBerHeader( + int tag) + { + if (_tagged) + { + int tagNum = _tagNo | Asn1Tags.Tagged; + + if (_isExplicit) + { + WriteHdr(tagNum | Asn1Tags.Constructed); + WriteHdr(tag); + } + else + { + if ((tag & Asn1Tags.Constructed) != 0) + { + WriteHdr(tagNum | Asn1Tags.Constructed); + } + else + { + WriteHdr(tagNum); + } + } + } + else + { + WriteHdr(tag); + } + } + + protected void WriteBerBody( + Stream contentStream) + { + Streams.PipeAll(contentStream, Out); + } + + protected void WriteBerEnd() + { + Out.WriteByte(0x00); + Out.WriteByte(0x00); + + if (_tagged && _isExplicit) // write extra end for tag header + { + Out.WriteByte(0x00); + Out.WriteByte(0x00); + } + } + } +} diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs new file mode 100644 index 000000000..7468a6b0b --- /dev/null +++ b/crypto/src/asn1/BEROctetStringGenerator.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerOctetStringGenerator + : BerGenerator + { + public BerOctetStringGenerator(Stream outStream) + : base(outStream) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString); + } + + public BerOctetStringGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream, tagNo, isExplicit) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString); + } + + public Stream GetOctetOutputStream() + { + return GetOctetOutputStream(new byte[1000]); // limit for CER encoding. + } + + public Stream GetOctetOutputStream( + int bufSize) + { + return bufSize < 1 + ? GetOctetOutputStream() + : GetOctetOutputStream(new byte[bufSize]); + } + + public Stream GetOctetOutputStream( + byte[] buf) + { + return new BufferedBerOctetStream(this, buf); + } + + private class BufferedBerOctetStream + : BaseOutputStream + { + private byte[] _buf; + private int _off; + private readonly BerOctetStringGenerator _gen; + private readonly DerOutputStream _derOut; + + internal BufferedBerOctetStream( + BerOctetStringGenerator gen, + byte[] buf) + { + _gen = gen; + _buf = buf; + _off = 0; + _derOut = new DerOutputStream(_gen.Out); + } + + public override void WriteByte( + byte b) + { + _buf[_off++] = b; + + if (_off == _buf.Length) + { + DerOctetString.Encode(_derOut, _buf, 0, _off); + _off = 0; + } + } + + public override void Write( + byte[] buf, + int offset, + int len) + { + while (len > 0) + { + int numToCopy = System.Math.Min(len, _buf.Length - _off); + + if (numToCopy == _buf.Length) + { + DerOctetString.Encode(_derOut, buf, offset, numToCopy); + } + else + { + Array.Copy(buf, offset, _buf, _off, numToCopy); + + _off += numToCopy; + if (_off < _buf.Length) + break; + + DerOctetString.Encode(_derOut, _buf, 0, _off); + _off = 0; + } + + offset += numToCopy; + len -= numToCopy; + } + } + + public override void Close() + { + if (_off != 0) + { + DerOctetString.Encode(_derOut, _buf, 0, _off); + } + + _gen.WriteBerEnd(); + base.Close(); + } + } + } +} diff --git a/crypto/src/asn1/BEROctetStringParser.cs b/crypto/src/asn1/BEROctetStringParser.cs new file mode 100644 index 000000000..3bfd2a98d --- /dev/null +++ b/crypto/src/asn1/BEROctetStringParser.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerOctetStringParser + : Asn1OctetStringParser + { + private readonly Asn1StreamParser _parser; + + internal BerOctetStringParser( + Asn1StreamParser parser) + { + _parser = parser; + } + + public Stream GetOctetStream() + { + return new ConstructedOctetStream(_parser); + } + + public Asn1Object ToAsn1Object() + { + try + { + return new BerOctetString(Streams.ReadAll(GetOctetStream())); + } + catch (IOException e) + { + throw new Asn1ParsingException("IOException converting stream to byte array: " + e.Message, e); + } + } + } +} diff --git a/crypto/src/asn1/BERSequenceGenerator.cs b/crypto/src/asn1/BERSequenceGenerator.cs new file mode 100644 index 000000000..5ea2c9b82 --- /dev/null +++ b/crypto/src/asn1/BERSequenceGenerator.cs @@ -0,0 +1,24 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerSequenceGenerator + : BerGenerator + { + public BerSequenceGenerator( + Stream outStream) + : base(outStream) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence); + } + + public BerSequenceGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream, tagNo, isExplicit) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence); + } + } +} diff --git a/crypto/src/asn1/BERSequenceParser.cs b/crypto/src/asn1/BERSequenceParser.cs new file mode 100644 index 000000000..8474b8d24 --- /dev/null +++ b/crypto/src/asn1/BERSequenceParser.cs @@ -0,0 +1,24 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class BerSequenceParser + : Asn1SequenceParser + { + private readonly Asn1StreamParser _parser; + + internal BerSequenceParser( + Asn1StreamParser parser) + { + this._parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return _parser.ReadObject(); + } + + public Asn1Object ToAsn1Object() + { + return new BerSequence(_parser.ReadVector()); + } + } +} diff --git a/crypto/src/asn1/BERSetGenerator.cs b/crypto/src/asn1/BERSetGenerator.cs new file mode 100644 index 000000000..72b1f903a --- /dev/null +++ b/crypto/src/asn1/BERSetGenerator.cs @@ -0,0 +1,24 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerSetGenerator + : BerGenerator + { + public BerSetGenerator( + Stream outStream) + : base(outStream) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set); + } + + public BerSetGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream, tagNo, isExplicit) + { + WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set); + } + } +} diff --git a/crypto/src/asn1/BERSetParser.cs b/crypto/src/asn1/BERSetParser.cs new file mode 100644 index 000000000..aa9ccbc12 --- /dev/null +++ b/crypto/src/asn1/BERSetParser.cs @@ -0,0 +1,24 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class BerSetParser + : Asn1SetParser + { + private readonly Asn1StreamParser _parser; + + internal BerSetParser( + Asn1StreamParser parser) + { + this._parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return _parser.ReadObject(); + } + + public Asn1Object ToAsn1Object() + { + return new BerSet(_parser.ReadVector(), false); + } + } +} diff --git a/crypto/src/asn1/BERTaggedObjectParser.cs b/crypto/src/asn1/BERTaggedObjectParser.cs new file mode 100644 index 000000000..354437a6a --- /dev/null +++ b/crypto/src/asn1/BERTaggedObjectParser.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerTaggedObjectParser + : Asn1TaggedObjectParser + { + private bool _constructed; + private int _tagNumber; + private Asn1StreamParser _parser; + + [Obsolete] + internal BerTaggedObjectParser( + int baseTag, + int tagNumber, + Stream contentStream) + : this((baseTag & Asn1Tags.Constructed) != 0, tagNumber, new Asn1StreamParser(contentStream)) + { + } + + internal BerTaggedObjectParser( + bool constructed, + int tagNumber, + Asn1StreamParser parser) + { + _constructed = constructed; + _tagNumber = tagNumber; + _parser = parser; + } + + public bool IsConstructed + { + get { return _constructed; } + } + + public int TagNo + { + get { return _tagNumber; } + } + + public IAsn1Convertible GetObjectParser( + int tag, + bool isExplicit) + { + 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 Asn1Object ToAsn1Object() + { + try + { + return _parser.ReadTaggedObject(_constructed, _tagNumber); + } + catch (IOException e) + { + throw new Asn1ParsingException(e.Message); + } + } + } +} diff --git a/crypto/src/asn1/BerApplicationSpecific.cs b/crypto/src/asn1/BerApplicationSpecific.cs new file mode 100644 index 000000000..65fbecbe1 --- /dev/null +++ b/crypto/src/asn1/BerApplicationSpecific.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerApplicationSpecific + : DerApplicationSpecific + { + public BerApplicationSpecific( + int tagNo, + Asn1EncodableVector vec) + : base(tagNo, vec) + { + } + } +} diff --git a/crypto/src/asn1/BerApplicationSpecificParser.cs b/crypto/src/asn1/BerApplicationSpecificParser.cs new file mode 100644 index 000000000..7d2c4b3e8 --- /dev/null +++ b/crypto/src/asn1/BerApplicationSpecificParser.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerApplicationSpecificParser + : IAsn1ApplicationSpecificParser + { + private readonly int tag; + private readonly Asn1StreamParser parser; + + internal BerApplicationSpecificParser( + int tag, + Asn1StreamParser parser) + { + this.tag = tag; + this.parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return parser.ReadObject(); + } + + public Asn1Object ToAsn1Object() + { + return new BerApplicationSpecific(tag, parser.ReadVector()); + } + } +} diff --git a/crypto/src/asn1/BerNull.cs b/crypto/src/asn1/BerNull.cs new file mode 100644 index 000000000..0751bbac3 --- /dev/null +++ b/crypto/src/asn1/BerNull.cs @@ -0,0 +1,35 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * A BER Null object. + */ + public class BerNull + : DerNull + { + public static new readonly BerNull Instance = new BerNull(0); + + [Obsolete("Use static Instance object")] + public BerNull() + { + } + + private BerNull(int dummy) : base(dummy) + { + } + + internal override void Encode( + DerOutputStream derOut) + { + if (derOut is Asn1OutputStream || derOut is BerOutputStream) + { + derOut.WriteByte(Asn1Tags.Null); + } + else + { + base.Encode(derOut); + } + } + } +} diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs new file mode 100644 index 000000000..a7c8ad33e --- /dev/null +++ b/crypto/src/asn1/BerOctetString.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class BerOctetString + : DerOctetString, IEnumerable + { + public static BerOctetString FromSequence(Asn1Sequence seq) + { + IList v = Platform.CreateArrayList(); + + foreach (Asn1Encodable obj in seq) + { + v.Add(obj); + } + + return new BerOctetString(v); + } + + private const int MaxLength = 1000; + + /** + * convert a vector of octet strings into a single byte string + */ + private static byte[] ToBytes( + IEnumerable octs) + { + MemoryStream bOut = new MemoryStream(); + foreach (DerOctetString o in octs) + { + byte[] octets = o.GetOctets(); + bOut.Write(octets, 0, octets.Length); + } + return bOut.ToArray(); + } + + private readonly IEnumerable octs; + + /// The octets making up the octet string. + public BerOctetString( + byte[] str) + : base(str) + { + } + + public BerOctetString( + IEnumerable octets) + : base(ToBytes(octets)) + { + this.octs = octets; + } + + public BerOctetString( + Asn1Object obj) + : base(obj) + { + } + + public BerOctetString( + Asn1Encodable obj) + : base(obj.ToAsn1Object()) + { + } + + public override byte[] GetOctets() + { + return str; + } + + /** + * return the DER octets that make up this string. + */ + public IEnumerator GetEnumerator() + { + if (octs == null) + { + return GenerateOcts().GetEnumerator(); + } + + return octs.GetEnumerator(); + } + + [Obsolete("Use GetEnumerator() instead")] + public IEnumerator GetObjects() + { + return GetEnumerator(); + } + + private IList GenerateOcts() + { + IList vec = Platform.CreateArrayList(); + for (int i = 0; i < str.Length; i += MaxLength) + { + int end = System.Math.Min(str.Length, i + MaxLength); + + byte[] nStr = new byte[end - i]; + + Array.Copy(str, i, nStr, 0, nStr.Length); + + vec.Add(new DerOctetString(nStr)); + } + return vec; + } + + internal override void Encode( + DerOutputStream derOut) + { + if (derOut is Asn1OutputStream || derOut is BerOutputStream) + { + derOut.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString); + + derOut.WriteByte(0x80); + + // + // write out the octet array + // + foreach (DerOctetString oct in this) + { + derOut.WriteObject(oct); + } + + derOut.WriteByte(0x00); + derOut.WriteByte(0x00); + } + else + { + base.Encode(derOut); + } + } + } +} diff --git a/crypto/src/asn1/BerOutputStream.cs b/crypto/src/asn1/BerOutputStream.cs new file mode 100644 index 000000000..b3ece10d3 --- /dev/null +++ b/crypto/src/asn1/BerOutputStream.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + // TODO Make Obsolete in favour of Asn1OutputStream? + public class BerOutputStream + : DerOutputStream + { + public BerOutputStream(Stream os) : base(os) + { + } + + [Obsolete("Use version taking an Asn1Encodable arg instead")] + public override void WriteObject( + object obj) + { + if (obj == null) + { + WriteNull(); + } + else if (obj is Asn1Object) + { + ((Asn1Object)obj).Encode(this); + } + else if (obj is Asn1Encodable) + { + ((Asn1Encodable)obj).ToAsn1Object().Encode(this); + } + else + { + throw new IOException("object not BerEncodable"); + } + } + } +} diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs new file mode 100644 index 000000000..70b43fc79 --- /dev/null +++ b/crypto/src/asn1/BerSequence.cs @@ -0,0 +1,69 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class BerSequence + : DerSequence + { + public static new readonly BerSequence Empty = new BerSequence(); + + public static new BerSequence FromVector( + Asn1EncodableVector v) + { + return v.Count < 1 ? Empty : new BerSequence(v); + } + + /** + * create an empty sequence + */ + public BerSequence() + { + } + + /** + * create a sequence containing one object + */ + public BerSequence( + Asn1Encodable obj) + : base(obj) + { + } + + public BerSequence( + params Asn1Encodable[] v) + : base(v) + { + } + + /** + * create a sequence containing a vector of objects. + */ + public BerSequence( + Asn1EncodableVector v) + : base(v) + { + } + + /* + */ + internal override void Encode( + DerOutputStream derOut) + { + if (derOut is Asn1OutputStream || derOut is BerOutputStream) + { + derOut.WriteByte(Asn1Tags.Sequence | Asn1Tags.Constructed); + derOut.WriteByte(0x80); + + foreach (Asn1Encodable o in this) + { + derOut.WriteObject(o); + } + + derOut.WriteByte(0x00); + derOut.WriteByte(0x00); + } + else + { + base.Encode(derOut); + } + } + } +} diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs new file mode 100644 index 000000000..a181e172d --- /dev/null +++ b/crypto/src/asn1/BerSet.cs @@ -0,0 +1,70 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class BerSet + : DerSet + { + public static new readonly BerSet Empty = new BerSet(); + + public static new BerSet FromVector( + Asn1EncodableVector v) + { + return v.Count < 1 ? Empty : new BerSet(v); + } + + internal static new BerSet FromVector( + Asn1EncodableVector v, + bool needsSorting) + { + return v.Count < 1 ? Empty : new BerSet(v, needsSorting); + } + + /** + * create an empty sequence + */ + public BerSet() + { + } + + /** + * create a set containing one object + */ + public BerSet(Asn1Encodable obj) : base(obj) + { + } + + /** + * create a set containing a vector of objects. + */ + public BerSet(Asn1EncodableVector v) : base(v, false) + { + } + + internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting) + { + } + + /* + */ + internal override void Encode( + DerOutputStream derOut) + { + if (derOut is Asn1OutputStream || derOut is BerOutputStream) + { + derOut.WriteByte(Asn1Tags.Set | Asn1Tags.Constructed); + derOut.WriteByte(0x80); + + foreach (Asn1Encodable o in this) + { + derOut.WriteObject(o); + } + + derOut.WriteByte(0x00); + derOut.WriteByte(0x00); + } + else + { + base.Encode(derOut); + } + } + } +} diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs new file mode 100644 index 000000000..228b136cb --- /dev/null +++ b/crypto/src/asn1/BerTaggedObject.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * 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 + : DerTaggedObject + { + /** + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + public BerTaggedObject( + int tagNo, + Asn1Encodable obj) + : base(tagNo, obj) + { + } + + /** + * @param explicitly true if an explicitly tagged object. + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + public BerTaggedObject( + bool explicitly, + int tagNo, + Asn1Encodable obj) + : base(explicitly, tagNo, obj) + { + } + + /** + * create an implicitly tagged object that contains a zero + * length sequence. + */ + public BerTaggedObject( + int tagNo) + : base(false, tagNo, BerSequence.Empty) + { + } + + internal override void Encode( + DerOutputStream derOut) + { + if (derOut is Asn1OutputStream || derOut is BerOutputStream) + { + derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo); + derOut.WriteByte(0x80); + + if (!IsEmpty()) + { + if (!explicitly) + { + IEnumerable eObj; + if (obj is Asn1OctetString) + { + if (obj is BerOctetString) + { + eObj = (BerOctetString) obj; + } + else + { + Asn1OctetString octs = (Asn1OctetString)obj; + eObj = new BerOctetString(octs.GetOctets()); + } + } + else if (obj is Asn1Sequence) + { + eObj = (Asn1Sequence) obj; + } + else if (obj is Asn1Set) + { + eObj = (Asn1Set) obj; + } + else + { + throw Platform.CreateNotImplementedException(obj.GetType().Name); + } + + foreach (Asn1Encodable o in eObj) + { + derOut.WriteObject(o); + } + } + else + { + derOut.WriteObject(obj); + } + } + + derOut.WriteByte(0x00); + derOut.WriteByte(0x00); + } + else + { + base.Encode(derOut); + } + } + } +} diff --git a/crypto/src/asn1/ConstructedOctetStream.cs b/crypto/src/asn1/ConstructedOctetStream.cs new file mode 100644 index 000000000..1773b22cc --- /dev/null +++ b/crypto/src/asn1/ConstructedOctetStream.cs @@ -0,0 +1,102 @@ +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + internal class ConstructedOctetStream + : BaseInputStream + { + private readonly Asn1StreamParser _parser; + + private bool _first = true; + private Stream _currentStream; + + internal ConstructedOctetStream( + Asn1StreamParser parser) + { + _parser = parser; + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (_currentStream == null) + { + if (!_first) + return 0; + + Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject(); + + if (s == null) + return 0; + + _first = false; + _currentStream = s.GetOctetStream(); + } + + int totalRead = 0; + + for (;;) + { + int numRead = _currentStream.Read(buffer, offset + totalRead, count - totalRead); + + if (numRead > 0) + { + totalRead += numRead; + + if (totalRead == count) + return totalRead; + } + else + { + Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject(); + + if (aos == null) + { + _currentStream = null; + return totalRead; + } + + _currentStream = aos.GetOctetStream(); + } + } + } + + public override int ReadByte() + { + if (_currentStream == null) + { + if (!_first) + return 0; + + Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject(); + + if (s == null) + return 0; + + _first = false; + _currentStream = s.GetOctetStream(); + } + + for (;;) + { + int b = _currentStream.ReadByte(); + + if (b >= 0) + { + return b; + } + + Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject(); + + if (aos == null) + { + _currentStream = null; + return -1; + } + + _currentStream = aos.GetOctetStream(); + } + } + } +} diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs new file mode 100644 index 000000000..a342d6520 --- /dev/null +++ b/crypto/src/asn1/DERExternal.cs @@ -0,0 +1,207 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Class representing the DER-type External + */ + public class DerExternal + : Asn1Object + { + private DerObjectIdentifier directReference; + private DerInteger indirectReference; + private Asn1Object dataValueDescriptor; + private int encoding; + private Asn1Object externalContent; + + public DerExternal( + Asn1EncodableVector vector) + { + int offset = 0; + Asn1Object enc = GetObjFromVector(vector, offset); + if (enc is DerObjectIdentifier) + { + directReference = (DerObjectIdentifier)enc; + offset++; + enc = GetObjFromVector(vector, offset); + } + if (enc is DerInteger) + { + indirectReference = (DerInteger) enc; + offset++; + enc = GetObjFromVector(vector, offset); + } + if (!(enc is DerTaggedObject)) + { + dataValueDescriptor = (Asn1Object) enc; + offset++; + enc = GetObjFromVector(vector, offset); + } + if (!(enc is DerTaggedObject)) + { + throw new InvalidOperationException( + "No tagged object found in vector. Structure doesn't seem to be of type External"); + } + + if (vector.Count != offset + 1) + throw new ArgumentException("input vector too large", "vector"); + + if (!(enc is DerTaggedObject)) + throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector"); + + DerTaggedObject obj = (DerTaggedObject)enc; + + // Use property accessor to include check on value + Encoding = obj.TagNo; + + if (encoding < 0 || encoding > 2) + throw new InvalidOperationException("invalid encoding value"); + + externalContent = obj.GetObject(); + } + + /** + * Creates a new instance of DerExternal + * See X.690 for more informations about the meaning of these parameters + * @param directReference The direct reference or null if not set. + * @param indirectReference The indirect reference or null if not set. + * @param dataValueDescriptor The data value descriptor or null if not set. + * @param externalData The external data in its encoded form. + */ + public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, DerTaggedObject externalData) + : this(directReference, indirectReference, dataValueDescriptor, externalData.TagNo, externalData.ToAsn1Object()) + { + } + + /** + * Creates a new instance of DerExternal. + * See X.690 for more informations about the meaning of these parameters + * @param directReference The direct reference or null if not set. + * @param indirectReference The indirect reference or null if not set. + * @param dataValueDescriptor The data value descriptor or null if not set. + * @param encoding The encoding to be used for the external data + * @param externalData The external data + */ + public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, int encoding, Asn1Object externalData) + { + DirectReference = directReference; + IndirectReference = indirectReference; + DataValueDescriptor = dataValueDescriptor; + Encoding = encoding; + ExternalContent = externalData.ToAsn1Object(); + } + + internal override void Encode(DerOutputStream derOut) + { + MemoryStream ms = new MemoryStream(); + WriteEncodable(ms, directReference); + WriteEncodable(ms, indirectReference); + WriteEncodable(ms, dataValueDescriptor); + WriteEncodable(ms, new DerTaggedObject(Asn1Tags.External, externalContent)); + + derOut.WriteEncoded(Asn1Tags.Constructed, Asn1Tags.External, ms.ToArray()); + } + + protected override int Asn1GetHashCode() + { + int ret = externalContent.GetHashCode(); + if (directReference != null) + { + ret ^= directReference.GetHashCode(); + } + if (indirectReference != null) + { + ret ^= indirectReference.GetHashCode(); + } + if (dataValueDescriptor != null) + { + ret ^= dataValueDescriptor.GetHashCode(); + } + return ret; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + if (this == asn1Object) + return true; + + DerExternal other = asn1Object as DerExternal; + + if (other == null) + return false; + + return Platform.Equals(directReference, other.directReference) + && Platform.Equals(indirectReference, other.indirectReference) + && Platform.Equals(dataValueDescriptor, other.dataValueDescriptor) + && externalContent.Equals(other.externalContent); + } + + public Asn1Object DataValueDescriptor + { + get { return dataValueDescriptor; } + set { this.dataValueDescriptor = value; } + } + + public DerObjectIdentifier DirectReference + { + get { return directReference; } + set { this.directReference = value; } + } + + /** + * The encoding of the content. Valid values are + *
    + *
  • 0 single-ASN1-type
  • + *
  • 1 OCTET STRING
  • + *
  • 2 BIT STRING
  • + *
+ */ + public int Encoding + { + get + { + return encoding; + } + set + { + if (encoding < 0 || encoding > 2) + throw new InvalidOperationException("invalid encoding value: " + encoding); + + this.encoding = value; + } + } + + public Asn1Object ExternalContent + { + get { return externalContent; } + set { this.externalContent = value; } + } + + public DerInteger IndirectReference + { + get { return indirectReference; } + set { this.indirectReference = value; } + } + + private static Asn1Object GetObjFromVector(Asn1EncodableVector v, int index) + { + if (v.Count <= index) + throw new ArgumentException("too few objects in input vector", "v"); + + return v[index].ToAsn1Object(); + } + + private static void WriteEncodable(MemoryStream ms, Asn1Encodable e) + { + if (e != null) + { + byte[] bs = e.GetDerEncoded(); + ms.Write(bs, 0, bs.Length); + } + } + } +} diff --git a/crypto/src/asn1/DERExternalParser.cs b/crypto/src/asn1/DERExternalParser.cs new file mode 100644 index 000000000..70e426fed --- /dev/null +++ b/crypto/src/asn1/DERExternalParser.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerExternalParser + : Asn1Encodable + { + private readonly Asn1StreamParser _parser; + + public DerExternalParser(Asn1StreamParser parser) + { + this._parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return _parser.ReadObject(); + } + + public override Asn1Object ToAsn1Object() + { + return new DerExternal(_parser.ReadVector()); + } + } +} diff --git a/crypto/src/asn1/DERGenerator.cs b/crypto/src/asn1/DERGenerator.cs new file mode 100644 index 000000000..aab40fefa --- /dev/null +++ b/crypto/src/asn1/DERGenerator.cs @@ -0,0 +1,107 @@ +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public abstract class DerGenerator + : Asn1Generator + { + private bool _tagged = false; + private bool _isExplicit; + private int _tagNo; + + protected DerGenerator( + Stream outStream) + : base(outStream) + { + } + + protected DerGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream) + { + _tagged = true; + _isExplicit = isExplicit; + _tagNo = tagNo; + } + + private static void WriteLength( + Stream outStr, + int length) + { + if (length > 127) + { + int size = 1; + int val = length; + + while ((val >>= 8) != 0) + { + size++; + } + + outStr.WriteByte((byte)(size | 0x80)); + + for (int i = (size - 1) * 8; i >= 0; i -= 8) + { + outStr.WriteByte((byte)(length >> i)); + } + } + else + { + outStr.WriteByte((byte)length); + } + } + + internal static void WriteDerEncoded( + Stream outStream, + int tag, + byte[] bytes) + { + outStream.WriteByte((byte) tag); + WriteLength(outStream, bytes.Length); + outStream.Write(bytes, 0, bytes.Length); + } + + internal void WriteDerEncoded( + int tag, + byte[] bytes) + { + if (_tagged) + { + int tagNum = _tagNo | Asn1Tags.Tagged; + + if (_isExplicit) + { + int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.Tagged; + MemoryStream bOut = new MemoryStream(); + WriteDerEncoded(bOut, tag, bytes); + WriteDerEncoded(Out, newTag, bOut.ToArray()); + } + else + { + if ((tag & Asn1Tags.Constructed) != 0) + { + tagNum |= Asn1Tags.Constructed; + } + + WriteDerEncoded(Out, tagNum, bytes); + } + } + else + { + WriteDerEncoded(Out, tag, bytes); + } + } + + internal static void WriteDerEncoded( + Stream outStr, + int tag, + Stream inStr) + { + WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr)); + } + } +} diff --git a/crypto/src/asn1/DEROctetStringParser.cs b/crypto/src/asn1/DEROctetStringParser.cs new file mode 100644 index 000000000..b0d3ad8cf --- /dev/null +++ b/crypto/src/asn1/DEROctetStringParser.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerOctetStringParser + : Asn1OctetStringParser + { + private readonly DefiniteLengthInputStream stream; + + internal DerOctetStringParser( + DefiniteLengthInputStream stream) + { + this.stream = stream; + } + + public Stream GetOctetStream() + { + return stream; + } + + public Asn1Object ToAsn1Object() + { + try + { + return new DerOctetString(stream.ToArray()); + } + catch (IOException e) + { + throw new InvalidOperationException("IOException converting stream to byte array: " + e.Message, e); + } + } + } +} diff --git a/crypto/src/asn1/DERSequenceGenerator.cs b/crypto/src/asn1/DERSequenceGenerator.cs new file mode 100644 index 000000000..4c2bfd012 --- /dev/null +++ b/crypto/src/asn1/DERSequenceGenerator.cs @@ -0,0 +1,40 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerSequenceGenerator + : DerGenerator + { + private readonly MemoryStream _bOut = new MemoryStream(); + + public DerSequenceGenerator( + Stream outStream) + : base(outStream) + { + } + + public DerSequenceGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream, tagNo, isExplicit) + { + } + + public override void AddObject( + Asn1Encodable obj) + { + new DerOutputStream(_bOut).WriteObject(obj); + } + + public override Stream GetRawOutputStream() + { + return _bOut; + } + + public override void Close() + { + WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray()); + } + } +} diff --git a/crypto/src/asn1/DERSequenceParser.cs b/crypto/src/asn1/DERSequenceParser.cs new file mode 100644 index 000000000..69c2b9b2d --- /dev/null +++ b/crypto/src/asn1/DERSequenceParser.cs @@ -0,0 +1,24 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class DerSequenceParser + : Asn1SequenceParser + { + private readonly Asn1StreamParser _parser; + + internal DerSequenceParser( + Asn1StreamParser parser) + { + this._parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return _parser.ReadObject(); + } + + public Asn1Object ToAsn1Object() + { + return new DerSequence(_parser.ReadVector()); + } + } +} diff --git a/crypto/src/asn1/DERSetGenerator.cs b/crypto/src/asn1/DERSetGenerator.cs new file mode 100644 index 000000000..455ca88ac --- /dev/null +++ b/crypto/src/asn1/DERSetGenerator.cs @@ -0,0 +1,40 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerSetGenerator + : DerGenerator + { + private readonly MemoryStream _bOut = new MemoryStream(); + + public DerSetGenerator( + Stream outStream) + : base(outStream) + { + } + + public DerSetGenerator( + Stream outStream, + int tagNo, + bool isExplicit) + : base(outStream, tagNo, isExplicit) + { + } + + public override void AddObject( + Asn1Encodable obj) + { + new DerOutputStream(_bOut).WriteObject(obj); + } + + public override Stream GetRawOutputStream() + { + return _bOut; + } + + public override void Close() + { + WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray()); + } + } +} diff --git a/crypto/src/asn1/DERSetParser.cs b/crypto/src/asn1/DERSetParser.cs new file mode 100644 index 000000000..d67f135be --- /dev/null +++ b/crypto/src/asn1/DERSetParser.cs @@ -0,0 +1,24 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class DerSetParser + : Asn1SetParser + { + private readonly Asn1StreamParser _parser; + + internal DerSetParser( + Asn1StreamParser parser) + { + this._parser = parser; + } + + public IAsn1Convertible ReadObject() + { + return _parser.ReadObject(); + } + + public Asn1Object ToAsn1Object() + { + return new DerSet(_parser.ReadVector(), false); + } + } +} diff --git a/crypto/src/asn1/DefiniteLengthInputStream.cs b/crypto/src/asn1/DefiniteLengthInputStream.cs new file mode 100644 index 000000000..4ae803c0e --- /dev/null +++ b/crypto/src/asn1/DefiniteLengthInputStream.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + class DefiniteLengthInputStream + : LimitedInputStream + { + private static readonly byte[] EmptyBytes = new byte[0]; + + private readonly int _originalLength; + private int _remaining; + + internal DefiniteLengthInputStream( + Stream inStream, + int length) + : base(inStream, length) + { + if (length < 0) + throw new ArgumentException("negative lengths not allowed", "length"); + + this._originalLength = length; + this._remaining = length; + + if (length == 0) + { + SetParentEofDetect(true); + } + } + + internal int Remaining + { + get { return _remaining; } + } + + public override int ReadByte() + { + if (_remaining == 0) + return -1; + + int b = _in.ReadByte(); + + if (b < 0) + throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); + + if (--_remaining == 0) + { + SetParentEofDetect(true); + } + + return b; + } + + public override int Read( + byte[] buf, + int off, + int len) + { + if (_remaining == 0) + return 0; + + int toRead = System.Math.Min(len, _remaining); + int numRead = _in.Read(buf, off, toRead); + + if (numRead < 1) + throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); + + if ((_remaining -= numRead) == 0) + { + SetParentEofDetect(true); + } + + return numRead; + } + + internal void ReadAllIntoByteArray(byte[] buf) + { + if (_remaining != buf.Length) + throw new ArgumentException("buffer length not right for data"); + + if ((_remaining -= Streams.ReadFully(_in, buf)) != 0) + throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); + SetParentEofDetect(true); + } + + internal byte[] ToArray() + { + if (_remaining == 0) + return EmptyBytes; + + byte[] bytes = new byte[_remaining]; + if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0) + throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); + SetParentEofDetect(true); + return bytes; + } + } +} diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs new file mode 100644 index 000000000..394c7431e --- /dev/null +++ b/crypto/src/asn1/DerApplicationSpecific.cs @@ -0,0 +1,237 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Base class for an application specific object + */ + public class DerApplicationSpecific + : Asn1Object + { + private readonly bool isConstructed; + private readonly int tag; + private readonly byte[] octets; + + internal DerApplicationSpecific( + bool 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 obj) + : this(true, tag, obj) + { + } + + public DerApplicationSpecific( + bool isExplicit, + int tag, + Asn1Encodable obj) + { + Asn1Object asn1Obj = obj.ToAsn1Object(); + + byte[] data = asn1Obj.GetDerEncoded(); + + this.isConstructed = isExplicit || asn1Obj is Asn1Set || asn1Obj is Asn1Sequence; + this.tag = tag; + + if (isExplicit) + { + this.octets = data; + } + else + { + int lenBytes = GetLengthOfHeader(data); + byte[] tmp = new byte[data.Length - lenBytes]; + Array.Copy(data, lenBytes, tmp, 0, tmp.Length); + this.octets = tmp; + } + } + + public DerApplicationSpecific( + int tagNo, + Asn1EncodableVector vec) + { + this.tag = tagNo; + this.isConstructed = true; + MemoryStream bOut = new MemoryStream(); + + for (int i = 0; i != vec.Count; i++) + { + try + { + byte[] bs = vec[i].GetDerEncoded(); + bOut.Write(bs, 0, bs.Length); + } + catch (IOException e) + { + throw new InvalidOperationException("malformed object", e); + } + } + this.octets = bOut.ToArray(); + } + + private int GetLengthOfHeader( + byte[] data) + { + int length = data[1]; // 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 InvalidOperationException("DER length more than 4 bytes: " + size); + } + + return size + 2; + } + + return 2; + } + + public bool IsConstructed() + { + return isConstructed; + } + + public byte[] GetContents() + { + return octets; + } + + public int ApplicationTag + { + get { return tag; } + } + + /** + * Return the enclosed object assuming explicit tagging. + * + * @return the resulting object + * @throws IOException if reconstruction fails. + */ + public Asn1Object GetObject() + { + return FromByteArray(GetContents()); + } + + /** + * 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 Asn1Object GetObject( + int derTagNo) + { + if (derTagNo >= 0x1f) + throw new IOException("unsupported tag number"); + + byte[] orig = this.GetEncoded(); + byte[] tmp = ReplaceTagNumber(derTagNo, orig); + + if ((orig[0] & Asn1Tags.Constructed) != 0) + { + tmp[0] |= Asn1Tags.Constructed; + } + + return FromByteArray(tmp);; + } + + internal override void Encode( + DerOutputStream derOut) + { + int classBits = Asn1Tags.Application; + if (isConstructed) + { + classBits |= Asn1Tags.Constructed; + } + + derOut.WriteEncoded(classBits, tag, octets); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerApplicationSpecific other = asn1Object as DerApplicationSpecific; + + if (other == null) + return false; + + return this.isConstructed == other.isConstructed + && this.tag == other.tag + && Arrays.AreEqual(this.octets, other.octets); + } + + protected override int Asn1GetHashCode() + { + return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets); + } + + private byte[] ReplaceTagNumber( + int newTag, + byte[] input) + { + 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 InvalidOperationException("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]; + + Array.Copy(input, index, tmp, 1, tmp.Length - 1); + + tmp[0] = (byte)newTag; + + return tmp; + } + } +} diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs new file mode 100644 index 000000000..4f7e0a635 --- /dev/null +++ b/crypto/src/asn1/DerBMPString.cs @@ -0,0 +1,115 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der BMPString object. + */ + public class DerBmpString + : DerStringBase + { + private readonly string str; + + /** + * return a BMP string from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static DerBmpString GetInstance( + object obj) + { + if (obj == null || obj is DerBmpString) + { + return (DerBmpString)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a BMP string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerBmpString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerBmpString) + { + return GetInstance(o); + } + + return new DerBmpString(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - byte encoded string. + */ + public DerBmpString( + byte[] str) + { + if (str == null) + throw new ArgumentNullException("str"); + + char[] cs = new char[str.Length / 2]; + + for (int i = 0; i != cs.Length; i++) + { + cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff)); + } + + this.str = new string(cs); + } + + /** + * basic constructor + */ + public DerBmpString( + string str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerBmpString other = asn1Object as DerBmpString; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + internal override void Encode( + DerOutputStream derOut) + { + char[] c = str.ToCharArray(); + byte[] b = new byte[c.Length * 2]; + + for (int i = 0; i != c.Length; i++) + { + b[2 * i] = (byte)(c[i] >> 8); + b[2 * i + 1] = (byte)c[i]; + } + + derOut.WriteEncoded(Asn1Tags.BmpString, b); + } + } +} diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs new file mode 100644 index 000000000..d5cb872bc --- /dev/null +++ b/crypto/src/asn1/DerBitString.cs @@ -0,0 +1,248 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerBitString + : DerStringBase + { + private static readonly char[] table + = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + private readonly byte[] data; + private readonly int padBits; + + /** + * return the correct number of pad bits for a bit string defined in + * a 32 bit constant + */ + static internal 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; + } + + /** + * return the correct number of bytes for a bit string defined in + * a 32 bit constant + */ + static internal 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 + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerBitString GetInstance( + object obj) + { + if (obj == null || obj is DerBitString) + { + return (DerBitString) obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a Bit string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerBitString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerBitString) + { + return GetInstance(o); + } + + return FromAsn1Octets(((Asn1OctetString)o).GetOctets()); + } + + internal DerBitString( + byte data, + int padBits) + { + this.data = new byte[]{ 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) + { + // TODO Deep copy? + this.data = data; + this.padBits = padBits; + } + + public DerBitString( + byte[] data) + { + // TODO Deep copy? + this.data = data; + } + + public DerBitString( + Asn1Encodable obj) + { + this.data = obj.GetDerEncoded(); + //this.padBits = 0; + } + + public byte[] GetBytes() + { + return data; + } + + public int PadBits + { + get { return padBits; } + } + + /** + * @return the value of the bit string as an int (truncating if necessary) + */ + public int IntValue + { + get + { + int value = 0; + + for (int i = 0; i != data.Length && i != 4; i++) + { + value |= (data[i] & 0xff) << (8 * i); + } + + return value; + } + } + + internal override void Encode( + DerOutputStream derOut) + { + byte[] bytes = new byte[GetBytes().Length + 1]; + + bytes[0] = (byte) PadBits; + Array.Copy(GetBytes(), 0, bytes, 1, bytes.Length - 1); + + derOut.WriteEncoded(Asn1Tags.BitString, bytes); + } + + protected override int Asn1GetHashCode() + { + return padBits.GetHashCode() ^ Arrays.GetHashCode(data); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerBitString other = asn1Object as DerBitString; + + if (other == null) + return false; + + return this.padBits == other.padBits + && Arrays.AreEqual(this.data, other.data); + } + + public override string GetString() + { + StringBuilder buffer = new StringBuilder("#"); + + byte[] str = GetDerEncoded(); + + for (int i = 0; i != str.Length; i++) + { + uint ubyte = str[i]; + buffer.Append(table[(ubyte >> 4) & 0xf]); + buffer.Append(table[str[i] & 0xf]); + } + + return buffer.ToString(); + } + + internal static DerBitString FromAsn1Octets(byte[] octets) + { + if (octets.Length < 1) + throw new ArgumentException("truncated BIT STRING detected"); + + int padBits = octets[0]; + byte[] data = new byte[octets.Length - 1]; + Array.Copy(octets, 1, data, 0, data.Length); + return new DerBitString(data, padBits); + } + } +} + diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs new file mode 100644 index 000000000..41ccae8a1 --- /dev/null +++ b/crypto/src/asn1/DerBoolean.cs @@ -0,0 +1,110 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerBoolean + : Asn1Object + { + private readonly byte value; + + public static readonly DerBoolean False = new DerBoolean(false); + public static readonly DerBoolean True = new DerBoolean(true); + + /** + * return a bool from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerBoolean GetInstance( + object obj) + { + if (obj == null || obj is DerBoolean) + { + return (DerBoolean) obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a DerBoolean from the passed in bool. + */ + public static DerBoolean GetInstance( + bool value) + { + return value ? True : False; + } + + /** + * return a Boolean from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerBoolean GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerBoolean) + { + return GetInstance(o); + } + + return new DerBoolean(((Asn1OctetString)o).GetOctets()); + } + + public DerBoolean( + byte[] val) + { + if (val.Length != 1) + throw new ArgumentException("byte value should have 1 byte in it", "val"); + + // TODO Are there any constraints on the possible byte values? + this.value = val[0]; + } + + private DerBoolean( + bool value) + { + this.value = value ? (byte)0xff : (byte)0; + } + + public bool IsTrue + { + get { return value != 0; } + } + + internal override void Encode( + DerOutputStream derOut) + { + // TODO Should we make sure the byte value is one of '0' or '0xff' here? + derOut.WriteEncoded(Asn1Tags.Boolean, new byte[]{ value }); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerBoolean other = asn1Object as DerBoolean; + + if (other == null) + return false; + + return IsTrue == other.IsTrue; + } + + protected override int Asn1GetHashCode() + { + return IsTrue.GetHashCode(); + } + + public override string ToString() + { + return IsTrue ? "TRUE" : "FALSE"; + } + } +} diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs new file mode 100644 index 000000000..0e67e6dbe --- /dev/null +++ b/crypto/src/asn1/DerEnumerated.cs @@ -0,0 +1,100 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerEnumerated + : Asn1Object + { + private readonly byte[] bytes; + + /** + * return an integer from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerEnumerated GetInstance( + object obj) + { + if (obj == null || obj is DerEnumerated) + { + return (DerEnumerated)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an Enumerated from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerEnumerated GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerEnumerated) + { + return GetInstance(o); + } + + return new DerEnumerated(((Asn1OctetString)o).GetOctets()); + } + + public DerEnumerated( + int val) + { + bytes = BigInteger.ValueOf(val).ToByteArray(); + } + + public DerEnumerated( + BigInteger val) + { + bytes = val.ToByteArray(); + } + + public DerEnumerated( + byte[] bytes) + { + this.bytes = bytes; + } + + public BigInteger Value + { + get + { + return new BigInteger(bytes); + } + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.Enumerated, bytes); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerEnumerated other = asn1Object as DerEnumerated; + + if (other == null) + return false; + + return Arrays.AreEqual(this.bytes, other.bytes); + } + + protected override int Asn1GetHashCode() + { + return Arrays.GetHashCode(bytes); + } + } +} diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs new file mode 100644 index 000000000..0e20b53bd --- /dev/null +++ b/crypto/src/asn1/DerGeneralString.cs @@ -0,0 +1,81 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerGeneralString + : DerStringBase + { + private readonly string str; + + public static DerGeneralString GetInstance( + object obj) + { + if (obj == null || obj is DerGeneralString) + { + return (DerGeneralString) obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + + obj.GetType().Name); + } + + public static DerGeneralString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerGeneralString) + { + return GetInstance(o); + } + + return new DerGeneralString(((Asn1OctetString)o).GetOctets()); + } + + public DerGeneralString( + byte[] str) + : this(Strings.FromAsciiByteArray(str)) + { + } + + public DerGeneralString( + string str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + public byte[] GetOctets() + { + return Strings.ToAsciiByteArray(str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.GeneralString, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerGeneralString other = asn1Object as DerGeneralString; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + } +} diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs new file mode 100644 index 000000000..dae60e876 --- /dev/null +++ b/crypto/src/asn1/DerGeneralizedTime.cs @@ -0,0 +1,305 @@ +using System; +using System.Globalization; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Generalized time object. + */ + public class DerGeneralizedTime + : Asn1Object + { + private readonly string time; + + /** + * return a generalized time from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerGeneralizedTime GetInstance( + object obj) + { + if (obj == null || obj is DerGeneralizedTime) + { + return (DerGeneralizedTime)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj"); + } + + /** + * return a Generalized Time object from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerGeneralizedTime GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerGeneralizedTime) + { + return GetInstance(o); + } + + return new DerGeneralizedTime(((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 ArgumentException if string is an illegal format. + */ + public DerGeneralizedTime( + string time) + { + this.time = time; + + try + { + ToDateTime(); + } + catch (FormatException e) + { + throw new ArgumentException("invalid date string: " + e.Message); + } + } + + /** + * base constructor from a local time object + */ + public DerGeneralizedTime( + DateTime time) + { + this.time = time.ToString(@"yyyyMMddHHmmss\Z"); + } + + internal DerGeneralizedTime( + byte[] bytes) + { + // + // explicitly convert to characters + // + this.time = Strings.FromAsciiByteArray(bytes); + } + + /** + * Return the time. + * @return The time string as it appeared in the encoded object. + */ + public string TimeString + { + get { return time; } + } + + /** + * return the time - always in the form of + * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm). + *

+ * Normally in a certificate we would expect "Z" rather than "GMT", + * however adding the "GMT" means we can just use: + *

+         *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+         * 
+ * To read in the time and Get a date which is compatible with our local + * time zone.

+ */ + public string GetTime() + { + // + // standardise the format. + // + if (time[time.Length - 1] == 'Z') + { + return time.Substring(0, time.Length - 1) + "GMT+00:00"; + } + else + { + int signPos = time.Length - 5; + char sign = time[signPos]; + if (sign == '-' || sign == '+') + { + return time.Substring(0, signPos) + + "GMT" + + time.Substring(signPos, 3) + + ":" + + time.Substring(signPos + 3); + } + else + { + signPos = time.Length - 3; + sign = time[signPos]; + if (sign == '-' || sign == '+') + { + return time.Substring(0, signPos) + + "GMT" + + time.Substring(signPos) + + ":00"; + } + } + } + + return time + CalculateGmtOffset(); + } + + private string CalculateGmtOffset() + { + char sign = '+'; + DateTime time = ToDateTime(); + +#if SILVERLIGHT + long offset = time.Ticks - time.ToUniversalTime().Ticks; + if (offset < 0) + { + sign = '-'; + offset = -offset; + } + int hours = (int)(offset / TimeSpan.TicksPerHour); + int minutes = (int)(offset / TimeSpan.TicksPerMinute) % 60; +#else + // Note: GetUtcOffset incorporates Daylight Savings offset + TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(time); + if (offset.CompareTo(TimeSpan.Zero) < 0) + { + sign = '-'; + offset = offset.Duration(); + } + int hours = offset.Hours; + int minutes = offset.Minutes; +#endif + + return "GMT" + sign + Convert(hours) + ":" + Convert(minutes); + } + + private static string Convert( + int time) + { + if (time < 10) + { + return "0" + time; + } + + return time.ToString(); + } + + public DateTime ToDateTime() + { + string formatStr; + string d = time; + bool makeUniversal = false; + + if (d.EndsWith("Z")) + { + if (HasFractionalSeconds) + { + int fCount = d.Length - d.IndexOf('.') - 2; + formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"\Z"; + } + else + { + formatStr = @"yyyyMMddHHmmss\Z"; + } + } + else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0) + { + d = GetTime(); + makeUniversal = true; + + if (HasFractionalSeconds) + { + int fCount = d.IndexOf("GMT") - 1 - d.IndexOf('.'); + formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"'GMT'zzz"; + } + else + { + formatStr = @"yyyyMMddHHmmss'GMT'zzz"; + } + } + else + { + if (HasFractionalSeconds) + { + int fCount = d.Length - 1 - d.IndexOf('.'); + formatStr = @"yyyyMMddHHmmss." + FString(fCount); + } + else + { + formatStr = @"yyyyMMddHHmmss"; + } + + // TODO? +// dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); + } + + return ParseDateString(d, formatStr, makeUniversal); + } + + private string FString( + int count) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; ++i) + { + sb.Append('f'); + } + return sb.ToString(); + } + + private DateTime ParseDateString( + string dateStr, + string formatStr, + bool makeUniversal) + { + DateTime dt = DateTime.ParseExact( + dateStr, + formatStr, + DateTimeFormatInfo.InvariantInfo); + + return makeUniversal ? dt.ToUniversalTime() : dt; + } + + private bool HasFractionalSeconds + { + get { return time.IndexOf('.') == 14; } + } + + private byte[] GetOctets() + { + return Strings.ToAsciiByteArray(time); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerGeneralizedTime other = asn1Object as DerGeneralizedTime; + + if (other == null) + return false; + + return this.time.Equals(other.time); + } + + protected override int Asn1GetHashCode() + { + return time.GetHashCode(); + } + } +} diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs new file mode 100644 index 000000000..9fa2cba3c --- /dev/null +++ b/crypto/src/asn1/DerIA5String.cs @@ -0,0 +1,145 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der IA5String object - this is an ascii string. + */ + public class DerIA5String + : DerStringBase + { + private readonly string str; + + /** + * return a IA5 string from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerIA5String GetInstance( + object obj) + { + if (obj == null || obj is DerIA5String) + { + return (DerIA5String)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an IA5 string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerIA5String GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerIA5String) + { + return GetInstance(o); + } + + return new DerIA5String(((Asn1OctetString)o).GetOctets()); + } + + /** + * basic constructor - with bytes. + */ + public DerIA5String( + byte[] str) + : this(Strings.FromAsciiByteArray(str), false) + { + } + + /** + * basic constructor - without validation. + */ + public DerIA5String( + string str) + : this(str, false) + { + } + + /** + * Constructor with optional validation. + * + * @param string the base string to wrap. + * @param validate whether or not to check the string. + * @throws ArgumentException if validate is true and the string + * contains characters that should not be in an IA5String. + */ + public DerIA5String( + string str, + bool validate) + { + if (str == null) + throw new ArgumentNullException("str"); + if (validate && !IsIA5String(str)) + throw new ArgumentException("string contains illegal characters", "str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + public byte[] GetOctets() + { + return Strings.ToAsciiByteArray(str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.IA5String, GetOctets()); + } + + protected override int Asn1GetHashCode() + { + return this.str.GetHashCode(); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerIA5String other = asn1Object as DerIA5String; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + /** + * return true if the passed in String can be represented without + * loss as an IA5String, false otherwise. + * + * @return true if in printable set, false otherwise. + */ + public static bool IsIA5String( + string str) + { + foreach (char ch in str) + { + if (ch > 0x007f) + { + return false; + } + } + + return true; + } + } +} diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs new file mode 100644 index 000000000..eb0614515 --- /dev/null +++ b/crypto/src/asn1/DerInteger.cs @@ -0,0 +1,117 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerInteger + : Asn1Object + { + private readonly byte[] bytes; + + /** + * return an integer from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerInteger GetInstance( + object obj) + { + if (obj == null || obj is DerInteger) + { + return (DerInteger)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an Integer from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerInteger GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerInteger) + { + return GetInstance(o); + } + + return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets()); + } + + public DerInteger( + int value) + { + bytes = BigInteger.ValueOf(value).ToByteArray(); + } + + public DerInteger( + BigInteger value) + { + if (value == null) + throw new ArgumentNullException("value"); + + bytes = value.ToByteArray(); + } + + public DerInteger( + byte[] bytes) + { + this.bytes = bytes; + } + + public BigInteger Value + { + get { return new BigInteger(bytes); } + } + + /** + * in some cases positive values Get crammed into a space, + * that's not quite big enough... + */ + public BigInteger PositiveValue + { + get { return new BigInteger(1, bytes); } + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.Integer, bytes); + } + + protected override int Asn1GetHashCode() + { + return Arrays.GetHashCode(bytes); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerInteger other = asn1Object as DerInteger; + + if (other == null) + return false; + + return Arrays.AreEqual(this.bytes, other.bytes); + } + + public override string ToString() + { + return Value.ToString(); + } + } +} diff --git a/crypto/src/asn1/DerNull.cs b/crypto/src/asn1/DerNull.cs new file mode 100644 index 000000000..a802f6486 --- /dev/null +++ b/crypto/src/asn1/DerNull.cs @@ -0,0 +1,41 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * A Null object. + */ + public class DerNull + : Asn1Null + { + public static readonly DerNull Instance = new DerNull(0); + + byte[] zeroBytes = new byte[0]; + + [Obsolete("Use static Instance object")] + public DerNull() + { + } + + protected internal DerNull(int dummy) + { + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.Null, zeroBytes); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + return asn1Object is DerNull; + } + + protected override int Asn1GetHashCode() + { + return -1; + } + } +} diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs new file mode 100644 index 000000000..6e2715a4d --- /dev/null +++ b/crypto/src/asn1/DerNumericString.cs @@ -0,0 +1,138 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }. + */ + public class DerNumericString + : DerStringBase + { + private readonly string str; + + /** + * return a Numeric string from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerNumericString GetInstance( + object obj) + { + if (obj == null || obj is DerNumericString) + { + return (DerNumericString)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an Numeric string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerNumericString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerNumericString) + { + return GetInstance(o); + } + + return new DerNumericString(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - with bytes. + */ + public DerNumericString( + byte[] str) + : this(Strings.FromAsciiByteArray(str), false) + { + } + + /** + * basic constructor - without validation.. + */ + public DerNumericString( + string str) + : this(str, false) + { + } + + /** + * Constructor with optional validation. + * + * @param string the base string to wrap. + * @param validate whether or not to check the string. + * @throws ArgumentException if validate is true and the string + * contains characters that should not be in a NumericString. + */ + public DerNumericString( + string str, + bool validate) + { + if (str == null) + throw new ArgumentNullException("str"); + if (validate && !IsNumericString(str)) + throw new ArgumentException("string contains illegal characters", "str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + public byte[] GetOctets() + { + return Strings.ToAsciiByteArray(str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.NumericString, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerNumericString other = asn1Object as DerNumericString; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + /** + * 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 bool IsNumericString( + string str) + { + foreach (char ch in str) + { + if (ch > 0x007f || (ch != ' ' && !char.IsDigit(ch))) + return false; + } + + return true; + } + } +} diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs new file mode 100644 index 000000000..f9f6a79d6 --- /dev/null +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -0,0 +1,347 @@ +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerObjectIdentifier + : Asn1Object + { + private readonly string identifier; + + private byte[] body = null; + + /** + * return an Oid from the passed in object + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerObjectIdentifier GetInstance(object obj) + { + if (obj == null || obj is DerObjectIdentifier) + return (DerObjectIdentifier) obj; + if (obj is byte[]) + return FromOctetString((byte[])obj); + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj"); + } + + /** + * return an object Identifier from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerObjectIdentifier GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(obj.GetObject()); + } + + public DerObjectIdentifier( + string identifier) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + if (!IsValidIdentifier(identifier)) + throw new FormatException("string " + identifier + " not an OID"); + + this.identifier = identifier; + } + + internal DerObjectIdentifier(DerObjectIdentifier oid, string branchID) + { + if (!IsValidBranchID(branchID, 0)) + throw new ArgumentException("string " + branchID + " not a valid OID branch", "branchID"); + + this.identifier = oid.Id + "." + branchID; + } + + // TODO Change to ID? + public string Id + { + get { return identifier; } + } + + public virtual DerObjectIdentifier Branch(string branchID) + { + return new DerObjectIdentifier(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 virtual bool On(DerObjectIdentifier stem) + { + string id = Id, stemId = stem.Id; + return id.Length > stemId.Length && id[stemId.Length] == '.' && id.StartsWith(stemId); + } + + internal DerObjectIdentifier(byte[] bytes) + { + this.identifier = MakeOidStringFromBytes(bytes); + this.body = Arrays.Clone(bytes); + } + + private void WriteField( + Stream outputStream, + long fieldValue) + { + byte[] result = new byte[9]; + int pos = 8; + result[pos] = (byte)(fieldValue & 0x7f); + while (fieldValue >= (1L << 7)) + { + fieldValue >>= 7; + result[--pos] = (byte)((fieldValue & 0x7f) | 0x80); + } + outputStream.Write(result, pos, 9 - pos); + } + + private void WriteField( + Stream outputStream, + BigInteger fieldValue) + { + int byteCount = (fieldValue.BitLength + 6) / 7; + if (byteCount == 0) + { + outputStream.WriteByte(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; + outputStream.Write(tmp, 0, tmp.Length); + } + } + + private void DoOutput(MemoryStream bOut) + { + OidTokenizer tok = new OidTokenizer(identifier); + + string token = tok.NextToken(); + int first = int.Parse(token) * 40; + + token = tok.NextToken(); + if (token.Length <= 18) + { + WriteField(bOut, first + Int64.Parse(token)); + } + else + { + WriteField(bOut, new BigInteger(token).Add(BigInteger.ValueOf(first))); + } + + while (tok.HasMoreTokens) + { + token = tok.NextToken(); + if (token.Length <= 18) + { + WriteField(bOut, Int64.Parse(token)); + } + else + { + WriteField(bOut, new BigInteger(token)); + } + } + } + + internal byte[] GetBody() + { + lock (this) + { + if (body == null) + { + MemoryStream bOut = new MemoryStream(); + DoOutput(bOut); + body = bOut.ToArray(); + } + } + + return body; + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.ObjectIdentifier, GetBody()); + } + + protected override int Asn1GetHashCode() + { + return identifier.GetHashCode(); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerObjectIdentifier other = asn1Object as DerObjectIdentifier; + + if (other == null) + return false; + + return this.identifier.Equals(other.identifier); + } + + public override string ToString() + { + return identifier; + } + + private static bool IsValidBranchID( + String branchID, int start) + { + bool periodAllowed = false; + + int pos = branchID.Length; + while (--pos >= start) + { + char ch = branchID[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 bool IsValidIdentifier(string identifier) + { + if (identifier.Length < 3 || identifier[1] != '.') + return false; + + char first = identifier[0]; + if (first < '0' || first > '2') + return false; + + return IsValidBranchID(identifier, 2); + } + + private const long LONG_LIMIT = (long.MaxValue >> 7) - 0x7f; + + private static string MakeOidStringFromBytes( + byte[] bytes) + { + StringBuilder objId = new StringBuilder(); + long value = 0; + BigInteger bigValue = null; + bool first = true; + + for (int i = 0; i != bytes.Length; i++) + { + int b = bytes[i]; + + 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); + } + } + } + + return objId.ToString(); + } + + private static readonly DerObjectIdentifier[] cache = new DerObjectIdentifier[1024]; + + internal static DerObjectIdentifier FromOctetString(byte[] enc) + { + int hashCode = Arrays.GetHashCode(enc); + int first = hashCode & 1023; + + lock (cache) + { + DerObjectIdentifier entry = cache[first]; + if (entry != null && Arrays.AreEqual(enc, entry.GetBody())) + { + return entry; + } + + return cache[first] = new DerObjectIdentifier(enc); + } + } + } +} diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs new file mode 100644 index 000000000..c046c9402 --- /dev/null +++ b/crypto/src/asn1/DerOctetString.cs @@ -0,0 +1,34 @@ +namespace Org.BouncyCastle.Asn1 +{ + public class DerOctetString + : Asn1OctetString + { + /// The octets making up the octet string. + public DerOctetString( + byte[] str) + : base(str) + { + } + + public DerOctetString( + Asn1Encodable obj) + : base(obj) + { + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.OctetString, str); + } + + internal static void Encode( + DerOutputStream derOut, + byte[] bytes, + int offset, + int length) + { + derOut.WriteEncoded(Asn1Tags.OctetString, bytes, offset, length); + } + } +} diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs new file mode 100644 index 000000000..f95d123f9 --- /dev/null +++ b/crypto/src/asn1/DerOutputStream.cs @@ -0,0 +1,160 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerOutputStream + : FilterStream + { + public DerOutputStream(Stream os) + : base(os) + { + } + + private void WriteLength( + int length) + { + if (length > 127) + { + int size = 1; + uint val = (uint) length; + + while ((val >>= 8) != 0) + { + size++; + } + + WriteByte((byte)(size | 0x80)); + + for (int i = (size - 1) * 8; i >= 0; i -= 8) + { + WriteByte((byte)(length >> i)); + } + } + else + { + WriteByte((byte)length); + } + } + + internal void WriteEncoded( + int tag, + byte[] bytes) + { + WriteByte((byte) tag); + WriteLength(bytes.Length); + Write(bytes, 0, bytes.Length); + } + + internal void WriteEncoded( + int tag, + byte[] bytes, + int offset, + int length) + { + WriteByte((byte) tag); + WriteLength(length); + Write(bytes, offset, length); + } + + internal void WriteTag( + int flags, + int tagNo) + { + if (tagNo < 31) + { + WriteByte((byte)(flags | tagNo)); + } + else + { + WriteByte((byte)(flags | 0x1f)); + if (tagNo < 128) + { + WriteByte((byte)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); + } + } + } + + internal void WriteEncoded( + int flags, + int tagNo, + byte[] bytes) + { + WriteTag(flags, tagNo); + WriteLength(bytes.Length); + Write(bytes, 0, bytes.Length); + } + + protected void WriteNull() + { + WriteByte(Asn1Tags.Null); + WriteByte(0x00); + } + + [Obsolete("Use version taking an Asn1Encodable arg instead")] + public virtual void WriteObject( + object obj) + { + if (obj == null) + { + WriteNull(); + } + else if (obj is Asn1Object) + { + ((Asn1Object)obj).Encode(this); + } + else if (obj is Asn1Encodable) + { + ((Asn1Encodable)obj).ToAsn1Object().Encode(this); + } + else + { + throw new IOException("object not Asn1Object"); + } + } + + public virtual void WriteObject( + Asn1Encodable obj) + { + if (obj == null) + { + WriteNull(); + } + else + { + obj.ToAsn1Object().Encode(this); + } + } + + public virtual void WriteObject( + Asn1Object obj) + { + if (obj == null) + { + WriteNull(); + } + else + { + obj.Encode(this); + } + } + } +} diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs new file mode 100644 index 000000000..cd2f46b48 --- /dev/null +++ b/crypto/src/asn1/DerPrintableString.cs @@ -0,0 +1,163 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der PrintableString object. + */ + public class DerPrintableString + : DerStringBase + { + private readonly string str; + + /** + * return a printable string from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerPrintableString GetInstance( + object obj) + { + if (obj == null || obj is DerPrintableString) + { + return (DerPrintableString)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a Printable string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerPrintableString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerPrintableString) + { + return GetInstance(o); + } + + return new DerPrintableString(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - byte encoded string. + */ + public DerPrintableString( + byte[] str) + : this(Strings.FromAsciiByteArray(str), false) + { + } + + /** + * basic constructor - this does not validate the string + */ + public DerPrintableString( + string str) + : this(str, false) + { + } + + /** + * Constructor with optional validation. + * + * @param string the base string to wrap. + * @param validate whether or not to check the string. + * @throws ArgumentException if validate is true and the string + * contains characters that should not be in a PrintableString. + */ + public DerPrintableString( + string str, + bool validate) + { + if (str == null) + throw new ArgumentNullException("str"); + if (validate && !IsPrintableString(str)) + throw new ArgumentException("string contains illegal characters", "str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + public byte[] GetOctets() + { + return Strings.ToAsciiByteArray(str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.PrintableString, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerPrintableString other = asn1Object as DerPrintableString; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + /** + * 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 bool IsPrintableString( + string str) + { + foreach (char ch in str) + { + if (ch > 0x007f) + return false; + + if (char.IsLetterOrDigit(ch)) + continue; + +// if (char.IsPunctuation(ch)) +// continue; + + switch (ch) + { + case ' ': + case '\'': + case '(': + case ')': + case '+': + case '-': + case '.': + case ':': + case '=': + case '?': + case '/': + case ',': + continue; + } + + return false; + } + + return true; + } + } +} diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs new file mode 100644 index 000000000..b50a77962 --- /dev/null +++ b/crypto/src/asn1/DerSequence.cs @@ -0,0 +1,85 @@ +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerSequence + : Asn1Sequence + { + public static readonly DerSequence Empty = new DerSequence(); + + public static DerSequence FromVector( + Asn1EncodableVector v) + { + return v.Count < 1 ? Empty : new DerSequence(v); + } + + /** + * create an empty sequence + */ + public DerSequence() + : base(0) + { + } + + /** + * create a sequence containing one object + */ + public DerSequence( + Asn1Encodable obj) + : base(1) + { + AddObject(obj); + } + + public DerSequence( + params Asn1Encodable[] v) + : base(v.Length) + { + foreach (Asn1Encodable ae in v) + { + AddObject(ae); + } + } + + /** + * create a sequence containing a vector of objects. + */ + public DerSequence( + Asn1EncodableVector v) + : base(v.Count) + { + foreach (Asn1Encodable ae in v) + { + AddObject(ae); + } + } + + /* + * A note on the implementation: + *

+ * 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 outputing Sequence, + * we also have to specify Constructed, and the objects length. + */ + internal override void Encode( + DerOutputStream derOut) + { + // TODO Intermediate buffer could be avoided if we could calculate expected length + MemoryStream bOut = new MemoryStream(); + DerOutputStream dOut = new DerOutputStream(bOut); + + foreach (Asn1Encodable obj in this) + { + dOut.WriteObject(obj); + } + + dOut.Close(); + + byte[] bytes = bOut.ToArray(); + + derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes); + } + } +} diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs new file mode 100644 index 000000000..c66dde8c7 --- /dev/null +++ b/crypto/src/asn1/DerSet.cs @@ -0,0 +1,108 @@ +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * A Der encoded set object + */ + public class DerSet + : Asn1Set + { + public static readonly DerSet Empty = new DerSet(); + + public static DerSet FromVector( + Asn1EncodableVector v) + { + return v.Count < 1 ? Empty : new DerSet(v); + } + + internal static DerSet FromVector( + Asn1EncodableVector v, + bool needsSorting) + { + return v.Count < 1 ? Empty : new DerSet(v, needsSorting); + } + + /** + * create an empty set + */ + public DerSet() + : base(0) + { + } + + /** + * @param obj - a single object that makes up the set. + */ + public DerSet( + Asn1Encodable obj) + : base(1) + { + AddObject(obj); + } + + public DerSet( + params Asn1Encodable[] v) + : base(v.Length) + { + foreach (Asn1Encodable o in v) + { + AddObject(o); + } + + Sort(); + } + + /** + * @param v - a vector of objects making up the set. + */ + public DerSet( + Asn1EncodableVector v) + : this(v, true) + { + } + + internal DerSet( + Asn1EncodableVector v, + bool needsSorting) + : base(v.Count) + { + foreach (Asn1Encodable o in v) + { + AddObject(o); + } + + if (needsSorting) + { + Sort(); + } + } + + /* + * A note on the implementation: + *

+ * 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 outputing Set, + * we also have to specify Constructed, and the objects length. + */ + internal override void Encode( + DerOutputStream derOut) + { + // TODO Intermediate buffer could be avoided if we could calculate expected length + MemoryStream bOut = new MemoryStream(); + DerOutputStream dOut = new DerOutputStream(bOut); + + foreach (Asn1Encodable obj in this) + { + dOut.WriteObject(obj); + } + + dOut.Close(); + + byte[] bytes = bOut.ToArray(); + + derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes); + } + } +} diff --git a/crypto/src/asn1/DerStringBase.cs b/crypto/src/asn1/DerStringBase.cs new file mode 100644 index 000000000..2a5fb041e --- /dev/null +++ b/crypto/src/asn1/DerStringBase.cs @@ -0,0 +1,22 @@ +namespace Org.BouncyCastle.Asn1 +{ + public abstract class DerStringBase + : Asn1Object, IAsn1String + { + protected DerStringBase() + { + } + + public abstract string GetString(); + + public override string ToString() + { + return GetString(); + } + + protected override int Asn1GetHashCode() + { + return GetString().GetHashCode(); + } + } +} diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs new file mode 100644 index 000000000..4dee6f30c --- /dev/null +++ b/crypto/src/asn1/DerT61String.cs @@ -0,0 +1,102 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der T61String (also the teletex string) - 8-bit characters + */ + public class DerT61String + : DerStringBase + { + private readonly string str; + + /** + * return a T61 string from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerT61String GetInstance( + object obj) + { + if (obj == null || obj is DerT61String) + { + return (DerT61String)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an T61 string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerT61String GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerT61String) + { + return GetInstance(o); + } + + return new DerT61String(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - with bytes. + */ + public DerT61String( + byte[] str) + : this(Strings.FromByteArray(str)) + { + } + + /** + * basic constructor - with string. + */ + public DerT61String( + string str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.T61String, GetOctets()); + } + + public byte[] GetOctets() + { + return Strings.ToByteArray(str); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerT61String other = asn1Object as DerT61String; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + } +} diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs new file mode 100644 index 000000000..717d724b6 --- /dev/null +++ b/crypto/src/asn1/DerTaggedObject.cs @@ -0,0 +1,72 @@ +namespace Org.BouncyCastle.Asn1 +{ + /** + * 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 + : Asn1TaggedObject + { + /** + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + public DerTaggedObject( + int tagNo, + Asn1Encodable obj) + : base(tagNo, obj) + { + } + + /** + * @param explicitly true if an explicitly tagged object. + * @param tagNo the tag number for this object. + * @param obj the tagged object. + */ + public DerTaggedObject( + bool explicitly, + int tagNo, + Asn1Encodable obj) + : base(explicitly, tagNo, obj) + { + } + + /** + * create an implicitly tagged object that contains a zero + * length sequence. + */ + public DerTaggedObject( + int tagNo) + : base(false, tagNo, DerSequence.Empty) + { + } + + internal override void Encode( + DerOutputStream derOut) + { + if (!IsEmpty()) + { + byte[] bytes = obj.GetDerEncoded(); + + if (explicitly) + { + derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes); + } + else + { + // + // need to mark constructed types... (preserve Constructed tag) + // + int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged; + derOut.WriteTag(flags, tagNo); + derOut.Write(bytes, 1, bytes.Length - 1); + } + } + else + { + derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, new byte[0]); + } + } + } +} diff --git a/crypto/src/asn1/DerUTCTime.cs b/crypto/src/asn1/DerUTCTime.cs new file mode 100644 index 000000000..56fabeb47 --- /dev/null +++ b/crypto/src/asn1/DerUTCTime.cs @@ -0,0 +1,263 @@ +using System; +using System.Globalization; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * UTC time object. + */ + public class DerUtcTime + : Asn1Object + { + private readonly string time; + + /** + * return an UTC Time from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerUtcTime GetInstance( + object obj) + { + if (obj == null || obj is DerUtcTime) + { + return (DerUtcTime)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an UTC Time from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerUtcTime GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerUtcTime) + { + return GetInstance(o); + } + + return new DerUtcTime(((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). + *

+ * @param time the time string.

+ */ + public DerUtcTime( + string time) + { + if (time == null) + throw new ArgumentNullException("time"); + + this.time = time; + + try + { + ToDateTime(); + } + catch (FormatException e) + { + throw new ArgumentException("invalid date string: " + e.Message); + } + } + + /** + * base constructor from a DateTime object + */ + public DerUtcTime( + DateTime time) + { + this.time = time.ToString("yyMMddHHmmss") + "Z"; + } + + internal DerUtcTime( + byte[] bytes) + { + // + // explicitly convert to characters + // + this.time = Strings.FromAsciiByteArray(bytes); + } + +// public DateTime ToDateTime() +// { +// string tm = this.AdjustedTimeString; +// +// return new DateTime( +// Int16.Parse(tm.Substring(0, 4)), +// Int16.Parse(tm.Substring(4, 2)), +// Int16.Parse(tm.Substring(6, 2)), +// Int16.Parse(tm.Substring(8, 2)), +// Int16.Parse(tm.Substring(10, 2)), +// Int16.Parse(tm.Substring(12, 2))); +// } + + /** + * return the time as a date based on whatever a 2 digit year will return. For + * standardised processing use ToAdjustedDateTime(). + * + * @return the resulting date + * @exception ParseException if the date string cannot be parsed. + */ + public DateTime ToDateTime() + { + return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz"); + } + + /** + * 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 DateTime ToAdjustedDateTime() + { + return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz"); + } + + private DateTime ParseDateString( + string dateStr, + string formatStr) + { + DateTime dt = DateTime.ParseExact( + dateStr, + formatStr, + DateTimeFormatInfo.InvariantInfo); + + return dt.ToUniversalTime(); + } + + /** + * return the time - always in the form of + * YYMMDDhhmmssGMT(+hh:mm|-hh:mm). + *

+ * Normally in a certificate we would expect "Z" rather than "GMT", + * however adding the "GMT" means we can just use: + *

+         *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
+         * 
+ * To read in the time and Get a date which is compatible with our local + * time zone.

+ *

+ * Note: 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 TimeString + { + get + { + // + // standardise the format. + // + if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0) + { + if (time.Length == 11) + { + return time.Substring(0, 10) + "00GMT+00:00"; + } + else + { + return time.Substring(0, 12) + "GMT+00:00"; + } + } + else + { + int index = time.IndexOf('-'); + if (index < 0) + { + index = time.IndexOf('+'); + } + string d = time; + + if (index == time.Length - 3) + { + d += "00"; + } + + if (index == 10) + { + return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2); + } + else + { + return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" + d.Substring(15, 2); + } + } + } + } + + [Obsolete("Use 'AdjustedTimeString' property instead")] + public string AdjustedTime + { + get { return AdjustedTimeString; } + } + + /// + /// Return a time string as an adjusted date with a 4 digit year. + /// This goes in the range of 1950 - 2049. + /// + public string AdjustedTimeString + { + get + { + string d = TimeString; + string c = d[0] < '5' ? "20" : "19"; + + return c + d; + } + } + + private byte[] GetOctets() + { + return Strings.ToAsciiByteArray(time); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.UtcTime, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerUtcTime other = asn1Object as DerUtcTime; + + if (other == null) + return false; + + return this.time.Equals(other.time); + } + + protected override int Asn1GetHashCode() + { + return time.GetHashCode(); + } + + public override string ToString() + { + return time; + } + } +} diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs new file mode 100644 index 000000000..92a50e824 --- /dev/null +++ b/crypto/src/asn1/DerUTF8String.cs @@ -0,0 +1,96 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der UTF8String object. + */ + public class DerUtf8String + : DerStringBase + { + private readonly string str; + + /** + * return an UTF8 string from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerUtf8String GetInstance( + object obj) + { + if (obj == null || obj is DerUtf8String) + { + return (DerUtf8String)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return an UTF8 string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerUtf8String GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerUtf8String) + { + return GetInstance(o); + } + + return new DerUtf8String(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - byte encoded string. + */ + public DerUtf8String( + byte[] str) + : this(Encoding.UTF8.GetString(str, 0, str.Length)) + { + } + + /** + * basic constructor + */ + public DerUtf8String( + string str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerUtf8String other = asn1Object as DerUtf8String; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str)); + } + } +} diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs new file mode 100644 index 000000000..305102f2f --- /dev/null +++ b/crypto/src/asn1/DerUniversalString.cs @@ -0,0 +1,107 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der UniversalString object. + */ + public class DerUniversalString + : DerStringBase + { + private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + private readonly byte[] str; + + /** + * return a Universal string from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerUniversalString GetInstance( + object obj) + { + if (obj == null || obj is DerUniversalString) + { + return (DerUniversalString)obj; + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a Universal string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerUniversalString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerUniversalString) + { + return GetInstance(o); + } + + return new DerUniversalString(Asn1OctetString.GetInstance(o).GetOctets()); + } + + /** + * basic constructor - byte encoded string. + */ + public DerUniversalString( + byte[] str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + StringBuilder buffer = new StringBuilder("#"); + byte[] enc = GetDerEncoded(); + + for (int i = 0; i != enc.Length; i++) + { + uint ubyte = enc[i]; + buffer.Append(table[(ubyte >> 4) & 0xf]); + buffer.Append(table[enc[i] & 0xf]); + } + + return buffer.ToString(); + } + + public byte[] GetOctets() + { + return (byte[]) str.Clone(); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.UniversalString, this.str); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerUniversalString other = asn1Object as DerUniversalString; + + if (other == null) + return false; + +// return this.GetString().Equals(other.GetString()); + return Arrays.AreEqual(this.str, other.str); + } + } +} diff --git a/crypto/src/asn1/DerUnknownTag.cs b/crypto/src/asn1/DerUnknownTag.cs new file mode 100644 index 000000000..1e0e61495 --- /dev/null +++ b/crypto/src/asn1/DerUnknownTag.cs @@ -0,0 +1,80 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * We insert one of these when we find a tag we don't recognise. + */ + public class DerUnknownTag + : Asn1Object + { + private readonly bool isConstructed; + private readonly int tag; + private readonly byte[] data; + + /** + * @param tag the tag value. + * @param data the contents octets. + */ + public DerUnknownTag( + int tag, + byte[] data) + : this(false, tag, data) + { + } + + public DerUnknownTag( + bool isConstructed, + int tag, + byte[] data) + { + if (data == null) + throw new ArgumentNullException("data"); + + this.isConstructed = isConstructed; + this.tag = tag; + this.data = data; + } + + public bool IsConstructed + { + get { return isConstructed; } + } + + public int Tag + { + get { return tag; } + } + + public byte[] GetData() + { + return data; + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(isConstructed ? Asn1Tags.Constructed : 0, tag, data); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerUnknownTag other = asn1Object as DerUnknownTag; + + if (other == null) + return false; + + return this.isConstructed == other.isConstructed + && this.tag == other.tag + && Arrays.AreEqual(this.data, other.data); + } + + protected override int Asn1GetHashCode() + { + return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(data); + } + } +} diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs new file mode 100644 index 000000000..84c9caade --- /dev/null +++ b/crypto/src/asn1/DerVisibleString.cs @@ -0,0 +1,111 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Der VisibleString object. + */ + public class DerVisibleString + : DerStringBase + { + private readonly string str; + + /** + * return a Visible string from the passed in object. + * + * @exception ArgumentException if the object cannot be converted. + */ + public static DerVisibleString GetInstance( + object obj) + { + if (obj == null || obj is DerVisibleString) + { + return (DerVisibleString)obj; + } + + if (obj is Asn1OctetString) + { + return new DerVisibleString(((Asn1OctetString)obj).GetOctets()); + } + + if (obj is Asn1TaggedObject) + { + return GetInstance(((Asn1TaggedObject)obj).GetObject()); + } + + throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name); + } + + /** + * return a Visible string from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the tagged object cannot + * be converted. + */ + public static DerVisibleString GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(obj.GetObject()); + } + + /** + * basic constructor - byte encoded string. + */ + public DerVisibleString( + byte[] str) + : this(Strings.FromAsciiByteArray(str)) + { + } + + /** + * basic constructor + */ + public DerVisibleString( + string str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = str; + } + + public override string GetString() + { + return str; + } + + public byte[] GetOctets() + { + return Strings.ToAsciiByteArray(str); + } + + internal override void Encode( + DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.VisibleString, GetOctets()); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerVisibleString other = asn1Object as DerVisibleString; + + if (other == null) + return false; + + return this.str.Equals(other.str); + } + + protected override int Asn1GetHashCode() + { + return this.str.GetHashCode(); + } + } +} diff --git a/crypto/src/asn1/IAsn1ApplicationSpecificParser.cs b/crypto/src/asn1/IAsn1ApplicationSpecificParser.cs new file mode 100644 index 000000000..89cf64c70 --- /dev/null +++ b/crypto/src/asn1/IAsn1ApplicationSpecificParser.cs @@ -0,0 +1,10 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + public interface IAsn1ApplicationSpecificParser + : IAsn1Convertible + { + IAsn1Convertible ReadObject(); + } +} diff --git a/crypto/src/asn1/IAsn1Choice.cs b/crypto/src/asn1/IAsn1Choice.cs new file mode 100644 index 000000000..ecd76e427 --- /dev/null +++ b/crypto/src/asn1/IAsn1Choice.cs @@ -0,0 +1,17 @@ + +namespace Org.BouncyCastle.Asn1 +{ + /** + * Marker interface for CHOICE objects - if you implement this in a roll-your-own + * object, any attempt to tag the object implicitly will convert the tag to an + * explicit one as the encoding rules require. + *

+ * If you use this interface your class should also implement the getInstance + * pattern which takes a tag object and the tagging mode used. + *

+ */ + public interface IAsn1Choice + { + // marker interface + } +} diff --git a/crypto/src/asn1/IAsn1Convertible.cs b/crypto/src/asn1/IAsn1Convertible.cs new file mode 100644 index 000000000..d3f83afc9 --- /dev/null +++ b/crypto/src/asn1/IAsn1Convertible.cs @@ -0,0 +1,7 @@ +namespace Org.BouncyCastle.Asn1 +{ + public interface IAsn1Convertible + { + Asn1Object ToAsn1Object(); + } +} diff --git a/crypto/src/asn1/IAsn1String.cs b/crypto/src/asn1/IAsn1String.cs new file mode 100644 index 000000000..cbc2635ff --- /dev/null +++ b/crypto/src/asn1/IAsn1String.cs @@ -0,0 +1,10 @@ +namespace Org.BouncyCastle.Asn1 +{ + /** + * basic interface for Der string objects. + */ + public interface IAsn1String + { + string GetString(); + } +} diff --git a/crypto/src/asn1/IndefiniteLengthInputStream.cs b/crypto/src/asn1/IndefiniteLengthInputStream.cs new file mode 100644 index 000000000..09d0e3a42 --- /dev/null +++ b/crypto/src/asn1/IndefiniteLengthInputStream.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + class IndefiniteLengthInputStream + : LimitedInputStream + { + private int _lookAhead; + private bool _eofOn00 = true; + + internal IndefiniteLengthInputStream( + Stream inStream, + int limit) + : base(inStream, limit) + { + _lookAhead = RequireByte(); + CheckForEof(); + } + + internal void SetEofOn00( + bool eofOn00) + { + _eofOn00 = eofOn00; + if (_eofOn00) + { + CheckForEof(); + } + } + + private bool CheckForEof() + { + if (_lookAhead == 0x00) + { + int extra = RequireByte(); + if (extra != 0) + { + throw new IOException("malformed end-of-contents marker"); + } + + _lookAhead = -1; + SetParentEofDetect(true); + return true; + } + return _lookAhead < 0; + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + // Only use this optimisation if we aren't checking for 00 + if (_eofOn00 || count <= 1) + return base.Read(buffer, offset, count); + + if (_lookAhead < 0) + return 0; + + int numRead = _in.Read(buffer, offset + 1, count - 1); + + if (numRead <= 0) + { + // Corrupted stream + throw new EndOfStreamException(); + } + + buffer[offset] = (byte)_lookAhead; + _lookAhead = RequireByte(); + + return numRead + 1; + } + + public override int ReadByte() + { + if (_eofOn00 && CheckForEof()) + return -1; + + int result = _lookAhead; + _lookAhead = RequireByte(); + return result; + } + + private int RequireByte() + { + int b = _in.ReadByte(); + if (b < 0) + { + // Corrupted stream + throw new EndOfStreamException(); + } + return b; + } + } +} + +//using System; +//using System.IO; + +//namespace Org.BouncyCastle.Asn1 +//{ +// class IndefiniteLengthInputStream +// : LimitedInputStream +// { +// private bool _eofReached = false; +// private bool _eofOn00 = true; + +// internal IndefiniteLengthInputStream( +// Stream inStream, +// int limit) +// : base(inStream, limit) +// { +// } + +// internal void SetEofOn00( +// bool eofOn00) +// { +// _eofOn00 = eofOn00; +// } + +// public override int Read( +// byte[] buffer, +// int offset, +// int count) +// { +// if (_eofReached) +// return 0; + +// if (_eofOn00) +// return base.Read(buffer, offset, count); + +// int numRead = _in.Read(buffer, offset, count); + +// if (numRead <= 0) +// throw new EndOfStreamException(); + +// return numRead; +// } + +// public override int ReadByte() +// { +// if (_eofReached) +// return -1; + +// int b1 = _in.ReadByte(); + +// if (b1 < 0) +// throw new EndOfStreamException(); + +// if (b1 == 0 && _eofOn00) +// { +// int b2 = _in.ReadByte(); + +// if (b2 < 0) +// throw new EndOfStreamException(); + +// if (b2 == 0) +// { +// _eofReached = true; +// SetParentEofDetect(true); +// return -1; +// } + +// throw new InvalidDataException(); +// } + +// return b1; +// } +// } +//} diff --git a/crypto/src/asn1/LazyASN1InputStream.cs b/crypto/src/asn1/LazyASN1InputStream.cs new file mode 100644 index 000000000..4cf2305fd --- /dev/null +++ b/crypto/src/asn1/LazyASN1InputStream.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1 +{ + public class LazyAsn1InputStream + : Asn1InputStream + { + public LazyAsn1InputStream( + byte[] input) + : base(input) + { + } + + public LazyAsn1InputStream( + Stream inputStream) + : base(inputStream) + { + } + + internal override DerSequence CreateDerSequence( + DefiniteLengthInputStream dIn) + { + return new LazyDerSequence(dIn.ToArray()); + } + + internal override DerSet CreateDerSet( + DefiniteLengthInputStream dIn) + { + return new LazyDerSet(dIn.ToArray()); + } + } +} diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs new file mode 100644 index 000000000..7301bc158 --- /dev/null +++ b/crypto/src/asn1/LazyDERSequence.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Diagnostics; + +namespace Org.BouncyCastle.Asn1 +{ + internal class LazyDerSequence + : DerSequence + { + private byte[] encoded; + + internal LazyDerSequence( + byte[] encoded) + { + this.encoded = encoded; + } + + private void Parse() + { + lock (this) + { + if (encoded != null) + { + Asn1InputStream e = new LazyAsn1InputStream(encoded); + + Asn1Object o; + while ((o = e.ReadObject()) != null) + { + AddObject(o); + } + + encoded = null; + } + } + } + + public override Asn1Encodable this[int index] + { + get + { + Parse(); + + return base[index]; + } + } + + public override IEnumerator GetEnumerator() + { + Parse(); + + return base.GetEnumerator(); + } + + public override int Count + { + get + { + Parse(); + + return base.Count; + } + } + + internal override void Encode( + DerOutputStream derOut) + { + lock (this) + { + if (encoded == null) + { + base.Encode(derOut); + } + else + { + derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, encoded); + } + } + } + } +} diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs new file mode 100644 index 000000000..e6c9319dd --- /dev/null +++ b/crypto/src/asn1/LazyDERSet.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Diagnostics; + +namespace Org.BouncyCastle.Asn1 +{ + internal class LazyDerSet + : DerSet + { + private byte[] encoded; + + internal LazyDerSet( + byte[] encoded) + { + this.encoded = encoded; + } + + private void Parse() + { + lock (this) + { + if (encoded != null) + { + Asn1InputStream e = new LazyAsn1InputStream(encoded); + + Asn1Object o; + while ((o = e.ReadObject()) != null) + { + AddObject(o); + } + + encoded = null; + } + } + } + + public override Asn1Encodable this[int index] + { + get + { + Parse(); + + return base[index]; + } + } + + public override IEnumerator GetEnumerator() + { + Parse(); + + return base.GetEnumerator(); + } + + public override int Count + { + get + { + Parse(); + + return base.Count; + } + } + + internal override void Encode( + DerOutputStream derOut) + { + lock (this) + { + if (encoded == null) + { + base.Encode(derOut); + } + else + { + derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, encoded); + } + } + } + } +} diff --git a/crypto/src/asn1/LimitedInputStream.cs b/crypto/src/asn1/LimitedInputStream.cs new file mode 100644 index 000000000..62486aa77 --- /dev/null +++ b/crypto/src/asn1/LimitedInputStream.cs @@ -0,0 +1,35 @@ +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Asn1 +{ + internal abstract class LimitedInputStream + : BaseInputStream + { + protected readonly Stream _in; + private int _limit; + + internal LimitedInputStream( + Stream inStream, + int limit) + { + this._in = inStream; + this._limit = limit; + } + + internal virtual int GetRemaining() + { + // TODO: maybe one day this can become more accurate + return _limit; + } + + protected virtual void SetParentEofDetect(bool on) + { + if (_in is IndefiniteLengthInputStream) + { + ((IndefiniteLengthInputStream)_in).SetEofOn00(on); + } + } + } +} diff --git a/crypto/src/asn1/OidTokenizer.cs b/crypto/src/asn1/OidTokenizer.cs new file mode 100644 index 000000000..6e76e8c8b --- /dev/null +++ b/crypto/src/asn1/OidTokenizer.cs @@ -0,0 +1,45 @@ +namespace 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; + } + + public bool HasMoreTokens + { + get { return index != -1; } + } + + public string NextToken() + { + if (index == -1) + { + return null; + } + + int end = oid.IndexOf('.', index); + if (end == -1) + { + string lastToken = oid.Substring(index); + index = -1; + return lastToken; + } + + string nextToken = oid.Substring(index, end - index); + index = end + 1; + return nextToken; + } + } +} diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs new file mode 100644 index 000000000..075e5384c --- /dev/null +++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs @@ -0,0 +1,39 @@ +using System; + +namespace Org.BouncyCastle.Asn1.BC +{ + public abstract class BCObjectIdentifiers + { + // iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle + // 1.3.6.1.4.1.22554 + public static readonly DerObjectIdentifier bc = new DerObjectIdentifier("1.3.6.1.4.1.22554"); + + // pbe(1) algorithms + public static readonly DerObjectIdentifier bc_pbe = new DerObjectIdentifier(bc + ".1"); + + // SHA-1(1) + public static readonly DerObjectIdentifier bc_pbe_sha1 = new DerObjectIdentifier(bc_pbe + ".1"); + + // SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4)) + public static readonly DerObjectIdentifier bc_pbe_sha256 = new DerObjectIdentifier(bc_pbe + ".2.1"); + public static readonly DerObjectIdentifier bc_pbe_sha384 = new DerObjectIdentifier(bc_pbe + ".2.2"); + public static readonly DerObjectIdentifier bc_pbe_sha512 = new DerObjectIdentifier(bc_pbe + ".2.3"); + public static readonly DerObjectIdentifier bc_pbe_sha224 = new DerObjectIdentifier(bc_pbe + ".2.4"); + + // PKCS-5(1)|PKCS-12(2) + public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs5 = new DerObjectIdentifier(bc_pbe_sha1 + ".1"); + public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12 = new DerObjectIdentifier(bc_pbe_sha1 + ".2"); + + public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs5 = new DerObjectIdentifier(bc_pbe_sha256 + ".1"); + public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12 = new DerObjectIdentifier(bc_pbe_sha256 + ".2"); + + // AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42)) + public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.2"); + public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.22"); + public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.42"); + + public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.2"); + public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.22"); + public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.42"); + } +} \ No newline at end of file diff --git a/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs b/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs new file mode 100644 index 000000000..3cdb128a6 --- /dev/null +++ b/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs @@ -0,0 +1,60 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CAKeyUpdAnnContent + : Asn1Encodable + { + private readonly CmpCertificate oldWithNew; + private readonly CmpCertificate newWithOld; + private readonly CmpCertificate newWithNew; + + private CAKeyUpdAnnContent(Asn1Sequence seq) + { + oldWithNew = CmpCertificate.GetInstance(seq[0]); + newWithOld = CmpCertificate.GetInstance(seq[1]); + newWithNew = CmpCertificate.GetInstance(seq[2]); + } + + public static CAKeyUpdAnnContent GetInstance(object obj) + { + if (obj is CAKeyUpdAnnContent) + return (CAKeyUpdAnnContent)obj; + + if (obj is Asn1Sequence) + return new CAKeyUpdAnnContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual CmpCertificate OldWithNew + { + get { return oldWithNew; } + } + + public virtual CmpCertificate NewWithOld + { + get { return newWithOld; } + } + + public virtual CmpCertificate NewWithNew + { + get { return newWithNew; } + } + + /** + *
+		 * 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
+		 *  }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(oldWithNew, newWithOld, newWithNew); + } + } +} diff --git a/crypto/src/asn1/cmp/CertConfirmContent.cs b/crypto/src/asn1/cmp/CertConfirmContent.cs new file mode 100644 index 000000000..f4016d8d8 --- /dev/null +++ b/crypto/src/asn1/cmp/CertConfirmContent.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertConfirmContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private CertConfirmContent(Asn1Sequence seq) + { + content = seq; + } + + public static CertConfirmContent GetInstance(object obj) + { + if (obj is CertConfirmContent) + return (CertConfirmContent)obj; + + if (obj is Asn1Sequence) + return new CertConfirmContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual CertStatus[] ToCertStatusArray() + { + CertStatus[] result = new CertStatus[content.Count]; + for (int i = 0; i != result.Length; i++) + { + result[i] = CertStatus.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * CertConfirmContent ::= SEQUENCE OF CertStatus
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/CertOrEncCert.cs b/crypto/src/asn1/cmp/CertOrEncCert.cs new file mode 100644 index 000000000..4c049c180 --- /dev/null +++ b/crypto/src/asn1/cmp/CertOrEncCert.cs @@ -0,0 +1,85 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertOrEncCert + : Asn1Encodable, IAsn1Choice + { + private readonly CmpCertificate certificate; + private readonly EncryptedValue encryptedCert; + + private CertOrEncCert(Asn1TaggedObject tagged) + { + if (tagged.TagNo == 0) + { + certificate = CmpCertificate.GetInstance(tagged.GetObject()); + } + else if (tagged.TagNo == 1) + { + encryptedCert = EncryptedValue.GetInstance(tagged.GetObject()); + } + else + { + throw new ArgumentException("unknown tag: " + tagged.TagNo, "tagged"); + } + } + + public static CertOrEncCert GetInstance(object obj) + { + if (obj is CertOrEncCert) + return (CertOrEncCert)obj; + + if (obj is Asn1TaggedObject) + return new CertOrEncCert((Asn1TaggedObject)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public CertOrEncCert(CmpCertificate certificate) + { + if (certificate == null) + throw new ArgumentNullException("certificate"); + + this.certificate = certificate; + } + + public CertOrEncCert(EncryptedValue encryptedCert) + { + if (encryptedCert == null) + throw new ArgumentNullException("encryptedCert"); + + this.encryptedCert = encryptedCert; + } + + public virtual CmpCertificate Certificate + { + get { return certificate; } + } + + public virtual EncryptedValue EncryptedCert + { + get { return encryptedCert; } + } + + /** + *
+		 * CertOrEncCert ::= CHOICE {
+		 *                      certificate     [0] CMPCertificate,
+		 *                      encryptedCert   [1] EncryptedValue
+		 *           }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + if (certificate != null) + { + return new DerTaggedObject(true, 0, certificate); + } + + return new DerTaggedObject(true, 1, encryptedCert); + } + } +} diff --git a/crypto/src/asn1/cmp/CertRepMessage.cs b/crypto/src/asn1/cmp/CertRepMessage.cs new file mode 100644 index 000000000..c22b079c8 --- /dev/null +++ b/crypto/src/asn1/cmp/CertRepMessage.cs @@ -0,0 +1,94 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertRepMessage + : Asn1Encodable + { + private readonly Asn1Sequence caPubs; + private readonly Asn1Sequence response; + + private CertRepMessage(Asn1Sequence seq) + { + int index = 0; + + if (seq.Count > 1) + { + caPubs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[index++], true); + } + + response = Asn1Sequence.GetInstance(seq[index]); + } + + public static CertRepMessage GetInstance(object obj) + { + if (obj is CertRepMessage) + return (CertRepMessage)obj; + + if (obj is Asn1Sequence) + return new CertRepMessage((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public CertRepMessage(CmpCertificate[] caPubs, CertResponse[] response) + { + if (response == null) + throw new ArgumentNullException("response"); + + if (caPubs != null) + { + this.caPubs = new DerSequence(caPubs); + } + + this.response = new DerSequence(response); + } + + public virtual CmpCertificate[] GetCAPubs() + { + if (caPubs == null) + return null; + + CmpCertificate[] results = new CmpCertificate[caPubs.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CmpCertificate.GetInstance(caPubs[i]); + } + return results; + } + + public virtual CertResponse[] GetResponse() + { + CertResponse[] results = new CertResponse[response.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CertResponse.GetInstance(response[i]); + } + return results; + } + + /** + *
+		 * CertRepMessage ::= SEQUENCE {
+		 *                          caPubs       [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+		 *                                                                             OPTIONAL,
+		 *                          response         SEQUENCE OF CertResponse
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (caPubs != null) + { + v.Add(new DerTaggedObject(true, 1, caPubs)); + } + + v.Add(response); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/CertResponse.cs b/crypto/src/asn1/cmp/CertResponse.cs new file mode 100644 index 000000000..246b8ce70 --- /dev/null +++ b/crypto/src/asn1/cmp/CertResponse.cs @@ -0,0 +1,115 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertResponse + : Asn1Encodable + { + private readonly DerInteger certReqId; + private readonly PkiStatusInfo status; + private readonly CertifiedKeyPair certifiedKeyPair; + private readonly Asn1OctetString rspInfo; + + private CertResponse(Asn1Sequence seq) + { + certReqId = DerInteger.GetInstance(seq[0]); + status = PkiStatusInfo.GetInstance(seq[1]); + + if (seq.Count >= 3) + { + if (seq.Count == 3) + { + Asn1Encodable o = seq[2]; + if (o is Asn1OctetString) + { + rspInfo = Asn1OctetString.GetInstance(o); + } + else + { + certifiedKeyPair = CertifiedKeyPair.GetInstance(o); + } + } + else + { + certifiedKeyPair = CertifiedKeyPair.GetInstance(seq[2]); + rspInfo = Asn1OctetString.GetInstance(seq[3]); + } + } + } + + public static CertResponse GetInstance(object obj) + { + if (obj is CertResponse) + return (CertResponse)obj; + + if (obj is Asn1Sequence) + return new CertResponse((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public CertResponse( + DerInteger certReqId, + PkiStatusInfo status) + : this(certReqId, status, null, null) + { + } + + public CertResponse( + DerInteger certReqId, + PkiStatusInfo status, + CertifiedKeyPair certifiedKeyPair, + Asn1OctetString rspInfo) + { + if (certReqId == null) + throw new ArgumentNullException("certReqId"); + + if (status == null) + throw new ArgumentNullException("status"); + + this.certReqId = certReqId; + this.status = status; + this.certifiedKeyPair = certifiedKeyPair; + this.rspInfo = rspInfo; + } + + public virtual DerInteger CertReqID + { + get { return certReqId; } + } + + public virtual PkiStatusInfo Status + { + get { return status; } + } + + public virtual CertifiedKeyPair CertifiedKeyPair + { + get { return certifiedKeyPair; } + } + + /** + *
+		 * 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]
+		 *             }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certReqId, status); + v.AddOptional(certifiedKeyPair); + v.AddOptional(rspInfo); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/CertStatus.cs b/crypto/src/asn1/cmp/CertStatus.cs new file mode 100644 index 000000000..52d5ac504 --- /dev/null +++ b/crypto/src/asn1/cmp/CertStatus.cs @@ -0,0 +1,84 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertStatus + : Asn1Encodable + { + private readonly Asn1OctetString certHash; + private readonly DerInteger certReqId; + private readonly PkiStatusInfo statusInfo; + + private CertStatus(Asn1Sequence seq) + { + certHash = Asn1OctetString.GetInstance(seq[0]); + certReqId = DerInteger.GetInstance(seq[1]); + + if (seq.Count > 2) + { + statusInfo = PkiStatusInfo.GetInstance(seq[2]); + } + } + + public CertStatus(byte[] certHash, BigInteger certReqId) + { + this.certHash = new DerOctetString(certHash); + this.certReqId = new DerInteger(certReqId); + } + + public CertStatus(byte[] certHash, BigInteger certReqId, PkiStatusInfo statusInfo) + { + this.certHash = new DerOctetString(certHash); + this.certReqId = new DerInteger(certReqId); + this.statusInfo = statusInfo; + } + + public static CertStatus GetInstance(object obj) + { + if (obj is CertStatus) + return (CertStatus)obj; + + if (obj is Asn1Sequence) + return new CertStatus((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual Asn1OctetString CertHash + { + get { return certHash; } + } + + public virtual DerInteger CertReqID + { + get { return certReqId; } + } + + public virtual PkiStatusInfo StatusInfo + { + get { return statusInfo; } + } + + /** + *
+		 * 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
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certHash, certReqId); + v.AddOptional(statusInfo); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/CertifiedKeyPair.cs b/crypto/src/asn1/cmp/CertifiedKeyPair.cs new file mode 100644 index 000000000..655dde0c5 --- /dev/null +++ b/crypto/src/asn1/cmp/CertifiedKeyPair.cs @@ -0,0 +1,114 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CertifiedKeyPair + : Asn1Encodable + { + private readonly CertOrEncCert certOrEncCert; + private readonly EncryptedValue privateKey; + private readonly PkiPublicationInfo publicationInfo; + + private CertifiedKeyPair(Asn1Sequence seq) + { + certOrEncCert = CertOrEncCert.GetInstance(seq[0]); + + if (seq.Count >= 2) + { + if (seq.Count == 2) + { + Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1]); + if (tagged.TagNo == 0) + { + privateKey = EncryptedValue.GetInstance(tagged.GetObject()); + } + else + { + publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetObject()); + } + } + else + { + privateKey = EncryptedValue.GetInstance(Asn1TaggedObject.GetInstance(seq[1])); + publicationInfo = PkiPublicationInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[2])); + } + } + } + + public static CertifiedKeyPair GetInstance(object obj) + { + if (obj is CertifiedKeyPair) + return (CertifiedKeyPair)obj; + + if (obj is Asn1Sequence) + return new CertifiedKeyPair((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public CertifiedKeyPair( + CertOrEncCert certOrEncCert) + : this(certOrEncCert, null, null) + { + } + + public CertifiedKeyPair( + CertOrEncCert certOrEncCert, + EncryptedValue privateKey, + PkiPublicationInfo publicationInfo + ) + { + if (certOrEncCert == null) + throw new ArgumentNullException("certOrEncCert"); + + this.certOrEncCert = certOrEncCert; + this.privateKey = privateKey; + this.publicationInfo = publicationInfo; + } + + public virtual CertOrEncCert CertOrEncCert + { + get { return certOrEncCert; } + } + + public virtual EncryptedValue PrivateKey + { + get { return privateKey; } + } + + public virtual PkiPublicationInfo PublicationInfo + { + get { return publicationInfo; } + } + + /** + *
+		 * CertifiedKeyPair ::= SEQUENCE {
+		 *                                  certOrEncCert       CertOrEncCert,
+		 *                                  privateKey      [0] EncryptedValue      OPTIONAL,
+		 *                                  -- see [CRMF] for comment on encoding
+		 *                                  publicationInfo [1] PKIPublicationInfo  OPTIONAL
+		 *       }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(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/crypto/src/asn1/cmp/Challenge.cs b/crypto/src/asn1/cmp/Challenge.cs new file mode 100644 index 000000000..bee5f96f5 --- /dev/null +++ b/crypto/src/asn1/cmp/Challenge.cs @@ -0,0 +1,79 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class Challenge + : Asn1Encodable + { + private readonly AlgorithmIdentifier owf; + private readonly Asn1OctetString witness; + private readonly Asn1OctetString challenge; + + private Challenge(Asn1Sequence seq) + { + int index = 0; + + if (seq.Count == 3) + { + owf = AlgorithmIdentifier.GetInstance(seq[index++]); + } + + witness = Asn1OctetString.GetInstance(seq[index++]); + challenge = Asn1OctetString.GetInstance(seq[index]); + } + + public static Challenge GetInstance(object obj) + { + if (obj is Challenge) + return (Challenge)obj; + + if (obj is Asn1Sequence) + return new Challenge((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual AlgorithmIdentifier Owf + { + get { return owf; } + } + + /** + *
+		 * 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)
+		 *                 --   }
+		 *      }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + v.AddOptional(owf); + v.Add(witness); + v.Add(challenge); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/CmpCertificate.cs b/crypto/src/asn1/cmp/CmpCertificate.cs new file mode 100644 index 000000000..16ee30059 --- /dev/null +++ b/crypto/src/asn1/cmp/CmpCertificate.cs @@ -0,0 +1,80 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CmpCertificate + : Asn1Encodable, IAsn1Choice + { + private readonly X509CertificateStructure x509v3PKCert; + private readonly AttributeCertificate x509v2AttrCert; + + /** + * Note: the addition of attribute certificates is a BC extension. + */ + public CmpCertificate(AttributeCertificate x509v2AttrCert) + { + this.x509v2AttrCert = x509v2AttrCert; + } + + public CmpCertificate(X509CertificateStructure x509v3PKCert) + { + if (x509v3PKCert.Version != 3) + throw new ArgumentException("only version 3 certificates allowed", "x509v3PKCert"); + + this.x509v3PKCert = x509v3PKCert; + } + + public static CmpCertificate GetInstance(object obj) + { + if (obj is CmpCertificate) + return (CmpCertificate)obj; + + if (obj is Asn1Sequence) + return new CmpCertificate(X509CertificateStructure.GetInstance(obj)); + + if (obj is Asn1TaggedObject) + return new CmpCertificate(AttributeCertificate.GetInstance(((Asn1TaggedObject)obj).GetObject())); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual bool IsX509v3PKCert + { + get { return x509v3PKCert != null; } + } + + public virtual X509CertificateStructure X509v3PKCert + { + get { return x509v3PKCert; } + } + + public virtual AttributeCertificate X509v2AttrCert + { + get { return x509v2AttrCert; } + } + + /** + *
+         * CMPCertificate ::= CHOICE {
+         *            x509v3PKCert        Certificate
+         *            x509v2AttrCert      [1] AttributeCertificate
+         *  }
+         * 
+ * Note: the addition of attribute certificates is a BC extension. + * + * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + if (x509v2AttrCert != null) + { + // explicit following CMP conventions + return new DerTaggedObject(true, 1, x509v2AttrCert); + } + + return x509v3PKCert.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs b/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs new file mode 100644 index 000000000..7e8274175 --- /dev/null +++ b/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs @@ -0,0 +1,106 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public abstract class CmpObjectIdentifiers + { + // RFC 4210 + + // id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13} + public static readonly DerObjectIdentifier passwordBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.13"); + + // id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30} + public static readonly DerObjectIdentifier dhBasedMac = new DerObjectIdentifier("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} + public static readonly DerObjectIdentifier it_caProtEncCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.1"); + public static readonly DerObjectIdentifier it_signKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.2"); + public static readonly DerObjectIdentifier it_encKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.3"); + public static readonly DerObjectIdentifier it_preferredSymAlg = new DerObjectIdentifier("1.3.6.1.5.5.7.4.4"); + public static readonly DerObjectIdentifier it_caKeyUpdateInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.4.5"); + public static readonly DerObjectIdentifier it_currentCRL = new DerObjectIdentifier("1.3.6.1.5.5.7.4.6"); + public static readonly DerObjectIdentifier it_unsupportedOIDs = new DerObjectIdentifier("1.3.6.1.5.5.7.4.7"); + public static readonly DerObjectIdentifier it_keyPairParamReq = new DerObjectIdentifier("1.3.6.1.5.5.7.4.10"); + public static readonly DerObjectIdentifier it_keyPairParamRep = new DerObjectIdentifier("1.3.6.1.5.5.7.4.11"); + public static readonly DerObjectIdentifier it_revPassphrase = new DerObjectIdentifier("1.3.6.1.5.5.7.4.12"); + public static readonly DerObjectIdentifier it_implicitConfirm = new DerObjectIdentifier("1.3.6.1.5.5.7.4.13"); + public static readonly DerObjectIdentifier it_confirmWaitTime = new DerObjectIdentifier("1.3.6.1.5.5.7.4.14"); + public static readonly DerObjectIdentifier it_origPKIMessage = new DerObjectIdentifier("1.3.6.1.5.5.7.4.15"); + public static readonly DerObjectIdentifier it_suppLangTags = new DerObjectIdentifier("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) } + + public static readonly DerObjectIdentifier regCtrl_regToken = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.1"); + public static readonly DerObjectIdentifier regCtrl_authenticator = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.2"); + public static readonly DerObjectIdentifier regCtrl_pkiPublicationInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.3"); + public static readonly DerObjectIdentifier regCtrl_pkiArchiveOptions = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.4"); + public static readonly DerObjectIdentifier regCtrl_oldCertID = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.5"); + public static readonly DerObjectIdentifier regCtrl_protocolEncrKey = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.6"); + + // From RFC4210: + // id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7} + public static readonly DerObjectIdentifier regCtrl_altCertTemplate = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.7"); + + public static readonly DerObjectIdentifier regInfo_utf8Pairs = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.1"); + public static readonly DerObjectIdentifier regInfo_certReq = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.2"); + + // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 } + // + // id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types + // + // id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21} + public static readonly DerObjectIdentifier ct_encKeyWithID = new DerObjectIdentifier("1.2.840.113549.1.9.16.1.21"); + } +} diff --git a/crypto/src/asn1/cmp/CrlAnnContent.cs b/crypto/src/asn1/cmp/CrlAnnContent.cs new file mode 100644 index 000000000..3dc11d32c --- /dev/null +++ b/crypto/src/asn1/cmp/CrlAnnContent.cs @@ -0,0 +1,49 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class CrlAnnContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private CrlAnnContent(Asn1Sequence seq) + { + content = seq; + } + + public static CrlAnnContent GetInstance(object obj) + { + if (obj is CrlAnnContent) + return (CrlAnnContent)obj; + + if (obj is Asn1Sequence) + return new CrlAnnContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual CertificateList[] ToCertificateListArray() + { + CertificateList[] result = new CertificateList[content.Count]; + for (int i = 0; i != result.Length; ++ i) + { + result[i] = CertificateList.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * CrlAnnContent ::= SEQUENCE OF CertificateList
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/ErrorMsgContent.cs b/crypto/src/asn1/cmp/ErrorMsgContent.cs new file mode 100644 index 000000000..f4dc584ea --- /dev/null +++ b/crypto/src/asn1/cmp/ErrorMsgContent.cs @@ -0,0 +1,94 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class ErrorMsgContent + : Asn1Encodable + { + private readonly PkiStatusInfo pkiStatusInfo; + private readonly DerInteger errorCode; + private readonly PkiFreeText errorDetails; + + private ErrorMsgContent(Asn1Sequence seq) + { + pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]); + + for (int pos = 1; pos < seq.Count; ++pos) + { + Asn1Encodable ae = seq[pos]; + if (ae is DerInteger) + { + errorCode = DerInteger.GetInstance(ae); + } + else + { + errorDetails = PkiFreeText.GetInstance(ae); + } + } + } + + public static ErrorMsgContent GetInstance(object obj) + { + if (obj is ErrorMsgContent) + return (ErrorMsgContent)obj; + + if (obj is Asn1Sequence) + return new ErrorMsgContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public ErrorMsgContent(PkiStatusInfo pkiStatusInfo) + : this(pkiStatusInfo, null, null) + { + } + + public ErrorMsgContent( + PkiStatusInfo pkiStatusInfo, + DerInteger errorCode, + PkiFreeText errorDetails) + { + if (pkiStatusInfo == null) + throw new ArgumentNullException("pkiStatusInfo"); + + this.pkiStatusInfo = pkiStatusInfo; + this.errorCode = errorCode; + this.errorDetails = errorDetails; + } + + public virtual PkiStatusInfo PkiStatusInfo + { + get { return pkiStatusInfo; } + } + + public virtual DerInteger ErrorCode + { + get { return errorCode; } + } + + public virtual PkiFreeText ErrorDetails + { + get { return errorDetails; } + } + + /** + *
+		 * ErrorMsgContent ::= SEQUENCE {
+		 *                        pKIStatusInfo          PKIStatusInfo,
+		 *                        errorCode              INTEGER           OPTIONAL,
+		 *                        -- implementation-specific error codes
+		 *                        errorDetails           PKIFreeText       OPTIONAL
+		 *                        -- implementation-specific error details
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo); + v.AddOptional(errorCode); + v.AddOptional(errorDetails); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/GenMsgContent.cs b/crypto/src/asn1/cmp/GenMsgContent.cs new file mode 100644 index 000000000..9f042491c --- /dev/null +++ b/crypto/src/asn1/cmp/GenMsgContent.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class GenMsgContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private GenMsgContent(Asn1Sequence seq) + { + content = seq; + } + + public static GenMsgContent GetInstance(object obj) + { + if (obj is GenMsgContent) + return (GenMsgContent)obj; + + if (obj is Asn1Sequence) + return new GenMsgContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public GenMsgContent(params InfoTypeAndValue[] itv) + { + content = new DerSequence(itv); + } + + public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray() + { + InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = InfoTypeAndValue.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/GenRepContent.cs b/crypto/src/asn1/cmp/GenRepContent.cs new file mode 100644 index 000000000..5bdc5550a --- /dev/null +++ b/crypto/src/asn1/cmp/GenRepContent.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class GenRepContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private GenRepContent(Asn1Sequence seq) + { + content = seq; + } + + public static GenRepContent GetInstance(object obj) + { + if (obj is GenRepContent) + return (GenRepContent)obj; + + if (obj is Asn1Sequence) + return new GenRepContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public GenRepContent(params InfoTypeAndValue[] itv) + { + content = new DerSequence(itv); + } + + public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray() + { + InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = InfoTypeAndValue.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/InfoTypeAndValue.cs b/crypto/src/asn1/cmp/InfoTypeAndValue.cs new file mode 100644 index 000000000..9b51dba02 --- /dev/null +++ b/crypto/src/asn1/cmp/InfoTypeAndValue.cs @@ -0,0 +1,121 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + /** + * 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}
+     * 
+ */ + public class InfoTypeAndValue + : Asn1Encodable + { + private readonly DerObjectIdentifier infoType; + private readonly Asn1Encodable infoValue; + + private InfoTypeAndValue(Asn1Sequence seq) + { + infoType = DerObjectIdentifier.GetInstance(seq[0]); + + if (seq.Count > 1) + { + infoValue = (Asn1Encodable)seq[1]; + } + } + + public static InfoTypeAndValue GetInstance(object obj) + { + if (obj is InfoTypeAndValue) + return (InfoTypeAndValue)obj; + + if (obj is Asn1Sequence) + return new InfoTypeAndValue((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public InfoTypeAndValue( + DerObjectIdentifier infoType) + { + this.infoType = infoType; + this.infoValue = null; + } + + public InfoTypeAndValue( + DerObjectIdentifier infoType, + Asn1Encodable optionalValue) + { + this.infoType = infoType; + this.infoValue = optionalValue; + } + + public virtual DerObjectIdentifier InfoType + { + get { return infoType; } + } + + public virtual Asn1Encodable InfoValue + { + get { return infoValue; } + } + + /** + *
+         * InfoTypeAndValue ::= SEQUENCE {
+         *                         infoType               OBJECT IDENTIFIER,
+         *                         infoValue              ANY DEFINED BY infoType  OPTIONAL
+         * }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(infoType); + + if (infoValue != null) + { + v.Add(infoValue); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/KeyRecRepContent.cs b/crypto/src/asn1/cmp/KeyRecRepContent.cs new file mode 100644 index 000000000..b0352f048 --- /dev/null +++ b/crypto/src/asn1/cmp/KeyRecRepContent.cs @@ -0,0 +1,115 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class KeyRecRepContent + : Asn1Encodable + { + private readonly PkiStatusInfo status; + private readonly CmpCertificate newSigCert; + private readonly Asn1Sequence caCerts; + private readonly Asn1Sequence keyPairHist; + + private KeyRecRepContent(Asn1Sequence seq) + { + status = PkiStatusInfo.GetInstance(seq[0]); + + for (int pos = 1; pos < seq.Count; ++pos) + { + Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]); + + switch (tObj.TagNo) + { + 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 ArgumentException("unknown tag number: " + tObj.TagNo, "seq"); + } + } + } + + public static KeyRecRepContent GetInstance(object obj) + { + if (obj is KeyRecRepContent) + return (KeyRecRepContent)obj; + + if (obj is Asn1Sequence) + return new KeyRecRepContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual PkiStatusInfo Status + { + get { return status; } + } + + public virtual CmpCertificate NewSigCert + { + get { return newSigCert; } + } + + public virtual CmpCertificate[] GetCACerts() + { + if (caCerts == null) + return null; + + CmpCertificate[] results = new CmpCertificate[caCerts.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CmpCertificate.GetInstance(caCerts[i]); + } + return results; + } + + public virtual CertifiedKeyPair[] GetKeyPairHist() + { + if (keyPairHist == null) + return null; + + CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CertifiedKeyPair.GetInstance(keyPairHist[i]); + } + return results; + } + + /** + *
+		 * 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
+		 *              }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(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/crypto/src/asn1/cmp/OobCertHash.cs b/crypto/src/asn1/cmp/OobCertHash.cs new file mode 100644 index 000000000..63ddff7c4 --- /dev/null +++ b/crypto/src/asn1/cmp/OobCertHash.cs @@ -0,0 +1,87 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class OobCertHash + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlg; + private readonly CertId certId; + private readonly DerBitString hashVal; + + private OobCertHash(Asn1Sequence seq) + { + int index = seq.Count - 1; + + hashVal = DerBitString.GetInstance(seq[index--]); + + for (int i = index; i >= 0; i--) + { + Asn1TaggedObject tObj = (Asn1TaggedObject)seq[i]; + + if (tObj.TagNo == 0) + { + hashAlg = AlgorithmIdentifier.GetInstance(tObj, true); + } + else + { + certId = CertId.GetInstance(tObj, true); + } + } + } + + public static OobCertHash GetInstance(object obj) + { + if (obj is OobCertHash) + return (OobCertHash)obj; + + if (obj is Asn1Sequence) + return new OobCertHash((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual AlgorithmIdentifier HashAlg + { + get { return hashAlg; } + } + + public virtual CertId CertID + { + get { return certId; } + } + + /** + *
+		 * 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.
+		 *       }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/cmp/PKIBody.cs b/crypto/src/asn1/cmp/PKIBody.cs new file mode 100644 index 000000000..3205a907e --- /dev/null +++ b/crypto/src/asn1/cmp/PKIBody.cs @@ -0,0 +1,186 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiBody + : Asn1Encodable, IAsn1Choice + { + public const int TYPE_INIT_REQ = 0; + public const int TYPE_INIT_REP = 1; + public const int TYPE_CERT_REQ = 2; + public const int TYPE_CERT_REP = 3; + public const int TYPE_P10_CERT_REQ = 4; + public const int TYPE_POPO_CHALL = 5; + public const int TYPE_POPO_REP = 6; + public const int TYPE_KEY_UPDATE_REQ = 7; + public const int TYPE_KEY_UPDATE_REP = 8; + public const int TYPE_KEY_RECOVERY_REQ = 9; + public const int TYPE_KEY_RECOVERY_REP = 10; + public const int TYPE_REVOCATION_REQ = 11; + public const int TYPE_REVOCATION_REP = 12; + public const int TYPE_CROSS_CERT_REQ = 13; + public const int TYPE_CROSS_CERT_REP = 14; + public const int TYPE_CA_KEY_UPDATE_ANN = 15; + public const int TYPE_CERT_ANN = 16; + public const int TYPE_REVOCATION_ANN = 17; + public const int TYPE_CRL_ANN = 18; + public const int TYPE_CONFIRM = 19; + public const int TYPE_NESTED = 20; + public const int TYPE_GEN_MSG = 21; + public const int TYPE_GEN_REP = 22; + public const int TYPE_ERROR = 23; + public const int TYPE_CERT_CONFIRM = 24; + public const int TYPE_POLL_REQ = 25; + public const int TYPE_POLL_REP = 26; + + private int tagNo; + private Asn1Encodable body; + + public static PkiBody GetInstance(object obj) + { + if (obj is PkiBody) + return (PkiBody)obj; + + if (obj is Asn1TaggedObject) + return new PkiBody((Asn1TaggedObject)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + private PkiBody(Asn1TaggedObject tagged) + { + tagNo = tagged.TagNo; + 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 ArgumentException("unknown tag number: " + type, "type"); + } + } + + public virtual int Type + { + get { return tagNo; } + } + + public virtual Asn1Encodable Content + { + get { return body; } + } + + /** + *
+         * 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
+         * }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerTaggedObject(true, tagNo, body); + } + } +} diff --git a/crypto/src/asn1/cmp/PKIConfirmContent.cs b/crypto/src/asn1/cmp/PKIConfirmContent.cs new file mode 100644 index 000000000..98645766a --- /dev/null +++ b/crypto/src/asn1/cmp/PKIConfirmContent.cs @@ -0,0 +1,34 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiConfirmContent + : Asn1Encodable + { + public static PkiConfirmContent GetInstance(object obj) + { + if (obj is PkiConfirmContent) + return (PkiConfirmContent)obj; + + if (obj is Asn1Null) + return new PkiConfirmContent(); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public PkiConfirmContent() + { + } + + /** + *
+		 * PkiConfirmContent ::= NULL
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return DerNull.Instance; + } + } +} diff --git a/crypto/src/asn1/cmp/PKIFailureInfo.cs b/crypto/src/asn1/cmp/PKIFailureInfo.cs new file mode 100644 index 000000000..1df0e0693 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIFailureInfo.cs @@ -0,0 +1,73 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + /** + *
+	 * 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
+	 * 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
+	 *  systemFailure       (25)
+	 *    -- the request cannot be handled due to system failure
+	 * 
+ */ + public class PkiFailureInfo + : DerBitString + { + public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier + public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify) + public const int BadRequest = (1 << 5); + public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy + public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria + public const int BadDataFormat = (1 << 2); + public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token + public const int IncorrectData = 1; // the requester's data is incorrect (for notary services) + public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy) + public const int BadPop = (1 << 14); // the proof-of-possession failed + public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available + public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA + public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA + public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available + public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure + + /** + * Basic constructor. + */ + public PkiFailureInfo( + int info) + : base(GetBytes(info), GetPadBits(info)) + { + } + + public PkiFailureInfo( + DerBitString info) + : base(info.GetBytes(), info.PadBits) + { + } + + public override string ToString() + { + return "PkiFailureInfo: 0x" + this.IntValue.ToString("X"); + } + } +} diff --git a/crypto/src/asn1/cmp/PKIFreeText.cs b/crypto/src/asn1/cmp/PKIFreeText.cs new file mode 100644 index 000000000..571c8d93a --- /dev/null +++ b/crypto/src/asn1/cmp/PKIFreeText.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiFreeText + : Asn1Encodable + { + internal Asn1Sequence strings; + + public static PkiFreeText GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public static PkiFreeText GetInstance( + object obj) + { + if (obj is PkiFreeText) + { + return (PkiFreeText)obj; + } + else if (obj is Asn1Sequence) + { + return new PkiFreeText((Asn1Sequence)obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public PkiFreeText( + Asn1Sequence seq) + { + foreach (object o in seq) + { + if (!(o is DerUtf8String)) + { + throw new ArgumentException("attempt to insert non UTF8 STRING into PkiFreeText"); + } + } + + this.strings = seq; + } + + public PkiFreeText( + DerUtf8String p) + { + strings = new DerSequence(p); + } + + /** + * Return the number of string elements present. + * + * @return number of elements present. + */ + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return strings.Count; } + } + + public int Count + { + get { return strings.Count; } + } + + /** + * Return the UTF8STRING at index. + * + * @param index index of the string of interest + * @return the string at index. + */ + public DerUtf8String this[int index] + { + get { return (DerUtf8String) strings[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public DerUtf8String GetStringAt( + int index) + { + return this[index]; + } + + /** + *
+		 * PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + return strings; + } + } +} diff --git a/crypto/src/asn1/cmp/PKIHeader.cs b/crypto/src/asn1/cmp/PKIHeader.cs new file mode 100644 index 000000000..e758e9f16 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIHeader.cs @@ -0,0 +1,237 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiHeader + : Asn1Encodable + { + /** + * Value for a "null" recipient or sender. + */ + public static readonly GeneralName NULL_NAME = new GeneralName(X509Name.GetInstance(new DerSequence())); + + public static readonly int CMP_1999 = 1; + public static readonly int CMP_2000 = 2; + + private readonly DerInteger pvno; + private readonly GeneralName sender; + private readonly GeneralName recipient; + private readonly DerGeneralizedTime messageTime; + private readonly AlgorithmIdentifier protectionAlg; + private readonly Asn1OctetString senderKID; // KeyIdentifier + private readonly Asn1OctetString recipKID; // KeyIdentifier + private readonly Asn1OctetString transactionID; + private readonly Asn1OctetString senderNonce; + private readonly Asn1OctetString recipNonce; + private readonly PkiFreeText freeText; + private readonly Asn1Sequence generalInfo; + + private PkiHeader(Asn1Sequence seq) + { + pvno = DerInteger.GetInstance(seq[0]); + sender = GeneralName.GetInstance(seq[1]); + recipient = GeneralName.GetInstance(seq[2]); + + for (int pos = 3; pos < seq.Count; ++pos) + { + Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos]; + + switch (tObj.TagNo) + { + case 0: + messageTime = DerGeneralizedTime.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 ArgumentException("unknown tag number: " + tObj.TagNo, "seq"); + } + } + } + + public static PkiHeader GetInstance(object obj) + { + if (obj is PkiHeader) + return (PkiHeader)obj; + + if (obj is Asn1Sequence) + return new PkiHeader((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public PkiHeader( + int pvno, + GeneralName sender, + GeneralName recipient) + : this(new DerInteger(pvno), sender, recipient) + { + } + + private PkiHeader( + DerInteger pvno, + GeneralName sender, + GeneralName recipient) + { + this.pvno = pvno; + this.sender = sender; + this.recipient = recipient; + } + + public virtual DerInteger Pvno + { + get { return pvno; } + } + + public virtual GeneralName Sender + { + get { return sender; } + } + + public virtual GeneralName Recipient + { + get { return recipient; } + } + + public virtual DerGeneralizedTime MessageTime + { + get { return messageTime; } + } + + public virtual AlgorithmIdentifier ProtectionAlg + { + get { return protectionAlg; } + } + + public virtual Asn1OctetString SenderKID + { + get { return senderKID; } + } + + public virtual Asn1OctetString RecipKID + { + get { return recipKID; } + } + + public virtual Asn1OctetString TransactionID + { + get { return transactionID; } + } + + public virtual Asn1OctetString SenderNonce + { + get { return senderNonce; } + } + + public virtual Asn1OctetString RecipNonce + { + get { return recipNonce; } + } + + public virtual PkiFreeText FreeText + { + get { return freeText; } + } + + public virtual InfoTypeAndValue[] GetGeneralInfo() + { + if (generalInfo == null) + { + return null; + } + InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.Count]; + for (int i = 0; i < results.Length; i++) + { + results[i] = InfoTypeAndValue.GetInstance(generalInfo[i]); + } + return results; + } + + /** + *
+         *  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)
+         * }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, 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 static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj) + { + if (obj != null) + { + v.Add(new DerTaggedObject(true, tagNo, obj)); + } + } + } +} diff --git a/crypto/src/asn1/cmp/PKIHeaderBuilder.cs b/crypto/src/asn1/cmp/PKIHeaderBuilder.cs new file mode 100644 index 000000000..00073c062 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIHeaderBuilder.cs @@ -0,0 +1,223 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiHeaderBuilder + { + private DerInteger pvno; + private GeneralName sender; + private GeneralName recipient; + private DerGeneralizedTime 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 DerInteger(pvno), sender, recipient) + { + } + + private PkiHeaderBuilder( + DerInteger pvno, + GeneralName sender, + GeneralName recipient) + { + this.pvno = pvno; + this.sender = sender; + this.recipient = recipient; + } + + public virtual PkiHeaderBuilder SetMessageTime(DerGeneralizedTime time) + { + messageTime = time; + return this; + } + + public virtual PkiHeaderBuilder SetProtectionAlg(AlgorithmIdentifier aid) + { + protectionAlg = aid; + return this; + } + + public virtual PkiHeaderBuilder SetSenderKID(byte[] kid) + { + return SetSenderKID(kid == null ? null : new DerOctetString(kid)); + } + + public virtual PkiHeaderBuilder SetSenderKID(Asn1OctetString kid) + { + senderKID = kid; + return this; + } + + public virtual PkiHeaderBuilder SetRecipKID(byte[] kid) + { + return SetRecipKID(kid == null ? null : new DerOctetString(kid)); + } + + public virtual PkiHeaderBuilder SetRecipKID(DerOctetString kid) + { + recipKID = kid; + return this; + } + + public virtual PkiHeaderBuilder SetTransactionID(byte[] tid) + { + return SetTransactionID(tid == null ? null : new DerOctetString(tid)); + } + + public virtual PkiHeaderBuilder SetTransactionID(Asn1OctetString tid) + { + transactionID = tid; + return this; + } + + public virtual PkiHeaderBuilder SetSenderNonce(byte[] nonce) + { + return SetSenderNonce(nonce == null ? null : new DerOctetString(nonce)); + } + + public virtual PkiHeaderBuilder SetSenderNonce(Asn1OctetString nonce) + { + senderNonce = nonce; + return this; + } + + public virtual PkiHeaderBuilder SetRecipNonce(byte[] nonce) + { + return SetRecipNonce(nonce == null ? null : new DerOctetString(nonce)); + } + + public virtual PkiHeaderBuilder SetRecipNonce(Asn1OctetString nonce) + { + recipNonce = nonce; + return this; + } + + public virtual PkiHeaderBuilder SetFreeText(PkiFreeText text) + { + freeText = text; + return this; + } + + public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue genInfo) + { + return SetGeneralInfo(MakeGeneralInfoSeq(genInfo)); + } + + public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue[] genInfos) + { + return SetGeneralInfo(MakeGeneralInfoSeq(genInfos)); + } + + public virtual 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; + } + + /** + *
+		 *  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)
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public virtual PkiHeader Build() + { + Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, 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/crypto/src/asn1/cmp/PKIMessage.cs b/crypto/src/asn1/cmp/PKIMessage.cs new file mode 100644 index 000000000..086a2d938 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIMessage.cs @@ -0,0 +1,140 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiMessage + : Asn1Encodable + { + private readonly PkiHeader header; + private readonly PkiBody body; + private readonly DerBitString protection; + private readonly Asn1Sequence extraCerts; + + private PkiMessage(Asn1Sequence seq) + { + header = PkiHeader.GetInstance(seq[0]); + body = PkiBody.GetInstance(seq[1]); + + for (int pos = 2; pos < seq.Count; ++pos) + { + Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object(); + + if (tObj.TagNo == 0) + { + protection = DerBitString.GetInstance(tObj, true); + } + else + { + extraCerts = Asn1Sequence.GetInstance(tObj, true); + } + } + } + + public static PkiMessage GetInstance(object obj) + { + if (obj is PkiMessage) + return (PkiMessage)obj; + + if (obj != null) + return new PkiMessage(Asn1Sequence.GetInstance(obj)); + + 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) + { + this.extraCerts = new DerSequence(extraCerts); + } + } + + 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 virtual PkiHeader Header + { + get { return header; } + } + + public virtual PkiBody Body + { + get { return body; } + } + + public virtual DerBitString Protection + { + get { return protection; } + } + + public virtual CmpCertificate[] GetExtraCerts() + { + if (extraCerts == null) + return null; + + CmpCertificate[] results = new CmpCertificate[extraCerts.Count]; + for (int i = 0; i < results.Length; ++i) + { + results[i] = CmpCertificate.GetInstance(extraCerts[i]); + } + return results; + } + + /** + *
+         * PkiMessage ::= SEQUENCE {
+         *                  header           PKIHeader,
+         *                  body             PKIBody,
+         *                  protection   [0] PKIProtection OPTIONAL,
+         *                  extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+         *                                                                     OPTIONAL
+         * }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(header, body); + + AddOptional(v, 0, protection); + AddOptional(v, 1, extraCerts); + + return new DerSequence(v); + } + + private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj) + { + if (obj != null) + { + v.Add(new DerTaggedObject(true, tagNo, obj)); + } + } + } +} diff --git a/crypto/src/asn1/cmp/PKIMessages.cs b/crypto/src/asn1/cmp/PKIMessages.cs new file mode 100644 index 000000000..ddabdf4ae --- /dev/null +++ b/crypto/src/asn1/cmp/PKIMessages.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiMessages + : Asn1Encodable + { + private Asn1Sequence content; + + private PkiMessages(Asn1Sequence seq) + { + content = seq; + } + + public static PkiMessages GetInstance(object obj) + { + if (obj is PkiMessages) + return (PkiMessages)obj; + + if (obj is Asn1Sequence) + return new PkiMessages((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public PkiMessages(params PkiMessage[] msgs) + { + content = new DerSequence(msgs); + } + + public virtual PkiMessage[] ToPkiMessageArray() + { + PkiMessage[] result = new PkiMessage[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = PkiMessage.GetInstance(content[i]); + } + return result; + } + + /** + *
+         * PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/PKIStatus.cs b/crypto/src/asn1/cmp/PKIStatus.cs new file mode 100644 index 000000000..b03dd3d62 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIStatus.cs @@ -0,0 +1,62 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public enum PkiStatus + { + Granted = 0, + GrantedWithMods = 1, + Rejection = 2, + Waiting = 3, + RevocationWarning = 4, + RevocationNotification = 5, + KeyUpdateWarning = 6, + } + + public class PkiStatusEncodable + : Asn1Encodable + { + public static readonly PkiStatusEncodable granted = new PkiStatusEncodable(PkiStatus.Granted); + public static readonly PkiStatusEncodable grantedWithMods = new PkiStatusEncodable(PkiStatus.GrantedWithMods); + public static readonly PkiStatusEncodable rejection = new PkiStatusEncodable(PkiStatus.Rejection); + public static readonly PkiStatusEncodable waiting = new PkiStatusEncodable(PkiStatus.Waiting); + public static readonly PkiStatusEncodable revocationWarning = new PkiStatusEncodable(PkiStatus.RevocationWarning); + public static readonly PkiStatusEncodable revocationNotification = new PkiStatusEncodable(PkiStatus.RevocationNotification); + public static readonly PkiStatusEncodable keyUpdateWaiting = new PkiStatusEncodable(PkiStatus.KeyUpdateWarning); + + private readonly DerInteger status; + + private PkiStatusEncodable(PkiStatus status) + : this(new DerInteger((int)status)) + { + } + + private PkiStatusEncodable(DerInteger status) + { + this.status = status; + } + + public static PkiStatusEncodable GetInstance(object obj) + { + if (obj is PkiStatusEncodable) + return (PkiStatusEncodable)obj; + + if (obj is DerInteger) + return new PkiStatusEncodable((DerInteger)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual BigInteger Value + { + get { return status.Value; } + } + + public override Asn1Object ToAsn1Object() + { + return status; + } + } +} diff --git a/crypto/src/asn1/cmp/PKIStatusInfo.cs b/crypto/src/asn1/cmp/PKIStatusInfo.cs new file mode 100644 index 000000000..2463e0081 --- /dev/null +++ b/crypto/src/asn1/cmp/PKIStatusInfo.cs @@ -0,0 +1,165 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PkiStatusInfo + : Asn1Encodable + { + DerInteger status; + PkiFreeText statusString; + DerBitString failInfo; + + public static PkiStatusInfo GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public static PkiStatusInfo GetInstance( + object obj) + { + if (obj is PkiStatusInfo) + { + return (PkiStatusInfo)obj; + } + else if (obj is Asn1Sequence) + { + return new PkiStatusInfo((Asn1Sequence)obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public PkiStatusInfo( + Asn1Sequence seq) + { + this.status = DerInteger.GetInstance(seq[0]); + + this.statusString = null; + this.failInfo = null; + + if (seq.Count > 2) + { + this.statusString = PkiFreeText.GetInstance(seq[1]); + this.failInfo = DerBitString.GetInstance(seq[2]); + } + else if (seq.Count > 1) + { + object obj = seq[1]; + if (obj is DerBitString) + { + this.failInfo = DerBitString.GetInstance(obj); + } + else + { + this.statusString = PkiFreeText.GetInstance(obj); + } + } + } + + /** + * @param status + */ + public PkiStatusInfo(int status) + { + this.status = new DerInteger(status); + } + + /** + * @param status + * @param statusString + */ + public PkiStatusInfo( + int status, + PkiFreeText statusString) + { + this.status = new DerInteger(status); + this.statusString = statusString; + } + + public PkiStatusInfo( + int status, + PkiFreeText statusString, + PkiFailureInfo failInfo) + { + this.status = new DerInteger(status); + this.statusString = statusString; + this.failInfo = failInfo; + } + + public BigInteger Status + { + get + { + return status.Value; + } + } + + public PkiFreeText StatusString + { + get + { + return statusString; + } + } + + public DerBitString FailInfo + { + get + { + return failInfo; + } + } + + /** + *
+		 * 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
+		 *
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(status); + + if (statusString != null) + { + v.Add(statusString); + } + + if (failInfo!= null) + { + v.Add(failInfo); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/PbmParameter.cs b/crypto/src/asn1/cmp/PbmParameter.cs new file mode 100644 index 000000000..59b1bd7bb --- /dev/null +++ b/crypto/src/asn1/cmp/PbmParameter.cs @@ -0,0 +1,100 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PbmParameter + : Asn1Encodable + { + private Asn1OctetString salt; + private AlgorithmIdentifier owf; + private DerInteger iterationCount; + private AlgorithmIdentifier mac; + + private PbmParameter(Asn1Sequence seq) + { + salt = Asn1OctetString.GetInstance(seq[0]); + owf = AlgorithmIdentifier.GetInstance(seq[1]); + iterationCount = DerInteger.GetInstance(seq[2]); + mac = AlgorithmIdentifier.GetInstance(seq[3]); + } + + public static PbmParameter GetInstance(object obj) + { + if (obj is PbmParameter) + return (PbmParameter)obj; + + if (obj is Asn1Sequence) + return new PbmParameter((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public PbmParameter( + byte[] salt, + AlgorithmIdentifier owf, + int iterationCount, + AlgorithmIdentifier mac) + : this(new DerOctetString(salt), owf, new DerInteger(iterationCount), mac) + { + } + + public PbmParameter( + Asn1OctetString salt, + AlgorithmIdentifier owf, + DerInteger iterationCount, + AlgorithmIdentifier mac) + { + this.salt = salt; + this.owf = owf; + this.iterationCount = iterationCount; + this.mac = mac; + } + + public virtual Asn1OctetString Salt + { + get { return salt; } + } + + public virtual AlgorithmIdentifier Owf + { + get { return owf; } + } + + public virtual DerInteger IterationCount + { + get { return iterationCount; } + } + + public virtual AlgorithmIdentifier Mac + { + get { return mac; } + } + + /** + *
+         *  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])
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(salt, owf, iterationCount, mac); + } + } +} diff --git a/crypto/src/asn1/cmp/PollRepContent.cs b/crypto/src/asn1/cmp/PollRepContent.cs new file mode 100644 index 000000000..4045ac7ed --- /dev/null +++ b/crypto/src/asn1/cmp/PollRepContent.cs @@ -0,0 +1,66 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PollRepContent + : Asn1Encodable + { + private readonly DerInteger certReqId; + private readonly DerInteger checkAfter; + private readonly PkiFreeText reason; + + private PollRepContent(Asn1Sequence seq) + { + certReqId = DerInteger.GetInstance(seq[0]); + checkAfter = DerInteger.GetInstance(seq[1]); + + if (seq.Count > 2) + { + reason = PkiFreeText.GetInstance(seq[2]); + } + } + + public static PollRepContent GetInstance(object obj) + { + if (obj is PollRepContent) + return (PollRepContent)obj; + + if (obj is Asn1Sequence) + return new PollRepContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual DerInteger CertReqID + { + get { return certReqId; } + } + + public virtual DerInteger CheckAfter + { + get { return checkAfter; } + } + + public virtual PkiFreeText Reason + { + get { return reason; } + } + + /** + *
+		 * PollRepContent ::= SEQUENCE OF SEQUENCE {
+		 *         certReqId              INTEGER,
+		 *         checkAfter             INTEGER,  -- time in seconds
+		 *         reason                 PKIFreeText OPTIONAL
+		 *     }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certReqId, checkAfter); + v.AddOptional(reason); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/PollReqContent.cs b/crypto/src/asn1/cmp/PollReqContent.cs new file mode 100644 index 000000000..ca2164151 --- /dev/null +++ b/crypto/src/asn1/cmp/PollReqContent.cs @@ -0,0 +1,59 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PollReqContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private PollReqContent(Asn1Sequence seq) + { + content = seq; + } + + public static PollReqContent GetInstance(object obj) + { + if (obj is PollReqContent) + return (PollReqContent)obj; + + if (obj is Asn1Sequence) + return new PollReqContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual DerInteger[][] GetCertReqIDs() + { + DerInteger[][] result = new DerInteger[content.Count][]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = SequenceToDerIntegerArray((Asn1Sequence)content[i]); + } + return result; + } + + private static DerInteger[] SequenceToDerIntegerArray(Asn1Sequence seq) + { + DerInteger[] result = new DerInteger[seq.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = DerInteger.GetInstance(seq[i]); + } + return result; + } + + /** + *
+		 * PollReqContent ::= SEQUENCE OF SEQUENCE {
+		 *                        certReqId              INTEGER
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs b/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs new file mode 100644 index 000000000..20b173b85 --- /dev/null +++ b/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PopoDecKeyChallContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private PopoDecKeyChallContent(Asn1Sequence seq) + { + content = seq; + } + + public static PopoDecKeyChallContent GetInstance(object obj) + { + if (obj is PopoDecKeyChallContent) + return (PopoDecKeyChallContent)obj; + + if (obj is Asn1Sequence) + return new PopoDecKeyChallContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual Challenge[] ToChallengeArray() + { + Challenge[] result = new Challenge[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = Challenge.GetInstance(content[i]); + } + return result; + } + + /** + *
+	     * PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+	     * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs b/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs new file mode 100644 index 000000000..8c322e4ec --- /dev/null +++ b/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class PopoDecKeyRespContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private PopoDecKeyRespContent(Asn1Sequence seq) + { + content = seq; + } + + public static PopoDecKeyRespContent GetInstance(object obj) + { + if (obj is PopoDecKeyRespContent) + return (PopoDecKeyRespContent)obj; + + if (obj is Asn1Sequence) + return new PopoDecKeyRespContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual DerInteger[] ToDerIntegerArray() + { + DerInteger[] result = new DerInteger[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = DerInteger.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cmp/ProtectedPart.cs b/crypto/src/asn1/cmp/ProtectedPart.cs new file mode 100644 index 000000000..db6798fee --- /dev/null +++ b/crypto/src/asn1/cmp/ProtectedPart.cs @@ -0,0 +1,58 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class ProtectedPart + : Asn1Encodable + { + private readonly PkiHeader header; + private readonly PkiBody body; + + private ProtectedPart(Asn1Sequence seq) + { + header = PkiHeader.GetInstance(seq[0]); + body = PkiBody.GetInstance(seq[1]); + } + + public static ProtectedPart GetInstance(object obj) + { + if (obj is ProtectedPart) + return (ProtectedPart)obj; + + if (obj is Asn1Sequence) + return new ProtectedPart((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public ProtectedPart(PkiHeader header, PkiBody body) + { + this.header = header; + this.body = body; + } + + public virtual PkiHeader Header + { + get { return header; } + } + + public virtual PkiBody Body + { + get { return body; } + } + + /** + *
+		 * ProtectedPart ::= SEQUENCE {
+		 *                    header    PKIHeader,
+		 *                    body      PKIBody
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(header, body); + } + } +} diff --git a/crypto/src/asn1/cmp/RevAnnContent.cs b/crypto/src/asn1/cmp/RevAnnContent.cs new file mode 100644 index 000000000..2c3bd5f77 --- /dev/null +++ b/crypto/src/asn1/cmp/RevAnnContent.cs @@ -0,0 +1,86 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class RevAnnContent + : Asn1Encodable + { + private readonly PkiStatusEncodable status; + private readonly CertId certId; + private readonly DerGeneralizedTime willBeRevokedAt; + private readonly DerGeneralizedTime badSinceDate; + private readonly X509Extensions crlDetails; + + private RevAnnContent(Asn1Sequence seq) + { + status = PkiStatusEncodable.GetInstance(seq[0]); + certId = CertId.GetInstance(seq[1]); + willBeRevokedAt = DerGeneralizedTime.GetInstance(seq[2]); + badSinceDate = DerGeneralizedTime.GetInstance(seq[3]); + + if (seq.Count > 4) + { + crlDetails = X509Extensions.GetInstance(seq[4]); + } + } + + public static RevAnnContent GetInstance(object obj) + { + if (obj is RevAnnContent) + return (RevAnnContent)obj; + + if (obj is Asn1Sequence) + return new RevAnnContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual PkiStatusEncodable Status + { + get { return status; } + } + + public virtual CertId CertID + { + get { return certId; } + } + + public virtual DerGeneralizedTime WillBeRevokedAt + { + get { return willBeRevokedAt; } + } + + public virtual DerGeneralizedTime BadSinceDate + { + get { return badSinceDate; } + } + + public virtual X509Extensions CrlDetails + { + get { return crlDetails; } + } + + /** + *
+		 * RevAnnContent ::= SEQUENCE {
+		 *       status              PKIStatus,
+		 *       certId              CertId,
+		 *       willBeRevokedAt     GeneralizedTime,
+		 *       badSinceDate        GeneralizedTime,
+		 *       crlDetails          Extensions  OPTIONAL
+		 *        -- extra CRL details (e.g., crl number, reason, location, etc.)
+		 * }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(status, certId, willBeRevokedAt, badSinceDate); + v.AddOptional(crlDetails); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/RevDetails.cs b/crypto/src/asn1/cmp/RevDetails.cs new file mode 100644 index 000000000..1bd95f1db --- /dev/null +++ b/crypto/src/asn1/cmp/RevDetails.cs @@ -0,0 +1,75 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class RevDetails + : Asn1Encodable + { + private readonly CertTemplate certDetails; + private readonly X509Extensions crlEntryDetails; + + private RevDetails(Asn1Sequence seq) + { + certDetails = CertTemplate.GetInstance(seq[0]); + + if (seq.Count > 1) + { + crlEntryDetails = X509Extensions.GetInstance(seq[1]); + } + } + + public static RevDetails GetInstance(object obj) + { + if (obj is RevDetails) + return (RevDetails)obj; + + if (obj is Asn1Sequence) + return new RevDetails((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public RevDetails(CertTemplate certDetails) + { + this.certDetails = certDetails; + } + + public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails) + { + this.crlEntryDetails = crlEntryDetails; + } + + public virtual CertTemplate CertDetails + { + get { return certDetails; } + } + + public virtual X509Extensions CrlEntryDetails + { + get { return crlEntryDetails; } + } + + /** + *
+		* 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
+		*             }
+		* 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certDetails); + v.AddOptional(crlEntryDetails); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cmp/RevRepContent.cs b/crypto/src/asn1/cmp/RevRepContent.cs new file mode 100644 index 000000000..47987265a --- /dev/null +++ b/crypto/src/asn1/cmp/RevRepContent.cs @@ -0,0 +1,112 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class RevRepContent + : Asn1Encodable + { + private readonly Asn1Sequence status; + private readonly Asn1Sequence revCerts; + private readonly Asn1Sequence crls; + + private RevRepContent(Asn1Sequence seq) + { + status = Asn1Sequence.GetInstance(seq[0]); + + for (int pos = 1; pos < seq.Count; ++pos) + { + Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]); + + if (tObj.TagNo == 0) + { + revCerts = Asn1Sequence.GetInstance(tObj, true); + } + else + { + crls = Asn1Sequence.GetInstance(tObj, true); + } + } + } + + public static RevRepContent GetInstance(object obj) + { + if (obj is RevRepContent) + return (RevRepContent)obj; + + if (obj is Asn1Sequence) + return new RevRepContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual PkiStatusInfo[] GetStatus() + { + PkiStatusInfo[] results = new PkiStatusInfo[status.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = PkiStatusInfo.GetInstance(status[i]); + } + return results; + } + + public virtual CertId[] GetRevCerts() + { + if (revCerts == null) + return null; + + CertId[] results = new CertId[revCerts.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CertId.GetInstance(revCerts[i]); + } + return results; + } + + public virtual CertificateList[] GetCrls() + { + if (crls == null) + return null; + + CertificateList[] results = new CertificateList[crls.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = CertificateList.GetInstance(crls[i]); + } + return results; + } + + /** + *
+		 * 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)
+		 *   }
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(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/crypto/src/asn1/cmp/RevRepContentBuilder.cs b/crypto/src/asn1/cmp/RevRepContentBuilder.cs new file mode 100644 index 000000000..cc17d1d4c --- /dev/null +++ b/crypto/src/asn1/cmp/RevRepContentBuilder.cs @@ -0,0 +1,55 @@ +using System; + +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class RevRepContentBuilder + { + private readonly Asn1EncodableVector status = new Asn1EncodableVector(); + private readonly Asn1EncodableVector revCerts = new Asn1EncodableVector(); + private readonly Asn1EncodableVector crls = new Asn1EncodableVector(); + + public virtual RevRepContentBuilder Add(PkiStatusInfo status) + { + this.status.Add(status); + return this; + } + + public virtual RevRepContentBuilder Add(PkiStatusInfo status, CertId certId) + { + if (this.status.Count != this.revCerts.Count) + throw new InvalidOperationException("status and revCerts sequence must be in common order"); + + this.status.Add(status); + this.revCerts.Add(certId); + return this; + } + + public virtual RevRepContentBuilder AddCrl(CertificateList crl) + { + this.crls.Add(crl); + return this; + } + + public virtual RevRepContent Build() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + v.Add(new DerSequence(status)); + + if (revCerts.Count != 0) + { + v.Add(new DerTaggedObject(true, 0, new DerSequence(revCerts))); + } + + if (crls.Count != 0) + { + v.Add(new DerTaggedObject(true, 1, new DerSequence(crls))); + } + + return RevRepContent.GetInstance(new DerSequence(v)); + } + } +} diff --git a/crypto/src/asn1/cmp/RevReqContent.cs b/crypto/src/asn1/cmp/RevReqContent.cs new file mode 100644 index 000000000..fbf869203 --- /dev/null +++ b/crypto/src/asn1/cmp/RevReqContent.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cmp +{ + public class RevReqContent + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private RevReqContent(Asn1Sequence seq) + { + content = seq; + } + + public static RevReqContent GetInstance(object obj) + { + if (obj is RevReqContent) + return (RevReqContent)obj; + + if (obj is Asn1Sequence) + return new RevReqContent((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public RevReqContent(params RevDetails[] revDetails) + { + this.content = new DerSequence(revDetails); + } + + public virtual RevDetails[] ToRevDetailsArray() + { + RevDetails[] result = new RevDetails[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = RevDetails.GetInstance(content[i]); + } + return result; + } + + /** + *
+		 * RevReqContent ::= SEQUENCE OF RevDetails
+		 * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/cms/Attribute.cs b/crypto/src/asn1/cms/Attribute.cs new file mode 100644 index 000000000..c4a104a3f --- /dev/null +++ b/crypto/src/asn1/cms/Attribute.cs @@ -0,0 +1,70 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class Attribute + : Asn1Encodable + { + private DerObjectIdentifier attrType; + private Asn1Set attrValues; + + /** + * return an Attribute object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static Attribute GetInstance( + object obj) + { + if (obj == null || obj is Attribute) + return (Attribute) obj; + + if (obj is Asn1Sequence) + return new Attribute((Asn1Sequence) obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public Attribute( + Asn1Sequence seq) + { + attrType = (DerObjectIdentifier)seq[0]; + attrValues = (Asn1Set)seq[1]; + } + + public Attribute( + DerObjectIdentifier attrType, + Asn1Set attrValues) + { + this.attrType = attrType; + this.attrValues = attrValues; + } + + public DerObjectIdentifier AttrType + { + get { return attrType; } + } + + public Asn1Set AttrValues + { + get { return attrValues; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+        * Attribute ::= SEQUENCE {
+        *     attrType OBJECT IDENTIFIER,
+        *     attrValues SET OF AttributeValue
+        * }
+        * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(attrType, attrValues); + } + } +} diff --git a/crypto/src/asn1/cms/AttributeTable.cs b/crypto/src/asn1/cms/AttributeTable.cs new file mode 100644 index 000000000..8a3ee5d0e --- /dev/null +++ b/crypto/src/asn1/cms/AttributeTable.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class AttributeTable + { + private readonly IDictionary attributes; + +#if !SILVERLIGHT + [Obsolete] + public AttributeTable( + Hashtable attrs) + { + this.attributes = Platform.CreateHashtable(attrs); + } +#endif + + public AttributeTable( + IDictionary attrs) + { + this.attributes = Platform.CreateHashtable(attrs); + } + + public AttributeTable( + Asn1EncodableVector v) + { + this.attributes = Platform.CreateHashtable(v.Count); + + foreach (Asn1Encodable o in v) + { + Attribute a = Attribute.GetInstance(o); + + AddAttribute(a); + } + } + + public AttributeTable( + Asn1Set s) + { + this.attributes = Platform.CreateHashtable(s.Count); + + for (int i = 0; i != s.Count; i++) + { + Attribute a = Attribute.GetInstance(s[i]); + + AddAttribute(a); + } + } + + public AttributeTable( + Attributes attrs) + : this(Asn1Set.GetInstance(attrs.ToAsn1Object())) + { + } + + private void AddAttribute( + Attribute a) + { + DerObjectIdentifier oid = a.AttrType; + object obj = attributes[oid]; + + if (obj == null) + { + attributes[oid] = a; + } + else + { + IList v; + + if (obj is Attribute) + { + v = Platform.CreateArrayList(); + + v.Add(obj); + v.Add(a); + } + else + { + v = (IList) obj; + + v.Add(a); + } + + attributes[oid] = v; + } + } + + /// Return the first attribute matching the given OBJECT IDENTIFIER + public Attribute this[DerObjectIdentifier oid] + { + get + { + object obj = attributes[oid]; + + if (obj is IList) + { + return (Attribute)((IList)obj)[0]; + } + + return (Attribute) obj; + } + } + + [Obsolete("Use 'object[oid]' syntax instead")] + public Attribute Get( + DerObjectIdentifier oid) + { + return this[oid]; + } + + /** + * 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( + DerObjectIdentifier oid) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + object obj = attributes[oid]; + + if (obj is IList) + { + foreach (Attribute a in (IList)obj) + { + v.Add(a); + } + } + else if (obj != null) + { + v.Add((Attribute) obj); + } + + return v; + } + + public int Count + { + get + { + int total = 0; + + foreach (object o in attributes.Values) + { + if (o is IList) + { + total += ((IList)o).Count; + } + else + { + ++total; + } + } + + return total; + } + } + + public IDictionary ToDictionary() + { + return Platform.CreateHashtable(attributes); + } + +#if !SILVERLIGHT + [Obsolete("Use 'ToDictionary' instead")] + public Hashtable ToHashtable() + { + return new Hashtable(attributes); + } +#endif + + public Asn1EncodableVector ToAsn1EncodableVector() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + foreach (object obj in attributes.Values) + { + if (obj is IList) + { + foreach (object el in (IList)obj) + { + v.Add(Attribute.GetInstance(el)); + } + } + else + { + v.Add(Attribute.GetInstance(obj)); + } + } + + return v; + } + + public Attributes ToAttributes() + { + return new Attributes(this.ToAsn1EncodableVector()); + } + + /** + * Return a new table with the passed in attribute added. + * + * @param attrType + * @param attrValue + * @return + */ + public AttributeTable Add(DerObjectIdentifier attrType, Asn1Encodable attrValue) + { + AttributeTable newTable = new AttributeTable(attributes); + + newTable.AddAttribute(new Attribute(attrType, new DerSet(attrValue))); + + return newTable; + } + + public AttributeTable Remove(DerObjectIdentifier attrType) + { + AttributeTable newTable = new AttributeTable(attributes); + + newTable.attributes.Remove(attrType); + + return newTable; + } + } +} diff --git a/crypto/src/asn1/cms/Attributes.cs b/crypto/src/asn1/cms/Attributes.cs new file mode 100644 index 000000000..5b6b13034 --- /dev/null +++ b/crypto/src/asn1/cms/Attributes.cs @@ -0,0 +1,55 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class Attributes + : Asn1Encodable + { + private readonly Asn1Set attributes; + + private Attributes(Asn1Set attributes) + { + this.attributes = attributes; + } + + public Attributes(Asn1EncodableVector v) + { + attributes = new BerSet(v); + } + + public static Attributes GetInstance(object obj) + { + if (obj is Attributes) + return (Attributes)obj; + + if (obj != null) + return new Attributes(Asn1Set.GetInstance(obj)); + + return null; + } + + public virtual Attribute[] GetAttributes() + { + Attribute[] rv = new Attribute[attributes.Count]; + + for (int i = 0; i != rv.Length; i++) + { + rv[i] = Attribute.GetInstance(attributes[i]); + } + + return rv; + } + + /** + *
+         * Attributes ::=
+         *   SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+         * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + return attributes; + } + } +} diff --git a/crypto/src/asn1/cms/AuthEnvelopedData.cs b/crypto/src/asn1/cms/AuthEnvelopedData.cs new file mode 100644 index 000000000..4260d80f9 --- /dev/null +++ b/crypto/src/asn1/cms/AuthEnvelopedData.cs @@ -0,0 +1,203 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class AuthEnvelopedData + : Asn1Encodable + { + private DerInteger 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 DerInteger(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; + } + + private AuthEnvelopedData( + Asn1Sequence seq) + { + int index = 0; + + // TODO + // "It MUST be set to 0." + Asn1Object tmp = seq[index++].ToAsn1Object(); + version = (DerInteger)tmp; + + tmp = seq[index++].ToAsn1Object(); + if (tmp is Asn1TaggedObject) + { + originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false); + tmp = seq[index++].ToAsn1Object(); + } + + // TODO + // "There MUST be at least one element in the collection." + recipientInfos = Asn1Set.GetInstance(tmp); + + tmp = seq[index++].ToAsn1Object(); + authEncryptedContentInfo = EncryptedContentInfo.GetInstance(tmp); + + tmp = seq[index++].ToAsn1Object(); + if (tmp is Asn1TaggedObject) + { + authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false); + tmp = seq[index++].ToAsn1Object(); + } + else + { + // TODO + // "The authAttrs MUST be present if the content type carried in + // EncryptedContentInfo is not id-data." + } + + mac = Asn1OctetString.GetInstance(tmp); + + if (seq.Count > index) + { + tmp = seq[index++].ToAsn1Object(); + unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false); + } + } + + /** + * return an AuthEnvelopedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static AuthEnvelopedData GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return an AuthEnvelopedData object from the given object. + * + * @param obj the object we want converted. + * @throws ArgumentException if the object cannot be converted. + */ + public static AuthEnvelopedData GetInstance( + object obj) + { + if (obj == null || obj is AuthEnvelopedData) + return (AuthEnvelopedData)obj; + + if (obj is Asn1Sequence) + return new AuthEnvelopedData((Asn1Sequence)obj); + + throw new ArgumentException("Invalid AuthEnvelopedData: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorInfo OriginatorInfo + { + get { return originatorInfo; } + } + + public Asn1Set RecipientInfos + { + get { return recipientInfos; } + } + + public EncryptedContentInfo AuthEncryptedContentInfo + { + get { return authEncryptedContentInfo; } + } + + public Asn1Set AuthAttrs + { + get { return authAttrs; } + } + + public Asn1OctetString Mac + { + get { return mac; } + } + + public Asn1Set UnauthAttrs + { + get { return unauthAttrs; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 * 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 }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version); + + if (originatorInfo != null) + { + v.Add(new DerTaggedObject(false, 0, originatorInfo)); + } + + v.Add(recipientInfos, 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/crypto/src/asn1/cms/AuthEnvelopedDataParser.cs b/crypto/src/asn1/cms/AuthEnvelopedDataParser.cs new file mode 100644 index 000000000..35cb3bfcc --- /dev/null +++ b/crypto/src/asn1/cms/AuthEnvelopedDataParser.cs @@ -0,0 +1,145 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * Produce an object suitable for an Asn1OutputStream. + * + *
+	 * 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 }
+	 * 
+ */ + public class AuthEnvelopedDataParser + { + private Asn1SequenceParser seq; + private DerInteger version; + private IAsn1Convertible nextObject; + private bool originatorInfoCalled; + + public AuthEnvelopedDataParser( + Asn1SequenceParser seq) + { + this.seq = seq; + + // TODO + // "It MUST be set to 0." + this.version = (DerInteger)seq.ReadObject(); + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorInfo GetOriginatorInfo() + { + originatorInfoCalled = true; + + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0) + { + Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false); + nextObject = null; + return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object()); + } + + return null; + } + + public Asn1SetParser GetRecipientInfos() + { + if (!originatorInfoCalled) + { + GetOriginatorInfo(); + } + + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + Asn1SetParser recipientInfos = (Asn1SetParser)nextObject; + nextObject = null; + return recipientInfos; + } + + public EncryptedContentInfoParser GetAuthEncryptedContentInfo() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject != null) + { + Asn1SequenceParser o = (Asn1SequenceParser) nextObject; + nextObject = null; + return new EncryptedContentInfoParser(o); + } + + return null; + } + + public Asn1SetParser GetAuthAttrs() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject is Asn1TaggedObjectParser) + { + IAsn1Convertible o = nextObject; + nextObject = null; + return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false); + } + + // TODO + // "The authAttrs MUST be present if the content type carried in + // EncryptedContentInfo is not id-data." + + return null; + } + + public Asn1OctetString GetMac() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + IAsn1Convertible o = nextObject; + nextObject = null; + + return Asn1OctetString.GetInstance(o.ToAsn1Object()); + } + + public Asn1SetParser GetUnauthAttrs() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject != null) + { + IAsn1Convertible o = nextObject; + nextObject = null; + return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false); + } + + return null; + } + } +} diff --git a/crypto/src/asn1/cms/AuthenticatedData.cs b/crypto/src/asn1/cms/AuthenticatedData.cs new file mode 100644 index 000000000..15286d1aa --- /dev/null +++ b/crypto/src/asn1/cms/AuthenticatedData.cs @@ -0,0 +1,270 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class AuthenticatedData + : Asn1Encodable + { + private DerInteger 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 ArgumentException("digestAlgorithm and authAttrs must be set together"); + } + } + + version = new DerInteger(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; + } + + private AuthenticatedData( + Asn1Sequence seq) + { + int index = 0; + + version = (DerInteger)seq[index++]; + + Asn1Encodable tmp = seq[index++]; + if (tmp is Asn1TaggedObject) + { + originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false); + tmp = seq[index++]; + } + + recipientInfos = Asn1Set.GetInstance(tmp); + macAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]); + + tmp = seq[index++]; + if (tmp is Asn1TaggedObject) + { + digestAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject)tmp, false); + tmp = seq[index++]; + } + + encapsulatedContentInfo = ContentInfo.GetInstance(tmp); + + tmp = seq[index++]; + if (tmp is Asn1TaggedObject) + { + authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false); + tmp = seq[index++]; + } + + mac = Asn1OctetString.GetInstance(tmp); + + if (seq.Count > index) + { + unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false); + } + } + + /** + * return an AuthenticatedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static AuthenticatedData GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return an AuthenticatedData object from the given object. + * + * @param obj the object we want converted. + * @throws ArgumentException if the object cannot be converted. + */ + public static AuthenticatedData GetInstance( + object obj) + { + if (obj == null || obj is AuthenticatedData) + { + return (AuthenticatedData)obj; + } + + if (obj is Asn1Sequence) + { + return new AuthenticatedData((Asn1Sequence)obj); + } + + throw new ArgumentException("Invalid AuthenticatedData: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorInfo OriginatorInfo + { + get { return originatorInfo; } + } + + public Asn1Set RecipientInfos + { + get { return recipientInfos; } + } + + public AlgorithmIdentifier MacAlgorithm + { + get { return macAlgorithm; } + } + + public AlgorithmIdentifier DigestAlgorithm + { + get { return digestAlgorithm; } + } + + public ContentInfo EncapsulatedContentInfo + { + get { return encapsulatedContentInfo; } + } + + public Asn1Set AuthAttrs + { + get { return authAttrs; } + } + + public Asn1OctetString Mac + { + get { return mac; } + } + + public Asn1Set UnauthAttrs + { + get { return unauthAttrs; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 * 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
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version); + + if (originatorInfo != null) + { + v.Add(new DerTaggedObject(false, 0, originatorInfo)); + } + + v.Add(recipientInfos, 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; + + int ver = 0; + + foreach (object obj in origInfo.Certificates) + { + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tag = (Asn1TaggedObject)obj; + + if (tag.TagNo == 2) + { + ver = 1; + } + else if (tag.TagNo == 3) + { + ver = 3; + break; + } + } + } + + foreach (object obj in origInfo.Crls) + { + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tag = (Asn1TaggedObject)obj; + + if (tag.TagNo == 1) + { + ver = 3; + break; + } + } + } + + return ver; + } + } +} diff --git a/crypto/src/asn1/cms/AuthenticatedDataParser.cs b/crypto/src/asn1/cms/AuthenticatedDataParser.cs new file mode 100644 index 000000000..4b80d1b02 --- /dev/null +++ b/crypto/src/asn1/cms/AuthenticatedDataParser.cs @@ -0,0 +1,182 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * Produce an object suitable for an Asn1OutputStream. + *
+	 * 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
+	 * 
+ */ + public class AuthenticatedDataParser + { + private Asn1SequenceParser seq; + private DerInteger version; + private IAsn1Convertible nextObject; + private bool originatorInfoCalled; + + public AuthenticatedDataParser( + Asn1SequenceParser seq) + { + this.seq = seq; + this.version = (DerInteger)seq.ReadObject(); + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorInfo GetOriginatorInfo() + { + originatorInfoCalled = true; + + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0) + { + Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false); + nextObject = null; + return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object()); + } + + return null; + } + + public Asn1SetParser GetRecipientInfos() + { + if (!originatorInfoCalled) + { + GetOriginatorInfo(); + } + + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + Asn1SetParser recipientInfos = (Asn1SetParser)nextObject; + nextObject = null; + return recipientInfos; + } + + public AlgorithmIdentifier GetMacAlgorithm() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject != null) + { + Asn1SequenceParser o = (Asn1SequenceParser)nextObject; + nextObject = null; + return AlgorithmIdentifier.GetInstance(o.ToAsn1Object()); + } + + return null; + } + + public AlgorithmIdentifier GetDigestAlgorithm() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject is Asn1TaggedObjectParser) + { + AlgorithmIdentifier obj = AlgorithmIdentifier.GetInstance( + (Asn1TaggedObject)nextObject.ToAsn1Object(), false); + nextObject = null; + return obj; + } + + return null; + } + + public ContentInfoParser GetEnapsulatedContentInfo() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject != null) + { + Asn1SequenceParser o = (Asn1SequenceParser)nextObject; + nextObject = null; + return new ContentInfoParser(o); + } + + return null; + } + + public Asn1SetParser GetAuthAttrs() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject is Asn1TaggedObjectParser) + { + IAsn1Convertible o = nextObject; + nextObject = null; + return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false); + } + + return null; + } + + public Asn1OctetString GetMac() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + IAsn1Convertible o = nextObject; + nextObject = null; + + return Asn1OctetString.GetInstance(o.ToAsn1Object()); + } + + public Asn1SetParser GetUnauthAttrs() + { + if (nextObject == null) + { + nextObject = seq.ReadObject(); + } + + if (nextObject != null) + { + IAsn1Convertible o = nextObject; + nextObject = null; + return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false); + } + + return null; + } + } +} diff --git a/crypto/src/asn1/cms/CMSAttributes.cs b/crypto/src/asn1/cms/CMSAttributes.cs new file mode 100644 index 000000000..fca2b6738 --- /dev/null +++ b/crypto/src/asn1/cms/CMSAttributes.cs @@ -0,0 +1,14 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public abstract class CmsAttributes + { + public static readonly DerObjectIdentifier ContentType = PkcsObjectIdentifiers.Pkcs9AtContentType; + public static readonly DerObjectIdentifier MessageDigest = PkcsObjectIdentifiers.Pkcs9AtMessageDigest; + public static readonly DerObjectIdentifier SigningTime = PkcsObjectIdentifiers.Pkcs9AtSigningTime; + public static readonly DerObjectIdentifier CounterSignature = PkcsObjectIdentifiers.Pkcs9AtCounterSignature; + public static readonly DerObjectIdentifier ContentHint = PkcsObjectIdentifiers.IdAAContentHint; + } +} diff --git a/crypto/src/asn1/cms/CMSObjectIdentifiers.cs b/crypto/src/asn1/cms/CMSObjectIdentifiers.cs new file mode 100644 index 000000000..2ad0a3c7c --- /dev/null +++ b/crypto/src/asn1/cms/CMSObjectIdentifiers.cs @@ -0,0 +1,28 @@ +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public abstract class CmsObjectIdentifiers + { + public static readonly DerObjectIdentifier Data = PkcsObjectIdentifiers.Data; + public static readonly DerObjectIdentifier SignedData = PkcsObjectIdentifiers.SignedData; + public static readonly DerObjectIdentifier EnvelopedData = PkcsObjectIdentifiers.EnvelopedData; + public static readonly DerObjectIdentifier SignedAndEnvelopedData = PkcsObjectIdentifiers.SignedAndEnvelopedData; + public static readonly DerObjectIdentifier DigestedData = PkcsObjectIdentifiers.DigestedData; + public static readonly DerObjectIdentifier EncryptedData = PkcsObjectIdentifiers.EncryptedData; + public static readonly DerObjectIdentifier AuthenticatedData = PkcsObjectIdentifiers.IdCTAuthData; + public static readonly DerObjectIdentifier CompressedData = PkcsObjectIdentifiers.IdCTCompressedData; + public static readonly DerObjectIdentifier AuthEnvelopedData = PkcsObjectIdentifiers.IdCTAuthEnvelopedData; + public static readonly DerObjectIdentifier timestampedData = PkcsObjectIdentifiers.IdCTTimestampedData; + + /** + * The other Revocation Info arc + * id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) } + */ + public static readonly DerObjectIdentifier id_ri = new DerObjectIdentifier("1.3.6.1.5.5.7.16"); + + public static readonly DerObjectIdentifier id_ri_ocsp_response = id_ri.Branch("2"); + public static readonly DerObjectIdentifier id_ri_scvp = id_ri.Branch("4"); + } +} diff --git a/crypto/src/asn1/cms/CompressedData.cs b/crypto/src/asn1/cms/CompressedData.cs new file mode 100644 index 000000000..5a2869b8c --- /dev/null +++ b/crypto/src/asn1/cms/CompressedData.cs @@ -0,0 +1,96 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * RFC 3274 - CMS Compressed Data. + *
+     * CompressedData ::= Sequence {
+     *  version CMSVersion,
+     *  compressionAlgorithm CompressionAlgorithmIdentifier,
+     *  encapContentInfo EncapsulatedContentInfo
+     * }
+     * 
+ */ + public class CompressedData + : Asn1Encodable + { + private DerInteger version; + private AlgorithmIdentifier compressionAlgorithm; + private ContentInfo encapContentInfo; + + public CompressedData( + AlgorithmIdentifier compressionAlgorithm, + ContentInfo encapContentInfo) + { + this.version = new DerInteger(0); + this.compressionAlgorithm = compressionAlgorithm; + this.encapContentInfo = encapContentInfo; + } + + public CompressedData( + Asn1Sequence seq) + { + this.version = (DerInteger) seq[0]; + this.compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + this.encapContentInfo = ContentInfo.GetInstance(seq[2]); + } + + /** + * return a CompressedData object from a tagged object. + * + * @param ato the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static CompressedData GetInstance( + Asn1TaggedObject ato, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(ato, explicitly)); + } + + /** + * return a CompressedData object from the given object. + * + * @param _obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static CompressedData GetInstance( + object obj) + { + if (obj == null || obj is CompressedData) + return (CompressedData)obj; + + if (obj is Asn1Sequence) + return new CompressedData((Asn1Sequence) obj); + + throw new ArgumentException("Invalid CompressedData: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public AlgorithmIdentifier CompressionAlgorithmIdentifier + { + get { return compressionAlgorithm; } + } + + public ContentInfo EncapContentInfo + { + get { return encapContentInfo; } + } + + public override Asn1Object ToAsn1Object() + { + return new BerSequence(version, compressionAlgorithm, encapContentInfo); + } + } +} diff --git a/crypto/src/asn1/cms/CompressedDataParser.cs b/crypto/src/asn1/cms/CompressedDataParser.cs new file mode 100644 index 000000000..7c53453df --- /dev/null +++ b/crypto/src/asn1/cms/CompressedDataParser.cs @@ -0,0 +1,47 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * RFC 3274 - CMS Compressed Data. + *
+	* CompressedData ::= SEQUENCE {
+	*  version CMSVersion,
+	*  compressionAlgorithm CompressionAlgorithmIdentifier,
+	*  encapContentInfo EncapsulatedContentInfo
+	* }
+	* 
+ */ + public class CompressedDataParser + { + private DerInteger _version; + private AlgorithmIdentifier _compressionAlgorithm; + private ContentInfoParser _encapContentInfo; + + public CompressedDataParser( + Asn1SequenceParser seq) + { + this._version = (DerInteger)seq.ReadObject(); + this._compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object()); + this._encapContentInfo = new ContentInfoParser((Asn1SequenceParser)seq.ReadObject()); + } + + public DerInteger Version + { + get { return _version; } + } + + public AlgorithmIdentifier CompressionAlgorithmIdentifier + { + get { return _compressionAlgorithm; } + } + + public ContentInfoParser GetEncapContentInfo() + { + return _encapContentInfo; + } + } +} diff --git a/crypto/src/asn1/cms/ContentInfo.cs b/crypto/src/asn1/cms/ContentInfo.cs new file mode 100644 index 000000000..278ceca46 --- /dev/null +++ b/crypto/src/asn1/cms/ContentInfo.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class ContentInfo + : Asn1Encodable + { + private readonly DerObjectIdentifier contentType; + private readonly Asn1Encodable content; + + public static ContentInfo GetInstance( + object obj) + { + if (obj == null || obj is ContentInfo) + return (ContentInfo) obj; + + if (obj is Asn1Sequence) + return new ContentInfo((Asn1Sequence) obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name); + } + + public static ContentInfo GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + private ContentInfo( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + contentType = (DerObjectIdentifier) seq[0]; + + if (seq.Count > 1) + { + Asn1TaggedObject tagged = (Asn1TaggedObject) seq[1]; + if (!tagged.IsExplicit() || tagged.TagNo != 0) + throw new ArgumentException("Bad tag for 'content'", "seq"); + + content = tagged.GetObject(); + } + } + + public ContentInfo( + DerObjectIdentifier contentType, + Asn1Encodable content) + { + this.contentType = contentType; + this.content = content; + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public Asn1Encodable Content + { + get { return content; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ContentInfo ::= Sequence {
+         *          contentType ContentType,
+         *          content
+         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(contentType); + + if (content != null) + { + v.Add(new BerTaggedObject(0, content)); + } + + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/ContentInfoParser.cs b/crypto/src/asn1/cms/ContentInfoParser.cs new file mode 100644 index 000000000..541cc0f59 --- /dev/null +++ b/crypto/src/asn1/cms/ContentInfoParser.cs @@ -0,0 +1,40 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * Produce an object suitable for an Asn1OutputStream. + *
+	* ContentInfo ::= SEQUENCE {
+	*          contentType ContentType,
+	*          content
+	*          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+	* 
+ */ + public class ContentInfoParser + { + private DerObjectIdentifier contentType; + private Asn1TaggedObjectParser content; + + public ContentInfoParser( + Asn1SequenceParser seq) + { + contentType = (DerObjectIdentifier)seq.ReadObject(); + content = (Asn1TaggedObjectParser)seq.ReadObject(); + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public IAsn1Convertible GetContent( + int tag) + { + if (content == null) + return null; + + return content.GetObjectParser(tag, true); + } + } +} diff --git a/crypto/src/asn1/cms/EncryptedContentInfo.cs b/crypto/src/asn1/cms/EncryptedContentInfo.cs new file mode 100644 index 000000000..4fdc47138 --- /dev/null +++ b/crypto/src/asn1/cms/EncryptedContentInfo.cs @@ -0,0 +1,94 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class EncryptedContentInfo + : Asn1Encodable + { + private DerObjectIdentifier contentType; + private AlgorithmIdentifier contentEncryptionAlgorithm; + private Asn1OctetString encryptedContent; + + public EncryptedContentInfo( + DerObjectIdentifier contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + Asn1OctetString encryptedContent) + { + this.contentType = contentType; + this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; + this.encryptedContent = encryptedContent; + } + + public EncryptedContentInfo( + Asn1Sequence seq) + { + contentType = (DerObjectIdentifier) seq[0]; + contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + + if (seq.Count > 2) + { + encryptedContent = Asn1OctetString.GetInstance( + (Asn1TaggedObject) seq[2], false); + } + } + + /** + * return an EncryptedContentInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static EncryptedContentInfo GetInstance( + object obj) + { + if (obj == null || obj is EncryptedContentInfo) + return (EncryptedContentInfo)obj; + + if (obj is Asn1Sequence) + return new EncryptedContentInfo((Asn1Sequence)obj); + + throw new ArgumentException("Invalid EncryptedContentInfo: " + obj.GetType().Name); + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public AlgorithmIdentifier ContentEncryptionAlgorithm + { + get { return contentEncryptionAlgorithm; } + } + + public Asn1OctetString EncryptedContent + { + get { return encryptedContent; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * EncryptedContentInfo ::= Sequence {
+         *     contentType ContentType,
+         *     contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+         *     encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + contentType, contentEncryptionAlgorithm); + + if (encryptedContent != null) + { + v.Add(new BerTaggedObject(false, 0, encryptedContent)); + } + + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/EncryptedContentInfoParser.cs b/crypto/src/asn1/cms/EncryptedContentInfoParser.cs new file mode 100644 index 000000000..af748b1b3 --- /dev/null +++ b/crypto/src/asn1/cms/EncryptedContentInfoParser.cs @@ -0,0 +1,46 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + *
+	* EncryptedContentInfo ::= SEQUENCE {
+	*     contentType ContentType,
+	*     contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+	*     encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+	* }
+	* 
+ */ + public class EncryptedContentInfoParser + { + private DerObjectIdentifier _contentType; + private AlgorithmIdentifier _contentEncryptionAlgorithm; + private Asn1TaggedObjectParser _encryptedContent; + + public EncryptedContentInfoParser( + Asn1SequenceParser seq) + { + _contentType = (DerObjectIdentifier)seq.ReadObject(); + _contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object()); + _encryptedContent = (Asn1TaggedObjectParser)seq.ReadObject(); + } + + public DerObjectIdentifier ContentType + { + get { return _contentType; } + } + + public AlgorithmIdentifier ContentEncryptionAlgorithm + { + get { return _contentEncryptionAlgorithm; } + } + + public IAsn1Convertible GetEncryptedContent( + int tag) + { + return _encryptedContent.GetObjectParser(tag, false); + } + } +} diff --git a/crypto/src/asn1/cms/EncryptedData.cs b/crypto/src/asn1/cms/EncryptedData.cs new file mode 100644 index 000000000..5b8378282 --- /dev/null +++ b/crypto/src/asn1/cms/EncryptedData.cs @@ -0,0 +1,95 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class EncryptedData + : Asn1Encodable + { + private readonly DerInteger version; + private readonly EncryptedContentInfo encryptedContentInfo; + private readonly Asn1Set unprotectedAttrs; + + public static EncryptedData GetInstance( + object obj) + { + if (obj is EncryptedData) + return (EncryptedData) obj; + + if (obj is Asn1Sequence) + return new EncryptedData((Asn1Sequence) obj); + + throw new ArgumentException("Invalid EncryptedData: " + obj.GetType().Name); + } + + public EncryptedData( + EncryptedContentInfo encInfo) + : this(encInfo, null) + { + } + + public EncryptedData( + EncryptedContentInfo encInfo, + Asn1Set unprotectedAttrs) + { + if (encInfo == null) + throw new ArgumentNullException("encInfo"); + + this.version = new DerInteger((unprotectedAttrs == null) ? 0 : 2); + this.encryptedContentInfo = encInfo; + this.unprotectedAttrs = unprotectedAttrs; + } + + private EncryptedData( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 2 || seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.version = DerInteger.GetInstance(seq[0]); + this.encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[1]); + + if (seq.Count > 2) + { + this.unprotectedAttrs = Asn1Set.GetInstance(seq[2]); + } + } + + public virtual DerInteger Version + { + get { return version; } + } + + public virtual EncryptedContentInfo EncryptedContentInfo + { + get { return encryptedContentInfo; } + } + + public virtual Asn1Set UnprotectedAttrs + { + get { return unprotectedAttrs; } + } + + /** + *
+		*       EncryptedData ::= SEQUENCE {
+		*                     version CMSVersion,
+		*                     encryptedContentInfo EncryptedContentInfo,
+		*                     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+		* 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version, encryptedContentInfo); + + if (unprotectedAttrs != null) + { + v.Add(new BerTaggedObject(false, 1, unprotectedAttrs)); + } + + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/EnvelopedData.cs b/crypto/src/asn1/cms/EnvelopedData.cs new file mode 100644 index 000000000..09f291a93 --- /dev/null +++ b/crypto/src/asn1/cms/EnvelopedData.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class EnvelopedData + : Asn1Encodable + { + private DerInteger version; + private OriginatorInfo originatorInfo; + private Asn1Set recipientInfos; + private EncryptedContentInfo encryptedContentInfo; + private Asn1Set unprotectedAttrs; + + public EnvelopedData( + OriginatorInfo originatorInfo, + Asn1Set recipientInfos, + EncryptedContentInfo encryptedContentInfo, + Asn1Set unprotectedAttrs) + { + this.version = new DerInteger(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) + { + this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, Asn1Set.GetInstance(unprotectedAttrs))); + this.originatorInfo = originatorInfo; + this.recipientInfos = recipientInfos; + this.encryptedContentInfo = encryptedContentInfo; + this.unprotectedAttrs = Asn1Set.GetInstance(unprotectedAttrs); + } + + [Obsolete("Use 'GetInstance' instead")] + public EnvelopedData( + Asn1Sequence seq) + { + int index = 0; + + version = (DerInteger) seq[index++]; + + object tmp = seq[index++]; + + if (tmp is Asn1TaggedObject) + { + originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject) tmp, false); + tmp = seq[index++]; + } + + recipientInfos = Asn1Set.GetInstance(tmp); + encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[index++]); + + if (seq.Count > index) + { + unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject) seq[index], false); + } + } + + /** + * return an EnvelopedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static EnvelopedData GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return an EnvelopedData object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static EnvelopedData GetInstance( + object obj) + { + if (obj is EnvelopedData) + return (EnvelopedData)obj; + if (obj == null) + return null; + return new EnvelopedData(Asn1Sequence.GetInstance(obj)); + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorInfo OriginatorInfo + { + get { return originatorInfo; } + } + + public Asn1Set RecipientInfos + { + get { return recipientInfos; } + } + + public EncryptedContentInfo EncryptedContentInfo + { + get { return encryptedContentInfo; } + } + + public Asn1Set UnprotectedAttrs + { + get { return unprotectedAttrs; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * EnvelopedData ::= Sequence {
+         *     version CMSVersion,
+         *     originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+         *     recipientInfos RecipientInfos,
+         *     encryptedContentInfo EncryptedContentInfo,
+         *     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version); + + if (originatorInfo != null) + { + v.Add(new DerTaggedObject(false, 0, originatorInfo)); + } + + v.Add(recipientInfos, 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) + { + if (originatorInfo != null || unprotectedAttrs != null) + { + return 2; + } + + foreach (object o in recipientInfos) + { + RecipientInfo ri = RecipientInfo.GetInstance(o); + + if (ri.Version.Value.IntValue != 0) + { + return 2; + } + } + + return 0; + } + } +} diff --git a/crypto/src/asn1/cms/EnvelopedDataParser.cs b/crypto/src/asn1/cms/EnvelopedDataParser.cs new file mode 100644 index 000000000..599353791 --- /dev/null +++ b/crypto/src/asn1/cms/EnvelopedDataParser.cs @@ -0,0 +1,107 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * Produce an object suitable for an Asn1OutputStream. + *
+	* EnvelopedData ::= SEQUENCE {
+	*     version CMSVersion,
+	*     originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+	*     recipientInfos RecipientInfos,
+	*     encryptedContentInfo EncryptedContentInfo,
+	*     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+	* }
+	* 
+ */ + public class EnvelopedDataParser + { + private Asn1SequenceParser _seq; + private DerInteger _version; + private IAsn1Convertible _nextObject; + private bool _originatorInfoCalled; + + public EnvelopedDataParser( + Asn1SequenceParser seq) + { + this._seq = seq; + this._version = (DerInteger)seq.ReadObject(); + } + + public DerInteger Version + { + get { return _version; } + } + + public OriginatorInfo GetOriginatorInfo() + { + _originatorInfoCalled = true; + + if (_nextObject == null) + { + _nextObject = _seq.ReadObject(); + } + + if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0) + { + Asn1SequenceParser originatorInfo = (Asn1SequenceParser) + ((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Sequence, false); + _nextObject = null; + return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object()); + } + + return null; + } + + public Asn1SetParser GetRecipientInfos() + { + if (!_originatorInfoCalled) + { + GetOriginatorInfo(); + } + + if (_nextObject == null) + { + _nextObject = _seq.ReadObject(); + } + + Asn1SetParser recipientInfos = (Asn1SetParser)_nextObject; + _nextObject = null; + return recipientInfos; + } + + public EncryptedContentInfoParser GetEncryptedContentInfo() + { + if (_nextObject == null) + { + _nextObject = _seq.ReadObject(); + } + + if (_nextObject != null) + { + Asn1SequenceParser o = (Asn1SequenceParser) _nextObject; + _nextObject = null; + return new EncryptedContentInfoParser(o); + } + + return null; + } + + public Asn1SetParser GetUnprotectedAttrs() + { + if (_nextObject == null) + { + _nextObject = _seq.ReadObject(); + } + + if (_nextObject != null) + { + IAsn1Convertible o = _nextObject; + _nextObject = null; + return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false); + } + + return null; + } + } +} diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs new file mode 100644 index 000000000..4745e565b --- /dev/null +++ b/crypto/src/asn1/cms/Evidence.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class Evidence + : Asn1Encodable, IAsn1Choice + { + private TimeStampTokenEvidence tstEvidence; + + public Evidence(TimeStampTokenEvidence tstEvidence) + { + this.tstEvidence = tstEvidence; + } + + private Evidence(Asn1TaggedObject tagged) + { + if (tagged.TagNo == 0) + { + this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false); + } + } + + public static Evidence GetInstance(object obj) + { + if (obj is Evidence) + return (Evidence)obj; + + if (obj is Asn1TaggedObject) + return new Evidence(Asn1TaggedObject.GetInstance(obj)); + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public virtual TimeStampTokenEvidence TstEvidence + { + get { return tstEvidence; } + } + + public override Asn1Object ToAsn1Object() + { + if (tstEvidence != null) + return new DerTaggedObject(false, 0, tstEvidence); + + return null; + } + } +} diff --git a/crypto/src/asn1/cms/IssuerAndSerialNumber.cs b/crypto/src/asn1/cms/IssuerAndSerialNumber.cs new file mode 100644 index 000000000..b509e7e19 --- /dev/null +++ b/crypto/src/asn1/cms/IssuerAndSerialNumber.cs @@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class IssuerAndSerialNumber + : Asn1Encodable + { + private X509Name name; + private DerInteger serialNumber; + + public static IssuerAndSerialNumber GetInstance(object obj) + { + if (obj == null) + return null; + IssuerAndSerialNumber existing = obj as IssuerAndSerialNumber; + if (existing != null) + return existing; + return new IssuerAndSerialNumber(Asn1Sequence.GetInstance(obj)); + } + + [Obsolete("Use GetInstance() instead")] + public IssuerAndSerialNumber( + Asn1Sequence seq) + { + this.name = X509Name.GetInstance(seq[0]); + this.serialNumber = (DerInteger) seq[1]; + } + + public IssuerAndSerialNumber( + X509Name name, + BigInteger serialNumber) + { + this.name = name; + this.serialNumber = new DerInteger(serialNumber); + } + + public IssuerAndSerialNumber( + X509Name name, + DerInteger serialNumber) + { + this.name = name; + this.serialNumber = serialNumber; + } + + public X509Name Name + { + get { return name; } + } + + public DerInteger SerialNumber + { + get { return serialNumber; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(name, serialNumber); + } + } +} diff --git a/crypto/src/asn1/cms/KEKIdentifier.cs b/crypto/src/asn1/cms/KEKIdentifier.cs new file mode 100644 index 000000000..e5d1d9090 --- /dev/null +++ b/crypto/src/asn1/cms/KEKIdentifier.cs @@ -0,0 +1,119 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class KekIdentifier + : Asn1Encodable + { + private Asn1OctetString keyIdentifier; + private DerGeneralizedTime date; + private OtherKeyAttribute other; + + public KekIdentifier( + byte[] keyIdentifier, + DerGeneralizedTime date, + OtherKeyAttribute other) + { + this.keyIdentifier = new DerOctetString(keyIdentifier); + this.date = date; + this.other = other; + } + + public KekIdentifier( + Asn1Sequence seq) + { + keyIdentifier = (Asn1OctetString) seq[0]; + + switch (seq.Count) + { + case 1: + break; + case 2: + if (seq[1] is DerGeneralizedTime) + { + date = (DerGeneralizedTime) seq[1]; + } + else + { + other = OtherKeyAttribute.GetInstance(seq[2]); + } + break; + case 3: + date = (DerGeneralizedTime) seq[1]; + other = OtherKeyAttribute.GetInstance(seq[2]); + break; + default: + throw new ArgumentException("Invalid KekIdentifier"); + } + } + + /** + * return a KekIdentifier object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KekIdentifier GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return a KekIdentifier object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static KekIdentifier GetInstance( + object obj) + { + if (obj == null || obj is KekIdentifier) + return (KekIdentifier)obj; + + if (obj is Asn1Sequence) + return new KekIdentifier((Asn1Sequence)obj); + + throw new ArgumentException("Invalid KekIdentifier: " + obj.GetType().Name); + } + + public Asn1OctetString KeyIdentifier + { + get { return keyIdentifier; } + } + + public DerGeneralizedTime Date + { + get { return date; } + } + + public OtherKeyAttribute Other + { + get { return other; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * KekIdentifier ::= Sequence {
+         *     keyIdentifier OCTET STRING,
+         *     date GeneralizedTime OPTIONAL,
+         *     other OtherKeyAttribute OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(keyIdentifier); + v.AddOptional(date, other); + return new DerSequence(v); + } + } +} + diff --git a/crypto/src/asn1/cms/KEKRecipientInfo.cs b/crypto/src/asn1/cms/KEKRecipientInfo.cs new file mode 100644 index 000000000..d847b50cc --- /dev/null +++ b/crypto/src/asn1/cms/KEKRecipientInfo.cs @@ -0,0 +1,106 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class KekRecipientInfo + : Asn1Encodable + { + private DerInteger version; + private KekIdentifier kekID; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private Asn1OctetString encryptedKey; + + public KekRecipientInfo( + KekIdentifier kekID, + AlgorithmIdentifier keyEncryptionAlgorithm, + Asn1OctetString encryptedKey) + { + this.version = new DerInteger(4); + this.kekID = kekID; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public KekRecipientInfo( + Asn1Sequence seq) + { + version = (DerInteger) seq[0]; + kekID = KekIdentifier.GetInstance(seq[1]); + keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); + encryptedKey = (Asn1OctetString) seq[3]; + } + + /** + * return a KekRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KekRecipientInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return a KekRecipientInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static KekRecipientInfo GetInstance( + object obj) + { + if (obj == null || obj is KekRecipientInfo) + return (KekRecipientInfo)obj; + + if(obj is Asn1Sequence) + return new KekRecipientInfo((Asn1Sequence)obj); + + throw new ArgumentException("Invalid KekRecipientInfo: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public KekIdentifier KekID + { + get { return kekID; } + } + + public AlgorithmIdentifier KeyEncryptionAlgorithm + { + get { return keyEncryptionAlgorithm; } + } + + public Asn1OctetString EncryptedKey + { + get { return encryptedKey; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * KekRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 4
+         *     kekID KekIdentifier,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     encryptedKey EncryptedKey
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(version, kekID, keyEncryptionAlgorithm, encryptedKey); + } + } +} diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs new file mode 100644 index 000000000..fa6fdb0f3 --- /dev/null +++ b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs @@ -0,0 +1,92 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class KeyAgreeRecipientIdentifier + : Asn1Encodable, IAsn1Choice + { + /** + * return an KeyAgreeRecipientIdentifier object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KeyAgreeRecipientIdentifier GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return an KeyAgreeRecipientIdentifier object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static KeyAgreeRecipientIdentifier GetInstance( + object obj) + { + if (obj == null || obj is KeyAgreeRecipientIdentifier) + return (KeyAgreeRecipientIdentifier)obj; + + if (obj is Asn1Sequence) + return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.GetInstance(obj)); + + if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 0) + { + return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.GetInstance( + (Asn1TaggedObject)obj, false)); + } + + throw new ArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.GetType().FullName, "obj"); + } + + private readonly IssuerAndSerialNumber issuerSerial; + private readonly RecipientKeyIdentifier rKeyID; + + public KeyAgreeRecipientIdentifier( + IssuerAndSerialNumber issuerSerial) + { + this.issuerSerial = issuerSerial; + } + + public KeyAgreeRecipientIdentifier( + RecipientKeyIdentifier rKeyID) + { + this.rKeyID = rKeyID; + } + + public IssuerAndSerialNumber IssuerAndSerialNumber + { + get { return issuerSerial; } + } + + public RecipientKeyIdentifier RKeyID + { + get { return rKeyID; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 * KeyAgreeRecipientIdentifier ::= CHOICE {
+		 *     issuerAndSerialNumber IssuerAndSerialNumber,
+		 *     rKeyId [0] IMPLICIT RecipientKeyIdentifier
+		 * }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + if (issuerSerial != null) + { + return issuerSerial.ToAsn1Object(); + } + + return new DerTaggedObject(false, 0, rKeyID); + } + } +} diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs new file mode 100644 index 000000000..aafb008d4 --- /dev/null +++ b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs @@ -0,0 +1,141 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class KeyAgreeRecipientInfo + : Asn1Encodable + { + private DerInteger 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 DerInteger(3); + this.originator = originator; + this.ukm = ukm; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.recipientEncryptedKeys = recipientEncryptedKeys; + } + + public KeyAgreeRecipientInfo( + Asn1Sequence seq) + { + int index = 0; + + version = (DerInteger) seq[index++]; + originator = OriginatorIdentifierOrKey.GetInstance( + (Asn1TaggedObject) seq[index++], true); + + if (seq[index] is Asn1TaggedObject) + { + ukm = Asn1OctetString.GetInstance( + (Asn1TaggedObject) seq[index++], true); + } + + keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance( + seq[index++]); + + recipientEncryptedKeys = (Asn1Sequence) seq[index++]; + } + + /** + * return a KeyAgreeRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KeyAgreeRecipientInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return a KeyAgreeRecipientInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static KeyAgreeRecipientInfo GetInstance( + object obj) + { + if (obj == null || obj is KeyAgreeRecipientInfo) + return (KeyAgreeRecipientInfo)obj; + + if (obj is Asn1Sequence) + return new KeyAgreeRecipientInfo((Asn1Sequence)obj); + + throw new ArgumentException( + "Illegal object in KeyAgreeRecipientInfo: " + obj.GetType().Name); + + } + + public DerInteger Version + { + get { return version; } + } + + public OriginatorIdentifierOrKey Originator + { + get { return originator; } + } + + public Asn1OctetString UserKeyingMaterial + { + get { return ukm; } + } + + public AlgorithmIdentifier KeyEncryptionAlgorithm + { + get { return keyEncryptionAlgorithm; } + } + + public Asn1Sequence RecipientEncryptedKeys + { + get { return recipientEncryptedKeys; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * KeyAgreeRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 3
+         *     originator [0] EXPLICIT OriginatorIdentifierOrKey,
+         *     ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     recipientEncryptedKeys RecipientEncryptedKeys
+         * }
+		 *
+		 * UserKeyingMaterial ::= OCTET STRING
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, new DerTaggedObject(true, 0, originator)); + + if (ukm != null) + { + v.Add(new DerTaggedObject(true, 1, ukm)); + } + + v.Add(keyEncryptionAlgorithm, recipientEncryptedKeys); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/KeyTransRecipientInfo.cs b/crypto/src/asn1/cms/KeyTransRecipientInfo.cs new file mode 100644 index 000000000..aae18c59d --- /dev/null +++ b/crypto/src/asn1/cms/KeyTransRecipientInfo.cs @@ -0,0 +1,99 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class KeyTransRecipientInfo + : Asn1Encodable + { + private DerInteger version; + private RecipientIdentifier rid; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private Asn1OctetString encryptedKey; + + public KeyTransRecipientInfo( + RecipientIdentifier rid, + AlgorithmIdentifier keyEncryptionAlgorithm, + Asn1OctetString encryptedKey) + { + if (rid.ToAsn1Object() is Asn1TaggedObject) + { + this.version = new DerInteger(2); + } + else + { + this.version = new DerInteger(0); + } + + this.rid = rid; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public KeyTransRecipientInfo( + Asn1Sequence seq) + { + this.version = (DerInteger) seq[0]; + this.rid = RecipientIdentifier.GetInstance(seq[1]); + this.keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); + this.encryptedKey = (Asn1OctetString) seq[3]; + } + + /** + * return a KeyTransRecipientInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static KeyTransRecipientInfo GetInstance( + object obj) + { + if (obj == null || obj is KeyTransRecipientInfo) + return (KeyTransRecipientInfo) obj; + + if(obj is Asn1Sequence) + return new KeyTransRecipientInfo((Asn1Sequence) obj); + + throw new ArgumentException( + "Illegal object in KeyTransRecipientInfo: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public RecipientIdentifier RecipientIdentifier + { + get { return rid; } + } + + public AlgorithmIdentifier KeyEncryptionAlgorithm + { + get { return keyEncryptionAlgorithm; } + } + + public Asn1OctetString EncryptedKey + { + get { return encryptedKey; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * KeyTransRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 0 or 2
+         *     rid RecipientIdentifier,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     encryptedKey EncryptedKey
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(version, rid, keyEncryptionAlgorithm, encryptedKey); + } + } +} diff --git a/crypto/src/asn1/cms/MetaData.cs b/crypto/src/asn1/cms/MetaData.cs new file mode 100644 index 000000000..ad2b5c426 --- /dev/null +++ b/crypto/src/asn1/cms/MetaData.cs @@ -0,0 +1,94 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class MetaData + : Asn1Encodable + { + private DerBoolean hashProtected; + private DerUtf8String fileName; + private DerIA5String mediaType; + private Attributes otherMetaData; + + public MetaData( + DerBoolean 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 = DerBoolean.GetInstance(seq[0]); + + int index = 1; + + if (index < seq.Count && seq[index] is DerUtf8String) + { + this.fileName = DerUtf8String.GetInstance(seq[index++]); + } + if (index < seq.Count && seq[index] is DerIA5String) + { + this.mediaType = DerIA5String.GetInstance(seq[index++]); + } + if (index < seq.Count) + { + this.otherMetaData = Attributes.GetInstance(seq[index++]); + } + } + + public static MetaData GetInstance(object obj) + { + if (obj is MetaData) + return (MetaData)obj; + + if (obj != null) + return new MetaData(Asn1Sequence.GetInstance(obj)); + + return null; + } + + /** + *
+		 * MetaData ::= SEQUENCE {
+		 *   hashProtected        BOOLEAN,
+		 *   fileName             UTF8String OPTIONAL,
+		 *   mediaType            IA5String OPTIONAL,
+		 *   otherMetaData        Attributes OPTIONAL
+		 * }
+		 * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(hashProtected); + v.AddOptional(fileName, mediaType, otherMetaData); + return new DerSequence(v); + } + + public virtual bool IsHashProtected + { + get { return hashProtected.IsTrue; } + } + + public virtual DerUtf8String FileName + { + get { return fileName; } + } + + public virtual DerIA5String MediaType + { + get { return mediaType; } + } + + public virtual Attributes OtherMetaData + { + get { return otherMetaData; } + } + } +} diff --git a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs new file mode 100644 index 000000000..d33a11725 --- /dev/null +++ b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs @@ -0,0 +1,168 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OriginatorIdentifierOrKey + : Asn1Encodable, IAsn1Choice + { + private Asn1Encodable id; + + public OriginatorIdentifierOrKey( + IssuerAndSerialNumber id) + { + this.id = id; + } + + [Obsolete("Use version taking a 'SubjectKeyIdentifier'")] + public OriginatorIdentifierOrKey( + Asn1OctetString id) + : this(new SubjectKeyIdentifier(id)) + { + } + + public OriginatorIdentifierOrKey( + SubjectKeyIdentifier id) + { + this.id = new DerTaggedObject(false, 0, id); + } + + public OriginatorIdentifierOrKey( + OriginatorPublicKey id) + { + this.id = new DerTaggedObject(false, 1, id); + } + + [Obsolete("Use more specific version")] + public OriginatorIdentifierOrKey( + Asn1Object id) + { + this.id = id; + } + + private OriginatorIdentifierOrKey( + Asn1TaggedObject id) + { + // TODO Add validation + this.id = id; + } + + /** + * return an OriginatorIdentifierOrKey object from a tagged object. + * + * @param o the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorIdentifierOrKey GetInstance( + Asn1TaggedObject o, + bool explicitly) + { + if (!explicitly) + { + throw new ArgumentException( + "Can't implicitly tag OriginatorIdentifierOrKey"); + } + + return GetInstance(o.GetObject()); + } + + /** + * return an OriginatorIdentifierOrKey object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static OriginatorIdentifierOrKey GetInstance( + object o) + { + if (o == null || o is OriginatorIdentifierOrKey) + return (OriginatorIdentifierOrKey)o; + + if (o is IssuerAndSerialNumber) + return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o); + + if (o is SubjectKeyIdentifier) + return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o); + + if (o is OriginatorPublicKey) + return new OriginatorIdentifierOrKey((OriginatorPublicKey)o); + + if (o is Asn1TaggedObject) + return new OriginatorIdentifierOrKey((Asn1TaggedObject)o); + + throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + o.GetType().Name); + } + + public Asn1Encodable ID + { + get { return id; } + } + + public IssuerAndSerialNumber IssuerAndSerialNumber + { + get + { + if (id is IssuerAndSerialNumber) + { + return (IssuerAndSerialNumber)id; + } + + return null; + } + } + + public SubjectKeyIdentifier SubjectKeyIdentifier + { + get + { + if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 0) + { + return SubjectKeyIdentifier.GetInstance((Asn1TaggedObject)id, false); + } + + return null; + } + } + + [Obsolete("Use 'OriginatorPublicKey' property")] + public OriginatorPublicKey OriginatorKey + { + get { return OriginatorPublicKey; } + } + + public OriginatorPublicKey OriginatorPublicKey + { + get + { + if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 1) + { + return OriginatorPublicKey.GetInstance((Asn1TaggedObject)id, false); + } + + return null; + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OriginatorIdentifierOrKey ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier,
+         *     originatorKey [1] OriginatorPublicKey
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return id.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/cms/OriginatorInfo.cs b/crypto/src/asn1/cms/OriginatorInfo.cs new file mode 100644 index 000000000..b4549bc36 --- /dev/null +++ b/crypto/src/asn1/cms/OriginatorInfo.cs @@ -0,0 +1,121 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OriginatorInfo + : Asn1Encodable + { + private Asn1Set certs; + private Asn1Set crls; + + public OriginatorInfo( + Asn1Set certs, + Asn1Set crls) + { + this.certs = certs; + this.crls = crls; + } + + public OriginatorInfo( + Asn1Sequence seq) + { + switch (seq.Count) + { + case 0: // empty + break; + case 1: + Asn1TaggedObject o = (Asn1TaggedObject) seq[0]; + switch (o.TagNo) + { + case 0 : + certs = Asn1Set.GetInstance(o, false); + break; + case 1 : + crls = Asn1Set.GetInstance(o, false); + break; + default: + throw new ArgumentException("Bad tag in OriginatorInfo: " + o.TagNo); + } + break; + case 2: + certs = Asn1Set.GetInstance((Asn1TaggedObject) seq[0], false); + crls = Asn1Set.GetInstance((Asn1TaggedObject) seq[1], false); + break; + default: + throw new ArgumentException("OriginatorInfo too big"); + } + } + + /** + * return an OriginatorInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return an OriginatorInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static OriginatorInfo GetInstance( + object obj) + { + if (obj == null || obj is OriginatorInfo) + return (OriginatorInfo)obj; + + if (obj is Asn1Sequence) + return new OriginatorInfo((Asn1Sequence)obj); + + throw new ArgumentException("Invalid OriginatorInfo: " + obj.GetType().Name); + } + + public Asn1Set Certificates + { + get { return certs; } + } + + public Asn1Set Crls + { + get { return crls; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OriginatorInfo ::= Sequence {
+         *     certs [0] IMPLICIT CertificateSet OPTIONAL,
+         *     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/cms/OriginatorPublicKey.cs b/crypto/src/asn1/cms/OriginatorPublicKey.cs new file mode 100644 index 000000000..aabaf4386 --- /dev/null +++ b/crypto/src/asn1/cms/OriginatorPublicKey.cs @@ -0,0 +1,87 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OriginatorPublicKey + : Asn1Encodable + { + private AlgorithmIdentifier algorithm; + private DerBitString publicKey; + + public OriginatorPublicKey( + AlgorithmIdentifier algorithm, + byte[] publicKey) + { + this.algorithm = algorithm; + this.publicKey = new DerBitString(publicKey); + } + + public OriginatorPublicKey( + Asn1Sequence seq) + { + algorithm = AlgorithmIdentifier.GetInstance(seq[0]); + publicKey = (DerBitString) seq[1]; + } + + /** + * return an OriginatorPublicKey object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorPublicKey GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return an OriginatorPublicKey object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static OriginatorPublicKey GetInstance( + object obj) + { + if (obj == null || obj is OriginatorPublicKey) + return (OriginatorPublicKey)obj; + + if (obj is Asn1Sequence) + return new OriginatorPublicKey((Asn1Sequence) obj); + + throw new ArgumentException("Invalid OriginatorPublicKey: " + obj.GetType().Name); + } + + public AlgorithmIdentifier Algorithm + { + get { return algorithm; } + } + + public DerBitString PublicKey + { + get { return publicKey; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OriginatorPublicKey ::= Sequence {
+         *     algorithm AlgorithmIdentifier,
+         *     publicKey BIT STRING
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algorithm, publicKey); + } + } +} diff --git a/crypto/src/asn1/cms/OtherKeyAttribute.cs b/crypto/src/asn1/cms/OtherKeyAttribute.cs new file mode 100644 index 000000000..271059175 --- /dev/null +++ b/crypto/src/asn1/cms/OtherKeyAttribute.cs @@ -0,0 +1,70 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OtherKeyAttribute + : Asn1Encodable + { + private DerObjectIdentifier keyAttrId; + private Asn1Encodable keyAttr; + + /** + * return an OtherKeyAttribute object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static OtherKeyAttribute GetInstance( + object obj) + { + if (obj == null || obj is OtherKeyAttribute) + return (OtherKeyAttribute) obj; + + if (obj is Asn1Sequence) + return new OtherKeyAttribute((Asn1Sequence) obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public OtherKeyAttribute( + Asn1Sequence seq) + { + keyAttrId = (DerObjectIdentifier) seq[0]; + keyAttr = seq[1]; + } + + public OtherKeyAttribute( + DerObjectIdentifier keyAttrId, + Asn1Encodable keyAttr) + { + this.keyAttrId = keyAttrId; + this.keyAttr = keyAttr; + } + + public DerObjectIdentifier KeyAttrId + { + get { return keyAttrId; } + } + + public Asn1Encodable KeyAttr + { + get { return keyAttr; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OtherKeyAttribute ::= Sequence {
+         *     keyAttrId OBJECT IDENTIFIER,
+         *     keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(keyAttrId, keyAttr); + } + } +} diff --git a/crypto/src/asn1/cms/OtherRecipientInfo.cs b/crypto/src/asn1/cms/OtherRecipientInfo.cs new file mode 100644 index 000000000..80dd68e7c --- /dev/null +++ b/crypto/src/asn1/cms/OtherRecipientInfo.cs @@ -0,0 +1,83 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OtherRecipientInfo + : Asn1Encodable + { + private readonly DerObjectIdentifier oriType; + private readonly Asn1Encodable oriValue; + + public OtherRecipientInfo( + DerObjectIdentifier oriType, + Asn1Encodable oriValue) + { + this.oriType = oriType; + this.oriValue = oriValue; + } + + [Obsolete("Use GetInstance() instead")] + public OtherRecipientInfo( + Asn1Sequence seq) + { + oriType = DerObjectIdentifier.GetInstance(seq[0]); + oriValue = seq[1]; + } + + /** + * return a OtherRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OtherRecipientInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return a OtherRecipientInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static OtherRecipientInfo GetInstance( + object obj) + { + if (obj == null) + return null; + OtherRecipientInfo existing = obj as OtherRecipientInfo; + if (existing != null) + return existing; + return new OtherRecipientInfo(Asn1Sequence.GetInstance(obj)); + } + + public virtual DerObjectIdentifier OriType + { + get { return oriType; } + } + + public virtual Asn1Encodable OriValue + { + get { return oriValue; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OtherRecipientInfo ::= Sequence {
+         *    oriType OBJECT IDENTIFIER,
+         *    oriValue ANY DEFINED BY oriType }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(oriType, oriValue); + } + } +} diff --git a/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs new file mode 100644 index 000000000..78354896f --- /dev/null +++ b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs @@ -0,0 +1,77 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class OtherRevocationInfoFormat + : Asn1Encodable + { + private readonly DerObjectIdentifier otherRevInfoFormat; + private readonly Asn1Encodable otherRevInfo; + + public OtherRevocationInfoFormat( + DerObjectIdentifier otherRevInfoFormat, + Asn1Encodable otherRevInfo) + { + this.otherRevInfoFormat = otherRevInfoFormat; + this.otherRevInfo = otherRevInfo; + } + + private OtherRevocationInfoFormat(Asn1Sequence seq) + { + otherRevInfoFormat = DerObjectIdentifier.GetInstance(seq[0]); + otherRevInfo = seq[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, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return a OtherRevocationInfoFormat object from the given object. + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OtherRevocationInfoFormat GetInstance(object obj) + { + if (obj is OtherRevocationInfoFormat) + return (OtherRevocationInfoFormat)obj; + if (obj != null) + return new OtherRevocationInfoFormat(Asn1Sequence.GetInstance(obj)); + return null; + } + + public virtual DerObjectIdentifier InfoFormat + { + get { return otherRevInfoFormat; } + } + + public virtual Asn1Encodable Info + { + get { return otherRevInfo; } + } + + /** + * Produce an object suitable for an ASN1OutputStream. + *
+         * OtherRevocationInfoFormat ::= SEQUENCE {
+         *      otherRevInfoFormat OBJECT IDENTIFIER,
+         *      otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(otherRevInfoFormat, otherRevInfo); + } + } +} diff --git a/crypto/src/asn1/cms/PasswordRecipientInfo.cs b/crypto/src/asn1/cms/PasswordRecipientInfo.cs new file mode 100644 index 000000000..800b57951 --- /dev/null +++ b/crypto/src/asn1/cms/PasswordRecipientInfo.cs @@ -0,0 +1,133 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class PasswordRecipientInfo + : Asn1Encodable + { + private readonly DerInteger version; + private readonly AlgorithmIdentifier keyDerivationAlgorithm; + private readonly AlgorithmIdentifier keyEncryptionAlgorithm; + private readonly Asn1OctetString encryptedKey; + + public PasswordRecipientInfo( + AlgorithmIdentifier keyEncryptionAlgorithm, + Asn1OctetString encryptedKey) + { + this.version = new DerInteger(0); + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public PasswordRecipientInfo( + AlgorithmIdentifier keyDerivationAlgorithm, + AlgorithmIdentifier keyEncryptionAlgorithm, + Asn1OctetString encryptedKey) + { + this.version = new DerInteger(0); + this.keyDerivationAlgorithm = keyDerivationAlgorithm; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public PasswordRecipientInfo( + Asn1Sequence seq) + { + version = (DerInteger) seq[0]; + + if (seq[1] is Asn1TaggedObject) + { + keyDerivationAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject) seq[1], false); + keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); + encryptedKey = (Asn1OctetString) seq[3]; + } + else + { + keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + encryptedKey = (Asn1OctetString) seq[2]; + } + } + + /** + * return a PasswordRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicitly true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static PasswordRecipientInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /** + * return a PasswordRecipientInfo object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static PasswordRecipientInfo GetInstance( + object obj) + { + if (obj == null || obj is PasswordRecipientInfo) + return (PasswordRecipientInfo) obj; + + if (obj is Asn1Sequence) + return new PasswordRecipientInfo((Asn1Sequence) obj); + + throw new ArgumentException("Invalid PasswordRecipientInfo: " + obj.GetType().Name); + } + + public DerInteger Version + { + get { return version; } + } + + public AlgorithmIdentifier KeyDerivationAlgorithm + { + get { return keyDerivationAlgorithm; } + } + + public AlgorithmIdentifier KeyEncryptionAlgorithm + { + get { return keyEncryptionAlgorithm; } + } + + public Asn1OctetString EncryptedKey + { + get { return encryptedKey; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * PasswordRecipientInfo ::= Sequence {
+         *   version CMSVersion,   -- Always set to 0
+         *   keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+         *                             OPTIONAL,
+         *  keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *  encryptedKey EncryptedKey }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version); + + if (keyDerivationAlgorithm != null) + { + v.Add(new DerTaggedObject(false, 0, keyDerivationAlgorithm)); + } + + v.Add(keyEncryptionAlgorithm, encryptedKey); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/RecipientEncryptedKey.cs b/crypto/src/asn1/cms/RecipientEncryptedKey.cs new file mode 100644 index 000000000..5ba25a742 --- /dev/null +++ b/crypto/src/asn1/cms/RecipientEncryptedKey.cs @@ -0,0 +1,88 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class RecipientEncryptedKey + : Asn1Encodable + { + private readonly KeyAgreeRecipientIdentifier identifier; + private readonly Asn1OctetString encryptedKey; + + private RecipientEncryptedKey( + Asn1Sequence seq) + { + identifier = KeyAgreeRecipientIdentifier.GetInstance(seq[0]); + encryptedKey = (Asn1OctetString) seq[1]; + } + + /** + * return an RecipientEncryptedKey object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static RecipientEncryptedKey GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return a RecipientEncryptedKey object from the given object. + * + * @param obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static RecipientEncryptedKey GetInstance( + object obj) + { + if (obj == null || obj is RecipientEncryptedKey) + { + return (RecipientEncryptedKey) obj; + } + + if (obj is Asn1Sequence) + { + return new RecipientEncryptedKey((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid RecipientEncryptedKey: " + obj.GetType().FullName, "obj"); + } + + public RecipientEncryptedKey( + KeyAgreeRecipientIdentifier id, + Asn1OctetString encryptedKey) + { + this.identifier = id; + this.encryptedKey = encryptedKey; + } + + public KeyAgreeRecipientIdentifier Identifier + { + get { return identifier; } + } + + public Asn1OctetString EncryptedKey + { + get { return encryptedKey; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 * RecipientEncryptedKey ::= SEQUENCE {
+		 *     rid KeyAgreeRecipientIdentifier,
+		 *     encryptedKey EncryptedKey
+		 * }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(identifier, encryptedKey); + } + } +} diff --git a/crypto/src/asn1/cms/RecipientIdentifier.cs b/crypto/src/asn1/cms/RecipientIdentifier.cs new file mode 100644 index 000000000..4982bc16a --- /dev/null +++ b/crypto/src/asn1/cms/RecipientIdentifier.cs @@ -0,0 +1,89 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class RecipientIdentifier + : Asn1Encodable, IAsn1Choice + { + private Asn1Encodable id; + + public RecipientIdentifier( + IssuerAndSerialNumber id) + { + this.id = id; + } + + public RecipientIdentifier( + Asn1OctetString id) + { + this.id = new DerTaggedObject(false, 0, id); + } + + public RecipientIdentifier( + Asn1Object id) + { + this.id = id; + } + + /** + * return a RecipientIdentifier object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static RecipientIdentifier GetInstance( + object o) + { + if (o == null || o is RecipientIdentifier) + return (RecipientIdentifier)o; + + if (o is IssuerAndSerialNumber) + return new RecipientIdentifier((IssuerAndSerialNumber) o); + + if (o is Asn1OctetString) + return new RecipientIdentifier((Asn1OctetString) o); + + if (o is Asn1Object) + return new RecipientIdentifier((Asn1Object) o); + + throw new ArgumentException( + "Illegal object in RecipientIdentifier: " + o.GetType().Name); + } + + public bool IsTagged + { + get { return (id is Asn1TaggedObject); } + } + + public Asn1Encodable ID + { + get + { + if (id is Asn1TaggedObject) + { + return Asn1OctetString.GetInstance((Asn1TaggedObject) id, false); + } + + return IssuerAndSerialNumber.GetInstance(id); + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * RecipientIdentifier ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return id.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/cms/RecipientInfo.cs b/crypto/src/asn1/cms/RecipientInfo.cs new file mode 100644 index 000000000..daaf5a5e4 --- /dev/null +++ b/crypto/src/asn1/cms/RecipientInfo.cs @@ -0,0 +1,145 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class RecipientInfo + : Asn1Encodable, IAsn1Choice + { + internal 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( + Asn1Object info) + { + this.info = info; + } + + public static RecipientInfo GetInstance( + object o) + { + if (o == null || o is RecipientInfo) + return (RecipientInfo) o; + + if (o is Asn1Sequence) + return new RecipientInfo((Asn1Sequence) o); + + if (o is Asn1TaggedObject) + return new RecipientInfo((Asn1TaggedObject) o); + + throw new ArgumentException("unknown object in factory: " + o.GetType().Name); + } + + public DerInteger Version + { + get + { + if (info is Asn1TaggedObject) + { + Asn1TaggedObject o = (Asn1TaggedObject) info; + + switch (o.TagNo) + { + case 1: + return KeyAgreeRecipientInfo.GetInstance(o, false).Version; + case 2: + return GetKekInfo(o).Version; + case 3: + return PasswordRecipientInfo.GetInstance(o, false).Version; + case 4: + return new DerInteger(0); // no syntax version for OtherRecipientInfo + default: + throw new InvalidOperationException("unknown tag"); + } + } + + return KeyTransRecipientInfo.GetInstance(info).Version; + } + } + + public bool IsTagged + { + get { return info is Asn1TaggedObject; } + } + + public Asn1Encodable Info + { + get + { + if (info is Asn1TaggedObject) + { + Asn1TaggedObject o = (Asn1TaggedObject) info; + + switch (o.TagNo) + { + 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 InvalidOperationException("unknown tag"); + } + } + + return KeyTransRecipientInfo.GetInstance(info); + } + } + + private KekRecipientInfo GetKekInfo( + Asn1TaggedObject o) + { + // For compatibility with erroneous version, we don't always pass 'false' here + return KekRecipientInfo.GetInstance(o, o.IsExplicit()); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * RecipientInfo ::= CHOICE {
+         *     ktri KeyTransRecipientInfo,
+         *     kari [1] KeyAgreeRecipientInfo,
+         *     kekri [2] KekRecipientInfo,
+         *     pwri [3] PasswordRecipientInfo,
+         *     ori [4] OtherRecipientInfo }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return info.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/cms/RecipientKeyIdentifier.cs b/crypto/src/asn1/cms/RecipientKeyIdentifier.cs new file mode 100644 index 000000000..f3e45644b --- /dev/null +++ b/crypto/src/asn1/cms/RecipientKeyIdentifier.cs @@ -0,0 +1,137 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class RecipientKeyIdentifier + : Asn1Encodable + { + private Asn1OctetString subjectKeyIdentifier; + private DerGeneralizedTime date; + private OtherKeyAttribute other; + + public RecipientKeyIdentifier( + Asn1OctetString subjectKeyIdentifier, + DerGeneralizedTime date, + OtherKeyAttribute other) + { + this.subjectKeyIdentifier = subjectKeyIdentifier; + this.date = date; + this.other = other; + } + + public RecipientKeyIdentifier( + byte[] subjectKeyIdentifier) + : this(subjectKeyIdentifier, null, null) + { + } + + public RecipientKeyIdentifier( + byte[] subjectKeyIdentifier, + DerGeneralizedTime date, + OtherKeyAttribute other) + { + this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier); + this.date = date; + this.other = other; + } + + public RecipientKeyIdentifier( + Asn1Sequence seq) + { + subjectKeyIdentifier = Asn1OctetString.GetInstance( + seq[0]); + + switch(seq.Count) + { + case 1: + break; + case 2: + if (seq[1] is DerGeneralizedTime) + { + date = (DerGeneralizedTime) seq[1]; + } + else + { + other = OtherKeyAttribute.GetInstance(seq[2]); + } + break; + case 3: + date = (DerGeneralizedTime) seq[1]; + other = OtherKeyAttribute.GetInstance(seq[2]); + break; + default: + throw new ArgumentException("Invalid RecipientKeyIdentifier"); + } + } + + /** + * return a RecipientKeyIdentifier object from a tagged object. + * + * @param _ato the tagged object holding the object we want. + * @param _explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static RecipientKeyIdentifier GetInstance( + Asn1TaggedObject ato, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(ato, explicitly)); + } + + /** + * return a RecipientKeyIdentifier object from the given object. + * + * @param _obj the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static RecipientKeyIdentifier GetInstance( + object obj) + { + if (obj == null || obj is RecipientKeyIdentifier) + return (RecipientKeyIdentifier) obj; + + if (obj is Asn1Sequence) + return new RecipientKeyIdentifier((Asn1Sequence) obj); + + throw new ArgumentException("Invalid RecipientKeyIdentifier: " + obj.GetType().Name); + } + + public Asn1OctetString SubjectKeyIdentifier + { + get { return subjectKeyIdentifier; } + } + + public DerGeneralizedTime Date + { + get { return date; } + } + + public OtherKeyAttribute OtherKeyAttribute + { + get { return other; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * RecipientKeyIdentifier ::= Sequence {
+         *     subjectKeyIdentifier SubjectKeyIdentifier,
+         *     date GeneralizedTime OPTIONAL,
+         *     other OtherKeyAttribute OPTIONAL
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(subjectKeyIdentifier); + v.AddOptional(date, other); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/SCVPReqRes.cs b/crypto/src/asn1/cms/SCVPReqRes.cs new file mode 100644 index 000000000..486979a29 --- /dev/null +++ b/crypto/src/asn1/cms/SCVPReqRes.cs @@ -0,0 +1,77 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class ScvpReqRes + : Asn1Encodable + { + private readonly ContentInfo request; + private readonly ContentInfo response; + + public static ScvpReqRes GetInstance(object obj) + { + if (obj is ScvpReqRes) + return (ScvpReqRes)obj; + if (obj != null) + return new ScvpReqRes(Asn1Sequence.GetInstance(obj)); + return null; + } + + private ScvpReqRes(Asn1Sequence seq) + { + if (seq[0] is Asn1TaggedObject) + { + this.request = ContentInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[0]), true); + this.response = ContentInfo.GetInstance(seq[1]); + } + else + { + this.request = null; + this.response = ContentInfo.GetInstance(seq[0]); + } + } + + public ScvpReqRes(ContentInfo response) + : this(null, response) + { + } + + public ScvpReqRes(ContentInfo request, ContentInfo response) + { + this.request = request; + this.response = response; + } + + public virtual ContentInfo Request + { + get { return request; } + } + + public virtual ContentInfo Response + { + get { return response; } + } + + /** + *
+         *    ScvpReqRes ::= SEQUENCE {
+         *    request  [0] EXPLICIT ContentInfo OPTIONAL,
+         *    response     ContentInfo }
+         * 
+ * @return the ASN.1 primitive representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (request != null) + { + v.Add(new DerTaggedObject(true, 0, request)); + } + + v.Add(response); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs new file mode 100644 index 000000000..6cea79a49 --- /dev/null +++ b/crypto/src/asn1/cms/SignedData.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + * a signed data object. + */ + public class SignedData + : Asn1Encodable + { + private static readonly DerInteger Version1 = new DerInteger(1); + private static readonly DerInteger Version3 = new DerInteger(3); + private static readonly DerInteger Version4 = new DerInteger(4); + private static readonly DerInteger Version5 = new DerInteger(5); + + private readonly DerInteger version; + private readonly Asn1Set digestAlgorithms; + private readonly ContentInfo contentInfo; + private readonly Asn1Set certificates; + private readonly Asn1Set crls; + private readonly Asn1Set signerInfos; + private readonly bool certsBer; + private readonly bool crlsBer; + + public static SignedData GetInstance( + object obj) + { + if (obj is SignedData) + return (SignedData) obj; + + if (obj is Asn1Sequence) + return new SignedData((Asn1Sequence) obj); + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public SignedData( + Asn1Set digestAlgorithms, + ContentInfo contentInfo, + Asn1Set certificates, + Asn1Set crls, + Asn1Set signerInfos) + { + this.version = CalculateVersion(contentInfo.ContentType, certificates, crls, signerInfos); + this.digestAlgorithms = digestAlgorithms; + this.contentInfo = contentInfo; + this.certificates = certificates; + this.crls = crls; + this.signerInfos = signerInfos; + this.crlsBer = crls is BerSet; + this.certsBer = certificates is BerSet; + } + + // RFC3852, section 5.1: + // IF ((certificates is present) AND + // (any certificates with a type of other are present)) OR + // ((crls is present) AND + // (any crls with a type of other are present)) + // THEN version MUST be 5 + // ELSE + // IF (certificates is present) AND + // (any version 2 attribute certificates are present) + // THEN version MUST be 4 + // ELSE + // IF ((certificates is present) AND + // (any version 1 attribute certificates are present)) OR + // (any SignerInfo structures are version 3) OR + // (encapContentInfo eContentType is other than id-data) + // THEN version MUST be 3 + // ELSE version MUST be 1 + // + private DerInteger CalculateVersion( + DerObjectIdentifier contentOid, + Asn1Set certs, + Asn1Set crls, + Asn1Set signerInfs) + { + bool otherCert = false; + bool otherCrl = false; + bool attrCertV1Found = false; + bool attrCertV2Found = false; + + if (certs != null) + { + foreach (object obj in certs) + { + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tagged = (Asn1TaggedObject)obj; + + if (tagged.TagNo == 1) + { + attrCertV1Found = true; + } + else if (tagged.TagNo == 2) + { + attrCertV2Found = true; + } + else if (tagged.TagNo == 3) + { + otherCert = true; + break; + } + } + } + } + + if (otherCert) + { + return Version5; + } + + if (crls != null) + { + foreach (object obj in crls) + { + if (obj is Asn1TaggedObject) + { + otherCrl = true; + break; + } + } + } + + if (otherCrl) + { + return Version5; + } + + if (attrCertV2Found) + { + return Version4; + } + + if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs)) + { + return Version3; + } + + return Version1; + } + + private bool CheckForVersion3( + Asn1Set signerInfs) + { + foreach (object obj in signerInfs) + { + SignerInfo s = SignerInfo.GetInstance(obj); + + if (s.Version.Value.IntValue == 3) + { + return true; + } + } + + return false; + } + + private SignedData( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + version = (DerInteger)e.Current; + + e.MoveNext(); + digestAlgorithms = ((Asn1Set)e.Current); + + e.MoveNext(); + contentInfo = ContentInfo.GetInstance(e.Current); + + while (e.MoveNext()) + { + Asn1Object o = (Asn1Object)e.Current; + + // + // 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 is Asn1TaggedObject) + { + Asn1TaggedObject tagged = (Asn1TaggedObject)o; + + switch (tagged.TagNo) + { + case 0: + certsBer = tagged is BerTaggedObject; + certificates = Asn1Set.GetInstance(tagged, false); + break; + case 1: + crlsBer = tagged is BerTaggedObject; + crls = Asn1Set.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("unknown tag value " + tagged.TagNo); + } + } + else + { + signerInfos = (Asn1Set) o; + } + } + } + + public DerInteger Version + { + get { return version; } + } + + public Asn1Set DigestAlgorithms + { + get { return digestAlgorithms; } + } + + public ContentInfo EncapContentInfo + { + get { return contentInfo; } + } + + public Asn1Set Certificates + { + get { return certificates; } + } + + public Asn1Set CRLs + { + get { return crls; } + } + + public Asn1Set SignerInfos + { + get { return signerInfos; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * SignedData ::= Sequence {
+         *     version CMSVersion,
+         *     digestAlgorithms DigestAlgorithmIdentifiers,
+         *     encapContentInfo EncapsulatedContentInfo,
+         *     certificates [0] IMPLICIT CertificateSet OPTIONAL,
+         *     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+         *     signerInfos SignerInfos
+         *   }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, digestAlgorithms, 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/crypto/src/asn1/cms/SignedDataParser.cs b/crypto/src/asn1/cms/SignedDataParser.cs new file mode 100644 index 000000000..341309263 --- /dev/null +++ b/crypto/src/asn1/cms/SignedDataParser.cs @@ -0,0 +1,112 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1.Cms +{ + /** + *
+	* SignedData ::= SEQUENCE {
+	*     version CMSVersion,
+	*     digestAlgorithms DigestAlgorithmIdentifiers,
+	*     encapContentInfo EncapsulatedContentInfo,
+	*     certificates [0] IMPLICIT CertificateSet OPTIONAL,
+	*     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+	*     signerInfos SignerInfos
+	*   }
+	* 
+ */ + public class SignedDataParser + { + private Asn1SequenceParser _seq; + private DerInteger _version; + private object _nextObject; + private bool _certsCalled; + private bool _crlsCalled; + + public static SignedDataParser GetInstance( + object o) + { + if (o is Asn1Sequence) + return new SignedDataParser(((Asn1Sequence)o).Parser); + + if (o is Asn1SequenceParser) + return new SignedDataParser((Asn1SequenceParser)o); + + throw new IOException("unknown object encountered: " + o.GetType().Name); + } + + public SignedDataParser( + Asn1SequenceParser seq) + { + this._seq = seq; + this._version = (DerInteger)seq.ReadObject(); + } + + public DerInteger Version + { + get { return _version; } + } + + public Asn1SetParser GetDigestAlgorithms() + { + return (Asn1SetParser)_seq.ReadObject(); + } + + public ContentInfoParser GetEncapContentInfo() + { + return new ContentInfoParser((Asn1SequenceParser)_seq.ReadObject()); + } + + public Asn1SetParser GetCertificates() + { + _certsCalled = true; + _nextObject = _seq.ReadObject(); + + if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0) + { + Asn1SetParser certs = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false); + _nextObject = null; + + return certs; + } + + return null; + } + + public Asn1SetParser GetCrls() + { + if (!_certsCalled) + throw new IOException("GetCerts() has not been called."); + + _crlsCalled = true; + + if (_nextObject == null) + { + _nextObject = _seq.ReadObject(); + } + + if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 1) + { + Asn1SetParser crls = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false); + _nextObject = null; + + return crls; + } + + return null; + } + + public Asn1SetParser GetSignerInfos() + { + 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/crypto/src/asn1/cms/SignerIdentifier.cs b/crypto/src/asn1/cms/SignerIdentifier.cs new file mode 100644 index 000000000..5742cee75 --- /dev/null +++ b/crypto/src/asn1/cms/SignerIdentifier.cs @@ -0,0 +1,89 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class SignerIdentifier + : Asn1Encodable, IAsn1Choice + { + private Asn1Encodable id; + + public SignerIdentifier( + IssuerAndSerialNumber id) + { + this.id = id; + } + + public SignerIdentifier( + Asn1OctetString id) + { + this.id = new DerTaggedObject(false, 0, id); + } + + public SignerIdentifier( + Asn1Object id) + { + this.id = id; + } + + /** + * return a SignerIdentifier object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static SignerIdentifier GetInstance( + object o) + { + if (o == null || o is SignerIdentifier) + return (SignerIdentifier) o; + + if (o is IssuerAndSerialNumber) + return new SignerIdentifier((IssuerAndSerialNumber) o); + + if (o is Asn1OctetString) + return new SignerIdentifier((Asn1OctetString) o); + + if (o is Asn1Object) + return new SignerIdentifier((Asn1Object) o); + + throw new ArgumentException( + "Illegal object in SignerIdentifier: " + o.GetType().Name); + } + + public bool IsTagged + { + get { return (id is Asn1TaggedObject); } + } + + public Asn1Encodable ID + { + get + { + if (id is Asn1TaggedObject) + { + return Asn1OctetString.GetInstance((Asn1TaggedObject)id, false); + } + + return id; + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * SignerIdentifier ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return id.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/cms/SignerInfo.cs b/crypto/src/asn1/cms/SignerInfo.cs new file mode 100644 index 000000000..a4e893d96 --- /dev/null +++ b/crypto/src/asn1/cms/SignerInfo.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class SignerInfo + : Asn1Encodable + { + private DerInteger version; + private SignerIdentifier sid; + private AlgorithmIdentifier digAlgorithm; + private Asn1Set authenticatedAttributes; + private AlgorithmIdentifier digEncryptionAlgorithm; + private Asn1OctetString encryptedDigest; + private Asn1Set unauthenticatedAttributes; + + public static SignerInfo GetInstance( + object obj) + { + if (obj == null || obj is SignerInfo) + return (SignerInfo) obj; + + if (obj is Asn1Sequence) + return new SignerInfo((Asn1Sequence) obj); + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public SignerInfo( + SignerIdentifier sid, + AlgorithmIdentifier digAlgorithm, + Asn1Set authenticatedAttributes, + AlgorithmIdentifier digEncryptionAlgorithm, + Asn1OctetString encryptedDigest, + Asn1Set unauthenticatedAttributes) + { + this.version = new DerInteger(sid.IsTagged ? 3 : 1); + this.sid = sid; + this.digAlgorithm = digAlgorithm; + this.authenticatedAttributes = authenticatedAttributes; + this.digEncryptionAlgorithm = digEncryptionAlgorithm; + this.encryptedDigest = encryptedDigest; + this.unauthenticatedAttributes = unauthenticatedAttributes; + } + + public SignerInfo( + SignerIdentifier sid, + AlgorithmIdentifier digAlgorithm, + Attributes authenticatedAttributes, + AlgorithmIdentifier digEncryptionAlgorithm, + Asn1OctetString encryptedDigest, + Attributes unauthenticatedAttributes) + { + this.version = new DerInteger(sid.IsTagged ? 3 : 1); + this.sid = sid; + this.digAlgorithm = digAlgorithm; + this.authenticatedAttributes = Asn1Set.GetInstance(authenticatedAttributes); + this.digEncryptionAlgorithm = digEncryptionAlgorithm; + this.encryptedDigest = encryptedDigest; + this.unauthenticatedAttributes = Asn1Set.GetInstance(unauthenticatedAttributes); + } + + [Obsolete("Use 'GetInstance' instead")] + public SignerInfo( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + version = (DerInteger) e.Current; + + e.MoveNext(); + sid = SignerIdentifier.GetInstance(e.Current); + + e.MoveNext(); + digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current); + + e.MoveNext(); + object obj = e.Current; + + if (obj is Asn1TaggedObject) + { + authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false); + + e.MoveNext(); + digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current); + } + else + { + authenticatedAttributes = null; + digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj); + } + + e.MoveNext(); + encryptedDigest = DerOctetString.GetInstance(e.Current); + + if (e.MoveNext()) + { + unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false); + } + else + { + unauthenticatedAttributes = null; + } + } + + public DerInteger Version + { + get { return version; } + } + + public SignerIdentifier SignerID + { + get { return sid; } + } + + public Asn1Set AuthenticatedAttributes + { + get { return authenticatedAttributes; } + } + + public AlgorithmIdentifier DigestAlgorithm + { + get { return digAlgorithm; } + } + + public Asn1OctetString EncryptedDigest + { + get { return encryptedDigest; } + } + + public AlgorithmIdentifier DigestEncryptionAlgorithm + { + get { return digEncryptionAlgorithm; } + } + + public Asn1Set UnauthenticatedAttributes + { + get { return unauthenticatedAttributes; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  SignerInfo ::= Sequence {
+         *      version Version,
+         *      SignerIdentifier sid,
+         *      digestAlgorithm DigestAlgorithmIdentifier,
+         *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+         *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+         *      encryptedDigest EncryptedDigest,
+         *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+         *  }
+         *
+         *  EncryptedDigest ::= OCTET STRING
+         *
+         *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, sid, digAlgorithm); + + if (authenticatedAttributes != null) + { + v.Add(new DerTaggedObject(false, 0, authenticatedAttributes)); + } + + v.Add(digEncryptionAlgorithm, encryptedDigest); + + if (unauthenticatedAttributes != null) + { + v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/Time.cs b/crypto/src/asn1/cms/Time.cs new file mode 100644 index 000000000..d113bfa2e --- /dev/null +++ b/crypto/src/asn1/cms/Time.cs @@ -0,0 +1,118 @@ +using System; +using System.Globalization; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class Time + : Asn1Encodable, IAsn1Choice + { + private readonly Asn1Object time; + + public static Time GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(obj.GetObject()); + } + + public Time( + Asn1Object time) + { + if (!(time is DerUtcTime) + && !(time is DerGeneralizedTime)) + { + throw new ArgumentException("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( + DateTime date) + { + string d = date.ToString("yyyyMMddHHmmss") + "Z"; + + int year = int.Parse(d.Substring(0, 4)); + + if (year < 1950 || year > 2049) + { + time = new DerGeneralizedTime(d); + } + else + { + time = new DerUtcTime(d.Substring(2)); + } + } + + public static Time GetInstance( + object obj) + { + if (obj == null || obj is Time) + return (Time)obj; + + if (obj is DerUtcTime) + return new Time((DerUtcTime)obj); + + if (obj is DerGeneralizedTime) + return new Time((DerGeneralizedTime)obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public string TimeString + { + get + { + if (time is DerUtcTime) + { + return ((DerUtcTime)time).AdjustedTimeString; + } + else + { + return ((DerGeneralizedTime)time).GetTime(); + } + } + } + + public DateTime Date + { + get + { + try + { + if (time is DerUtcTime) + { + return ((DerUtcTime)time).ToAdjustedDateTime(); + } + + return ((DerGeneralizedTime)time).ToDateTime(); + } + catch (FormatException e) + { + // this should never happen + throw new InvalidOperationException("invalid date string: " + e.Message); + } + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Time ::= CHOICE {
+         *             utcTime        UTCTime,
+         *             generalTime    GeneralizedTime }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return time; + } + } +} diff --git a/crypto/src/asn1/cms/TimeStampAndCRL.cs b/crypto/src/asn1/cms/TimeStampAndCRL.cs new file mode 100644 index 000000000..4cb5f2a52 --- /dev/null +++ b/crypto/src/asn1/cms/TimeStampAndCRL.cs @@ -0,0 +1,62 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class TimeStampAndCrl + : Asn1Encodable + { + private ContentInfo timeStamp; + private X509.CertificateList crl; + + public TimeStampAndCrl(ContentInfo timeStamp) + { + this.timeStamp = timeStamp; + } + + private TimeStampAndCrl(Asn1Sequence seq) + { + this.timeStamp = ContentInfo.GetInstance(seq[0]); + if (seq.Count == 2) + { + this.crl = X509.CertificateList.GetInstance(seq[1]); + } + } + + public static TimeStampAndCrl GetInstance(object obj) + { + if (obj is TimeStampAndCrl) + return (TimeStampAndCrl)obj; + + if (obj != null) + return new TimeStampAndCrl(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public virtual ContentInfo TimeStampToken + { + get { return this.timeStamp; } + } + + public virtual X509.CertificateList Crl + { + get { return this.crl; } + } + + /** + *
+		 * TimeStampAndCRL ::= SEQUENCE {
+		 *     timeStamp   TimeStampToken,          -- according to RFC 3161
+		 *     crl         CertificateList OPTIONAL -- according to RFC 5280
+		 *  }
+		 * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(timeStamp); + v.AddOptional(crl); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/TimeStampTokenEvidence.cs b/crypto/src/asn1/cms/TimeStampTokenEvidence.cs new file mode 100644 index 000000000..8625d058e --- /dev/null +++ b/crypto/src/asn1/cms/TimeStampTokenEvidence.cs @@ -0,0 +1,65 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class TimeStampTokenEvidence + : Asn1Encodable + { + private TimeStampAndCrl[] timeStampAndCrls; + + public TimeStampTokenEvidence(TimeStampAndCrl[] timeStampAndCrls) + { + this.timeStampAndCrls = timeStampAndCrls; + } + + public TimeStampTokenEvidence(TimeStampAndCrl timeStampAndCrl) + { + this.timeStampAndCrls = new TimeStampAndCrl[]{ timeStampAndCrl }; + } + + private TimeStampTokenEvidence(Asn1Sequence seq) + { + this.timeStampAndCrls = new TimeStampAndCrl[seq.Count]; + + int count = 0; + + foreach (Asn1Encodable ae in seq) + { + this.timeStampAndCrls[count++] = TimeStampAndCrl.GetInstance(ae.ToAsn1Object()); + } + } + + public static TimeStampTokenEvidence GetInstance(Asn1TaggedObject tagged, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(tagged, isExplicit)); + } + + public static TimeStampTokenEvidence GetInstance(object obj) + { + if (obj is TimeStampTokenEvidence) + return (TimeStampTokenEvidence)obj; + + if (obj != null) + return new TimeStampTokenEvidence(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public virtual TimeStampAndCrl[] ToTimeStampAndCrlArray() + { + return (TimeStampAndCrl[])timeStampAndCrls.Clone(); + } + + /** + *
+		 * TimeStampTokenEvidence ::=
+		 *    SEQUENCE SIZE(1..MAX) OF TimeStampAndCrl
+		 * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(timeStampAndCrls); + } + } +} diff --git a/crypto/src/asn1/cms/TimeStampedData.cs b/crypto/src/asn1/cms/TimeStampedData.cs new file mode 100644 index 000000000..15448a923 --- /dev/null +++ b/crypto/src/asn1/cms/TimeStampedData.cs @@ -0,0 +1,95 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class TimeStampedData + : Asn1Encodable + { + private DerInteger 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 DerInteger(1); + this.dataUri = dataUri; + this.metaData = metaData; + this.content = content; + this.temporalEvidence = temporalEvidence; + } + + private TimeStampedData(Asn1Sequence seq) + { + this.version = DerInteger.GetInstance(seq[0]); + + int index = 1; + if (seq[index] is DerIA5String) + { + this.dataUri = DerIA5String.GetInstance(seq[index++]); + } + if (seq[index] is MetaData || seq[index] is Asn1Sequence) + { + this.metaData = MetaData.GetInstance(seq[index++]); + } + if (seq[index] is Asn1OctetString) + { + this.content = Asn1OctetString.GetInstance(seq[index++]); + } + this.temporalEvidence = Evidence.GetInstance(seq[index]); + } + + public static TimeStampedData GetInstance(object obj) + { + if (obj is TimeStampedData) + return (TimeStampedData)obj; + + if (obj != null) + return new TimeStampedData(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public virtual DerIA5String DataUri + { + get { return dataUri; } + } + + public MetaData MetaData + { + get { return metaData; } + } + + public Asn1OctetString Content + { + get { return content; } + } + + public Evidence TemporalEvidence + { + get { return temporalEvidence; } + } + + /** + *
+		 * TimeStampedData ::= SEQUENCE {
+		 *   version              INTEGER { v1(1) },
+		 *   dataUri              IA5String OPTIONAL,
+		 *   metaData             MetaData OPTIONAL,
+		 *   content              OCTET STRING OPTIONAL,
+		 *   temporalEvidence     Evidence
+		 * }
+		 * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(version); + v.AddOptional(dataUri, metaData, content); + v.Add(temporalEvidence); + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/cms/TimeStampedDataParser.cs b/crypto/src/asn1/cms/TimeStampedDataParser.cs new file mode 100644 index 000000000..90307bff9 --- /dev/null +++ b/crypto/src/asn1/cms/TimeStampedDataParser.cs @@ -0,0 +1,76 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms +{ + public class TimeStampedDataParser + { + private DerInteger version; + private DerIA5String dataUri; + private MetaData metaData; + private Asn1OctetStringParser content; + private Evidence temporalEvidence; + private Asn1SequenceParser parser; + + private TimeStampedDataParser(Asn1SequenceParser parser) + { + this.parser = parser; + this.version = DerInteger.GetInstance(parser.ReadObject()); + + Asn1Object obj = parser.ReadObject().ToAsn1Object(); + + if (obj is DerIA5String) + { + this.dataUri = DerIA5String.GetInstance(obj); + obj = parser.ReadObject().ToAsn1Object(); + } + + if (//obj is MetaData || + obj is Asn1SequenceParser) + { + this.metaData = MetaData.GetInstance(obj.ToAsn1Object()); + obj = parser.ReadObject().ToAsn1Object(); + } + + if (obj is Asn1OctetStringParser) + { + this.content = (Asn1OctetStringParser)obj; + } + } + + public static TimeStampedDataParser GetInstance(object obj) + { + if (obj is Asn1Sequence) + return new TimeStampedDataParser(((Asn1Sequence)obj).Parser); + + if (obj is Asn1SequenceParser) + return new TimeStampedDataParser((Asn1SequenceParser)obj); + + return null; + } + + public virtual DerIA5String DataUri + { + get { return dataUri; } + } + + public virtual MetaData MetaData + { + get { return metaData; } + } + + public virtual Asn1OctetStringParser Content + { + get { return content; } + } + + public virtual Evidence GetTemporalEvidence() + { + if (temporalEvidence == null) + { + temporalEvidence = Evidence.GetInstance(parser.ReadObject().ToAsn1Object()); + } + + return temporalEvidence; + } + } +} diff --git a/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs b/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs new file mode 100644 index 000000000..53c5c706b --- /dev/null +++ b/crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs @@ -0,0 +1,103 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Cms.Ecc +{ + public class MQVuserKeyingMaterial + : Asn1Encodable + { + 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[0]); + + if (seq.Count > 1) + { + this.addedukm = Asn1OctetString.GetInstance( + (Asn1TaggedObject)seq[1], true); + } + } + + /** + * return an AuthEnvelopedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws ArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static MQVuserKeyingMaterial GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * return an AuthEnvelopedData object from the given object. + * + * @param obj the object we want converted. + * @throws ArgumentException if the object cannot be converted. + */ + public static MQVuserKeyingMaterial GetInstance( + object obj) + { + if (obj == null || obj is MQVuserKeyingMaterial) + { + return (MQVuserKeyingMaterial)obj; + } + + if (obj is Asn1Sequence) + { + return new MQVuserKeyingMaterial((Asn1Sequence)obj); + } + + throw new ArgumentException("Invalid MQVuserKeyingMaterial: " + obj.GetType().Name); + } + + public OriginatorPublicKey EphemeralPublicKey + { + get { return ephemeralPublicKey; } + } + + public Asn1OctetString AddedUkm + { + get { return addedukm; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		* MQVuserKeyingMaterial ::= SEQUENCE {
+		*   ephemeralPublicKey OriginatorPublicKey,
+		*   addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL  }
+		* 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(ephemeralPublicKey); + + if (addedukm != null) + { + v.Add(new DerTaggedObject(true, 0, addedukm)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/crmf/AttributeTypeAndValue.cs b/crypto/src/asn1/crmf/AttributeTypeAndValue.cs new file mode 100644 index 000000000..823668992 --- /dev/null +++ b/crypto/src/asn1/crmf/AttributeTypeAndValue.cs @@ -0,0 +1,66 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class AttributeTypeAndValue + : Asn1Encodable + { + private readonly DerObjectIdentifier type; + private readonly Asn1Encodable value; + + private AttributeTypeAndValue(Asn1Sequence seq) + { + type = (DerObjectIdentifier)seq[0]; + value = (Asn1Encodable)seq[1]; + } + + public static AttributeTypeAndValue GetInstance(object obj) + { + if (obj is AttributeTypeAndValue) + return (AttributeTypeAndValue)obj; + + if (obj is Asn1Sequence) + return new AttributeTypeAndValue((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public AttributeTypeAndValue( + String oid, + Asn1Encodable value) + : this(new DerObjectIdentifier(oid), value) + { + } + + public AttributeTypeAndValue( + DerObjectIdentifier type, + Asn1Encodable value) + { + this.type = type; + this.value = value; + } + + public virtual DerObjectIdentifier Type + { + get { return type; } + } + + public virtual Asn1Encodable Value + { + get { return value; } + } + + /** + *
+         * AttributeTypeAndValue ::= SEQUENCE {
+         *           type         OBJECT IDENTIFIER,
+         *           value        ANY DEFINED BY type }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(type, value); + } + } +} diff --git a/crypto/src/asn1/crmf/CertId.cs b/crypto/src/asn1/crmf/CertId.cs new file mode 100644 index 000000000..10c2cc8b4 --- /dev/null +++ b/crypto/src/asn1/crmf/CertId.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertId + : Asn1Encodable + { + private readonly GeneralName issuer; + private readonly DerInteger serialNumber; + + private CertId(Asn1Sequence seq) + { + issuer = GeneralName.GetInstance(seq[0]); + serialNumber = DerInteger.GetInstance(seq[1]); + } + + public static CertId GetInstance(object obj) + { + if (obj is CertId) + return (CertId)obj; + + if (obj is Asn1Sequence) + return new CertId((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public virtual GeneralName Issuer + { + get { return issuer; } + } + + public virtual DerInteger SerialNumber + { + get { return serialNumber; } + } + + /** + *
+         * CertId ::= SEQUENCE {
+         *                 issuer           GeneralName,
+         *                 serialNumber     INTEGER }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(issuer, serialNumber); + } + } +} diff --git a/crypto/src/asn1/crmf/CertReqMessages.cs b/crypto/src/asn1/crmf/CertReqMessages.cs new file mode 100644 index 000000000..9247281e8 --- /dev/null +++ b/crypto/src/asn1/crmf/CertReqMessages.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertReqMessages + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private CertReqMessages(Asn1Sequence seq) + { + content = seq; + } + + public static CertReqMessages GetInstance(object obj) + { + if (obj is CertReqMessages) + return (CertReqMessages)obj; + + if (obj is Asn1Sequence) + return new CertReqMessages((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public CertReqMessages(params CertReqMsg[] msgs) + { + content = new DerSequence(msgs); + } + + public virtual CertReqMsg[] ToCertReqMsgArray() + { + CertReqMsg[] result = new CertReqMsg[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = CertReqMsg.GetInstance(content[i]); + } + return result; + } + + /** + *
+         * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/crmf/CertReqMsg.cs b/crypto/src/asn1/crmf/CertReqMsg.cs new file mode 100644 index 000000000..2ca319a57 --- /dev/null +++ b/crypto/src/asn1/crmf/CertReqMsg.cs @@ -0,0 +1,106 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertReqMsg + : Asn1Encodable + { + private readonly CertRequest certReq; + private readonly ProofOfPossession popo; + private readonly Asn1Sequence regInfo; + + private CertReqMsg(Asn1Sequence seq) + { + certReq = CertRequest.GetInstance(seq[0]); + + for (int pos = 1; pos < seq.Count; ++pos) + { + object o = seq[pos]; + + if (o is Asn1TaggedObject || o is ProofOfPossession) + { + popo = ProofOfPossession.GetInstance(o); + } + else + { + regInfo = Asn1Sequence.GetInstance(o); + } + } + } + + public static CertReqMsg GetInstance(object obj) + { + if (obj is CertReqMsg) + return (CertReqMsg)obj; + + if (obj != null) + return new CertReqMsg(Asn1Sequence.GetInstance(obj)); + + return null; + } + + /** + * Creates a new CertReqMsg. + * @param certReq CertRequest + * @param popo may be null + * @param regInfo may be null + */ + public CertReqMsg( + CertRequest certReq, + ProofOfPossession popo, + AttributeTypeAndValue[] regInfo) + { + if (certReq == null) + throw new ArgumentNullException("certReq"); + + this.certReq = certReq; + this.popo = popo; + + if (regInfo != null) + { + this.regInfo = new DerSequence(regInfo); + } + } + + public virtual CertRequest CertReq + { + get { return certReq; } + } + + public virtual ProofOfPossession Popo + { + get { return popo; } + } + + public virtual AttributeTypeAndValue[] GetRegInfo() + { + if (regInfo == null) + return null; + + AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = AttributeTypeAndValue.GetInstance(regInfo[i]); + } + return results; + } + + /** + *
+         * CertReqMsg ::= SEQUENCE {
+         *                    certReq   CertRequest,
+         *                    pop       ProofOfPossession  OPTIONAL,
+         *                    -- content depends upon key type
+         *                    regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certReq); + v.AddOptional(popo); + v.AddOptional(regInfo); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/crmf/CertRequest.cs b/crypto/src/asn1/crmf/CertRequest.cs new file mode 100644 index 000000000..625a9b519 --- /dev/null +++ b/crypto/src/asn1/crmf/CertRequest.cs @@ -0,0 +1,82 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertRequest + : Asn1Encodable + { + private readonly DerInteger certReqId; + private readonly CertTemplate certTemplate; + private readonly Controls controls; + + private CertRequest(Asn1Sequence seq) + { + certReqId = DerInteger.GetInstance(seq[0]); + certTemplate = CertTemplate.GetInstance(seq[1]); + if (seq.Count > 2) + { + controls = Controls.GetInstance(seq[2]); + } + } + + public static CertRequest GetInstance(object obj) + { + if (obj is CertRequest) + return (CertRequest)obj; + + if (obj != null) + return new CertRequest(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public CertRequest( + int certReqId, + CertTemplate certTemplate, + Controls controls) + : this(new DerInteger(certReqId), certTemplate, controls) + { + } + + public CertRequest( + DerInteger certReqId, + CertTemplate certTemplate, + Controls controls) + { + this.certReqId = certReqId; + this.certTemplate = certTemplate; + this.controls = controls; + } + + public virtual DerInteger CertReqID + { + get { return certReqId; } + } + + public virtual CertTemplate CertTemplate + { + get { return certTemplate; } + } + + public virtual Controls Controls + { + get { return controls; } + } + + /** + *
+         * 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
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certReqId, certTemplate); + v.AddOptional(controls); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/crmf/CertTemplate.cs b/crypto/src/asn1/crmf/CertTemplate.cs new file mode 100644 index 000000000..3de9f1d5a --- /dev/null +++ b/crypto/src/asn1/crmf/CertTemplate.cs @@ -0,0 +1,149 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertTemplate + : Asn1Encodable + { + private readonly Asn1Sequence seq; + + private readonly DerInteger version; + private readonly DerInteger serialNumber; + private readonly AlgorithmIdentifier signingAlg; + private readonly X509Name issuer; + private readonly OptionalValidity validity; + private readonly X509Name subject; + private readonly SubjectPublicKeyInfo publicKey; + private readonly DerBitString issuerUID; + private readonly DerBitString subjectUID; + private readonly X509Extensions extensions; + + private CertTemplate(Asn1Sequence seq) + { + this.seq = seq; + + foreach (Asn1TaggedObject tObj in seq) + { + switch (tObj.TagNo) + { + case 0: + version = DerInteger.GetInstance(tObj, false); + break; + case 1: + serialNumber = DerInteger.GetInstance(tObj, false); + break; + case 2: + signingAlg = AlgorithmIdentifier.GetInstance(tObj, false); + break; + case 3: + issuer = X509Name.GetInstance(tObj, true); // CHOICE + break; + case 4: + validity = OptionalValidity.GetInstance(Asn1Sequence.GetInstance(tObj, false)); + break; + case 5: + subject = X509Name.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 = X509Extensions.GetInstance(tObj, false); + break; + default: + throw new ArgumentException("unknown tag: " + tObj.TagNo, "seq"); + } + } + } + + public static CertTemplate GetInstance(object obj) + { + if (obj is CertTemplate) + return (CertTemplate)obj; + + if (obj != null) + return new CertTemplate(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public virtual int Version + { + get { return version.Value.IntValue; } + } + + public virtual DerInteger SerialNumber + { + get { return serialNumber; } + } + + public virtual AlgorithmIdentifier SigningAlg + { + get { return signingAlg; } + } + + public virtual X509Name Issuer + { + get { return issuer; } + } + + public virtual OptionalValidity Validity + { + get { return validity; } + } + + public virtual X509Name Subject + { + get { return subject; } + } + + public virtual SubjectPublicKeyInfo PublicKey + { + get { return publicKey; } + } + + public virtual DerBitString IssuerUID + { + get { return issuerUID; } + } + + public virtual DerBitString SubjectUID + { + get { return subjectUID; } + } + + public virtual X509Extensions Extensions + { + get { return extensions; } + } + + /** + *
+         *  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 }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/crmf/CertTemplateBuilder.cs b/crypto/src/asn1/crmf/CertTemplateBuilder.cs new file mode 100644 index 000000000..51c73c4e1 --- /dev/null +++ b/crypto/src/asn1/crmf/CertTemplateBuilder.cs @@ -0,0 +1,125 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class CertTemplateBuilder + { + private DerInteger version; + private DerInteger serialNumber; + private AlgorithmIdentifier signingAlg; + private X509Name issuer; + private OptionalValidity validity; + private X509Name subject; + private SubjectPublicKeyInfo publicKey; + private DerBitString issuerUID; + private DerBitString subjectUID; + private X509Extensions extensions; + + /** Sets the X.509 version. Note: for X509v3, use 2 here. */ + public virtual CertTemplateBuilder SetVersion(int ver) + { + version = new DerInteger(ver); + return this; + } + + public virtual CertTemplateBuilder SetSerialNumber(DerInteger ser) + { + serialNumber = ser; + return this; + } + + public virtual CertTemplateBuilder SetSigningAlg(AlgorithmIdentifier aid) + { + signingAlg = aid; + return this; + } + + public virtual CertTemplateBuilder SetIssuer(X509Name name) + { + issuer = name; + return this; + } + + public virtual CertTemplateBuilder SetValidity(OptionalValidity v) + { + validity = v; + return this; + } + + public virtual CertTemplateBuilder SetSubject(X509Name name) + { + subject = name; + return this; + } + + public virtual CertTemplateBuilder SetPublicKey(SubjectPublicKeyInfo spki) + { + publicKey = spki; + return this; + } + + /** Sets the issuer unique ID (deprecated in X.509v3) */ + public virtual CertTemplateBuilder SetIssuerUID(DerBitString uid) + { + issuerUID = uid; + return this; + } + + /** Sets the subject unique ID (deprecated in X.509v3) */ + public virtual CertTemplateBuilder SetSubjectUID(DerBitString uid) + { + subjectUID = uid; + return this; + } + + public virtual CertTemplateBuilder SetExtensions(X509Extensions extens) + { + extensions = extens; + return this; + } + + /** + *
+         *  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 }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public virtual 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, bool isExplicit, Asn1Encodable obj) + { + if (obj != null) + { + v.Add(new DerTaggedObject(isExplicit, tagNo, obj)); + } + } + } +} diff --git a/crypto/src/asn1/crmf/Controls.cs b/crypto/src/asn1/crmf/Controls.cs new file mode 100644 index 000000000..cc52ea4bb --- /dev/null +++ b/crypto/src/asn1/crmf/Controls.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class Controls + : Asn1Encodable + { + private readonly Asn1Sequence content; + + private Controls(Asn1Sequence seq) + { + content = seq; + } + + public static Controls GetInstance(object obj) + { + if (obj is Controls) + return (Controls)obj; + + if (obj is Asn1Sequence) + return new Controls((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public Controls(params AttributeTypeAndValue[] atvs) + { + content = new DerSequence(atvs); + } + + public virtual AttributeTypeAndValue[] ToAttributeTypeAndValueArray() + { + AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.Count]; + for (int i = 0; i != result.Length; ++i) + { + result[i] = AttributeTypeAndValue.GetInstance(content[i]); + } + return result; + } + + /** + *
+         * Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return content; + } + } +} diff --git a/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs b/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs new file mode 100644 index 000000000..eaa1f7ba4 --- /dev/null +++ b/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs @@ -0,0 +1,23 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public abstract class CrmfObjectIdentifiers + { + public static readonly DerObjectIdentifier id_pkix = new DerObjectIdentifier("1.3.6.1.5.5.7"); + + // arc for Internet X.509 PKI protocols and their components + + public static readonly DerObjectIdentifier id_pkip = id_pkix.Branch("5"); + + public static readonly DerObjectIdentifier id_regCtrl = id_pkip.Branch("1"); + public static readonly DerObjectIdentifier id_regCtrl_regToken = id_regCtrl.Branch("1"); + public static readonly DerObjectIdentifier id_regCtrl_authenticator = id_regCtrl.Branch("2"); + public static readonly DerObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.Branch("3"); + public static readonly DerObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.Branch("4"); + + public static readonly DerObjectIdentifier id_ct_encKeyWithID = new DerObjectIdentifier(PkcsObjectIdentifiers.IdCT + ".21"); + } +} diff --git a/crypto/src/asn1/crmf/EncKeyWithID.cs b/crypto/src/asn1/crmf/EncKeyWithID.cs new file mode 100644 index 000000000..6de56fa0b --- /dev/null +++ b/crypto/src/asn1/crmf/EncKeyWithID.cs @@ -0,0 +1,103 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class EncKeyWithID + : Asn1Encodable + { + private readonly PrivateKeyInfo privKeyInfo; + private readonly Asn1Encodable identifier; + + public static EncKeyWithID GetInstance(object obj) + { + if (obj is EncKeyWithID) + return (EncKeyWithID)obj; + + if (obj != null) + return new EncKeyWithID(Asn1Sequence.GetInstance(obj)); + + return null; + } + + private EncKeyWithID(Asn1Sequence seq) + { + this.privKeyInfo = PrivateKeyInfo.GetInstance(seq[0]); + + if (seq.Count > 1) + { + if (!(seq[1] is DerUtf8String)) + { + this.identifier = GeneralName.GetInstance(seq[1]); + } + else + { + this.identifier = (Asn1Encodable)seq[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 virtual PrivateKeyInfo PrivateKey + { + get { return privKeyInfo; } + } + + public virtual bool HasIdentifier + { + get { return identifier != null; } + } + + public virtual bool IsIdentifierUtf8String + { + get { return identifier is DerUtf8String; } + } + + public virtual Asn1Encodable Identifier + { + get { return identifier; } + } + + /** + *
+         * EncKeyWithID ::= SEQUENCE {
+         *      privateKey           PrivateKeyInfo,
+         *      identifier CHOICE {
+         *         string               UTF8String,
+         *         generalName          GeneralName
+         *     } OPTIONAL
+         * }
+         * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(privKeyInfo); + v.AddOptional(identifier); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/crmf/EncryptedKey.cs b/crypto/src/asn1/crmf/EncryptedKey.cs new file mode 100644 index 000000000..850fbd219 --- /dev/null +++ b/crypto/src/asn1/crmf/EncryptedKey.cs @@ -0,0 +1,78 @@ +using System; + +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class EncryptedKey + : Asn1Encodable, IAsn1Choice + { + private readonly EnvelopedData envelopedData; + private readonly EncryptedValue encryptedValue; + + public static EncryptedKey GetInstance(object o) + { + if (o is EncryptedKey) + { + return (EncryptedKey)o; + } + else if (o is Asn1TaggedObject) + { + return new EncryptedKey(EnvelopedData.GetInstance((Asn1TaggedObject)o, false)); + } + else if (o is 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 virtual bool IsEncryptedValue + { + get { return encryptedValue != null; } + } + + public virtual Asn1Encodable Value + { + get + { + if (encryptedValue != null) + return encryptedValue; + + return envelopedData; + } + } + + /** + *
+         *    EncryptedKey ::= CHOICE {
+         *        encryptedValue        EncryptedValue, -- deprecated
+         *        envelopedData     [0] EnvelopedData }
+         *        -- The encrypted private key MUST be placed in the envelopedData
+         *        -- encryptedContentInfo encryptedContent OCTET STRING.
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + if (encryptedValue != null) + { + return encryptedValue.ToAsn1Object(); + } + + return new DerTaggedObject(false, 0, envelopedData); + } + } +} diff --git a/crypto/src/asn1/crmf/EncryptedValue.cs b/crypto/src/asn1/crmf/EncryptedValue.cs new file mode 100644 index 000000000..83122e220 --- /dev/null +++ b/crypto/src/asn1/crmf/EncryptedValue.cs @@ -0,0 +1,154 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class EncryptedValue + : Asn1Encodable + { + private readonly AlgorithmIdentifier intendedAlg; + private readonly AlgorithmIdentifier symmAlg; + private readonly DerBitString encSymmKey; + private readonly AlgorithmIdentifier keyAlg; + private readonly Asn1OctetString valueHint; + private readonly DerBitString encValue; + + private EncryptedValue(Asn1Sequence seq) + { + int index = 0; + while (seq[index] is Asn1TaggedObject) + { + Asn1TaggedObject tObj = (Asn1TaggedObject)seq[index]; + + switch (tObj.TagNo) + { + 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[index]); + } + + public static EncryptedValue GetInstance(object obj) + { + if (obj is EncryptedValue) + return (EncryptedValue)obj; + + if (obj != null) + return new EncryptedValue(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public EncryptedValue( + AlgorithmIdentifier intendedAlg, + AlgorithmIdentifier symmAlg, + DerBitString encSymmKey, + AlgorithmIdentifier keyAlg, + Asn1OctetString valueHint, + DerBitString encValue) + { + if (encValue == null) + { + throw new ArgumentNullException("encValue"); + } + + this.intendedAlg = intendedAlg; + this.symmAlg = symmAlg; + this.encSymmKey = encSymmKey; + this.keyAlg = keyAlg; + this.valueHint = valueHint; + this.encValue = encValue; + } + + public virtual AlgorithmIdentifier IntendedAlg + { + get { return intendedAlg; } + } + + public virtual AlgorithmIdentifier SymmAlg + { + get { return symmAlg; } + } + + public virtual DerBitString EncSymmKey + { + get { return encSymmKey; } + } + + public virtual AlgorithmIdentifier KeyAlg + { + get { return keyAlg; } + } + + public virtual Asn1OctetString ValueHint + { + get { return valueHint; } + } + + public virtual DerBitString EncValue + { + get { return encValue; } + } + + /** + *
+         * 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
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/crmf/OptionalValidity.cs b/crypto/src/asn1/crmf/OptionalValidity.cs new file mode 100644 index 000000000..d1a0f7ffb --- /dev/null +++ b/crypto/src/asn1/crmf/OptionalValidity.cs @@ -0,0 +1,71 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class OptionalValidity + : Asn1Encodable + { + private readonly Time notBefore; + private readonly Time notAfter; + + private OptionalValidity(Asn1Sequence seq) + { + foreach (Asn1TaggedObject tObj in seq) + { + if (tObj.TagNo == 0) + { + notBefore = Time.GetInstance(tObj, true); + } + else + { + notAfter = Time.GetInstance(tObj, true); + } + } + } + + public static OptionalValidity GetInstance(object obj) + { + if (obj == null || obj is OptionalValidity) + return (OptionalValidity)obj; + + return new OptionalValidity(Asn1Sequence.GetInstance(obj)); + } + + public virtual Time NotBefore + { + get { return notBefore; } + } + + public virtual Time NotAfter + { + get { return notAfter; } + } + + /** + *
+         * OptionalValidity ::= SEQUENCE {
+         *                        notBefore  [0] Time OPTIONAL,
+         *                        notAfter   [1] Time OPTIONAL } --at least one MUST be present
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/crmf/PKIArchiveOptions.cs b/crypto/src/asn1/crmf/PKIArchiveOptions.cs new file mode 100644 index 000000000..910f73b22 --- /dev/null +++ b/crypto/src/asn1/crmf/PKIArchiveOptions.cs @@ -0,0 +1,105 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class PkiArchiveOptions + : Asn1Encodable, IAsn1Choice + { + public const int encryptedPrivKey = 0; + public const int keyGenParameters = 1; + public const int archiveRemGenPrivKey = 2; + + private readonly Asn1Encodable value; + + public static PkiArchiveOptions GetInstance(object obj) + { + if (obj is PkiArchiveOptions) + return (PkiArchiveOptions)obj; + + if (obj is Asn1TaggedObject) + return new PkiArchiveOptions((Asn1TaggedObject)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + private PkiArchiveOptions(Asn1TaggedObject tagged) + { + switch (tagged.TagNo) + { + case encryptedPrivKey: + value = EncryptedKey.GetInstance(tagged.GetObject()); + break; + case keyGenParameters: + value = Asn1OctetString.GetInstance(tagged, false); + break; + case archiveRemGenPrivKey: + value = DerBoolean.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged"); + } + } + + public PkiArchiveOptions(EncryptedKey encKey) + { + this.value = encKey; + } + + public PkiArchiveOptions(Asn1OctetString keyGenParameters) + { + this.value = keyGenParameters; + } + + public PkiArchiveOptions(bool archiveRemGenPrivKey) + { + this.value = DerBoolean.GetInstance(archiveRemGenPrivKey); + } + + public virtual int Type + { + get + { + if (value is EncryptedKey) + return encryptedPrivKey; + + if (value is Asn1OctetString) + return keyGenParameters; + + return archiveRemGenPrivKey; + } + } + + public virtual Asn1Encodable Value + { + get { return value; } + } + + /** + *
+         *  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.
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + if (value is EncryptedKey) + { + return new DerTaggedObject(true, encryptedPrivKey, value); // choice + } + + if (value is Asn1OctetString) + { + return new DerTaggedObject(false, keyGenParameters, value); + } + + return new DerTaggedObject(false, archiveRemGenPrivKey, value); + } + } +} diff --git a/crypto/src/asn1/crmf/PKIPublicationInfo.cs b/crypto/src/asn1/crmf/PKIPublicationInfo.cs new file mode 100644 index 000000000..c8bc1403e --- /dev/null +++ b/crypto/src/asn1/crmf/PKIPublicationInfo.cs @@ -0,0 +1,64 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class PkiPublicationInfo + : Asn1Encodable + { + private readonly DerInteger action; + private readonly Asn1Sequence pubInfos; + + private PkiPublicationInfo(Asn1Sequence seq) + { + action = DerInteger.GetInstance(seq[0]); + pubInfos = Asn1Sequence.GetInstance(seq[1]); + } + + public static PkiPublicationInfo GetInstance(object obj) + { + if (obj is PkiPublicationInfo) + return (PkiPublicationInfo)obj; + + if (obj is Asn1Sequence) + return new PkiPublicationInfo((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual DerInteger Action + { + get { return action; } + } + + public virtual SinglePubInfo[] GetPubInfos() + { + if (pubInfos == null) + return null; + + SinglePubInfo[] results = new SinglePubInfo[pubInfos.Count]; + for (int i = 0; i != results.Length; ++i) + { + results[i] = SinglePubInfo.GetInstance(pubInfos[i]); + } + return results; + } + + /** + *
+         * 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)
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(action, pubInfos); + } + } +} diff --git a/crypto/src/asn1/crmf/PKMacValue.cs b/crypto/src/asn1/crmf/PKMacValue.cs new file mode 100644 index 000000000..20a08fd1d --- /dev/null +++ b/crypto/src/asn1/crmf/PKMacValue.cs @@ -0,0 +1,89 @@ +using System; + +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + /** + * Password-based MAC value for use with POPOSigningKeyInput. + */ + public class PKMacValue + : Asn1Encodable + { + private readonly AlgorithmIdentifier algID; + private readonly DerBitString macValue; + + private PKMacValue(Asn1Sequence seq) + { + this.algID = AlgorithmIdentifier.GetInstance(seq[0]); + this.macValue = DerBitString.GetInstance(seq[1]); + } + + public static PKMacValue GetInstance(object obj) + { + if (obj is PKMacValue) + return (PKMacValue)obj; + + if (obj is Asn1Sequence) + return new PKMacValue((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public static PKMacValue GetInstance(Asn1TaggedObject obj, bool 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 pbmParams, + DerBitString macValue) + : this(new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, pbmParams), macValue) + { + } + + /** + * Creates a new PKMACValue. + * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter + * @param value MAC of the DER-encoded SubjectPublicKeyInfo + */ + public PKMacValue( + AlgorithmIdentifier algID, + DerBitString macValue) + { + this.algID = algID; + this.macValue = macValue; + } + + public virtual AlgorithmIdentifier AlgID + { + get { return algID; } + } + + public virtual DerBitString MacValue + { + get { return macValue; } + } + + /** + *
+         * PKMACValue ::= SEQUENCE {
+         *      algId  AlgorithmIdentifier,
+         *      -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+         *      -- parameter value is PBMParameter
+         *      value  BIT STRING }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algID, macValue); + } + } +} diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs new file mode 100644 index 000000000..0cedc5127 --- /dev/null +++ b/crypto/src/asn1/crmf/PopoPrivKey.cs @@ -0,0 +1,84 @@ +using System; + +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class PopoPrivKey + : Asn1Encodable, IAsn1Choice + { + public const int thisMessage = 0; + public const int subsequentMessage = 1; + public const int dhMAC = 2; + public const int agreeMAC = 3; + public const int encryptedKey = 4; + + private readonly int tagNo; + private readonly Asn1Encodable obj; + + private PopoPrivKey(Asn1TaggedObject obj) + { + this.tagNo = obj.TagNo; + + switch (tagNo) + { + case thisMessage: + this.obj = DerBitString.GetInstance(obj, false); + break; + case subsequentMessage: + this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.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 ArgumentException("unknown tag in PopoPrivKey", "obj"); + } + } + + public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit) + { + return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged.GetObject())); + } + + public PopoPrivKey(SubsequentMessage msg) + { + this.tagNo = subsequentMessage; + this.obj = msg; + } + + public virtual int Type + { + get { return tagNo; } + } + + public virtual Asn1Encodable Value + { + get { return obj; } + } + + /** + *
+         * 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 }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerTaggedObject(false, tagNo, obj); + } + } +} diff --git a/crypto/src/asn1/crmf/PopoSigningKey.cs b/crypto/src/asn1/crmf/PopoSigningKey.cs new file mode 100644 index 000000000..614278eda --- /dev/null +++ b/crypto/src/asn1/crmf/PopoSigningKey.cs @@ -0,0 +1,115 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class PopoSigningKey + : Asn1Encodable + { + private readonly PopoSigningKeyInput poposkInput; + private readonly AlgorithmIdentifier algorithmIdentifier; + private readonly DerBitString signature; + + private PopoSigningKey(Asn1Sequence seq) + { + int index = 0; + + if (seq[index] is Asn1TaggedObject) + { + Asn1TaggedObject tagObj + = (Asn1TaggedObject) seq[index++]; + if (tagObj.TagNo != 0) + { + throw new ArgumentException( "Unknown PopoSigningKeyInput tag: " + tagObj.TagNo, "seq"); + } + poposkInput = PopoSigningKeyInput.GetInstance(tagObj.GetObject()); + } + algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[index++]); + signature = DerBitString.GetInstance(seq[index]); + } + + public static PopoSigningKey GetInstance(object obj) + { + if (obj is PopoSigningKey) + return (PopoSigningKey)obj; + + if (obj is Asn1Sequence) + return new PopoSigningKey((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public static PopoSigningKey GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * 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 virtual PopoSigningKeyInput PoposkInput + { + get { return poposkInput; } + } + + public virtual AlgorithmIdentifier AlgorithmIdentifier + { + get { return algorithmIdentifier; } + } + + public virtual DerBitString Signature + { + get { return signature; } + } + + /** + *
+         * 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.
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/crmf/PopoSigningKeyInput.cs b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs new file mode 100644 index 000000000..63695262f --- /dev/null +++ b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs @@ -0,0 +1,115 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class PopoSigningKeyInput + : Asn1Encodable + { + private readonly GeneralName sender; + private readonly PKMacValue publicKeyMac; + private readonly SubjectPublicKeyInfo publicKey; + + private PopoSigningKeyInput(Asn1Sequence seq) + { + Asn1Encodable authInfo = (Asn1Encodable)seq[0]; + + if (authInfo is Asn1TaggedObject) + { + Asn1TaggedObject tagObj = (Asn1TaggedObject)authInfo; + if (tagObj.TagNo != 0) + { + throw new ArgumentException("Unknown authInfo tag: " + tagObj.TagNo, "seq"); + } + sender = GeneralName.GetInstance(tagObj.GetObject()); + } + else + { + publicKeyMac = PKMacValue.GetInstance(authInfo); + } + + publicKey = SubjectPublicKeyInfo.GetInstance(seq[1]); + } + + public static PopoSigningKeyInput GetInstance(object obj) + { + if (obj is PopoSigningKeyInput) + return (PopoSigningKeyInput)obj; + + if (obj is Asn1Sequence) + return new PopoSigningKeyInput((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + /** 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 virtual GeneralName Sender + { + get { return sender; } + } + + /** Returns the publicKeyMac field, or null if authInfo is sender */ + public virtual PKMacValue PublicKeyMac + { + get { return publicKeyMac; } + } + + public virtual SubjectPublicKeyInfo PublicKey + { + get { return publicKey; } + } + + /** + *
+         * 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
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/crmf/ProofOfPossession.cs b/crypto/src/asn1/crmf/ProofOfPossession.cs new file mode 100644 index 000000000..fc00edb32 --- /dev/null +++ b/crypto/src/asn1/crmf/ProofOfPossession.cs @@ -0,0 +1,98 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class ProofOfPossession + : Asn1Encodable, IAsn1Choice + { + public const int TYPE_RA_VERIFIED = 0; + public const int TYPE_SIGNING_KEY = 1; + public const int TYPE_KEY_ENCIPHERMENT = 2; + public const int TYPE_KEY_AGREEMENT = 3; + + private readonly int tagNo; + private readonly Asn1Encodable obj; + + private ProofOfPossession(Asn1TaggedObject tagged) + { + tagNo = tagged.TagNo; + switch (tagNo) + { + case 0: + obj = DerNull.Instance; + break; + case 1: + obj = PopoSigningKey.GetInstance(tagged, false); + break; + case 2: + case 3: + obj = PopoPrivKey.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("unknown tag: " + tagNo, "tagged"); + } + } + + public static ProofOfPossession GetInstance(object obj) + { + if (obj is ProofOfPossession) + return (ProofOfPossession)obj; + + if (obj is Asn1TaggedObject) + return new ProofOfPossession((Asn1TaggedObject)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + /** 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 virtual int Type + { + get { return tagNo; } + } + + public virtual Asn1Encodable Object + { + get { return obj; } + } + + /** + *
+         * 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 }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + return new DerTaggedObject(false, tagNo, obj); + } + } +} diff --git a/crypto/src/asn1/crmf/SinglePubInfo.cs b/crypto/src/asn1/crmf/SinglePubInfo.cs new file mode 100644 index 000000000..eaf8a3efd --- /dev/null +++ b/crypto/src/asn1/crmf/SinglePubInfo.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class SinglePubInfo + : Asn1Encodable + { + private readonly DerInteger pubMethod; + private readonly GeneralName pubLocation; + + private SinglePubInfo(Asn1Sequence seq) + { + pubMethod = DerInteger.GetInstance(seq[0]); + + if (seq.Count == 2) + { + pubLocation = GeneralName.GetInstance(seq[1]); + } + } + + public static SinglePubInfo GetInstance(object obj) + { + if (obj is SinglePubInfo) + return (SinglePubInfo)obj; + + if (obj is Asn1Sequence) + return new SinglePubInfo((Asn1Sequence)obj); + + throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj"); + } + + public virtual GeneralName PubLocation + { + get { return pubLocation; } + } + + /** + *
+         * SinglePubInfo ::= SEQUENCE {
+         *        pubMethod    INTEGER {
+         *           dontCare    (0),
+         *           x500        (1),
+         *           web         (2),
+         *           ldap        (3) },
+         *       pubLocation  GeneralName OPTIONAL }
+         * 
+ * @return a basic ASN.1 object representation. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(pubMethod); + v.AddOptional(pubLocation); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/crmf/SubsequentMessage.cs b/crypto/src/asn1/crmf/SubsequentMessage.cs new file mode 100644 index 000000000..cc1c16492 --- /dev/null +++ b/crypto/src/asn1/crmf/SubsequentMessage.cs @@ -0,0 +1,27 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Crmf +{ + public class SubsequentMessage + : DerInteger + { + public static readonly SubsequentMessage encrCert = new SubsequentMessage(0); + public static readonly SubsequentMessage challengeResp = new SubsequentMessage(1); + + private SubsequentMessage(int value) + : base(value) + { + } + + public static SubsequentMessage ValueOf(int value) + { + if (value == 0) + return encrCert; + + if (value == 1) + return challengeResp; + + throw new ArgumentException("unknown value: " + value, "value"); + } + } +} diff --git a/crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs b/crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs new file mode 100644 index 000000000..e2f2c1848 --- /dev/null +++ b/crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs @@ -0,0 +1,51 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + public abstract class CryptoProObjectIdentifiers + { + // GOST Algorithms OBJECT IDENTIFIERS : + // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)} + public const string GostID = "1.2.643.2.2"; + + public static readonly DerObjectIdentifier GostR3411 = new DerObjectIdentifier(GostID + ".9"); + public static readonly DerObjectIdentifier GostR3411Hmac = new DerObjectIdentifier(GostID + ".10"); + + public static readonly DerObjectIdentifier GostR28147Cbc = new DerObjectIdentifier(GostID + ".21"); + + public static readonly DerObjectIdentifier ID_Gost28147_89_CryptoPro_A_ParamSet = new DerObjectIdentifier(GostID + ".31.1"); + + public static readonly DerObjectIdentifier GostR3410x94 = new DerObjectIdentifier(GostID + ".20"); + public static readonly DerObjectIdentifier GostR3410x2001 = new DerObjectIdentifier(GostID + ".19"); + public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x94 = new DerObjectIdentifier(GostID + ".4"); + public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x2001 = new DerObjectIdentifier(GostID + ".3"); + + // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) } + public static readonly DerObjectIdentifier GostR3411x94CryptoProParamSet = new DerObjectIdentifier(GostID + ".30.1"); + + // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) } + public static readonly DerObjectIdentifier GostR3410x94CryptoProA = new DerObjectIdentifier(GostID + ".32.2"); + public static readonly DerObjectIdentifier GostR3410x94CryptoProB = new DerObjectIdentifier(GostID + ".32.3"); + public static readonly DerObjectIdentifier GostR3410x94CryptoProC = new DerObjectIdentifier(GostID + ".32.4"); + public static readonly DerObjectIdentifier GostR3410x94CryptoProD = new DerObjectIdentifier(GostID + ".32.5"); + + // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) } + public static readonly DerObjectIdentifier GostR3410x94CryptoProXchA = new DerObjectIdentifier(GostID + ".33.1"); + public static readonly DerObjectIdentifier GostR3410x94CryptoProXchB = new DerObjectIdentifier(GostID + ".33.2"); + public static readonly DerObjectIdentifier GostR3410x94CryptoProXchC = new DerObjectIdentifier(GostID + ".33.3"); + + //{ iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) } + public static readonly DerObjectIdentifier GostR3410x2001CryptoProA = new DerObjectIdentifier(GostID + ".35.1"); + public static readonly DerObjectIdentifier GostR3410x2001CryptoProB = new DerObjectIdentifier(GostID + ".35.2"); + public static readonly DerObjectIdentifier GostR3410x2001CryptoProC = new DerObjectIdentifier(GostID + ".35.3"); + + // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) } + public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchA = new DerObjectIdentifier(GostID + ".36.0"); + public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchB = new DerObjectIdentifier(GostID + ".36.1"); + + public static readonly DerObjectIdentifier GostElSgDH3410Default = new DerObjectIdentifier(GostID + ".36.0"); + public static readonly DerObjectIdentifier GostElSgDH3410x1 = new DerObjectIdentifier(GostID + ".36.1"); + } +} diff --git a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs new file mode 100644 index 000000000..998e0e06f --- /dev/null +++ b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + /** + * table of the available named parameters for GOST 3410-2001. + */ + public sealed class ECGost3410NamedCurves + { + private ECGost3410NamedCurves() + { + } + + internal static readonly IDictionary objIds = Platform.CreateHashtable(); + internal static readonly IDictionary parameters = Platform.CreateHashtable(); + internal static readonly IDictionary names = Platform.CreateHashtable(); + + static ECGost3410NamedCurves() + { + BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); + BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323"); + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a + new BigInteger("166")); // b + + ECDomainParameters ecParams = new ECDomainParameters( + curve, + curve.CreatePoint( + BigInteger.One, // x + new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"), // y + false), + mod_q); + + parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = ecParams; + + mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); + mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323"); + + curve = new FpCurve( + mod_p, // p + new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), + new BigInteger("166")); + + ecParams = new ECDomainParameters( + curve, + curve.CreatePoint( + BigInteger.One, // x + new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"), // y + false), + mod_q); + + parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = ecParams; + + mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p + mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q + + curve = new FpCurve( + mod_p, // p + new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a + new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595")); // b + + ecParams = new ECDomainParameters( + curve, + curve.CreatePoint( + BigInteger.One, // x + new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124"), // y + false), + mod_q); // q + + parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = ecParams; + + mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); + mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); + + curve = new FpCurve( + mod_p, // p + new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), + new BigInteger("32858")); + + ecParams = new ECDomainParameters( + curve, + curve.CreatePoint( + BigInteger.Zero, // x + new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"), // y + false), + mod_q); + + parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = ecParams; + + mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p + mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q + curve = new FpCurve( + mod_p, // p + new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a + new BigInteger("32858")); // b + + ecParams = new ECDomainParameters( + curve, + curve.CreatePoint( + BigInteger.Zero, // x + new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"), // y + false), + mod_q); // q + + parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = ecParams; + + objIds["GostR3410-2001-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProA; + objIds["GostR3410-2001-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProB; + objIds["GostR3410-2001-CryptoPro-C"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProC; + objIds["GostR3410-2001-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA; + objIds["GostR3410-2001-CryptoPro-XchB"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB; + + names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = "GostR3410-2001-CryptoPro-A"; + names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = "GostR3410-2001-CryptoPro-B"; + names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = "GostR3410-2001-CryptoPro-C"; + names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = "GostR3410-2001-CryptoPro-XchA"; + names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = "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( + DerObjectIdentifier oid) + { + return (ECDomainParameters) parameters[oid]; + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + + public static ECDomainParameters GetByName( + string name) + { + DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name]; + + if (oid != null) + { + return (ECDomainParameters) parameters[oid]; + } + + return null; + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static string GetName( + DerObjectIdentifier oid) + { + return (string) names[oid]; + } + + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier) objIds[name]; + } + } +} diff --git a/crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs b/crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs new file mode 100644 index 000000000..6f4435d7b --- /dev/null +++ b/crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + public class ECGost3410ParamSetParameters + : Asn1Encodable + { + internal readonly DerInteger p, q, a, b, x, y; + + public static ECGost3410ParamSetParameters GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static ECGost3410ParamSetParameters GetInstance( + object obj) + { + if (obj == null || obj is ECGost3410ParamSetParameters) + { + return (ECGost3410ParamSetParameters) obj; + } + + if (obj is Asn1Sequence) + { + return new ECGost3410ParamSetParameters((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name); + } + + public ECGost3410ParamSetParameters( + BigInteger a, + BigInteger b, + BigInteger p, + BigInteger q, + int x, + BigInteger y) + { + this.a = new DerInteger(a); + this.b = new DerInteger(b); + this.p = new DerInteger(p); + this.q = new DerInteger(q); + this.x = new DerInteger(x); + this.y = new DerInteger(y); + } + + public ECGost3410ParamSetParameters( + Asn1Sequence seq) + { + if (seq.Count != 6) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.a = DerInteger.GetInstance(seq[0]); + this.b = DerInteger.GetInstance(seq[1]); + this.p = DerInteger.GetInstance(seq[2]); + this.q = DerInteger.GetInstance(seq[3]); + this.x = DerInteger.GetInstance(seq[4]); + this.y = DerInteger.GetInstance(seq[5]); + } + + public BigInteger P + { + get { return p.PositiveValue; } + } + + public BigInteger Q + { + get { return q.PositiveValue; } + } + + public BigInteger A + { + get { return a.PositiveValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(a, b, p, q, x, y); + } + } +} diff --git a/crypto/src/asn1/cryptopro/GOST28147Parameters.cs b/crypto/src/asn1/cryptopro/GOST28147Parameters.cs new file mode 100644 index 000000000..eb7e0e3f6 --- /dev/null +++ b/crypto/src/asn1/cryptopro/GOST28147Parameters.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + public class Gost28147Parameters + : Asn1Encodable + { + private readonly Asn1OctetString iv; + private readonly DerObjectIdentifier paramSet; + + public static Gost28147Parameters GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static Gost28147Parameters GetInstance( + object obj) + { + if (obj == null || obj is Gost28147Parameters) + { + return (Gost28147Parameters) obj; + } + + if (obj is Asn1Sequence) + { + return new Gost28147Parameters((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name); + } + + private Gost28147Parameters( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.iv = Asn1OctetString.GetInstance(seq[0]); + this.paramSet = DerObjectIdentifier.GetInstance(seq[1]); + } + + /** + *
+         * Gost28147-89-Parameters ::=
+         *               SEQUENCE {
+         *                       iv                   Gost28147-89-IV,
+         *                       encryptionParamSet   OBJECT IDENTIFIER
+         *                }
+         *
+         *   Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(iv, paramSet); + } + } +} diff --git a/crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs b/crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs new file mode 100644 index 000000000..66dba51d7 --- /dev/null +++ b/crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + /** + * table of the available named parameters for GOST 3410-94. + */ + public sealed class Gost3410NamedParameters + { + private Gost3410NamedParameters() + { + } + + private static readonly IDictionary objIds = Platform.CreateHashtable(); + private static readonly IDictionary parameters = Platform.CreateHashtable(); + + private static readonly 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 + // } + // } + + ); + + private static readonly 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 + // } + // } + //} + ); + + private static readonly Gost3410ParamSetParameters cryptoProXchA = new Gost3410ParamSetParameters( + 1024, + new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"), + new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"), + new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887") + ); + + static Gost3410NamedParameters() + { + parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProA] = cryptoProA; + parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProB] = cryptoProB; + //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProC] = cryptoProC; + //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProD] = cryptoProD; + parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA] = cryptoProXchA; + //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchB] = cryptoProXchA; + //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchC] = cryptoProXchA; + + objIds["GostR3410-94-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProA; + objIds["GostR3410-94-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProB; + objIds["GostR3410-94-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA; + } + + /** + * 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( + DerObjectIdentifier oid) + { + return (Gost3410ParamSetParameters) parameters[oid]; + } + + /** + * returns an enumeration containing the name strings for parameters + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + + public static Gost3410ParamSetParameters GetByName( + string name) + { + DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name]; + + if (oid != null) + { + return (Gost3410ParamSetParameters) parameters[oid]; + } + + return null; + } + + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier) objIds[name]; + } + } +} diff --git a/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs new file mode 100644 index 000000000..f133cdf1b --- /dev/null +++ b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + public class Gost3410ParamSetParameters + : Asn1Encodable + { + private readonly int keySize; + private readonly DerInteger p, q, a; + + public static Gost3410ParamSetParameters GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static Gost3410ParamSetParameters GetInstance( + object obj) + { + if (obj == null || obj is Gost3410ParamSetParameters) + { + return (Gost3410ParamSetParameters) obj; + } + + if (obj is Asn1Sequence) + { + return new Gost3410ParamSetParameters((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name); + } + + public Gost3410ParamSetParameters( + int keySize, + BigInteger p, + BigInteger q, + BigInteger a) + { + this.keySize = keySize; + this.p = new DerInteger(p); + this.q = new DerInteger(q); + this.a = new DerInteger(a); + } + + private Gost3410ParamSetParameters( + Asn1Sequence seq) + { + if (seq.Count != 4) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.keySize = DerInteger.GetInstance(seq[0]).Value.IntValue; + this.p = DerInteger.GetInstance(seq[1]); + this.q = DerInteger.GetInstance(seq[2]); + this.a = DerInteger.GetInstance(seq[3]); + } + + public int KeySize + { + get { return keySize; } + } + + public BigInteger P + { + get { return p.PositiveValue; } + } + + public BigInteger Q + { + get { return q.PositiveValue; } + } + + public BigInteger A + { + get { return a.PositiveValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(new DerInteger(keySize), p, q, a); + } + } +} diff --git a/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs new file mode 100644 index 000000000..8bc1460af --- /dev/null +++ b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs @@ -0,0 +1,99 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.CryptoPro +{ + public class Gost3410PublicKeyAlgParameters + : Asn1Encodable + { + private DerObjectIdentifier publicKeyParamSet; + private DerObjectIdentifier digestParamSet; + private DerObjectIdentifier encryptionParamSet; + + public static Gost3410PublicKeyAlgParameters GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static Gost3410PublicKeyAlgParameters GetInstance( + object obj) + { + if (obj == null || obj is Gost3410PublicKeyAlgParameters) + { + return (Gost3410PublicKeyAlgParameters) obj; + } + + if (obj is Asn1Sequence) + { + return new Gost3410PublicKeyAlgParameters((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name); + } + + public Gost3410PublicKeyAlgParameters( + DerObjectIdentifier publicKeyParamSet, + DerObjectIdentifier digestParamSet) + : this (publicKeyParamSet, digestParamSet, null) + { + } + + public Gost3410PublicKeyAlgParameters( + DerObjectIdentifier publicKeyParamSet, + DerObjectIdentifier digestParamSet, + DerObjectIdentifier encryptionParamSet) + { + if (publicKeyParamSet == null) + throw new ArgumentNullException("publicKeyParamSet"); + if (digestParamSet == null) + throw new ArgumentNullException("digestParamSet"); + + this.publicKeyParamSet = publicKeyParamSet; + this.digestParamSet = digestParamSet; + this.encryptionParamSet = encryptionParamSet; + } + + public Gost3410PublicKeyAlgParameters( + Asn1Sequence seq) + { + this.publicKeyParamSet = (DerObjectIdentifier) seq[0]; + this.digestParamSet = (DerObjectIdentifier) seq[1]; + + if (seq.Count > 2) + { + this.encryptionParamSet = (DerObjectIdentifier) seq[2]; + } + } + + public DerObjectIdentifier PublicKeyParamSet + { + get { return publicKeyParamSet; } + } + + public DerObjectIdentifier DigestParamSet + { + get { return digestParamSet; } + } + + public DerObjectIdentifier EncryptionParamSet + { + get { return encryptionParamSet; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + publicKeyParamSet, digestParamSet); + + if (encryptionParamSet != null) + { + v.Add(encryptionParamSet); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/eac/EACObjectIdentifiers.cs b/crypto/src/asn1/eac/EACObjectIdentifiers.cs new file mode 100644 index 000000000..d54ef0eba --- /dev/null +++ b/crypto/src/asn1/eac/EACObjectIdentifiers.cs @@ -0,0 +1,50 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Eac +{ + public abstract class EacObjectIdentifiers + { + // bsi-de OBJECT IDENTIFIER ::= { + // itu-t(0) identified-organization(4) etsi(0) + // reserved(127) etsi-identified-organization(0) 7 + // } + public static readonly DerObjectIdentifier bsi_de = new DerObjectIdentifier("0.4.0.127.0.7"); + + // id-PK OBJECT IDENTIFIER ::= { + // bsi-de protocols(2) smartcard(2) 1 + // } + public static readonly DerObjectIdentifier id_PK = new DerObjectIdentifier(bsi_de + ".2.2.1"); + + public static readonly DerObjectIdentifier id_PK_DH = new DerObjectIdentifier(id_PK + ".1"); + public static readonly DerObjectIdentifier id_PK_ECDH = new DerObjectIdentifier(id_PK + ".2"); + + // id-CA OBJECT IDENTIFIER ::= { + // bsi-de protocols(2) smartcard(2) 3 + // } + public static readonly DerObjectIdentifier id_CA = new DerObjectIdentifier(bsi_de + ".2.2.3"); + public static readonly DerObjectIdentifier id_CA_DH = new DerObjectIdentifier(id_CA + ".1"); + public static readonly DerObjectIdentifier id_CA_DH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_DH + ".1"); + public static readonly DerObjectIdentifier id_CA_ECDH = new DerObjectIdentifier(id_CA + ".2"); + public static readonly DerObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_ECDH + ".1"); + + // + // id-TA OBJECT IDENTIFIER ::= { + // bsi-de protocols(2) smartcard(2) 2 + // } + public static readonly DerObjectIdentifier id_TA = new DerObjectIdentifier(bsi_de + ".2.2.2"); + + public static readonly DerObjectIdentifier id_TA_RSA = new DerObjectIdentifier(id_TA + ".1"); + public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".1"); + public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".2"); + public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".3"); + public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".4"); + public static readonly DerObjectIdentifier id_TA_ECDSA = new DerObjectIdentifier(id_TA + ".2"); + public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_1 = new DerObjectIdentifier(id_TA_ECDSA + ".1"); + public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_224 = new DerObjectIdentifier(id_TA_ECDSA + ".2"); + public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_256 = new DerObjectIdentifier(id_TA_ECDSA + ".3"); + public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_384 = new DerObjectIdentifier(id_TA_ECDSA + ".4"); + public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_512 = new DerObjectIdentifier(id_TA_ECDSA + ".5"); + } +} diff --git a/crypto/src/asn1/esf/CertificateValues.cs b/crypto/src/asn1/esf/CertificateValues.cs new file mode 100644 index 000000000..e0fb39b83 --- /dev/null +++ b/crypto/src/asn1/esf/CertificateValues.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.3.1 Certificate Values Attribute Definition + /// + /// CertificateValues ::= SEQUENCE OF Certificate + /// + /// + public class CertificateValues + : Asn1Encodable + { + private readonly Asn1Sequence certificates; + + public static CertificateValues GetInstance( + object obj) + { + if (obj == null || obj is CertificateValues) + return (CertificateValues) obj; + + if (obj is Asn1Sequence) + return new CertificateValues((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CertificateValues' factory: " + + obj.GetType().Name, + "obj"); + } + + private CertificateValues( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + foreach (Asn1Encodable ae in seq) + { + X509CertificateStructure.GetInstance(ae.ToAsn1Object()); + } + + this.certificates = seq; + } + + public CertificateValues( + params X509CertificateStructure[] certificates) + { + if (certificates == null) + throw new ArgumentNullException("certificates"); + + this.certificates = new DerSequence(certificates); + } + + public CertificateValues( + IEnumerable certificates) + { + if (certificates == null) + throw new ArgumentNullException("certificates"); + if (!CollectionUtilities.CheckElementsAreOfType(certificates, typeof(X509CertificateStructure))) + throw new ArgumentException("Must contain only 'X509CertificateStructure' objects", "certificates"); + + this.certificates = new DerSequence( + Asn1EncodableVector.FromEnumerable(certificates)); + } + + public X509CertificateStructure[] GetCertificates() + { + X509CertificateStructure[] result = new X509CertificateStructure[certificates.Count]; + for (int i = 0; i < certificates.Count; ++i) + { + result[i] = X509CertificateStructure.GetInstance(certificates[i]); + } + return result; + } + + public override Asn1Object ToAsn1Object() + { + return certificates; + } + } +} diff --git a/crypto/src/asn1/esf/CommitmentTypeIdentifier.cs b/crypto/src/asn1/esf/CommitmentTypeIdentifier.cs new file mode 100644 index 000000000..65cd45b4a --- /dev/null +++ b/crypto/src/asn1/esf/CommitmentTypeIdentifier.cs @@ -0,0 +1,17 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Esf +{ + public abstract class CommitmentTypeIdentifier + { + public static readonly DerObjectIdentifier ProofOfOrigin = PkcsObjectIdentifiers.IdCtiEtsProofOfOrigin; + public static readonly DerObjectIdentifier ProofOfReceipt = PkcsObjectIdentifiers.IdCtiEtsProofOfReceipt; + public static readonly DerObjectIdentifier ProofOfDelivery = PkcsObjectIdentifiers.IdCtiEtsProofOfDelivery; + public static readonly DerObjectIdentifier ProofOfSender = PkcsObjectIdentifiers.IdCtiEtsProofOfSender; + public static readonly DerObjectIdentifier ProofOfApproval = PkcsObjectIdentifiers.IdCtiEtsProofOfApproval; + public static readonly DerObjectIdentifier ProofOfCreation = PkcsObjectIdentifiers.IdCtiEtsProofOfCreation; + } +} diff --git a/crypto/src/asn1/esf/CommitmentTypeIndication.cs b/crypto/src/asn1/esf/CommitmentTypeIndication.cs new file mode 100644 index 000000000..8342cbf8d --- /dev/null +++ b/crypto/src/asn1/esf/CommitmentTypeIndication.cs @@ -0,0 +1,95 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Esf +{ + public class CommitmentTypeIndication + : Asn1Encodable + { + private readonly DerObjectIdentifier commitmentTypeId; + private readonly Asn1Sequence commitmentTypeQualifier; + + public static CommitmentTypeIndication GetInstance( + object obj) + { + if (obj == null || obj is CommitmentTypeIndication) + return (CommitmentTypeIndication) obj; + + if (obj is Asn1Sequence) + return new CommitmentTypeIndication((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CommitmentTypeIndication' factory: " + + obj.GetType().Name, + "obj"); + } + + public CommitmentTypeIndication( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.commitmentTypeId = (DerObjectIdentifier) seq[0].ToAsn1Object(); + + if (seq.Count > 1) + { + this.commitmentTypeQualifier = (Asn1Sequence) seq[1].ToAsn1Object(); + } + } + + public CommitmentTypeIndication( + DerObjectIdentifier commitmentTypeId) + : this(commitmentTypeId, null) + { + } + + public CommitmentTypeIndication( + DerObjectIdentifier commitmentTypeId, + Asn1Sequence commitmentTypeQualifier) + { + if (commitmentTypeId == null) + throw new ArgumentNullException("commitmentTypeId"); + + this.commitmentTypeId = commitmentTypeId; + + if (commitmentTypeQualifier != null) + { + this.commitmentTypeQualifier = commitmentTypeQualifier; + } + } + + public DerObjectIdentifier CommitmentTypeID + { + get { return commitmentTypeId; } + } + + public Asn1Sequence CommitmentTypeQualifier + { + get { return commitmentTypeQualifier; } + } + + /** + *
+        * CommitmentTypeIndication ::= SEQUENCE {
+        *      commitmentTypeId   CommitmentTypeIdentifier,
+        *      commitmentTypeQualifier   SEQUENCE SIZE (1..MAX) OF
+        *              CommitmentTypeQualifier OPTIONAL }
+        * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(commitmentTypeId); + + if (commitmentTypeQualifier != null) + { + v.Add(commitmentTypeQualifier); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/CommitmentTypeQualifier.cs b/crypto/src/asn1/esf/CommitmentTypeQualifier.cs new file mode 100644 index 000000000..09ff70714 --- /dev/null +++ b/crypto/src/asn1/esf/CommitmentTypeQualifier.cs @@ -0,0 +1,119 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /** + * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126). + * + *
+    *   CommitmentTypeQualifier ::= SEQUENCE {
+    *       commitmentTypeIdentifier  CommitmentTypeIdentifier,
+    *       qualifier          ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+    * 
+ */ + public class CommitmentTypeQualifier + : Asn1Encodable + { + private readonly DerObjectIdentifier commitmentTypeIdentifier; + private readonly Asn1Object qualifier; + + /** + * Creates a new CommitmentTypeQualifier instance. + * + * @param commitmentTypeIdentifier a CommitmentTypeIdentifier value + */ + public CommitmentTypeQualifier( + DerObjectIdentifier commitmentTypeIdentifier) + : this(commitmentTypeIdentifier, null) + { + } + + /** + * Creates a new CommitmentTypeQualifier instance. + * + * @param commitmentTypeIdentifier a CommitmentTypeIdentifier value + * @param qualifier the qualifier, defined by the above field. + */ + public CommitmentTypeQualifier( + DerObjectIdentifier commitmentTypeIdentifier, + Asn1Encodable qualifier) + { + if (commitmentTypeIdentifier == null) + throw new ArgumentNullException("commitmentTypeIdentifier"); + + this.commitmentTypeIdentifier = commitmentTypeIdentifier; + + if (qualifier != null) + { + this.qualifier = qualifier.ToAsn1Object(); + } + } + + /** + * Creates a new CommitmentTypeQualifier instance. + * + * @param as CommitmentTypeQualifier structure + * encoded as an Asn1Sequence. + */ + public CommitmentTypeQualifier( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + commitmentTypeIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object(); + + if (seq.Count > 1) + { + qualifier = seq[1].ToAsn1Object(); + } + } + + public static CommitmentTypeQualifier GetInstance( + object obj) + { + if (obj == null || obj is CommitmentTypeQualifier) + return (CommitmentTypeQualifier) obj; + + if (obj is Asn1Sequence) + return new CommitmentTypeQualifier((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CommitmentTypeQualifier' factory: " + + obj.GetType().Name, + "obj"); + } + + public DerObjectIdentifier CommitmentTypeIdentifier + { + get { return commitmentTypeIdentifier; } + } + + public Asn1Object Qualifier + { + get { return qualifier; } + } + + /** + * Returns a DER-encodable representation of this instance. + * + * @return a Asn1Object value + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + commitmentTypeIdentifier); + + if (qualifier != null) + { + v.Add(qualifier); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/CompleteCertificateRefs.cs b/crypto/src/asn1/esf/CompleteCertificateRefs.cs new file mode 100644 index 000000000..7f1c835c9 --- /dev/null +++ b/crypto/src/asn1/esf/CompleteCertificateRefs.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.1 Complete Certificate Refs Attribute Definition + /// + /// CompleteCertificateRefs ::= SEQUENCE OF OtherCertID + /// + /// + public class CompleteCertificateRefs + : Asn1Encodable + { + private readonly Asn1Sequence otherCertIDs; + + public static CompleteCertificateRefs GetInstance( + object obj) + { + if (obj == null || obj is CompleteCertificateRefs) + return (CompleteCertificateRefs) obj; + + if (obj is Asn1Sequence) + return new CompleteCertificateRefs((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CompleteCertificateRefs' factory: " + + obj.GetType().Name, + "obj"); + } + + private CompleteCertificateRefs( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + foreach (Asn1Encodable ae in seq) + { + OtherCertID.GetInstance(ae.ToAsn1Object()); + } + + this.otherCertIDs = seq; + } + + public CompleteCertificateRefs( + params OtherCertID[] otherCertIDs) + { + if (otherCertIDs == null) + throw new ArgumentNullException("otherCertIDs"); + + this.otherCertIDs = new DerSequence(otherCertIDs); + } + + public CompleteCertificateRefs( + IEnumerable otherCertIDs) + { + if (otherCertIDs == null) + throw new ArgumentNullException("otherCertIDs"); + if (!CollectionUtilities.CheckElementsAreOfType(otherCertIDs, typeof(OtherCertID))) + throw new ArgumentException("Must contain only 'OtherCertID' objects", "otherCertIDs"); + + this.otherCertIDs = new DerSequence( + Asn1EncodableVector.FromEnumerable(otherCertIDs)); + } + + public OtherCertID[] GetOtherCertIDs() + { + OtherCertID[] result = new OtherCertID[otherCertIDs.Count]; + for (int i = 0; i < otherCertIDs.Count; ++i) + { + result[i] = OtherCertID.GetInstance(otherCertIDs[i].ToAsn1Object()); + } + return result; + } + + public override Asn1Object ToAsn1Object() + { + return otherCertIDs; + } + } +} diff --git a/crypto/src/asn1/esf/CompleteRevocationRefs.cs b/crypto/src/asn1/esf/CompleteRevocationRefs.cs new file mode 100644 index 000000000..4e1fb403d --- /dev/null +++ b/crypto/src/asn1/esf/CompleteRevocationRefs.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef + /// + /// + public class CompleteRevocationRefs + : Asn1Encodable + { + private readonly Asn1Sequence crlOcspRefs; + + public static CompleteRevocationRefs GetInstance( + object obj) + { + if (obj == null || obj is CompleteRevocationRefs) + return (CompleteRevocationRefs) obj; + + if (obj is Asn1Sequence) + return new CompleteRevocationRefs((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CompleteRevocationRefs' factory: " + + obj.GetType().Name, + "obj"); + } + + private CompleteRevocationRefs( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + foreach (Asn1Encodable ae in seq) + { + CrlOcspRef.GetInstance(ae.ToAsn1Object()); + } + + this.crlOcspRefs = seq; + } + + public CompleteRevocationRefs( + params CrlOcspRef[] crlOcspRefs) + { + if (crlOcspRefs == null) + throw new ArgumentNullException("crlOcspRefs"); + + this.crlOcspRefs = new DerSequence(crlOcspRefs); + } + + public CompleteRevocationRefs( + IEnumerable crlOcspRefs) + { + if (crlOcspRefs == null) + throw new ArgumentNullException("crlOcspRefs"); + if (!CollectionUtilities.CheckElementsAreOfType(crlOcspRefs, typeof(CrlOcspRef))) + throw new ArgumentException("Must contain only 'CrlOcspRef' objects", "crlOcspRefs"); + + this.crlOcspRefs = new DerSequence( + Asn1EncodableVector.FromEnumerable(crlOcspRefs)); + } + + public CrlOcspRef[] GetCrlOcspRefs() + { + CrlOcspRef[] result = new CrlOcspRef[crlOcspRefs.Count]; + for (int i = 0; i < crlOcspRefs.Count; ++i) + { + result[i] = CrlOcspRef.GetInstance(crlOcspRefs[i].ToAsn1Object()); + } + return result; + } + + public override Asn1Object ToAsn1Object() + { + return crlOcspRefs; + } + } +} diff --git a/crypto/src/asn1/esf/CrlIdentifier.cs b/crypto/src/asn1/esf/CrlIdentifier.cs new file mode 100644 index 000000000..dfff7d838 --- /dev/null +++ b/crypto/src/asn1/esf/CrlIdentifier.cs @@ -0,0 +1,110 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// CrlIdentifier ::= SEQUENCE + /// { + /// crlissuer Name, + /// crlIssuedTime UTCTime, + /// crlNumber INTEGER OPTIONAL + /// } + /// + /// + public class CrlIdentifier + : Asn1Encodable + { + private readonly X509Name crlIssuer; + private readonly DerUtcTime crlIssuedTime; + private readonly DerInteger crlNumber; + + public static CrlIdentifier GetInstance( + object obj) + { + if (obj == null || obj is CrlIdentifier) + return (CrlIdentifier) obj; + + if (obj is Asn1Sequence) + return new CrlIdentifier((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CrlIdentifier' factory: " + + obj.GetType().Name, + "obj"); + } + + private CrlIdentifier( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 2 || seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.crlIssuer = X509Name.GetInstance(seq[0]); + this.crlIssuedTime = DerUtcTime.GetInstance(seq[1]); + + if (seq.Count > 2) + { + this.crlNumber = DerInteger.GetInstance(seq[2]); + } + } + + public CrlIdentifier( + X509Name crlIssuer, + DateTime crlIssuedTime) + : this(crlIssuer, crlIssuedTime, null) + { + } + + public CrlIdentifier( + X509Name crlIssuer, + DateTime crlIssuedTime, + BigInteger crlNumber) + { + if (crlIssuer == null) + throw new ArgumentNullException("crlIssuer"); + + this.crlIssuer = crlIssuer; + this.crlIssuedTime = new DerUtcTime(crlIssuedTime); + + if (crlNumber != null) + { + this.crlNumber = new DerInteger(crlNumber); + } + } + + public X509Name CrlIssuer + { + get { return crlIssuer; } + } + + public DateTime CrlIssuedTime + { + get { return crlIssuedTime.ToAdjustedDateTime(); } + } + + public BigInteger CrlNumber + { + get { return crlNumber == null ? null : crlNumber.Value; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + crlIssuer.ToAsn1Object(), crlIssuedTime); + + if (crlNumber != null) + { + v.Add(crlNumber); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/CrlListID.cs b/crypto/src/asn1/esf/CrlListID.cs new file mode 100644 index 000000000..2aae9b965 --- /dev/null +++ b/crypto/src/asn1/esf/CrlListID.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// CRLListID ::= SEQUENCE + /// { + /// crls SEQUENCE OF CrlValidatedID + /// } + /// + /// + public class CrlListID + : Asn1Encodable + { + private readonly Asn1Sequence crls; + + public static CrlListID GetInstance( + object obj) + { + if (obj == null || obj is CrlListID) + return (CrlListID) obj; + + if (obj is Asn1Sequence) + return new CrlListID((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CrlListID' factory: " + + obj.GetType().Name, + "obj"); + } + + private CrlListID( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 1) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.crls = (Asn1Sequence) seq[0].ToAsn1Object(); + + foreach (Asn1Encodable ae in this.crls) + { + CrlValidatedID.GetInstance(ae.ToAsn1Object()); + } + } + + public CrlListID( + params CrlValidatedID[] crls) + { + if (crls == null) + throw new ArgumentNullException("crls"); + + this.crls = new DerSequence(crls); + } + + public CrlListID( + IEnumerable crls) + { + if (crls == null) + throw new ArgumentNullException("crls"); + if (!CollectionUtilities.CheckElementsAreOfType(crls, typeof(CrlValidatedID))) + throw new ArgumentException("Must contain only 'CrlValidatedID' objects", "crls"); + + this.crls = new DerSequence( + Asn1EncodableVector.FromEnumerable(crls)); + } + + public CrlValidatedID[] GetCrls() + { + CrlValidatedID[] result = new CrlValidatedID[crls.Count]; + for (int i = 0; i < crls.Count; ++i) + { + result[i] = CrlValidatedID.GetInstance(crls[i].ToAsn1Object()); + } + return result; + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(crls); + } + } +} diff --git a/crypto/src/asn1/esf/CrlOcspRef.cs b/crypto/src/asn1/esf/CrlOcspRef.cs new file mode 100644 index 000000000..c8e10d504 --- /dev/null +++ b/crypto/src/asn1/esf/CrlOcspRef.cs @@ -0,0 +1,111 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// CrlOcspRef ::= SEQUENCE { + /// crlids [0] CRLListID OPTIONAL, + /// ocspids [1] OcspListID OPTIONAL, + /// otherRev [2] OtherRevRefs OPTIONAL + /// } + /// + /// + public class CrlOcspRef + : Asn1Encodable + { + private readonly CrlListID crlids; + private readonly OcspListID ocspids; + private readonly OtherRevRefs otherRev; + + public static CrlOcspRef GetInstance( + object obj) + { + if (obj == null || obj is CrlOcspRef) + return (CrlOcspRef) obj; + + if (obj is Asn1Sequence) + return new CrlOcspRef((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CrlOcspRef' factory: " + + obj.GetType().Name, + "obj"); + } + + private CrlOcspRef( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + foreach (Asn1TaggedObject taggedObj in seq) + { + Asn1Object asn1Obj = taggedObj.GetObject(); + + switch (taggedObj.TagNo) + { + case 0: + this.crlids = CrlListID.GetInstance(asn1Obj); + break; + case 1: + this.ocspids = OcspListID.GetInstance(asn1Obj); + break; + case 2: + this.otherRev = OtherRevRefs.GetInstance(asn1Obj); + break; + default: + throw new ArgumentException("Illegal tag in CrlOcspRef", "seq"); + } + } + } + + public CrlOcspRef( + CrlListID crlids, + OcspListID ocspids, + OtherRevRefs otherRev) + { + this.crlids = crlids; + this.ocspids = ocspids; + this.otherRev = otherRev; + } + + public CrlListID CrlIDs + { + get { return crlids; } + } + + public OcspListID OcspIDs + { + get { return ocspids; } + } + + public OtherRevRefs OtherRev + { + get { return otherRev; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (crlids != null) + { + v.Add(new DerTaggedObject(true, 0, crlids.ToAsn1Object())); + } + + if (ocspids != null) + { + v.Add(new DerTaggedObject(true, 1, ocspids.ToAsn1Object())); + } + + if (otherRev != null) + { + v.Add(new DerTaggedObject(true, 2, otherRev.ToAsn1Object())); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/CrlValidatedID.cs b/crypto/src/asn1/esf/CrlValidatedID.cs new file mode 100644 index 000000000..165f547a8 --- /dev/null +++ b/crypto/src/asn1/esf/CrlValidatedID.cs @@ -0,0 +1,89 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// CrlValidatedID ::= SEQUENCE { + /// crlHash OtherHash, + /// crlIdentifier CrlIdentifier OPTIONAL} + /// + /// + public class CrlValidatedID + : Asn1Encodable + { + private readonly OtherHash crlHash; + private readonly CrlIdentifier crlIdentifier; + + public static CrlValidatedID GetInstance( + object obj) + { + if (obj == null || obj is CrlValidatedID) + return (CrlValidatedID) obj; + + if (obj is Asn1Sequence) + return new CrlValidatedID((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'CrlValidatedID' factory: " + + obj.GetType().Name, + "obj"); + } + + private CrlValidatedID( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.crlHash = OtherHash.GetInstance(seq[0].ToAsn1Object()); + + if (seq.Count > 1) + { + this.crlIdentifier = CrlIdentifier.GetInstance(seq[1].ToAsn1Object()); + } + } + + public CrlValidatedID( + OtherHash crlHash) + : this(crlHash, null) + { + } + + public CrlValidatedID( + OtherHash crlHash, + CrlIdentifier crlIdentifier) + { + if (crlHash == null) + throw new ArgumentNullException("crlHash"); + + this.crlHash = crlHash; + this.crlIdentifier = crlIdentifier; + } + + public OtherHash CrlHash + { + get { return crlHash; } + } + + public CrlIdentifier CrlIdentifier + { + get { return crlIdentifier; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(crlHash.ToAsn1Object()); + + if (crlIdentifier != null) + { + v.Add(crlIdentifier.ToAsn1Object()); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/ESFAttributes.cs b/crypto/src/asn1/esf/ESFAttributes.cs new file mode 100644 index 000000000..9401ffb8e --- /dev/null +++ b/crypto/src/asn1/esf/ESFAttributes.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Esf +{ + public abstract class EsfAttributes + { + public static readonly DerObjectIdentifier SigPolicyId = PkcsObjectIdentifiers.IdAAEtsSigPolicyID; + public static readonly DerObjectIdentifier CommitmentType = PkcsObjectIdentifiers.IdAAEtsCommitmentType; + public static readonly DerObjectIdentifier SignerLocation = PkcsObjectIdentifiers.IdAAEtsSignerLocation; + public static readonly DerObjectIdentifier SignerAttr = PkcsObjectIdentifiers.IdAAEtsSignerAttr; + public static readonly DerObjectIdentifier OtherSigCert = PkcsObjectIdentifiers.IdAAEtsOtherSigCert; + public static readonly DerObjectIdentifier ContentTimestamp = PkcsObjectIdentifiers.IdAAEtsContentTimestamp; + public static readonly DerObjectIdentifier CertificateRefs = PkcsObjectIdentifiers.IdAAEtsCertificateRefs; + public static readonly DerObjectIdentifier RevocationRefs = PkcsObjectIdentifiers.IdAAEtsRevocationRefs; + public static readonly DerObjectIdentifier CertValues = PkcsObjectIdentifiers.IdAAEtsCertValues; + public static readonly DerObjectIdentifier RevocationValues = PkcsObjectIdentifiers.IdAAEtsRevocationValues; + public static readonly DerObjectIdentifier EscTimeStamp = PkcsObjectIdentifiers.IdAAEtsEscTimeStamp; + public static readonly DerObjectIdentifier CertCrlTimestamp = PkcsObjectIdentifiers.IdAAEtsCertCrlTimestamp; + public static readonly DerObjectIdentifier ArchiveTimestamp = PkcsObjectIdentifiers.IdAAEtsArchiveTimestamp; + public static readonly DerObjectIdentifier ArchiveTimestampV2 = new DerObjectIdentifier(PkcsObjectIdentifiers.IdAA + ".48"); + } +} diff --git a/crypto/src/asn1/esf/OcspIdentifier.cs b/crypto/src/asn1/esf/OcspIdentifier.cs new file mode 100644 index 000000000..949b68243 --- /dev/null +++ b/crypto/src/asn1/esf/OcspIdentifier.cs @@ -0,0 +1,77 @@ +using System; + +using Org.BouncyCastle.Asn1.Ocsp; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// OcspIdentifier ::= SEQUENCE { + /// ocspResponderID ResponderID, + /// -- As in OCSP response data + /// producedAt GeneralizedTime + /// -- As in OCSP response data + /// } + /// + /// + public class OcspIdentifier + : Asn1Encodable + { + private readonly ResponderID ocspResponderID; + private readonly DerGeneralizedTime producedAt; + + public static OcspIdentifier GetInstance( + object obj) + { + if (obj == null || obj is OcspIdentifier) + return (OcspIdentifier) obj; + + if (obj is Asn1Sequence) + return new OcspIdentifier((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OcspIdentifier' factory: " + + obj.GetType().Name, + "obj"); + } + + private OcspIdentifier( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.ocspResponderID = ResponderID.GetInstance(seq[0].ToAsn1Object()); + this.producedAt = (DerGeneralizedTime) seq[1].ToAsn1Object(); + } + + public OcspIdentifier( + ResponderID ocspResponderID, + DateTime producedAt) + { + if (ocspResponderID == null) + throw new ArgumentNullException(); + + this.ocspResponderID = ocspResponderID; + this.producedAt = new DerGeneralizedTime(producedAt); + } + + public ResponderID OcspResponderID + { + get { return ocspResponderID; } + } + + public DateTime ProducedAt + { + get { return producedAt.ToDateTime(); } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(ocspResponderID, producedAt); + } + } +} diff --git a/crypto/src/asn1/esf/OcspListID.cs b/crypto/src/asn1/esf/OcspListID.cs new file mode 100644 index 000000000..1f3f3a337 --- /dev/null +++ b/crypto/src/asn1/esf/OcspListID.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// OcspListID ::= SEQUENCE { + /// ocspResponses SEQUENCE OF OcspResponsesID + /// } + /// + /// + public class OcspListID + : Asn1Encodable + { + private readonly Asn1Sequence ocspResponses; + + public static OcspListID GetInstance( + object obj) + { + if (obj == null || obj is OcspListID) + return (OcspListID) obj; + + if (obj is Asn1Sequence) + return new OcspListID((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OcspListID' factory: " + + obj.GetType().Name, + "obj"); + } + + private OcspListID( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 1) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.ocspResponses = (Asn1Sequence) seq[0].ToAsn1Object(); + + foreach (Asn1Encodable ae in this.ocspResponses) + { + OcspResponsesID.GetInstance(ae.ToAsn1Object()); + } + } + + public OcspListID( + params OcspResponsesID[] ocspResponses) + { + if (ocspResponses == null) + throw new ArgumentNullException("ocspResponses"); + + this.ocspResponses = new DerSequence(ocspResponses); + } + + public OcspListID( + IEnumerable ocspResponses) + { + if (ocspResponses == null) + throw new ArgumentNullException("ocspResponses"); + if (!CollectionUtilities.CheckElementsAreOfType(ocspResponses, typeof(OcspResponsesID))) + throw new ArgumentException("Must contain only 'OcspResponsesID' objects", "ocspResponses"); + + this.ocspResponses = new DerSequence( + Asn1EncodableVector.FromEnumerable(ocspResponses)); + } + + public OcspResponsesID[] GetOcspResponses() + { + OcspResponsesID[] result = new OcspResponsesID[ocspResponses.Count]; + for (int i = 0; i < ocspResponses.Count; ++i) + { + result[i] = OcspResponsesID.GetInstance(ocspResponses[i].ToAsn1Object()); + } + return result; + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(ocspResponses); + } + } +} diff --git a/crypto/src/asn1/esf/OcspResponsesID.cs b/crypto/src/asn1/esf/OcspResponsesID.cs new file mode 100644 index 000000000..e09508a01 --- /dev/null +++ b/crypto/src/asn1/esf/OcspResponsesID.cs @@ -0,0 +1,92 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// OcspResponsesID ::= SEQUENCE { + /// ocspIdentifier OcspIdentifier, + /// ocspRepHash OtherHash OPTIONAL + /// } + /// + /// + public class OcspResponsesID + : Asn1Encodable + { + private readonly OcspIdentifier ocspIdentifier; + private readonly OtherHash ocspRepHash; + + public static OcspResponsesID GetInstance( + object obj) + { + if (obj == null || obj is OcspResponsesID) + return (OcspResponsesID) obj; + + if (obj is Asn1Sequence) + return new OcspResponsesID((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OcspResponsesID' factory: " + + obj.GetType().Name, + "obj"); + } + + private OcspResponsesID( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.ocspIdentifier = OcspIdentifier.GetInstance(seq[0].ToAsn1Object()); + + if (seq.Count > 1) + { + this.ocspRepHash = OtherHash.GetInstance(seq[1].ToAsn1Object()); + } + } + + public OcspResponsesID( + OcspIdentifier ocspIdentifier) + : this(ocspIdentifier, null) + { + } + + public OcspResponsesID( + OcspIdentifier ocspIdentifier, + OtherHash ocspRepHash) + { + if (ocspIdentifier == null) + throw new ArgumentNullException("ocspIdentifier"); + + this.ocspIdentifier = ocspIdentifier; + this.ocspRepHash = ocspRepHash; + } + + public OcspIdentifier OcspIdentifier + { + get { return ocspIdentifier; } + } + + public OtherHash OcspRepHash + { + get { return ocspRepHash; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + ocspIdentifier.ToAsn1Object()); + + if (ocspRepHash != null) + { + v.Add(ocspRepHash.ToAsn1Object()); + } + + return new DerSequence(v); + } + + } +} diff --git a/crypto/src/asn1/esf/OtherCertID.cs b/crypto/src/asn1/esf/OtherCertID.cs new file mode 100644 index 000000000..6d1255535 --- /dev/null +++ b/crypto/src/asn1/esf/OtherCertID.cs @@ -0,0 +1,93 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// OtherCertID ::= SEQUENCE { + /// otherCertHash OtherHash, + /// issuerSerial IssuerSerial OPTIONAL + /// } + /// + /// + public class OtherCertID + : Asn1Encodable + { + private readonly OtherHash otherCertHash; + private readonly IssuerSerial issuerSerial; + + public static OtherCertID GetInstance( + object obj) + { + if (obj == null || obj is OtherCertID) + return (OtherCertID) obj; + + if (obj is Asn1Sequence) + return new OtherCertID((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OtherCertID' factory: " + + obj.GetType().Name, + "obj"); + } + + private OtherCertID( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.otherCertHash = OtherHash.GetInstance(seq[0].ToAsn1Object()); + + if (seq.Count > 1) + { + this.issuerSerial = IssuerSerial.GetInstance(seq[1].ToAsn1Object()); + } + } + + public OtherCertID( + OtherHash otherCertHash) + : this(otherCertHash, null) + { + } + + public OtherCertID( + OtherHash otherCertHash, + IssuerSerial issuerSerial) + { + if (otherCertHash == null) + throw new ArgumentNullException("otherCertHash"); + + this.otherCertHash = otherCertHash; + this.issuerSerial = issuerSerial; + } + + public OtherHash OtherCertHash + { + get { return otherCertHash; } + } + + public IssuerSerial IssuerSerial + { + get { return issuerSerial; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + otherCertHash.ToAsn1Object()); + + if (issuerSerial != null) + { + v.Add(issuerSerial.ToAsn1Object()); + } + + return new DerSequence(v); + } + + } +} diff --git a/crypto/src/asn1/esf/OtherHash.cs b/crypto/src/asn1/esf/OtherHash.cs new file mode 100644 index 000000000..2ee162478 --- /dev/null +++ b/crypto/src/asn1/esf/OtherHash.cs @@ -0,0 +1,88 @@ +using System; + +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// OtherHash ::= CHOICE { + /// sha1Hash OtherHashValue, -- This contains a SHA-1 hash + /// otherHash OtherHashAlgAndValue + /// } + /// + /// OtherHashValue ::= OCTET STRING + /// + /// + public class OtherHash + : Asn1Encodable, IAsn1Choice + { + private readonly Asn1OctetString sha1Hash; + private readonly OtherHashAlgAndValue otherHash; + + public static OtherHash GetInstance( + object obj) + { + if (obj == null || obj is OtherHash) + return (OtherHash) obj; + + if (obj is Asn1OctetString) + return new OtherHash((Asn1OctetString) obj); + + return new OtherHash( + OtherHashAlgAndValue.GetInstance(obj)); + } + + public OtherHash( + byte[] sha1Hash) + { + if (sha1Hash == null) + throw new ArgumentNullException("sha1Hash"); + + this.sha1Hash = new DerOctetString(sha1Hash); + } + + public OtherHash( + Asn1OctetString sha1Hash) + { + if (sha1Hash == null) + throw new ArgumentNullException("sha1Hash"); + + this.sha1Hash = sha1Hash; + } + + public OtherHash( + OtherHashAlgAndValue otherHash) + { + if (otherHash == null) + throw new ArgumentNullException("otherHash"); + + this.otherHash = otherHash; + } + + public AlgorithmIdentifier HashAlgorithm + { + get + { + return otherHash == null + ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1) + : otherHash.HashAlgorithm; + } + } + + public byte[] GetHashValue() + { + return otherHash == null + ? sha1Hash.GetOctets() + : otherHash.GetHashValue(); + } + + public override Asn1Object ToAsn1Object() + { + return otherHash == null + ? sha1Hash + : otherHash.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/esf/OtherHashAlgAndValue.cs b/crypto/src/asn1/esf/OtherHashAlgAndValue.cs new file mode 100644 index 000000000..b6bd4f498 --- /dev/null +++ b/crypto/src/asn1/esf/OtherHashAlgAndValue.cs @@ -0,0 +1,94 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// Summary description for OtherHashAlgAndValue. + /// + /// + /// + /// OtherHashAlgAndValue ::= SEQUENCE { + /// hashAlgorithm AlgorithmIdentifier, + /// hashValue OtherHashValue + /// } + /// + /// OtherHashValue ::= OCTET STRING + /// + /// + public class OtherHashAlgAndValue + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly Asn1OctetString hashValue; + + public static OtherHashAlgAndValue GetInstance( + object obj) + { + if (obj == null || obj is OtherHashAlgAndValue) + return (OtherHashAlgAndValue) obj; + + if (obj is Asn1Sequence) + return new OtherHashAlgAndValue((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OtherHashAlgAndValue' factory: " + + obj.GetType().Name, + "obj"); + } + + private OtherHashAlgAndValue( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0].ToAsn1Object()); + this.hashValue = (Asn1OctetString) seq[1].ToAsn1Object(); + } + + public OtherHashAlgAndValue( + AlgorithmIdentifier hashAlgorithm, + byte[] hashValue) + { + if (hashAlgorithm == null) + throw new ArgumentNullException("hashAlgorithm"); + if (hashValue == null) + throw new ArgumentNullException("hashValue"); + + this.hashAlgorithm = hashAlgorithm; + this.hashValue = new DerOctetString(hashValue); + } + + public OtherHashAlgAndValue( + AlgorithmIdentifier hashAlgorithm, + Asn1OctetString hashValue) + { + if (hashAlgorithm == null) + throw new ArgumentNullException("hashAlgorithm"); + if (hashValue == null) + throw new ArgumentNullException("hashValue"); + + this.hashAlgorithm = hashAlgorithm; + this.hashValue = hashValue; + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public byte[] GetHashValue() + { + return hashValue.GetOctets(); + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(hashAlgorithm, hashValue); + } + } +} diff --git a/crypto/src/asn1/esf/OtherRevRefs.cs b/crypto/src/asn1/esf/OtherRevRefs.cs new file mode 100644 index 000000000..56713e3f2 --- /dev/null +++ b/crypto/src/asn1/esf/OtherRevRefs.cs @@ -0,0 +1,78 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition + /// + /// OtherRevRefs ::= SEQUENCE + /// { + /// otherRevRefType OtherRevRefType, + /// otherRevRefs ANY DEFINED BY otherRevRefType + /// } + /// + /// OtherRevRefType ::= OBJECT IDENTIFIER + /// + /// + public class OtherRevRefs + : Asn1Encodable + { + private readonly DerObjectIdentifier otherRevRefType; + private readonly Asn1Object otherRevRefs; + + public static OtherRevRefs GetInstance( + object obj) + { + if (obj == null || obj is OtherRevRefs) + return (OtherRevRefs) obj; + + if (obj is Asn1Sequence) + return new OtherRevRefs((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OtherRevRefs' factory: " + + obj.GetType().Name, + "obj"); + } + + private OtherRevRefs( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.otherRevRefType = (DerObjectIdentifier) seq[0].ToAsn1Object(); + this.otherRevRefs = seq[1].ToAsn1Object(); + } + + public OtherRevRefs( + DerObjectIdentifier otherRevRefType, + Asn1Encodable otherRevRefs) + { + if (otherRevRefType == null) + throw new ArgumentNullException("otherRevRefType"); + if (otherRevRefs == null) + throw new ArgumentNullException("otherRevRefs"); + + this.otherRevRefType = otherRevRefType; + this.otherRevRefs = otherRevRefs.ToAsn1Object(); + } + + public DerObjectIdentifier OtherRevRefType + { + get { return otherRevRefType; } + } + + public Asn1Object OtherRevRefsObject + { + get { return otherRevRefs; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(otherRevRefType, otherRevRefs); + } + } +} diff --git a/crypto/src/asn1/esf/OtherRevVals.cs b/crypto/src/asn1/esf/OtherRevVals.cs new file mode 100644 index 000000000..b88a1a72a --- /dev/null +++ b/crypto/src/asn1/esf/OtherRevVals.cs @@ -0,0 +1,78 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 3126: 4.3.2 Revocation Values Attribute Definition + /// + /// OtherRevVals ::= SEQUENCE + /// { + /// otherRevValType OtherRevValType, + /// otherRevVals ANY DEFINED BY otherRevValType + /// } + /// + /// OtherRevValType ::= OBJECT IDENTIFIER + /// + /// + public class OtherRevVals + : Asn1Encodable + { + private readonly DerObjectIdentifier otherRevValType; + private readonly Asn1Object otherRevVals; + + public static OtherRevVals GetInstance( + object obj) + { + if (obj == null || obj is OtherRevVals) + return (OtherRevVals) obj; + + if (obj is Asn1Sequence) + return new OtherRevVals((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OtherRevVals' factory: " + + obj.GetType().Name, + "obj"); + } + + private OtherRevVals( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.otherRevValType = (DerObjectIdentifier) seq[0].ToAsn1Object(); + this.otherRevVals = seq[1].ToAsn1Object(); + } + + public OtherRevVals( + DerObjectIdentifier otherRevValType, + Asn1Encodable otherRevVals) + { + if (otherRevValType == null) + throw new ArgumentNullException("otherRevValType"); + if (otherRevVals == null) + throw new ArgumentNullException("otherRevVals"); + + this.otherRevValType = otherRevValType; + this.otherRevVals = otherRevVals.ToAsn1Object(); + } + + public DerObjectIdentifier OtherRevValType + { + get { return otherRevValType; } + } + + public Asn1Object OtherRevValsObject + { + get { return otherRevVals; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(otherRevValType, otherRevVals); + } + } +} diff --git a/crypto/src/asn1/esf/OtherSigningCertificate.cs b/crypto/src/asn1/esf/OtherSigningCertificate.cs new file mode 100644 index 000000000..90e385a33 --- /dev/null +++ b/crypto/src/asn1/esf/OtherSigningCertificate.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// OtherSigningCertificate ::= SEQUENCE { + /// certs SEQUENCE OF OtherCertID, + /// policies SEQUENCE OF PolicyInformation OPTIONAL + /// } + /// + /// + public class OtherSigningCertificate + : Asn1Encodable + { + private readonly Asn1Sequence certs; + private readonly Asn1Sequence policies; + + public static OtherSigningCertificate GetInstance( + object obj) + { + if (obj == null || obj is OtherSigningCertificate) + return (OtherSigningCertificate) obj; + + if (obj is Asn1Sequence) + return new OtherSigningCertificate((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'OtherSigningCertificate' factory: " + + obj.GetType().Name, + "obj"); + } + + private OtherSigningCertificate( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object()); + + if (seq.Count > 1) + { + this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object()); + } + } + + public OtherSigningCertificate( + params OtherCertID[] certs) + : this(certs, null) + { + } + + public OtherSigningCertificate( + OtherCertID[] certs, + params PolicyInformation[] policies) + { + if (certs == null) + throw new ArgumentNullException("certs"); + + this.certs = new DerSequence(certs); + + if (policies != null) + { + this.policies = new DerSequence(policies); + } + } + + public OtherSigningCertificate( + IEnumerable certs) + : this(certs, null) + { + } + + public OtherSigningCertificate( + IEnumerable certs, + IEnumerable policies) + { + if (certs == null) + throw new ArgumentNullException("certs"); + if (!CollectionUtilities.CheckElementsAreOfType(certs, typeof(OtherCertID))) + throw new ArgumentException("Must contain only 'OtherCertID' objects", "certs"); + + this.certs = new DerSequence( + Asn1EncodableVector.FromEnumerable(certs)); + + if (policies != null) + { + if (!CollectionUtilities.CheckElementsAreOfType(policies, typeof(PolicyInformation))) + throw new ArgumentException("Must contain only 'PolicyInformation' objects", "policies"); + + this.policies = new DerSequence( + Asn1EncodableVector.FromEnumerable(policies)); + } + } + + public OtherCertID[] GetCerts() + { + OtherCertID[] cs = new OtherCertID[certs.Count]; + for (int i = 0; i < certs.Count; ++i) + { + cs[i] = OtherCertID.GetInstance(certs[i].ToAsn1Object()); + } + return cs; + } + + public PolicyInformation[] GetPolicies() + { + if (policies == null) + return null; + + PolicyInformation[] ps = new PolicyInformation[policies.Count]; + for (int i = 0; i < policies.Count; ++i) + { + ps[i] = PolicyInformation.GetInstance(policies[i].ToAsn1Object()); + } + return ps; + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certs); + + if (policies != null) + { + v.Add(policies); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/RevocationValues.cs b/crypto/src/asn1/esf/RevocationValues.cs new file mode 100644 index 000000000..a7b47b47a --- /dev/null +++ b/crypto/src/asn1/esf/RevocationValues.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// RFC 5126: 6.3.4. revocation-values Attribute Definition + /// + /// RevocationValues ::= SEQUENCE { + /// crlVals [0] SEQUENCE OF CertificateList OPTIONAL, + /// ocspVals [1] SEQUENCE OF BasicOCSPResponse OPTIONAL, + /// otherRevVals [2] OtherRevVals OPTIONAL + /// } + /// + /// + public class RevocationValues + : Asn1Encodable + { + private readonly Asn1Sequence crlVals; + private readonly Asn1Sequence ocspVals; + private readonly OtherRevVals otherRevVals; + + public static RevocationValues GetInstance( + object obj) + { + if (obj == null || obj is RevocationValues) + return (RevocationValues) obj; + + return new RevocationValues(Asn1Sequence.GetInstance(obj)); + } + + private RevocationValues( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + foreach (Asn1TaggedObject taggedObj in seq) + { + Asn1Object asn1Obj = taggedObj.GetObject(); + switch (taggedObj.TagNo) + { + case 0: + Asn1Sequence crlValsSeq = (Asn1Sequence) asn1Obj; + foreach (Asn1Encodable ae in crlValsSeq) + { + CertificateList.GetInstance(ae.ToAsn1Object()); + } + this.crlVals = crlValsSeq; + break; + case 1: + Asn1Sequence ocspValsSeq = (Asn1Sequence) asn1Obj; + foreach (Asn1Encodable ae in ocspValsSeq) + { + BasicOcspResponse.GetInstance(ae.ToAsn1Object()); + } + this.ocspVals = ocspValsSeq; + break; + case 2: + this.otherRevVals = OtherRevVals.GetInstance(asn1Obj); + break; + default: + throw new ArgumentException("Illegal tag in RevocationValues", "seq"); + } + } + } + + public RevocationValues( + CertificateList[] crlVals, + BasicOcspResponse[] ocspVals, + OtherRevVals otherRevVals) + { + if (crlVals != null) + { + this.crlVals = new DerSequence(crlVals); + } + + if (ocspVals != null) + { + this.ocspVals = new DerSequence(ocspVals); + } + + this.otherRevVals = otherRevVals; + } + + public RevocationValues( + IEnumerable crlVals, + IEnumerable ocspVals, + OtherRevVals otherRevVals) + { + if (crlVals != null) + { + if (!CollectionUtilities.CheckElementsAreOfType(crlVals, typeof(CertificateList))) + throw new ArgumentException("Must contain only 'CertificateList' objects", "crlVals"); + + this.crlVals = new DerSequence( + Asn1EncodableVector.FromEnumerable(crlVals)); + } + + if (ocspVals != null) + { + if (!CollectionUtilities.CheckElementsAreOfType(ocspVals, typeof(BasicOcspResponse))) + throw new ArgumentException("Must contain only 'BasicOcspResponse' objects", "ocspVals"); + + this.ocspVals = new DerSequence( + Asn1EncodableVector.FromEnumerable(ocspVals)); + } + + this.otherRevVals = otherRevVals; + } + + public CertificateList[] GetCrlVals() + { + CertificateList[] result = new CertificateList[crlVals.Count]; + for (int i = 0; i < crlVals.Count; ++i) + { + result[i] = CertificateList.GetInstance(crlVals[i].ToAsn1Object()); + } + return result; + } + + public BasicOcspResponse[] GetOcspVals() + { + BasicOcspResponse[] result = new BasicOcspResponse[ocspVals.Count]; + for (int i = 0; i < ocspVals.Count; ++i) + { + result[i] = BasicOcspResponse.GetInstance(ocspVals[i].ToAsn1Object()); + } + return result; + } + + public OtherRevVals OtherRevVals + { + get { return otherRevVals; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (crlVals != null) + { + v.Add(new DerTaggedObject(true, 0, crlVals)); + } + + if (ocspVals != null) + { + v.Add(new DerTaggedObject(true, 1, ocspVals)); + } + + if (otherRevVals != null) + { + v.Add(new DerTaggedObject(true, 2, otherRevVals.ToAsn1Object())); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/SigPolicyQualifierInfo.cs b/crypto/src/asn1/esf/SigPolicyQualifierInfo.cs new file mode 100644 index 000000000..2d36bc751 --- /dev/null +++ b/crypto/src/asn1/esf/SigPolicyQualifierInfo.cs @@ -0,0 +1,71 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// SigPolicyQualifierInfo ::= SEQUENCE { + /// sigPolicyQualifierId SigPolicyQualifierId, + /// sigQualifier ANY DEFINED BY sigPolicyQualifierId + /// } + /// + /// SigPolicyQualifierId ::= OBJECT IDENTIFIER + /// + /// + public class SigPolicyQualifierInfo + : Asn1Encodable + { + private readonly DerObjectIdentifier sigPolicyQualifierId; + private readonly Asn1Object sigQualifier; + + public static SigPolicyQualifierInfo GetInstance( + object obj) + { + if (obj == null || obj is SigPolicyQualifierInfo) + return (SigPolicyQualifierInfo) obj; + + if (obj is Asn1Sequence) + return new SigPolicyQualifierInfo((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'SigPolicyQualifierInfo' factory: " + + obj.GetType().Name, + "obj"); + } + + private SigPolicyQualifierInfo( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.sigPolicyQualifierId = (DerObjectIdentifier) seq[0].ToAsn1Object(); + this.sigQualifier = seq[1].ToAsn1Object(); + } + + public SigPolicyQualifierInfo( + DerObjectIdentifier sigPolicyQualifierId, + Asn1Encodable sigQualifier) + { + this.sigPolicyQualifierId = sigPolicyQualifierId; + this.sigQualifier = sigQualifier.ToAsn1Object(); + } + + public DerObjectIdentifier SigPolicyQualifierId + { + get { return sigPolicyQualifierId; } + } + + public Asn1Object SigQualifier + { + get { return sigQualifier; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(sigPolicyQualifierId, sigQualifier); + } + } +} diff --git a/crypto/src/asn1/esf/SignaturePolicyId.cs b/crypto/src/asn1/esf/SignaturePolicyId.cs new file mode 100644 index 000000000..545be2cf4 --- /dev/null +++ b/crypto/src/asn1/esf/SignaturePolicyId.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// SignaturePolicyId ::= SEQUENCE { + /// sigPolicyIdentifier SigPolicyId, + /// sigPolicyHash SigPolicyHash, + /// sigPolicyQualifiers SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL + /// } + /// + /// SigPolicyId ::= OBJECT IDENTIFIER + /// + /// SigPolicyHash ::= OtherHashAlgAndValue + /// + /// + public class SignaturePolicyId + : Asn1Encodable + { + private readonly DerObjectIdentifier sigPolicyIdentifier; + private readonly OtherHashAlgAndValue sigPolicyHash; + private readonly Asn1Sequence sigPolicyQualifiers; + + public static SignaturePolicyId GetInstance( + object obj) + { + if (obj == null || obj is SignaturePolicyId) + return (SignaturePolicyId) obj; + + if (obj is Asn1Sequence) + return new SignaturePolicyId((Asn1Sequence) obj); + + throw new ArgumentException( + "Unknown object in 'SignaturePolicyId' factory: " + + obj.GetType().Name, + "obj"); + } + + private SignaturePolicyId( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + if (seq.Count < 2 || seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.sigPolicyIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object(); + this.sigPolicyHash = OtherHashAlgAndValue.GetInstance(seq[1].ToAsn1Object()); + + if (seq.Count > 2) + { + this.sigPolicyQualifiers = (Asn1Sequence) seq[2].ToAsn1Object(); + } + } + + public SignaturePolicyId( + DerObjectIdentifier sigPolicyIdentifier, + OtherHashAlgAndValue sigPolicyHash) + : this(sigPolicyIdentifier, sigPolicyHash, null) + { + } + + public SignaturePolicyId( + DerObjectIdentifier sigPolicyIdentifier, + OtherHashAlgAndValue sigPolicyHash, + params SigPolicyQualifierInfo[] sigPolicyQualifiers) + { + if (sigPolicyIdentifier == null) + throw new ArgumentNullException("sigPolicyIdentifier"); + if (sigPolicyHash == null) + throw new ArgumentNullException("sigPolicyHash"); + + this.sigPolicyIdentifier = sigPolicyIdentifier; + this.sigPolicyHash = sigPolicyHash; + + if (sigPolicyQualifiers != null) + { + this.sigPolicyQualifiers = new DerSequence(sigPolicyQualifiers); + } + } + + public SignaturePolicyId( + DerObjectIdentifier sigPolicyIdentifier, + OtherHashAlgAndValue sigPolicyHash, + IEnumerable sigPolicyQualifiers) + { + if (sigPolicyIdentifier == null) + throw new ArgumentNullException("sigPolicyIdentifier"); + if (sigPolicyHash == null) + throw new ArgumentNullException("sigPolicyHash"); + + this.sigPolicyIdentifier = sigPolicyIdentifier; + this.sigPolicyHash = sigPolicyHash; + + if (sigPolicyQualifiers != null) + { + if (!CollectionUtilities.CheckElementsAreOfType(sigPolicyQualifiers, typeof(SigPolicyQualifierInfo))) + throw new ArgumentException("Must contain only 'SigPolicyQualifierInfo' objects", "sigPolicyQualifiers"); + + this.sigPolicyQualifiers = new DerSequence( + Asn1EncodableVector.FromEnumerable(sigPolicyQualifiers)); + } + } + + public DerObjectIdentifier SigPolicyIdentifier + { + get { return sigPolicyIdentifier; } + } + + public OtherHashAlgAndValue SigPolicyHash + { + get { return sigPolicyHash; } + } + + public SigPolicyQualifierInfo[] GetSigPolicyQualifiers() + { + if (sigPolicyQualifiers == null) + return null; + + SigPolicyQualifierInfo[] infos = new SigPolicyQualifierInfo[sigPolicyQualifiers.Count]; + for (int i = 0; i < sigPolicyQualifiers.Count; ++i) + { + infos[i] = SigPolicyQualifierInfo.GetInstance(sigPolicyQualifiers[i]); + } + return infos; + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + sigPolicyIdentifier, sigPolicyHash.ToAsn1Object()); + + if (sigPolicyQualifiers != null) + { + v.Add(sigPolicyQualifiers.ToAsn1Object()); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs b/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs new file mode 100644 index 000000000..3a639f444 --- /dev/null +++ b/crypto/src/asn1/esf/SignaturePolicyIdentifier.cs @@ -0,0 +1,64 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /// + /// + /// SignaturePolicyIdentifier ::= CHOICE { + /// SignaturePolicyId SignaturePolicyId, + /// SignaturePolicyImplied SignaturePolicyImplied + /// } + /// + /// SignaturePolicyImplied ::= NULL + /// + /// + public class SignaturePolicyIdentifier + : Asn1Encodable, IAsn1Choice + { + private readonly SignaturePolicyId sigPolicy; + + public static SignaturePolicyIdentifier GetInstance( + object obj) + { + if (obj == null || obj is SignaturePolicyIdentifier) + return (SignaturePolicyIdentifier) obj; + + if (obj is SignaturePolicyId) + return new SignaturePolicyIdentifier((SignaturePolicyId) obj); + + if (obj is Asn1Null) + return new SignaturePolicyIdentifier(); + + throw new ArgumentException( + "Unknown object in 'SignaturePolicyIdentifier' factory: " + + obj.GetType().Name, + "obj"); + } + + public SignaturePolicyIdentifier() + { + this.sigPolicy = null; + } + + public SignaturePolicyIdentifier( + SignaturePolicyId signaturePolicyId) + { + if (signaturePolicyId == null) + throw new ArgumentNullException("signaturePolicyId"); + + this.sigPolicy = signaturePolicyId; + } + + public SignaturePolicyId SignaturePolicyId + { + get { return sigPolicy; } + } + + public override Asn1Object ToAsn1Object() + { + return sigPolicy == null + ? DerNull.Instance + : sigPolicy.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/esf/SignerAttribute.cs b/crypto/src/asn1/esf/SignerAttribute.cs new file mode 100644 index 000000000..ddee53c69 --- /dev/null +++ b/crypto/src/asn1/esf/SignerAttribute.cs @@ -0,0 +1,96 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Esf +{ + public class SignerAttribute + : Asn1Encodable + { + private Asn1Sequence claimedAttributes; + private AttributeCertificate certifiedAttributes; + + public static SignerAttribute GetInstance( + object obj) + { + if (obj == null || obj is SignerAttribute) + return (SignerAttribute) obj; + + if (obj is Asn1Sequence) + return new SignerAttribute(obj); + + throw new ArgumentException( + "Unknown object in 'SignerAttribute' factory: " + + obj.GetType().Name, + "obj"); + } + + private SignerAttribute( + object obj) + { + Asn1Sequence seq = (Asn1Sequence) obj; + DerTaggedObject taggedObject = (DerTaggedObject) seq[0]; + if (taggedObject.TagNo == 0) + { + claimedAttributes = Asn1Sequence.GetInstance(taggedObject, true); + } + else if (taggedObject.TagNo == 1) + { + certifiedAttributes = AttributeCertificate.GetInstance(taggedObject); + } + else + { + throw new ArgumentException("illegal tag.", "obj"); + } + } + + public SignerAttribute( + Asn1Sequence claimedAttributes) + { + this.claimedAttributes = claimedAttributes; + } + + public SignerAttribute( + AttributeCertificate certifiedAttributes) + { + this.certifiedAttributes = certifiedAttributes; + } + + public virtual Asn1Sequence ClaimedAttributes + { + get { return claimedAttributes; } + } + + public virtual AttributeCertificate CertifiedAttributes + { + get { return certifiedAttributes; } + } + + /** + * + *
+		*  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.
+		* 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (claimedAttributes != null) + { + v.Add(new DerTaggedObject(0, claimedAttributes)); + } + else + { + v.Add(new DerTaggedObject(1, certifiedAttributes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/esf/SignerLocation.cs b/crypto/src/asn1/esf/SignerLocation.cs new file mode 100644 index 000000000..d2cef51bb --- /dev/null +++ b/crypto/src/asn1/esf/SignerLocation.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Esf +{ + /** + * Signer-Location attribute (RFC3126). + * + *
+	*   SignerLocation ::= SEQUENCE {
+	*       countryName        [0] DirectoryString OPTIONAL,
+	*       localityName       [1] DirectoryString OPTIONAL,
+	*       postalAddress      [2] PostalAddress OPTIONAL }
+	*
+	*   PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+	* 
+ */ + public class SignerLocation + : Asn1Encodable + { + // TODO Should these be using DirectoryString? + private DerUtf8String countryName; + private DerUtf8String localityName; + private Asn1Sequence postalAddress; + + public SignerLocation( + Asn1Sequence seq) + { + foreach (Asn1TaggedObject obj in seq) + { + switch (obj.TagNo) + { + case 0: + this.countryName = DerUtf8String.GetInstance(obj, true); + break; + case 1: + this.localityName = DerUtf8String.GetInstance(obj, true); + break; + case 2: + bool isExplicit = obj.IsExplicit(); // handle erroneous implicitly tagged sequences + this.postalAddress = Asn1Sequence.GetInstance(obj, isExplicit); + if (postalAddress != null && postalAddress.Count > 6) + throw new ArgumentException("postal address must contain less than 6 strings"); + break; + default: + throw new ArgumentException("illegal tag"); + } + } + } + + public SignerLocation( + DerUtf8String countryName, + DerUtf8String localityName, + Asn1Sequence postalAddress) + { + if (postalAddress != null && postalAddress.Count > 6) + { + throw new ArgumentException("postal address must contain less than 6 strings"); + } + + if (countryName != null) + { + this.countryName = DerUtf8String.GetInstance(countryName.ToAsn1Object()); + } + + if (localityName != null) + { + this.localityName = DerUtf8String.GetInstance(localityName.ToAsn1Object()); + } + + if (postalAddress != null) + { + this.postalAddress = (Asn1Sequence) postalAddress.ToAsn1Object(); + } + } + + public static SignerLocation GetInstance( + object obj) + { + if (obj == null || obj is SignerLocation) + { + return (SignerLocation) obj; + } + + return new SignerLocation(Asn1Sequence.GetInstance(obj)); + } + + public DerUtf8String CountryName + { + get { return countryName; } + } + + public DerUtf8String LocalityName + { + get { return localityName; } + } + + public Asn1Sequence PostalAddress + { + get { return postalAddress; } + } + + /** + *
+		*   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)) }
+		* 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/ess/ContentHints.cs b/crypto/src/asn1/ess/ContentHints.cs new file mode 100644 index 000000000..a430fea8d --- /dev/null +++ b/crypto/src/asn1/ess/ContentHints.cs @@ -0,0 +1,92 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class ContentHints + : Asn1Encodable + { + private readonly DerUtf8String contentDescription; + private readonly DerObjectIdentifier contentType; + + public static ContentHints GetInstance( + object o) + { + if (o == null || o is ContentHints) + { + return (ContentHints)o; + } + + if (o is Asn1Sequence) + { + return new ContentHints((Asn1Sequence)o); + } + + throw new ArgumentException("unknown object in 'ContentHints' factory : " + + o.GetType().Name + "."); + } + + /** + * constructor + */ + private ContentHints( + Asn1Sequence seq) + { + IAsn1Convertible field = seq[0]; + if (field.ToAsn1Object() is DerUtf8String) + { + contentDescription = DerUtf8String.GetInstance(field); + contentType = DerObjectIdentifier.GetInstance(seq[1]); + } + else + { + contentType = DerObjectIdentifier.GetInstance(seq[0]); + } + } + + public ContentHints( + DerObjectIdentifier contentType) + { + this.contentType = contentType; + this.contentDescription = null; + } + + public ContentHints( + DerObjectIdentifier contentType, + DerUtf8String contentDescription) + { + this.contentType = contentType; + this.contentDescription = contentDescription; + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public DerUtf8String ContentDescription + { + get { return contentDescription; } + } + + /** + *
+		 * ContentHints ::= SEQUENCE {
+		 *   contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+		 *   contentType ContentType }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (contentDescription != null) + { + v.Add(contentDescription); + } + + v.Add(contentType); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ess/ContentIdentifier.cs b/crypto/src/asn1/ess/ContentIdentifier.cs new file mode 100644 index 000000000..8058dcc53 --- /dev/null +++ b/crypto/src/asn1/ess/ContentIdentifier.cs @@ -0,0 +1,65 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class ContentIdentifier + : Asn1Encodable + { + private Asn1OctetString value; + + public static ContentIdentifier GetInstance( + object o) + { + if (o == null || o is ContentIdentifier) + { + return (ContentIdentifier) o; + } + + if (o is Asn1OctetString) + { + return new ContentIdentifier((Asn1OctetString) o); + } + + throw new ArgumentException( + "unknown object in 'ContentIdentifier' factory : " + + o.GetType().Name + "."); + } + + /** + * Create from OCTET STRING whose octets represent the identifier. + */ + public ContentIdentifier( + Asn1OctetString value) + { + this.value = value; + } + + /** + * Create from byte array representing the identifier. + */ + public ContentIdentifier( + byte[] value) + : this(new DerOctetString(value)) + { + } + + public Asn1OctetString Value + { + get { return value; } + } + + /** + * The definition of ContentIdentifier is + *
+		 * ContentIdentifier ::=  OCTET STRING
+		 * 
+ * 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 override Asn1Object ToAsn1Object() + { + return value; + } + } +} diff --git a/crypto/src/asn1/ess/ESSCertID.cs b/crypto/src/asn1/ess/ESSCertID.cs new file mode 100644 index 000000000..4d449a746 --- /dev/null +++ b/crypto/src/asn1/ess/ESSCertID.cs @@ -0,0 +1,93 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class EssCertID + : Asn1Encodable + { + private Asn1OctetString certHash; + private IssuerSerial issuerSerial; + + public static EssCertID GetInstance( + object o) + { + if (o == null || o is EssCertID) + { + return (EssCertID) o; + } + + if (o is Asn1Sequence) + { + return new EssCertID((Asn1Sequence) o); + } + + throw new ArgumentException( + "unknown object in 'EssCertID' factory : " + + o.GetType().Name + "."); + } + + /** + * constructor + */ + public EssCertID( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + this.certHash = Asn1OctetString.GetInstance(seq[0]); + + if (seq.Count > 1) + { + issuerSerial = IssuerSerial.GetInstance(seq[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 IssuerSerial + { + get { return issuerSerial; } + } + + /** + *
+		 * EssCertID ::= SEQUENCE {
+		 *     certHash Hash,
+		 *     issuerSerial IssuerSerial OPTIONAL }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certHash); + + if (issuerSerial != null) + { + v.Add(issuerSerial); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ess/ESSCertIDv2.cs b/crypto/src/asn1/ess/ESSCertIDv2.cs new file mode 100644 index 000000000..35ce699e8 --- /dev/null +++ b/crypto/src/asn1/ess/ESSCertIDv2.cs @@ -0,0 +1,146 @@ +using System; + +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class EssCertIDv2 + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly byte[] certHash; + private readonly IssuerSerial issuerSerial; + + private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier( + NistObjectIdentifiers.IdSha256); + + public static EssCertIDv2 GetInstance(object obj) + { + if (obj == null) + return null; + EssCertIDv2 existing = obj as EssCertIDv2; + if (existing != null) + return existing; + return new EssCertIDv2(Asn1Sequence.GetInstance(obj)); + } + + private EssCertIDv2( + Asn1Sequence seq) + { + if (seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + int count = 0; + + if (seq[0] is Asn1OctetString) + { + // Default value + this.hashAlgorithm = DefaultAlgID; + } + else + { + this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[count++].ToAsn1Object()); + } + + this.certHash = Asn1OctetString.GetInstance(seq[count++].ToAsn1Object()).GetOctets(); + + if (seq.Count > count) + { + this.issuerSerial = IssuerSerial.GetInstance( + Asn1Sequence.GetInstance(seq[count].ToAsn1Object())); + } + } + + 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 = DefaultAlgID; + } + else + { + this.hashAlgorithm = algId; + } + + this.certHash = certHash; + this.issuerSerial = issuerSerial; + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return this.hashAlgorithm; } + } + + public byte[] GetCertHash() + { + return Arrays.Clone(certHash); + } + + public IssuerSerial IssuerSerial + { + get { return issuerSerial; } + } + + /** + *
+         * EssCertIDv2 ::=  SEQUENCE {
+         *     hashAlgorithm     AlgorithmIdentifier
+         *              DEFAULT {algorithm id-sha256},
+         *     certHash          Hash,
+         *     issuerSerial      IssuerSerial OPTIONAL
+         * }
+         *
+         * Hash ::= OCTET STRING
+         *
+         * IssuerSerial ::= SEQUENCE {
+         *     issuer         GeneralNames,
+         *     serialNumber   CertificateSerialNumber
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (!hashAlgorithm.Equals(DefaultAlgID)) + { + v.Add(hashAlgorithm); + } + + v.Add(new DerOctetString(certHash).ToAsn1Object()); + + if (issuerSerial != null) + { + v.Add(issuerSerial); + } + + return new DerSequence(v); + } + + } +} diff --git a/crypto/src/asn1/ess/OtherCertID.cs b/crypto/src/asn1/ess/OtherCertID.cs new file mode 100644 index 000000000..972ef8c6b --- /dev/null +++ b/crypto/src/asn1/ess/OtherCertID.cs @@ -0,0 +1,132 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ess +{ + [Obsolete("Use version in Asn1.Esf instead")] + public class OtherCertID + : Asn1Encodable + { + private Asn1Encodable otherCertHash; + private IssuerSerial issuerSerial; + + public static OtherCertID GetInstance( + object o) + { + if (o == null || o is OtherCertID) + { + return (OtherCertID) o; + } + + if (o is Asn1Sequence) + { + return new OtherCertID((Asn1Sequence) o); + } + + throw new ArgumentException( + "unknown object in 'OtherCertID' factory : " + + o.GetType().Name + "."); + } + + /** + * constructor + */ + public OtherCertID( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + if (seq[0].ToAsn1Object() is Asn1OctetString) + { + otherCertHash = Asn1OctetString.GetInstance(seq[0]); + } + else + { + otherCertHash = DigestInfo.GetInstance(seq[0]); + } + + if (seq.Count > 1) + { + issuerSerial = IssuerSerial.GetInstance(Asn1Sequence.GetInstance(seq[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 AlgorithmHash + { + get + { + if (otherCertHash.ToAsn1Object() is Asn1OctetString) + { + // SHA-1 + return new AlgorithmIdentifier("1.3.14.3.2.26"); + } + + return DigestInfo.GetInstance(otherCertHash).AlgorithmID; + } + } + + public byte[] GetCertHash() + { + if (otherCertHash.ToAsn1Object() is Asn1OctetString) + { + // SHA-1 + return ((Asn1OctetString) otherCertHash.ToAsn1Object()).GetOctets(); + } + + return DigestInfo.GetInstance(otherCertHash).GetDigest(); + } + + public IssuerSerial IssuerSerial + { + get { return issuerSerial; } + } + + /** + *
+		 * OtherCertID ::= SEQUENCE {
+		 *     otherCertHash    OtherHash,
+		 *     issuerSerial     IssuerSerial OPTIONAL }
+		 *
+		 * OtherHash ::= CHOICE {
+		 *     sha1Hash     OCTET STRING,
+		 *     otherHash    OtherHashAlgAndValue }
+		 *
+		 * OtherHashAlgAndValue ::= SEQUENCE {
+		 *     hashAlgorithm    AlgorithmIdentifier,
+		 *     hashValue        OCTET STRING }
+		 *
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(otherCertHash); + + if (issuerSerial != null) + { + v.Add(issuerSerial); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ess/OtherSigningCertificate.cs b/crypto/src/asn1/ess/OtherSigningCertificate.cs new file mode 100644 index 000000000..c165fecea --- /dev/null +++ b/crypto/src/asn1/ess/OtherSigningCertificate.cs @@ -0,0 +1,109 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ess +{ + [Obsolete("Use version in Asn1.Esf instead")] + public class OtherSigningCertificate + : Asn1Encodable + { + private Asn1Sequence certs, policies; + + public static OtherSigningCertificate GetInstance( + object o) + { + if (o == null || o is OtherSigningCertificate) + { + return (OtherSigningCertificate) o; + } + + if (o is Asn1Sequence) + { + return new OtherSigningCertificate((Asn1Sequence) o); + } + + throw new ArgumentException( + "unknown object in 'OtherSigningCertificate' factory : " + + o.GetType().Name + "."); + } + + /** + * constructors + */ + public OtherSigningCertificate( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + this.certs = Asn1Sequence.GetInstance(seq[0]); + + if (seq.Count > 1) + { + this.policies = Asn1Sequence.GetInstance(seq[1]); + } + } + + public OtherSigningCertificate( + OtherCertID otherCertID) + { + certs = new DerSequence(otherCertID); + } + + public OtherCertID[] GetCerts() + { + OtherCertID[] cs = new OtherCertID[certs.Count]; + + for (int i = 0; i != certs.Count; ++i) + { + cs[i] = OtherCertID.GetInstance(certs[i]); + } + + return cs; + } + + public PolicyInformation[] GetPolicies() + { + if (policies == null) + { + return null; + } + + PolicyInformation[] ps = new PolicyInformation[policies.Count]; + + for (int i = 0; i != policies.Count; i++) + { + ps[i] = PolicyInformation.GetInstance(policies[i]); + } + + return ps; + } + + /** + * The definition of OtherSigningCertificate is + *
+		 * OtherSigningCertificate ::=  SEQUENCE {
+		 *      certs        SEQUENCE OF OtherCertID,
+		 *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+		 * }
+		 * 
+ * 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 override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certs); + + if (policies != null) + { + v.Add(policies); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ess/SigningCertificate.cs b/crypto/src/asn1/ess/SigningCertificate.cs new file mode 100644 index 000000000..366749bc3 --- /dev/null +++ b/crypto/src/asn1/ess/SigningCertificate.cs @@ -0,0 +1,108 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class SigningCertificate + : Asn1Encodable + { + private Asn1Sequence certs, policies; + + public static SigningCertificate GetInstance( + object o) + { + if (o == null || o is SigningCertificate) + { + return (SigningCertificate) o; + } + + if (o is Asn1Sequence) + { + return new SigningCertificate((Asn1Sequence) o); + } + + throw new ArgumentException( + "unknown object in 'SigningCertificate' factory : " + + o.GetType().Name + "."); + } + + /** + * constructors + */ + public SigningCertificate( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + this.certs = Asn1Sequence.GetInstance(seq[0]); + + if (seq.Count > 1) + { + this.policies = Asn1Sequence.GetInstance(seq[1]); + } + } + + public SigningCertificate( + EssCertID essCertID) + { + certs = new DerSequence(essCertID); + } + + public EssCertID[] GetCerts() + { + EssCertID[] cs = new EssCertID[certs.Count]; + + for (int i = 0; i != certs.Count; i++) + { + cs[i] = EssCertID.GetInstance(certs[i]); + } + + return cs; + } + + public PolicyInformation[] GetPolicies() + { + if (policies == null) + { + return null; + } + + PolicyInformation[] ps = new PolicyInformation[policies.Count]; + + for (int i = 0; i != policies.Count; i++) + { + ps[i] = PolicyInformation.GetInstance(policies[i]); + } + + return ps; + } + + /** + * The definition of SigningCertificate is + *
+		 * SigningCertificate ::=  SEQUENCE {
+		 *      certs        SEQUENCE OF EssCertID,
+		 *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+		 * }
+		 * 
+ * 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 override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certs); + + if (policies != null) + { + v.Add(policies); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ess/SigningCertificateV2.cs b/crypto/src/asn1/ess/SigningCertificateV2.cs new file mode 100644 index 000000000..cabecc1ba --- /dev/null +++ b/crypto/src/asn1/ess/SigningCertificateV2.cs @@ -0,0 +1,112 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ess +{ + public class SigningCertificateV2 + : Asn1Encodable + { + private readonly Asn1Sequence certs; + private readonly Asn1Sequence policies; + + public static SigningCertificateV2 GetInstance( + object o) + { + if (o == null || o is SigningCertificateV2) + return (SigningCertificateV2) o; + + if (o is Asn1Sequence) + return new SigningCertificateV2((Asn1Sequence) o); + + throw new ArgumentException( + "unknown object in 'SigningCertificateV2' factory : " + + o.GetType().Name + "."); + } + + private SigningCertificateV2( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object()); + + if (seq.Count > 1) + { + this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object()); + } + } + + public SigningCertificateV2( + EssCertIDv2 cert) + { + this.certs = new DerSequence(cert); + } + + public SigningCertificateV2( + EssCertIDv2[] certs) + { + this.certs = new DerSequence(certs); + } + + public SigningCertificateV2( + EssCertIDv2[] certs, + PolicyInformation[] policies) + { + this.certs = new DerSequence(certs); + + if (policies != null) + { + this.policies = new DerSequence(policies); + } + } + + public EssCertIDv2[] GetCerts() + { + EssCertIDv2[] certIds = new EssCertIDv2[certs.Count]; + for (int i = 0; i != certs.Count; i++) + { + certIds[i] = EssCertIDv2.GetInstance(certs[i]); + } + return certIds; + } + + public PolicyInformation[] GetPolicies() + { + if (policies == null) + return null; + + PolicyInformation[] policyInformations = new PolicyInformation[policies.Count]; + for (int i = 0; i != policies.Count; i++) + { + policyInformations[i] = PolicyInformation.GetInstance(policies[i]); + } + return policyInformations; + } + + /** + * The definition of SigningCertificateV2 is + *
+         * SigningCertificateV2 ::=  SEQUENCE {
+         *      certs        SEQUENCE OF EssCertIDv2,
+         *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+         * }
+         * 
+ * 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 override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(certs); + + if (policies != null) + { + v.Add(policies); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs new file mode 100644 index 000000000..9311a3ac1 --- /dev/null +++ b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs @@ -0,0 +1,31 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Gnu +{ + public abstract class GnuObjectIdentifiers + { + public static readonly DerObjectIdentifier Gnu = new DerObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius + public static readonly DerObjectIdentifier GnuPG = new DerObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten) + public static readonly DerObjectIdentifier Notation = new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1"); // notation + public static readonly DerObjectIdentifier PkaAddress = new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1.1"); // pkaAddress + public static readonly DerObjectIdentifier GnuRadar = new DerObjectIdentifier("1.3.6.1.4.1.11591.3"); // GNU Radar + public static readonly DerObjectIdentifier DigestAlgorithm = new DerObjectIdentifier("1.3.6.1.4.1.11591.12"); // digestAlgorithm + public static readonly DerObjectIdentifier Tiger192 = new DerObjectIdentifier("1.3.6.1.4.1.11591.12.2"); // TIGER/192 + public static readonly DerObjectIdentifier EncryptionAlgorithm = new DerObjectIdentifier("1.3.6.1.4.1.11591.13"); // encryptionAlgorithm + public static readonly DerObjectIdentifier Serpent = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2"); // Serpent + public static readonly DerObjectIdentifier Serpent128Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.1"); // Serpent-128-ECB + public static readonly DerObjectIdentifier Serpent128Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.2"); // Serpent-128-CBC + public static readonly DerObjectIdentifier Serpent128Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.3"); // Serpent-128-OFB + public static readonly DerObjectIdentifier Serpent128Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.4"); // Serpent-128-CFB + public static readonly DerObjectIdentifier Serpent192Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.21"); // Serpent-192-ECB + public static readonly DerObjectIdentifier Serpent192Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.22"); // Serpent-192-CBC + public static readonly DerObjectIdentifier Serpent192Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.23"); // Serpent-192-OFB + public static readonly DerObjectIdentifier Serpent192Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.24"); // Serpent-192-CFB + public static readonly DerObjectIdentifier Serpent256Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.41"); // Serpent-256-ECB + public static readonly DerObjectIdentifier Serpent256Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.42"); // Serpent-256-CBC + public static readonly DerObjectIdentifier Serpent256Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.43"); // Serpent-256-OFB + public static readonly DerObjectIdentifier Serpent256Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB + public static readonly DerObjectIdentifier Crc = new DerObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms + public static readonly DerObjectIdentifier Crc32 = new DerObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32 + } +} diff --git a/crypto/src/asn1/iana/IANAObjectIdentifiers.cs b/crypto/src/asn1/iana/IANAObjectIdentifiers.cs new file mode 100644 index 000000000..63343f5ce --- /dev/null +++ b/crypto/src/asn1/iana/IANAObjectIdentifiers.cs @@ -0,0 +1,18 @@ +namespace Org.BouncyCastle.Asn1.Iana +{ + public abstract class IanaObjectIdentifiers + { + // id-SHA1 OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)} + // + + public static readonly DerObjectIdentifier IsakmpOakley = new DerObjectIdentifier("1.3.6.1.5.5.8.1"); + + public static readonly DerObjectIdentifier HmacMD5 = new DerObjectIdentifier(IsakmpOakley + ".1"); + public static readonly DerObjectIdentifier HmacSha1 = new DerObjectIdentifier(IsakmpOakley + ".2"); + + public static readonly DerObjectIdentifier HmacTiger = new DerObjectIdentifier(IsakmpOakley + ".3"); + + public static readonly DerObjectIdentifier HmacRipeMD160 = new DerObjectIdentifier(IsakmpOakley + ".4"); + } +} diff --git a/crypto/src/asn1/icao/CscaMasterList.cs b/crypto/src/asn1/icao/CscaMasterList.cs new file mode 100644 index 000000000..6890d8a2e --- /dev/null +++ b/crypto/src/asn1/icao/CscaMasterList.cs @@ -0,0 +1,83 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Icao +{ + /** + * The CscaMasterList object. This object can be wrapped in a + * CMSSignedData to be published in LDAP. + * + *
+	 * CscaMasterList ::= SEQUENCE {
+	 *   version                CscaMasterListVersion,
+	 *   certList               SET OF Certificate }
+	 *   
+	 * CscaMasterListVersion :: INTEGER {v0(0)}
+	 * 
+ */ + public class CscaMasterList + : Asn1Encodable + { + private DerInteger version = new DerInteger(0); + private X509CertificateStructure[] certList; + + public static CscaMasterList GetInstance( + object obj) + { + if (obj is CscaMasterList) + return (CscaMasterList)obj; + + if (obj != null) + return new CscaMasterList(Asn1Sequence.GetInstance(obj)); + + return null; + } + + private CscaMasterList( + Asn1Sequence seq) + { + if (seq == null || seq.Count == 0) + throw new ArgumentException("null or empty sequence passed."); + + if (seq.Count != 2) + throw new ArgumentException("Incorrect sequence size: " + seq.Count); + + this.version = DerInteger.GetInstance(seq[0]); + + Asn1Set certSet = Asn1Set.GetInstance(seq[1]); + + this.certList = new X509CertificateStructure[certSet.Count]; + for (int i = 0; i < certList.Length; i++) + { + certList[i] = X509CertificateStructure.GetInstance(certSet[i]); + } + } + + public CscaMasterList( + X509CertificateStructure[] certStructs) + { + certList = CopyCertList(certStructs); + } + + public virtual int Version + { + get { return version.Value.IntValue; } + } + + public X509CertificateStructure[] GetCertStructs() + { + return CopyCertList(certList); + } + + private static X509CertificateStructure[] CopyCertList(X509CertificateStructure[] orig) + { + return (X509CertificateStructure[])orig.Clone(); + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(version, new DerSet(certList)); + } + } +} diff --git a/crypto/src/asn1/icao/DataGroupHash.cs b/crypto/src/asn1/icao/DataGroupHash.cs new file mode 100644 index 000000000..e0d7eee7b --- /dev/null +++ b/crypto/src/asn1/icao/DataGroupHash.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Icao +{ + /** + * The DataGroupHash object. + *
+    * 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) }
+    *
+    * 
+ */ + public class DataGroupHash + : Asn1Encodable + { + private readonly DerInteger dataGroupNumber; + private readonly Asn1OctetString dataGroupHashValue; + + public static DataGroupHash GetInstance( + object obj) + { + if (obj is DataGroupHash) + return (DataGroupHash)obj; + + if (obj != null) + return new DataGroupHash(Asn1Sequence.GetInstance(obj)); + + return null; + } + + private DataGroupHash( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.dataGroupNumber = DerInteger.GetInstance(seq[0]); + this.dataGroupHashValue = Asn1OctetString.GetInstance(seq[1]); + } + + public DataGroupHash( + int dataGroupNumber, + Asn1OctetString dataGroupHashValue) + { + this.dataGroupNumber = new DerInteger(dataGroupNumber); + this.dataGroupHashValue = dataGroupHashValue; + } + + public int DataGroupNumber + { + get { return dataGroupNumber.Value.IntValue; } + } + + public Asn1OctetString DataGroupHashValue + { + get { return dataGroupHashValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(dataGroupNumber, dataGroupHashValue); + } + } +} diff --git a/crypto/src/asn1/icao/ICAOObjectIdentifiers.cs b/crypto/src/asn1/icao/ICAOObjectIdentifiers.cs new file mode 100644 index 000000000..389d4dacd --- /dev/null +++ b/crypto/src/asn1/icao/ICAOObjectIdentifiers.cs @@ -0,0 +1,34 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Icao +{ + public abstract class IcaoObjectIdentifiers + { + // + // base id + // + public static readonly DerObjectIdentifier IdIcao = new DerObjectIdentifier("2.23.136"); + + public static readonly DerObjectIdentifier IdIcaoMrtd = IdIcao.Branch("1"); + public static readonly DerObjectIdentifier IdIcaoMrtdSecurity = IdIcaoMrtd.Branch("1"); + + // LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2 + public static readonly DerObjectIdentifier IdIcaoLdsSecurityObject = IdIcaoMrtdSecurity.Branch("1"); + + // CSCA master list, see TR CSCA Countersigning and Master List issuance + public static readonly DerObjectIdentifier IdIcaoCscaMasterList = IdIcaoMrtdSecurity.Branch("2"); + public static readonly DerObjectIdentifier IdIcaoCscaMasterListSigningKey = IdIcaoMrtdSecurity.Branch("3"); + + // document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1 + public static readonly DerObjectIdentifier IdIcaoDocumentTypeList = IdIcaoMrtdSecurity.Branch("4"); + + // Active Authentication protocol, see draft TR LDS and PKI Maintenance, + // par. 5.2.2 + public static readonly DerObjectIdentifier IdIcaoAAProtocolObject = IdIcaoMrtdSecurity.Branch("5"); + + // CSCA name change and key reoll-over, see draft TR LDS and PKI + // Maintenance, par. 3.2.1 + public static readonly DerObjectIdentifier IdIcaoExtensions = IdIcaoMrtdSecurity.Branch("6"); + public static readonly DerObjectIdentifier IdIcaoExtensionsNamechangekeyrollover = IdIcaoExtensions.Branch("1"); + } +} diff --git a/crypto/src/asn1/icao/LDSSecurityObject.cs b/crypto/src/asn1/icao/LDSSecurityObject.cs new file mode 100644 index 000000000..c33ca6877 --- /dev/null +++ b/crypto/src/asn1/icao/LDSSecurityObject.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Icao +{ + /** + * The LDSSecurityObject object (V1.8). + *
+	 * 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)}
+	 * 
+ */ + public class LdsSecurityObject + : Asn1Encodable + { + public const int UBDataGroups = 16; + + private DerInteger version = new DerInteger(0); + private AlgorithmIdentifier digestAlgorithmIdentifier; + private DataGroupHash[] datagroupHash; + private LdsVersionInfo versionInfo; + + public static LdsSecurityObject GetInstance( + object obj) + { + if (obj is LdsSecurityObject) + return (LdsSecurityObject)obj; + + if (obj != null) + return new LdsSecurityObject(Asn1Sequence.GetInstance(obj)); + + return null; + } + + private LdsSecurityObject( + Asn1Sequence seq) + { + if (seq == null || seq.Count == 0) + throw new ArgumentException("null or empty sequence passed."); + + IEnumerator e = seq.GetEnumerator(); + + // version + e.MoveNext(); + version = DerInteger.GetInstance(e.Current); + // digestAlgorithmIdentifier + e.MoveNext(); + digestAlgorithmIdentifier = AlgorithmIdentifier.GetInstance(e.Current); + + e.MoveNext(); + Asn1Sequence datagroupHashSeq = Asn1Sequence.GetInstance(e.Current); + + if (version.Value.Equals(BigInteger.One)) + { + e.MoveNext(); + versionInfo = LdsVersionInfo.GetInstance(e.Current); + } + + CheckDatagroupHashSeqSize(datagroupHashSeq.Count); + + datagroupHash = new DataGroupHash[datagroupHashSeq.Count]; + for (int i= 0; i< datagroupHashSeq.Count; i++) + { + datagroupHash[i] = DataGroupHash.GetInstance(datagroupHashSeq[i]); + } + } + + public LdsSecurityObject( + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash) + { + this.version = new DerInteger(0); + this.digestAlgorithmIdentifier = digestAlgorithmIdentifier; + this.datagroupHash = datagroupHash; + + CheckDatagroupHashSeqSize(datagroupHash.Length); + } + + + public LdsSecurityObject( + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash, + LdsVersionInfo versionInfo) + { + this.version = new DerInteger(1); + this.digestAlgorithmIdentifier = digestAlgorithmIdentifier; + this.datagroupHash = datagroupHash; + this.versionInfo = versionInfo; + + CheckDatagroupHashSeqSize(datagroupHash.Length); + } + + private void CheckDatagroupHashSeqSize(int size) + { + if (size < 2 || size > UBDataGroups) + throw new ArgumentException("wrong size in DataGroupHashValues : not in (2.."+ UBDataGroups +")"); + } + + public BigInteger Version + { + get { return version.Value; } + } + + public AlgorithmIdentifier DigestAlgorithmIdentifier + { + get { return digestAlgorithmIdentifier; } + } + + public DataGroupHash[] GetDatagroupHash() + { + return datagroupHash; + } + + public LdsVersionInfo VersionInfo + { + get { return versionInfo; } + } + + public override Asn1Object ToAsn1Object() + { + DerSequence hashSeq = new DerSequence(datagroupHash); + + Asn1EncodableVector v = new Asn1EncodableVector(version, digestAlgorithmIdentifier, hashSeq); + + if (versionInfo != null) + { + v.Add(versionInfo); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/icao/LDSVersionInfo.cs b/crypto/src/asn1/icao/LDSVersionInfo.cs new file mode 100644 index 000000000..2cdcad2db --- /dev/null +++ b/crypto/src/asn1/icao/LDSVersionInfo.cs @@ -0,0 +1,61 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Icao +{ + public class LdsVersionInfo + : Asn1Encodable + { + 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.Count != 2) + throw new ArgumentException("sequence wrong size for LDSVersionInfo", "seq"); + + this.ldsVersion = DerPrintableString.GetInstance(seq[0]); + this.unicodeVersion = DerPrintableString.GetInstance(seq[1]); + } + + public static LdsVersionInfo GetInstance(object obj) + { + if (obj is LdsVersionInfo) + return (LdsVersionInfo)obj; + + if (obj != null) + return new LdsVersionInfo(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public virtual string GetLdsVersion() + { + return ldsVersion.GetString(); + } + + public virtual string GetUnicodeVersion() + { + return unicodeVersion.GetString(); + } + + /** + *
+		 * LDSVersionInfo ::= SEQUENCE {
+		 *    ldsVersion PRINTABLE STRING
+		 *    unicodeVersion PRINTABLE STRING
+		 *  }
+		 * 
+ * @return + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(ldsVersion, unicodeVersion); + } + } +} diff --git a/crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs b/crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs new file mode 100644 index 000000000..af60b030a --- /dev/null +++ b/crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs @@ -0,0 +1,177 @@ +namespace Org.BouncyCastle.Asn1.IsisMtt +{ + public abstract class IsisMttObjectIdentifiers + { + public static readonly DerObjectIdentifier IdIsisMtt = new DerObjectIdentifier("1.3.36.8"); + + public static readonly DerObjectIdentifier IdIsisMttCP = new DerObjectIdentifier(IdIsisMtt + ".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. + */ + public static readonly DerObjectIdentifier IdIsisMttCPAccredited = new DerObjectIdentifier(IdIsisMttCP + ".1"); + + public static readonly DerObjectIdentifier IdIsisMttAT = new DerObjectIdentifier(IdIsisMtt + ".3"); + + /** + * Certificate extensionDate of certificate generation + * + *
+		 *		DateOfCertGenSyntax ::= GeneralizedTime
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATDateOfCertGen = new DerObjectIdentifier(IdIsisMttAT + ".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. + */ + public static readonly DerObjectIdentifier IdIsisMttATProcuration = new DerObjectIdentifier(IdIsisMttAT + ".2"); + + /** + * Attribute to indicate admissions to certain professions. May be used as + * attribute in attribute certificate or as extension in a certificate + */ + public static readonly DerObjectIdentifier IdIsisMttATAdmission = new DerObjectIdentifier(IdIsisMttAT + ".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). + */ + public static readonly DerObjectIdentifier IdIsisMttATMonetaryLimit = new DerObjectIdentifier(IdIsisMttAT + ".4"); + + /** + * A declaration of majority. May be used as attribute in attribute + * certificate or as extension in a certificate + */ + public static readonly DerObjectIdentifier IdIsisMttATDeclarationOfMajority = new DerObjectIdentifier(IdIsisMttAT + ".5"); + + /** + * + * Serial number of the smart card containing the corresponding private key + * + *
+		 *		ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATIccsn = new DerObjectIdentifier(IdIsisMttAT + ".6"); + + /** + * + * Reference for a file of a smartcard that stores the public key of this + * certificate and that is used as �security anchor�. + * + *
+		 *		PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATPKReference = new DerObjectIdentifier(IdIsisMttAT + ".7"); + + /** + * Some other restriction regarding the usage of this certificate. May be + * used as attribute in attribute certificate or as extension in a + * certificate. + * + *
+		 *		RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		 * 
+ * + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction + */ + public static readonly DerObjectIdentifier IdIsisMttATRestriction = new DerObjectIdentifier(IdIsisMttAT + ".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. + * + *
+		 *		RetrieveIfAllowed ::= BOOLEAN
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATRetrieveIfAllowed = new DerObjectIdentifier(IdIsisMttAT + ".9"); + + /** + * SingleOCSPResponse extension: The certificate requested by the client by + * inserting the RetrieveIfAllowed extension in the request, will be + * returned in this extension. + * + * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate + */ + public static readonly DerObjectIdentifier IdIsisMttATRequestedCertificate = new DerObjectIdentifier(IdIsisMttAT + ".10"); + + /** + * Base ObjectIdentifier for naming authorities + */ + public static readonly DerObjectIdentifier IdIsisMttATNamingAuthorities = new DerObjectIdentifier(IdIsisMttAT + ".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. + * + *
+		 *		CertInDirSince ::= GeneralizedTime
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATCertInDirSince = new DerObjectIdentifier(IdIsisMttAT + ".12"); + + /** + * Hash of a certificate in OCSP. + * + * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash + */ + public static readonly DerObjectIdentifier IdIsisMttATCertHash = new DerObjectIdentifier(IdIsisMttAT + ".13"); + + /** + *
+		 *		NameAtBirth ::= DirectoryString(SIZE(1..64)
+		 * 
+ * + * Used in + * {@link Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes SubjectDirectoryAttributes} + */ + public static readonly DerObjectIdentifier IdIsisMttATNameAtBirth = new DerObjectIdentifier(IdIsisMttAT + ".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. + * + *
+		 *               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+		 * 
+ * + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax + */ + public static readonly DerObjectIdentifier IdIsisMttATAdditionalInformation = new DerObjectIdentifier(IdIsisMttAT + ".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. + * + *
+		 *		LiabilityLimitationFlagSyntax ::= BOOLEAN
+		 * 
+ */ + public static readonly DerObjectIdentifier IdIsisMttATLiabilityLimitationFlag = new DerObjectIdentifier("0.2.262.1.10.12.0"); + } +} diff --git a/crypto/src/asn1/isismtt/ocsp/CertHash.cs b/crypto/src/asn1/isismtt/ocsp/CertHash.cs new file mode 100644 index 000000000..da5b530e4 --- /dev/null +++ b/crypto/src/asn1/isismtt/ocsp/CertHash.cs @@ -0,0 +1,121 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp +{ + /** + * 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. + *

+ *

+ *

+	*     CertHash ::= SEQUENCE {
+	*       hashAlgorithm AlgorithmIdentifier,
+	*       certificateHash OCTET STRING
+	*     }
+	* 
+ */ + public class CertHash + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly byte[] certificateHash; + + public static CertHash GetInstance( + object obj) + { + if (obj == null || obj is CertHash) + { + return (CertHash) obj; + } + + if (obj is Asn1Sequence) + { + return new CertHash((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type CertHash: + *

+ *

+		*     CertHash ::= SEQUENCE {
+		*       hashAlgorithm AlgorithmIdentifier,
+		*       certificateHash OCTET STRING
+		*     }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private CertHash( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); + this.certificateHash = DerOctetString.GetInstance(seq[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) + { + if (hashAlgorithm == null) + throw new ArgumentNullException("hashAlgorithm"); + if (certificateHash == null) + throw new ArgumentNullException("certificateHash"); + + this.hashAlgorithm = hashAlgorithm; + this.certificateHash = (byte[]) certificateHash.Clone(); + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public byte[] CertificateHash + { + get { return (byte[]) certificateHash.Clone(); } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*     CertHash ::= SEQUENCE {
+		*       hashAlgorithm AlgorithmIdentifier,
+		*       certificateHash OCTET STRING
+		*     }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(hashAlgorithm, new DerOctetString(certificateHash)); + } + } +} diff --git a/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs new file mode 100644 index 000000000..7724bfed6 --- /dev/null +++ b/crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs @@ -0,0 +1,186 @@ +using System; +using System.IO; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp +{ + /** + * ISIS-MTT-Optional: The certificate requested by the client by inserting the + * RetrieveIfAllowed extension in the request, will be returned in this + * extension. + *

+ * ISIS-MTT-SigG: The signature act allows publishing certificates only then, + * when the certificate owner gives his isExplicit 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: + *

    + *
  • a) the responder supports the extension and is allowed to publish the + * certificate: RequestedCertificate returned including the requested + * certificate
  • + *
  • b) the responder supports the extension but is NOT allowed to publish + * the certificate: RequestedCertificate returned including an empty OCTET + * STRING
  • + *
  • c) the responder does not support the extension: RequestedCertificate is + * not included in the response
  • + *
+ * 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. + *

+ *

+	*            RequestedCertificate ::= CHOICE {
+	*              Certificate Certificate,
+	*              publicKeyCertificate [0] EXPLICIT OCTET STRING,
+	*              attributeCertificate [1] EXPLICIT OCTET STRING
+	*            }
+	* 
+ */ + public class RequestedCertificate + : Asn1Encodable, IAsn1Choice + { + public enum Choice + { + Certificate = -1, + PublicKeyCertificate = 0, + AttributeCertificate = 1 + } + + private readonly X509CertificateStructure cert; + private readonly byte[] publicKeyCert; + private readonly byte[] attributeCert; + + public static RequestedCertificate GetInstance( + object obj) + { + if (obj == null || obj is RequestedCertificate) + { + return (RequestedCertificate) obj; + } + + if (obj is Asn1Sequence) + { + return new RequestedCertificate(X509CertificateStructure.GetInstance(obj)); + } + + if (obj is Asn1TaggedObject) + { + return new RequestedCertificate((Asn1TaggedObject) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static RequestedCertificate GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + if (!isExplicit) + throw new ArgumentException("choice item must be explicitly tagged"); + + return GetInstance(obj.GetObject()); + } + + private RequestedCertificate( + Asn1TaggedObject tagged) + { + switch ((Choice) tagged.TagNo) + { + case Choice.AttributeCertificate: + this.attributeCert = Asn1OctetString.GetInstance(tagged, true).GetOctets(); + break; + case Choice.PublicKeyCertificate: + this.publicKeyCert = Asn1OctetString.GetInstance(tagged, true).GetOctets(); + break; + default: + throw new ArgumentException("unknown tag number: " + tagged.TagNo); + } + } + + /** + * Constructor from a given details. + *

+ * Only one parameter can be given. All other must be null. + * + * @param certificate Given as Certificate + */ + public RequestedCertificate( + X509CertificateStructure certificate) + { + this.cert = certificate; + } + + public RequestedCertificate( + Choice type, + byte[] certificateOctets) + : this(new DerTaggedObject((int) type, new DerOctetString(certificateOctets))) + { + } + + public Choice Type + { + get + { + if (cert != null) + return Choice.Certificate; + + if (publicKeyCert != null) + return Choice.PublicKeyCertificate; + + return Choice.AttributeCertificate; + } + } + + public byte[] GetCertificateBytes() + { + if (cert != null) + { + try + { + return cert.GetEncoded(); + } + catch (IOException e) + { + throw new InvalidOperationException("can't decode certificate: " + e); + } + } + + if (publicKeyCert != null) + return publicKeyCert; + + return attributeCert; + } + + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*            RequestedCertificate ::= CHOICE {
+		*              Certificate Certificate,
+		*              publicKeyCertificate [0] EXPLICIT OCTET STRING,
+		*              attributeCertificate [1] EXPLICIT OCTET STRING
+		*            }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + if (publicKeyCert != null) + { + return new DerTaggedObject(0, new DerOctetString(publicKeyCert)); + } + + if (attributeCert != null) + { + return new DerTaggedObject(1, new DerOctetString(attributeCert)); + } + + return cert.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs b/crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs new file mode 100644 index 000000000..f81d459c6 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs @@ -0,0 +1,70 @@ +using System; + +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * Some other information of non-restrictive nature regarding the usage of this + * certificate. + * + *
+	*    AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+	* 
+ */ + public class AdditionalInformationSyntax + : Asn1Encodable + { + private readonly DirectoryString information; + + public static AdditionalInformationSyntax GetInstance( + object obj) + { + if (obj is AdditionalInformationSyntax) + return (AdditionalInformationSyntax) obj; + + if (obj is IAsn1String) + return new AdditionalInformationSyntax(DirectoryString.GetInstance(obj)); + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj"); + } + + private AdditionalInformationSyntax( + DirectoryString information) + { + this.information = information; + } + + /** + * Constructor from a given details. + * + * @param information The describtion of the information. + */ + public AdditionalInformationSyntax( + string information) + { + this.information = new DirectoryString(information); + } + + public virtual DirectoryString Information + { + get { return information; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*   AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return information.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs b/crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs new file mode 100644 index 000000000..f322ef88f Binary files /dev/null and b/crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs differ diff --git a/crypto/src/asn1/isismtt/x509/Admissions.cs b/crypto/src/asn1/isismtt/x509/Admissions.cs new file mode 100644 index 000000000..40290c608 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/Admissions.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * An Admissions structure. + *

+ *

+	*            Admissions ::= SEQUENCE
+	*            {
+	*              admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+	*              namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+	*              professionInfos SEQUENCE OF ProfessionInfo
+	*            }
+	* 

+ *

+ * + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority + */ + public class Admissions + : Asn1Encodable + { + private readonly GeneralName admissionAuthority; + private readonly NamingAuthority namingAuthority; + private readonly Asn1Sequence professionInfos; + + public static Admissions GetInstance( + object obj) + { + if (obj == null || obj is Admissions) + { + return (Admissions) obj; + } + + if (obj is Asn1Sequence) + { + return new Admissions((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type ProcurationSyntax: + *

+ *

+		*            Admissions ::= SEQUENCE
+		*            {
+		*              admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+		*              namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+		*              professionInfos SEQUENCE OF ProfessionInfo
+		*            }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private Admissions( + Asn1Sequence seq) + { + if (seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + Asn1Encodable o = (Asn1Encodable) e.Current; + if (o is Asn1TaggedObject) + { + switch (((Asn1TaggedObject)o).TagNo) + { + case 0: + admissionAuthority = GeneralName.GetInstance((Asn1TaggedObject)o, true); + break; + case 1: + namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true); + break; + default: + throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo); + } + e.MoveNext(); + o = (Asn1Encodable) e.Current; + } + if (o is Asn1TaggedObject) + { + switch (((Asn1TaggedObject)o).TagNo) + { + case 1: + namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true); + break; + default: + throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo); + } + e.MoveNext(); + o = (Asn1Encodable) e.Current; + } + professionInfos = Asn1Sequence.GetInstance(o); + if (e.MoveNext()) + { + throw new ArgumentException("Bad object encountered: " + e.Current.GetType().Name); + } + } + + /** + * Constructor from a given details. + *

+ * Parameter professionInfos 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 virtual GeneralName AdmissionAuthority + { + get { return admissionAuthority; } + } + + public virtual NamingAuthority NamingAuthority + { + get { return namingAuthority; } + } + + public ProfessionInfo[] GetProfessionInfos() + { + ProfessionInfo[] infos = new ProfessionInfo[professionInfos.Count]; + int count = 0; + foreach (Asn1Encodable ae in professionInfos) + { + infos[count++] = ProfessionInfo.GetInstance(ae); + } + return infos; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*       Admissions ::= SEQUENCE
+		*       {
+		*         admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+		*         namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+		*         professionInfos SEQUENCE OF ProfessionInfo
+		*       }
+		* 

+ *

+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs new file mode 100644 index 000000000..dfac65040 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs @@ -0,0 +1,170 @@ +using System; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * A declaration of majority. + *

+ *

+	*           DeclarationOfMajoritySyntax ::= CHOICE
+	*           {
+	*             notYoungerThan [0] IMPLICIT INTEGER,
+	*             fullAgeAtCountry [1] IMPLICIT SEQUENCE
+	*             {
+	*               fullAge BOOLEAN DEFAULT TRUE,
+	*               country PrintableString (SIZE(2))
+	*             }
+	*             dateOfBirth [2] IMPLICIT GeneralizedTime
+	*           }
+	* 
+ *

+ * fullAgeAtCountry indicates the majority of the owner with respect to the laws + * of a specific country. + */ + public class DeclarationOfMajority + : Asn1Encodable, IAsn1Choice + { + public enum Choice + { + NotYoungerThan = 0, + FullAgeAtCountry = 1, + DateOfBirth = 2 + }; + + private readonly Asn1TaggedObject declaration; + + public DeclarationOfMajority( + int notYoungerThan) + { + declaration = new DerTaggedObject(false, 0, new DerInteger(notYoungerThan)); + } + + public DeclarationOfMajority( + bool fullAge, + string country) + { + if (country.Length > 2) + throw new ArgumentException("country can only be 2 characters"); + + DerPrintableString countryString = new DerPrintableString(country, true); + + DerSequence seq; + if (fullAge) + { + seq = new DerSequence(countryString); + } + else + { + seq = new DerSequence(DerBoolean.False, countryString); + } + + this.declaration = new DerTaggedObject(false, 1, seq); + } + + public DeclarationOfMajority( + DerGeneralizedTime dateOfBirth) + { + this.declaration = new DerTaggedObject(false, 2, dateOfBirth); + } + + public static DeclarationOfMajority GetInstance( + object obj) + { + if (obj == null || obj is DeclarationOfMajority) + { + return (DeclarationOfMajority) obj; + } + + if (obj is Asn1TaggedObject) + { + return new DeclarationOfMajority((Asn1TaggedObject) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private DeclarationOfMajority( + Asn1TaggedObject o) + { + if (o.TagNo > 2) + throw new ArgumentException("Bad tag number: " + o.TagNo); + + this.declaration = o; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*           DeclarationOfMajoritySyntax ::= CHOICE
+		*           {
+		*             notYoungerThan [0] IMPLICIT INTEGER,
+		*             fullAgeAtCountry [1] IMPLICIT SEQUENCE
+		*             {
+		*               fullAge BOOLEAN DEFAULT TRUE,
+		*               country PrintableString (SIZE(2))
+		*             }
+		*             dateOfBirth [2] IMPLICIT GeneralizedTime
+		*           }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return declaration; + } + + public Choice Type + { + get { return (Choice) declaration.TagNo; } + } + + /** + * @return notYoungerThan if that's what we are, -1 otherwise + */ + public virtual int NotYoungerThan + { + get + { + switch ((Choice) declaration.TagNo) + { + case Choice.NotYoungerThan: + return DerInteger.GetInstance(declaration, false).Value.IntValue; + default: + return -1; + } + } + } + + public virtual Asn1Sequence FullAgeAtCountry + { + get + { + switch ((Choice) declaration.TagNo) + { + case Choice.FullAgeAtCountry: + return Asn1Sequence.GetInstance(declaration, false); + default: + return null; + } + } + } + + public virtual DerGeneralizedTime DateOfBirth + { + get + { + switch ((Choice) declaration.TagNo) + { + case Choice.DateOfBirth: + return DerGeneralizedTime.GetInstance(declaration, false); + default: + return null; + } + } + } + } +} diff --git a/crypto/src/asn1/isismtt/x509/MonetaryLimit.cs b/crypto/src/asn1/isismtt/x509/MonetaryLimit.cs new file mode 100644 index 000000000..80b6b684b --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/MonetaryLimit.cs @@ -0,0 +1,121 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * 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). + *

+ * 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). + *

+ *

+	*    MonetaryLimitSyntax ::= SEQUENCE
+	*    {
+	*      currency PrintableString (SIZE(3)),
+	*      amount INTEGER,
+	*      exponent INTEGER
+	*    }
+	* 
+ *

+ * currency must be the ISO code. + *

+ * value = amount�10*exponent + */ + public class MonetaryLimit + : Asn1Encodable + { + private readonly DerPrintableString currency; + private readonly DerInteger amount; + private readonly DerInteger exponent; + + public static MonetaryLimit GetInstance( + object obj) + { + if (obj == null || obj is MonetaryLimit) + { + return (MonetaryLimit) obj; + } + + if (obj is Asn1Sequence) + { + return new MonetaryLimit(Asn1Sequence.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private MonetaryLimit( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + currency = DerPrintableString.GetInstance(seq[0]); + amount = DerInteger.GetInstance(seq[1]); + exponent = DerInteger.GetInstance(seq[2]); + } + + /** + * Constructor from a given details. + *

+ *

+ * 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 DerInteger(amount); + this.exponent = new DerInteger(exponent); + } + + public virtual string Currency + { + get { return currency.GetString(); } + } + + public virtual BigInteger Amount + { + get { return amount.Value; } + } + + public virtual BigInteger Exponent + { + get { return exponent.Value; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*    MonetaryLimitSyntax ::= SEQUENCE
+		*    {
+		*      currency PrintableString (SIZE(3)),
+		*      amount INTEGER,
+		*      exponent INTEGER
+		*    }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(currency, amount, exponent); + } + } +} diff --git a/crypto/src/asn1/isismtt/x509/NamingAuthority.cs b/crypto/src/asn1/isismtt/x509/NamingAuthority.cs new file mode 100644 index 000000000..4262fd0f4 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/NamingAuthority.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * Names of authorities which are responsible for the administration of title + * registers. + * + *
+	*             NamingAuthority ::= SEQUENCE 
+	*             {
+	*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+	*               namingAuthorityUrl IA5String OPTIONAL,
+	*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+	*             }
+	* 
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax + * + */ + public class NamingAuthority + : Asn1Encodable + { + /** + * 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 readonly DerObjectIdentifier IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + = new DerObjectIdentifier(IsisMttObjectIdentifiers.IdIsisMttATNamingAuthorities + ".1"); + + private readonly DerObjectIdentifier namingAuthorityID; + private readonly string namingAuthorityUrl; + private readonly DirectoryString namingAuthorityText; + + public static NamingAuthority GetInstance( + object obj) + { + if (obj == null || obj is NamingAuthority) + { + return (NamingAuthority) obj; + } + + if (obj is Asn1Sequence) + { + return new NamingAuthority((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static NamingAuthority GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * Constructor from Asn1Sequence. + *

+ *

+ *

+		*             NamingAuthority ::= SEQUENCE
+		*             {
+		*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+		*               namingAuthorityUrl IA5String OPTIONAL,
+		*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+		*             }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private NamingAuthority( + Asn1Sequence seq) + { + if (seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + IEnumerator e = seq.GetEnumerator(); + + if (e.MoveNext()) + { + Asn1Encodable o = (Asn1Encodable) e.Current; + if (o is DerObjectIdentifier) + { + namingAuthorityID = (DerObjectIdentifier) o; + } + else if (o is DerIA5String) + { + namingAuthorityUrl = DerIA5String.GetInstance(o).GetString(); + } + else if (o is IAsn1String) + { + namingAuthorityText = DirectoryString.GetInstance(o); + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + + if (e.MoveNext()) + { + Asn1Encodable o = (Asn1Encodable) e.Current; + if (o is DerIA5String) + { + namingAuthorityUrl = DerIA5String.GetInstance(o).GetString(); + } + else if (o is IAsn1String) + { + namingAuthorityText = DirectoryString.GetInstance(o); + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + + if (e.MoveNext()) + { + Asn1Encodable o = (Asn1Encodable) e.Current; + if (o is IAsn1String) + { + namingAuthorityText = DirectoryString.GetInstance(o); + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + } + + /** + * @return Returns the namingAuthorityID. + */ + public virtual DerObjectIdentifier NamingAuthorityID + { + get { return namingAuthorityID; } + } + + /** + * @return Returns the namingAuthorityText. + */ + public virtual DirectoryString NamingAuthorityText + { + get { return namingAuthorityText; } + } + + /** + * @return Returns the namingAuthorityUrl. + */ + public virtual string NamingAuthorityUrl + { + get { return namingAuthorityUrl; } + } + + /** + * Constructor from given details. + *

+ * 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( + DerObjectIdentifier namingAuthorityID, + string namingAuthorityUrl, + DirectoryString namingAuthorityText) + { + this.namingAuthorityID = namingAuthorityID; + this.namingAuthorityUrl = namingAuthorityUrl; + this.namingAuthorityText = namingAuthorityText; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*             NamingAuthority ::= SEQUENCE
+		*             {
+		*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+		*               namingAuthorityUrl IA5String OPTIONAL,
+		*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+		*             }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs b/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs new file mode 100644 index 000000000..a25df225e --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * Attribute to indicate that the certificate holder may sign in the name of a + * third person. + *

+ * 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). + *

+ *

+ * 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). + *

+ *
+	*               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 
+	*               }
+	* 
+ * + */ + public class ProcurationSyntax + : Asn1Encodable + { + private readonly string country; + private readonly DirectoryString typeOfSubstitution; + private readonly GeneralName thirdPerson; + private readonly IssuerSerial certRef; + + public static ProcurationSyntax GetInstance( + object obj) + { + if (obj == null || obj is ProcurationSyntax) + { + return (ProcurationSyntax) obj; + } + + if (obj is Asn1Sequence) + { + return new ProcurationSyntax((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type ProcurationSyntax: + *

+ *

+		*               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 + * } + *

+ * + * @param seq The ASN.1 sequence. + */ + private ProcurationSyntax( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + IEnumerator e = seq.GetEnumerator(); + + while (e.MoveNext()) + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current); + switch (o.TagNo) + { + case 1: + country = DerPrintableString.GetInstance(o, true).GetString(); + break; + case 2: + typeOfSubstitution = DirectoryString.GetInstance(o, true); + break; + case 3: + Asn1Object signingFor = o.GetObject(); + if (signingFor is Asn1TaggedObject) + { + thirdPerson = GeneralName.GetInstance(signingFor); + } + else + { + certRef = IssuerSerial.GetInstance(signingFor); + } + break; + default: + throw new ArgumentException("Bad tag number: " + o.TagNo); + } + } + } + + /** + * Constructor from a given details. + *

+ *

+ * Either generalName or certRef MUST be + * null. + * + * @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. + *

+ *

+ * Either generalName or certRef MUST be + * null. + * + * @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 virtual string Country + { + get { return country; } + } + + public virtual DirectoryString TypeOfSubstitution + { + get { return typeOfSubstitution; } + } + + public virtual GeneralName ThirdPerson + { + get { return thirdPerson; } + } + + public virtual IssuerSerial CertRef + { + get { return certRef; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*               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 + * } + *

+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/isismtt/x509/ProfessionInfo.cs b/crypto/src/asn1/isismtt/x509/ProfessionInfo.cs new file mode 100644 index 000000000..3bad2cbc4 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/ProfessionInfo.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * Professions, specializations, disciplines, fields of activity, etc. + * + *
+	*               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 
+	*               }
+	* 
+ * + * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax + */ + public class ProfessionInfo + : Asn1Encodable + { + /** + * Rechtsanw�ltin + */ + public static readonly DerObjectIdentifier Rechtsanwltin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".1"); + + /** + * Rechtsanwalt + */ + public static readonly DerObjectIdentifier Rechtsanwalt = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".2"); + + /** + * Rechtsbeistand + */ + public static readonly DerObjectIdentifier Rechtsbeistand = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".3"); + + /** + * Steuerberaterin + */ + public static readonly DerObjectIdentifier Steuerberaterin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".4"); + + /** + * Steuerberater + */ + public static readonly DerObjectIdentifier Steuerberater = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".5"); + + /** + * Steuerbevollm�chtigte + */ + public static readonly DerObjectIdentifier Steuerbevollmchtigte = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".6"); + + /** + * Steuerbevollm�chtigter + */ + public static readonly DerObjectIdentifier Steuerbevollmchtigter = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".7"); + + /** + * Notarin + */ + public static readonly DerObjectIdentifier Notarin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".8"); + + /** + * Notar + */ + public static readonly DerObjectIdentifier Notar = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".9"); + + /** + * Notarvertreterin + */ + public static readonly DerObjectIdentifier Notarvertreterin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".10"); + + /** + * Notarvertreter + */ + public static readonly DerObjectIdentifier Notarvertreter = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".11"); + + /** + * Notariatsverwalterin + */ + public static readonly DerObjectIdentifier Notariatsverwalterin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".12"); + + /** + * Notariatsverwalter + */ + public static readonly DerObjectIdentifier Notariatsverwalter = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".13"); + + /** + * Wirtschaftspr�ferin + */ + public static readonly DerObjectIdentifier Wirtschaftsprferin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".14"); + + /** + * Wirtschaftspr�fer + */ + public static readonly DerObjectIdentifier Wirtschaftsprfer = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".15"); + + /** + * Vereidigte Buchpr�ferin + */ + public static readonly DerObjectIdentifier VereidigteBuchprferin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".16"); + + /** + * Vereidigter Buchpr�fer + */ + public static readonly DerObjectIdentifier VereidigterBuchprfer = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".17"); + + /** + * Patentanw�ltin + */ + public static readonly DerObjectIdentifier Patentanwltin = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".18"); + + /** + * Patentanwalt + */ + public static readonly DerObjectIdentifier Patentanwalt = new DerObjectIdentifier( + NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".19"); + + private readonly NamingAuthority namingAuthority; + private readonly Asn1Sequence professionItems; + private readonly Asn1Sequence professionOids; + private readonly string registrationNumber; + private readonly Asn1OctetString addProfessionInfo; + + public static ProfessionInfo GetInstance( + object obj) + { + if (obj == null || obj is ProfessionInfo) + { + return (ProfessionInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new ProfessionInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ *

+ *

+		*               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
+		*               }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private ProfessionInfo( + Asn1Sequence seq) + { + if (seq.Count > 5) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + Asn1Encodable o = (Asn1Encodable) e.Current; + + if (o is Asn1TaggedObject) + { + Asn1TaggedObject ato = (Asn1TaggedObject) o; + if (ato.TagNo != 0) + throw new ArgumentException("Bad tag number: " + ato.TagNo); + + namingAuthority = NamingAuthority.GetInstance(ato, true); + e.MoveNext(); + o = (Asn1Encodable) e.Current; + } + + professionItems = Asn1Sequence.GetInstance(o); + + if (e.MoveNext()) + { + o = (Asn1Encodable) e.Current; + if (o is Asn1Sequence) + { + professionOids = Asn1Sequence.GetInstance(o); + } + else if (o is DerPrintableString) + { + registrationNumber = DerPrintableString.GetInstance(o).GetString(); + } + else if (o is Asn1OctetString) + { + addProfessionInfo = Asn1OctetString.GetInstance(o); + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + + if (e.MoveNext()) + { + o = (Asn1Encodable) e.Current; + if (o is DerPrintableString) + { + registrationNumber = DerPrintableString.GetInstance(o).GetString(); + } + else if (o is DerOctetString) + { + addProfessionInfo = (DerOctetString) o; + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + + if (e.MoveNext()) + { + o = (Asn1Encodable) e.Current; + if (o is DerOctetString) + { + addProfessionInfo = (DerOctetString) o; + } + else + { + throw new ArgumentException("Bad object encountered: " + o.GetType().Name); + } + } + } + + /** + * Constructor from given details. + *

+ * professionItems 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, + DerObjectIdentifier[] professionOids, + string registrationNumber, + Asn1OctetString addProfessionInfo) + { + this.namingAuthority = namingAuthority; + this.professionItems = new DerSequence(professionItems); + if (professionOids != null) + { + this.professionOids = new DerSequence(professionOids); + } + this.registrationNumber = registrationNumber; + this.addProfessionInfo = addProfessionInfo; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*               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
+		*               }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + 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 virtual Asn1OctetString AddProfessionInfo + { + get { return addProfessionInfo; } + } + + /** + * @return Returns the namingAuthority. + */ + public virtual NamingAuthority NamingAuthority + { + get { return namingAuthority; } + } + + /** + * @return Returns the professionItems. + */ + public virtual DirectoryString[] GetProfessionItems() + { + DirectoryString[] result = new DirectoryString[professionItems.Count]; + + for (int i = 0; i < professionItems.Count; ++i) + { + result[i] = DirectoryString.GetInstance(professionItems[i]); + } + + return result; + } + + /** + * @return Returns the professionOids. + */ + public virtual DerObjectIdentifier[] GetProfessionOids() + { + if (professionOids == null) + { + return new DerObjectIdentifier[0]; + } + + DerObjectIdentifier[] result = new DerObjectIdentifier[professionOids.Count]; + + for (int i = 0; i < professionOids.Count; ++i) + { + result[i] = DerObjectIdentifier.GetInstance(professionOids[i]); + } + + return result; + } + + /** + * @return Returns the registrationNumber. + */ + public virtual string RegistrationNumber + { + get { return registrationNumber; } + } + } +} diff --git a/crypto/src/asn1/isismtt/x509/Restriction.cs b/crypto/src/asn1/isismtt/x509/Restriction.cs new file mode 100644 index 000000000..c97766999 --- /dev/null +++ b/crypto/src/asn1/isismtt/x509/Restriction.cs @@ -0,0 +1,81 @@ +using System; + +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.IsisMtt.X509 +{ + /** + * Some other restriction regarding the usage of this certificate. + *

+ *

+	*  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+	* 
+ */ + public class Restriction + : Asn1Encodable + { + private readonly DirectoryString restriction; + + public static Restriction GetInstance( + object obj) + { + if (obj is Restriction) + return (Restriction) obj; + + if (obj is IAsn1String) + return new Restriction(DirectoryString.GetInstance(obj)); + + throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from DirectoryString. + *

+ * The DirectoryString is of type RestrictionSyntax: + *

+ *

+		*      RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		* 
+ * + * @param restriction A IAsn1String. + */ + private Restriction( + DirectoryString restriction) + { + this.restriction = restriction; + } + + /** + * Constructor from a given details. + * + * @param restriction The description of the restriction. + */ + public Restriction( + string restriction) + { + this.restriction = new DirectoryString(restriction); + } + + public virtual DirectoryString RestrictionString + { + get { return restriction; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*      RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		* 

+ *

+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return restriction.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/kisa/KISAObjectIdentifiers.cs b/crypto/src/asn1/kisa/KISAObjectIdentifiers.cs new file mode 100644 index 000000000..05351ec75 --- /dev/null +++ b/crypto/src/asn1/kisa/KISAObjectIdentifiers.cs @@ -0,0 +1,8 @@ +namespace Org.BouncyCastle.Asn1.Kisa +{ + public abstract class KisaObjectIdentifiers + { + public static readonly DerObjectIdentifier IdSeedCbc = new DerObjectIdentifier("1.2.410.200004.1.4"); + public static readonly DerObjectIdentifier IdNpkiAppCmsSeedWrap = new DerObjectIdentifier("1.2.410.200004.7.1.1.1"); + } +} diff --git a/crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs b/crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs new file mode 100644 index 000000000..b8aba7ee9 --- /dev/null +++ b/crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs @@ -0,0 +1,18 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Microsoft +{ + public abstract class MicrosoftObjectIdentifiers + { + // + // Microsoft + // iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) Microsoft(311) + // + public static readonly DerObjectIdentifier Microsoft = new DerObjectIdentifier("1.3.6.1.4.1.311"); + public static readonly DerObjectIdentifier MicrosoftCertTemplateV1 = new DerObjectIdentifier(Microsoft + ".20.2"); + public static readonly DerObjectIdentifier MicrosoftCAVersion = new DerObjectIdentifier(Microsoft + ".21.1"); + public static readonly DerObjectIdentifier MicrosoftPrevCACertHash = new DerObjectIdentifier(Microsoft + ".21.2"); + public static readonly DerObjectIdentifier MicrosoftCertTemplateV2 = new DerObjectIdentifier(Microsoft + ".21.7"); + public static readonly DerObjectIdentifier MicrosoftAppPolicies = new DerObjectIdentifier(Microsoft + ".21.10"); + } +} diff --git a/crypto/src/asn1/misc/CAST5CBCParameters.cs b/crypto/src/asn1/misc/CAST5CBCParameters.cs new file mode 100644 index 000000000..51fd6607a --- /dev/null +++ b/crypto/src/asn1/misc/CAST5CBCParameters.cs @@ -0,0 +1,74 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Misc +{ + public class Cast5CbcParameters + : Asn1Encodable + { + private readonly DerInteger keyLength; + private readonly Asn1OctetString iv; + + public static Cast5CbcParameters GetInstance( + object o) + { + if (o is Cast5CbcParameters) + { + return (Cast5CbcParameters) o; + } + + if (o is Asn1Sequence) + { + return new Cast5CbcParameters((Asn1Sequence) o); + } + + throw new ArgumentException("unknown object in Cast5CbcParameters factory"); + } + + public Cast5CbcParameters( + byte[] iv, + int keyLength) + { + this.iv = new DerOctetString(iv); + this.keyLength = new DerInteger(keyLength); + } + + private Cast5CbcParameters( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + iv = (Asn1OctetString) seq[0]; + keyLength = (DerInteger) seq[1]; + } + + public byte[] GetIV() + { + return Arrays.Clone(iv.GetOctets()); + } + + public int KeyLength + { + get { return keyLength.Value.IntValue; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * cast5CBCParameters ::= Sequence {
+         *                           iv         OCTET STRING DEFAULT 0,
+         *                                  -- Initialization vector
+         *                           keyLength  Integer
+         *                                  -- Key length, in bits
+         *                      }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(iv, keyLength); + } + } +} diff --git a/crypto/src/asn1/misc/IDEACBCPar.cs b/crypto/src/asn1/misc/IDEACBCPar.cs new file mode 100644 index 000000000..72a60b9dc --- /dev/null +++ b/crypto/src/asn1/misc/IDEACBCPar.cs @@ -0,0 +1,68 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Misc +{ + public class IdeaCbcPar + : Asn1Encodable + { + internal Asn1OctetString iv; + + public static IdeaCbcPar GetInstance( + object o) + { + if (o is IdeaCbcPar) + { + return (IdeaCbcPar) o; + } + + if (o is Asn1Sequence) + { + return new IdeaCbcPar((Asn1Sequence) o); + } + + throw new ArgumentException("unknown object in IDEACBCPar factory"); + } + + public IdeaCbcPar( + byte[] iv) + { + this.iv = new DerOctetString(iv); + } + + private IdeaCbcPar( + Asn1Sequence seq) + { + if (seq.Count == 1) + { + iv = (Asn1OctetString) seq[0]; + } + } + + public byte[] GetIV() + { + return iv == null ? null : iv.GetOctets(); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * IDEA-CBCPar ::= Sequence {
+         *                      iv    OCTET STRING OPTIONAL -- exactly 8 octets
+         *                  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (iv != null) + { + v.Add(iv); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs new file mode 100644 index 000000000..01004d889 --- /dev/null +++ b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs @@ -0,0 +1,48 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Misc +{ + public abstract class MiscObjectIdentifiers + { + // + // Netscape + // iso/itu(2) joint-assign(16) us(840) uscompany(1) Netscape(113730) cert-extensions(1) } + // + public static readonly DerObjectIdentifier Netscape = new DerObjectIdentifier("2.16.840.1.113730.1"); + public static readonly DerObjectIdentifier NetscapeCertType = new DerObjectIdentifier(Netscape + ".1"); + public static readonly DerObjectIdentifier NetscapeBaseUrl = new DerObjectIdentifier(Netscape + ".2"); + public static readonly DerObjectIdentifier NetscapeRevocationUrl = new DerObjectIdentifier(Netscape + ".3"); + public static readonly DerObjectIdentifier NetscapeCARevocationUrl = new DerObjectIdentifier(Netscape + ".4"); + public static readonly DerObjectIdentifier NetscapeRenewalUrl = new DerObjectIdentifier(Netscape + ".7"); + public static readonly DerObjectIdentifier NetscapeCAPolicyUrl = new DerObjectIdentifier(Netscape + ".8"); + public static readonly DerObjectIdentifier NetscapeSslServerName = new DerObjectIdentifier(Netscape + ".12"); + public static readonly DerObjectIdentifier NetscapeCertComment = new DerObjectIdentifier(Netscape + ".13"); + // + // Verisign + // iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) } + // + internal const string Verisign = "2.16.840.1.113733.1"; + + // + // CZAG - country, zip, age, and gender + // + public static readonly DerObjectIdentifier VerisignCzagExtension = new DerObjectIdentifier(Verisign + ".6.3"); + + // D&B D-U-N-S number + public static readonly DerObjectIdentifier VerisignDnbDunsNumber = new DerObjectIdentifier(Verisign + ".6.15"); + + // + // Novell + // iso/itu(2) country(16) us(840) organization(1) novell(113719) + // + public static readonly string Novell = "2.16.840.1.113719"; + public static readonly DerObjectIdentifier NovellSecurityAttribs = new DerObjectIdentifier(Novell + ".1.9.4.1"); + + // + // Entrust + // iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7) + // + public static readonly string Entrust = "1.2.840.113533.7"; + public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0"); + } +} diff --git a/crypto/src/asn1/misc/NetscapeCertType.cs b/crypto/src/asn1/misc/NetscapeCertType.cs new file mode 100644 index 000000000..d5db6523d --- /dev/null +++ b/crypto/src/asn1/misc/NetscapeCertType.cs @@ -0,0 +1,54 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Misc +{ + /** + * The NetscapeCertType object. + *
+     *    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) }
+     * 
+ */ + public class NetscapeCertType + : DerBitString + { + public const int SslClient = (1 << 7); + public const int SslServer = (1 << 6); + public const int Smime = (1 << 5); + public const int ObjectSigning = (1 << 4); + public const int Reserved = (1 << 3); + public const int SslCA = (1 << 2); + public const int SmimeCA = (1 << 1); + public const 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) + : base(GetBytes(usage), GetPadBits(usage)) + { + } + + public NetscapeCertType(DerBitString usage) + : base(usage.GetBytes(), usage.PadBits) + { + } + + public override string ToString() + { + byte[] data = GetBytes(); + return "NetscapeCertType: 0x" + (data[0] & 0xff).ToString("X"); + } + } +} diff --git a/crypto/src/asn1/misc/NetscapeRevocationURL.cs b/crypto/src/asn1/misc/NetscapeRevocationURL.cs new file mode 100644 index 000000000..6cac031f2 --- /dev/null +++ b/crypto/src/asn1/misc/NetscapeRevocationURL.cs @@ -0,0 +1,18 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Misc +{ + public class NetscapeRevocationUrl + : DerIA5String + { + public NetscapeRevocationUrl(DerIA5String str) + : base(str.GetString()) + { + } + + public override string ToString() + { + return "NetscapeRevocationUrl: " + this.GetString(); + } + } +} diff --git a/crypto/src/asn1/misc/VerisignCzagExtension.cs b/crypto/src/asn1/misc/VerisignCzagExtension.cs new file mode 100644 index 000000000..1c3054b32 --- /dev/null +++ b/crypto/src/asn1/misc/VerisignCzagExtension.cs @@ -0,0 +1,18 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Misc +{ + public class VerisignCzagExtension + : DerIA5String + { + public VerisignCzagExtension(DerIA5String str) + : base(str.GetString()) + { + } + + public override string ToString() + { + return "VerisignCzagExtension: " + this.GetString(); + } + } +} diff --git a/crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs b/crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs new file mode 100644 index 000000000..1e08b809d --- /dev/null +++ b/crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs @@ -0,0 +1,67 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Mozilla +{ + /** + * This is designed to parse + * the PublicKeyAndChallenge created by the KEYGEN tag included by + * Mozilla based browsers. + *
+	 *  PublicKeyAndChallenge ::= SEQUENCE {
+	 *    spki SubjectPublicKeyInfo,
+	 *    challenge IA5STRING
+	 *  }
+	 *
+	 *  
+ */ + public class PublicKeyAndChallenge + : Asn1Encodable + { + private Asn1Sequence pkacSeq; + private SubjectPublicKeyInfo spki; + private DerIA5String challenge; + + public static PublicKeyAndChallenge GetInstance( + object obj) + { + if (obj is PublicKeyAndChallenge) + { + return (PublicKeyAndChallenge) obj; + } + + if (obj is Asn1Sequence) + { + return new PublicKeyAndChallenge((Asn1Sequence) obj); + } + + throw new ArgumentException( + "unknown object in 'PublicKeyAndChallenge' factory : " + + obj.GetType().Name + "."); + } + + public PublicKeyAndChallenge( + Asn1Sequence seq) + { + pkacSeq = seq; + spki = SubjectPublicKeyInfo.GetInstance(seq[0]); + challenge = DerIA5String.GetInstance(seq[1]); + } + + public override Asn1Object ToAsn1Object() + { + return pkacSeq; + } + + public SubjectPublicKeyInfo SubjectPublicKeyInfo + { + get { return spki; } + } + + public DerIA5String Challenge + { + get { return challenge; } + } + } +} diff --git a/crypto/src/asn1/nist/NISTNamedCurves.cs b/crypto/src/asn1/nist/NISTNamedCurves.cs new file mode 100644 index 000000000..0e82dda7a --- /dev/null +++ b/crypto/src/asn1/nist/NISTNamedCurves.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.Nist +{ + /** + * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-3 + */ + public sealed class NistNamedCurves + { + private NistNamedCurves() + { + } + + private static readonly IDictionary objIds = Platform.CreateHashtable(); + private static readonly IDictionary names = Platform.CreateHashtable(); + + private static void DefineCurve( + string name, + DerObjectIdentifier oid) + { + objIds.Add(name, oid); + names.Add(oid, name); + } + + static NistNamedCurves() + { + 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) + { + DerObjectIdentifier oid = (DerObjectIdentifier) objIds[ + Platform.ToUpperInvariant(name)]; + + if (oid != null) + { + return GetByOid(oid); + } + + return null; + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters GetByOid( + DerObjectIdentifier oid) + { + return SecNamedCurves.GetByOid(oid); + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier) objIds[ + Platform.ToUpperInvariant(name)]; + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static string GetName( + DerObjectIdentifier oid) + { + return (string) names[oid]; + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + } +} diff --git a/crypto/src/asn1/nist/NISTObjectIdentifiers.cs b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs new file mode 100644 index 000000000..8eb5ed437 --- /dev/null +++ b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs @@ -0,0 +1,65 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Nist +{ + public sealed class NistObjectIdentifiers + { + private NistObjectIdentifiers() + { + } + + // + // NIST + // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3) + + // + // nistalgorithms(4) + // + public static readonly DerObjectIdentifier NistAlgorithm = new DerObjectIdentifier("2.16.840.1.101.3.4"); + + public static readonly DerObjectIdentifier HashAlgs = NistAlgorithm.Branch("2"); + + public static readonly DerObjectIdentifier IdSha256 = HashAlgs.Branch("1"); + public static readonly DerObjectIdentifier IdSha384 = HashAlgs.Branch("2"); + public static readonly DerObjectIdentifier IdSha512 = HashAlgs.Branch("3"); + public static readonly DerObjectIdentifier IdSha224 = HashAlgs.Branch("4"); + public static readonly DerObjectIdentifier IdSha512_224 = HashAlgs.Branch("5"); + public static readonly DerObjectIdentifier IdSha512_256 = HashAlgs.Branch("6"); + + public static readonly DerObjectIdentifier Aes = new DerObjectIdentifier(NistAlgorithm + ".1"); + + public static readonly DerObjectIdentifier IdAes128Ecb = new DerObjectIdentifier(Aes + ".1"); + public static readonly DerObjectIdentifier IdAes128Cbc = new DerObjectIdentifier(Aes + ".2"); + public static readonly DerObjectIdentifier IdAes128Ofb = new DerObjectIdentifier(Aes + ".3"); + public static readonly DerObjectIdentifier IdAes128Cfb = new DerObjectIdentifier(Aes + ".4"); + public static readonly DerObjectIdentifier IdAes128Wrap = new DerObjectIdentifier(Aes + ".5"); + public static readonly DerObjectIdentifier IdAes128Gcm = new DerObjectIdentifier(Aes + ".6"); + public static readonly DerObjectIdentifier IdAes128Ccm = new DerObjectIdentifier(Aes + ".7"); + + public static readonly DerObjectIdentifier IdAes192Ecb = new DerObjectIdentifier(Aes + ".21"); + public static readonly DerObjectIdentifier IdAes192Cbc = new DerObjectIdentifier(Aes + ".22"); + public static readonly DerObjectIdentifier IdAes192Ofb = new DerObjectIdentifier(Aes + ".23"); + public static readonly DerObjectIdentifier IdAes192Cfb = new DerObjectIdentifier(Aes + ".24"); + public static readonly DerObjectIdentifier IdAes192Wrap = new DerObjectIdentifier(Aes + ".25"); + public static readonly DerObjectIdentifier IdAes192Gcm = new DerObjectIdentifier(Aes + ".26"); + public static readonly DerObjectIdentifier IdAes192Ccm = new DerObjectIdentifier(Aes + ".27"); + + public static readonly DerObjectIdentifier IdAes256Ecb = new DerObjectIdentifier(Aes + ".41"); + public static readonly DerObjectIdentifier IdAes256Cbc = new DerObjectIdentifier(Aes + ".42"); + public static readonly DerObjectIdentifier IdAes256Ofb = new DerObjectIdentifier(Aes + ".43"); + public static readonly DerObjectIdentifier IdAes256Cfb = new DerObjectIdentifier(Aes + ".44"); + public static readonly DerObjectIdentifier IdAes256Wrap = new DerObjectIdentifier(Aes + ".45"); + public static readonly DerObjectIdentifier IdAes256Gcm = new DerObjectIdentifier(Aes + ".46"); + public static readonly DerObjectIdentifier IdAes256Ccm = new DerObjectIdentifier(Aes + ".47"); + + // + // signatures + // + public static readonly DerObjectIdentifier IdDsaWithSha2 = new DerObjectIdentifier(NistAlgorithm + ".3"); + + public static readonly DerObjectIdentifier DsaWithSha224 = new DerObjectIdentifier(IdDsaWithSha2 + ".1"); + public static readonly DerObjectIdentifier DsaWithSha256 = new DerObjectIdentifier(IdDsaWithSha2 + ".2"); + public static readonly DerObjectIdentifier DsaWithSha384 = new DerObjectIdentifier(IdDsaWithSha2 + ".3"); + public static readonly DerObjectIdentifier DsaWithSha512 = new DerObjectIdentifier(IdDsaWithSha2 + ".4"); + } +} diff --git a/crypto/src/asn1/ntt/NTTObjectIdentifiers.cs b/crypto/src/asn1/ntt/NTTObjectIdentifiers.cs new file mode 100644 index 000000000..cd2595600 --- /dev/null +++ b/crypto/src/asn1/ntt/NTTObjectIdentifiers.cs @@ -0,0 +1,14 @@ +namespace Org.BouncyCastle.Asn1.Ntt +{ + /// From RFC 3657 + public abstract class NttObjectIdentifiers + { + public static readonly DerObjectIdentifier IdCamellia128Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.2"); + public static readonly DerObjectIdentifier IdCamellia192Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.3"); + public static readonly DerObjectIdentifier IdCamellia256Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.4"); + + public static readonly DerObjectIdentifier IdCamellia128Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.2"); + public static readonly DerObjectIdentifier IdCamellia192Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.3"); + public static readonly DerObjectIdentifier IdCamellia256Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.4"); + } +} diff --git a/crypto/src/asn1/ocsp/BasicOCSPResponse.cs b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs new file mode 100644 index 000000000..dd666addf --- /dev/null +++ b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs @@ -0,0 +1,131 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class BasicOcspResponse + : Asn1Encodable + { + private readonly ResponseData tbsResponseData; + private readonly AlgorithmIdentifier signatureAlgorithm; + private readonly DerBitString signature; + private readonly Asn1Sequence certs; + + public static BasicOcspResponse GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static BasicOcspResponse GetInstance( + object obj) + { + if (obj == null || obj is BasicOcspResponse) + { + return (BasicOcspResponse)obj; + } + + if (obj is Asn1Sequence) + { + return new BasicOcspResponse((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + 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[0]); + this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + this.signature = (DerBitString)seq[2]; + + if (seq.Count > 3) + { + this.certs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[3], true); + } + } + + [Obsolete("Use TbsResponseData property instead")] + public ResponseData GetTbsResponseData() + { + return tbsResponseData; + } + + public ResponseData TbsResponseData + { + get { return tbsResponseData; } + } + + [Obsolete("Use SignatureAlgorithm property instead")] + public AlgorithmIdentifier GetSignatureAlgorithm() + { + return signatureAlgorithm; + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return signatureAlgorithm; } + } + + [Obsolete("Use Signature property instead")] + public DerBitString GetSignature() + { + return signature; + } + + public DerBitString Signature + { + get { return signature; } + } + + [Obsolete("Use Certs property instead")] + public Asn1Sequence GetCerts() + { + return certs; + } + + public Asn1Sequence Certs + { + get { return certs; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * BasicOcspResponse       ::= Sequence {
+         *      tbsResponseData      ResponseData,
+         *      signatureAlgorithm   AlgorithmIdentifier,
+         *      signature            BIT STRING,
+         *      certs                [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + tbsResponseData, signatureAlgorithm, signature); + + if (certs != null) + { + v.Add(new DerTaggedObject(true, 0, certs)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/CertID.cs b/crypto/src/asn1/ocsp/CertID.cs new file mode 100644 index 000000000..4b251095b --- /dev/null +++ b/crypto/src/asn1/ocsp/CertID.cs @@ -0,0 +1,98 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class CertID + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly Asn1OctetString issuerNameHash; + private readonly Asn1OctetString issuerKeyHash; + private readonly DerInteger serialNumber; + + public static CertID GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static CertID GetInstance( + object obj) + { + if (obj == null || obj is CertID) + { + return (CertID)obj; + } + + if (obj is Asn1Sequence) + { + return new CertID((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public CertID( + AlgorithmIdentifier hashAlgorithm, + Asn1OctetString issuerNameHash, + Asn1OctetString issuerKeyHash, + DerInteger serialNumber) + { + this.hashAlgorithm = hashAlgorithm; + this.issuerNameHash = issuerNameHash; + this.issuerKeyHash = issuerKeyHash; + this.serialNumber = serialNumber; + } + + private CertID( + Asn1Sequence seq) + { + if (seq.Count != 4) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); + this.issuerNameHash = Asn1OctetString.GetInstance(seq[1]); + this.issuerKeyHash = Asn1OctetString.GetInstance(seq[2]); + this.serialNumber = DerInteger.GetInstance(seq[3]); + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public Asn1OctetString IssuerNameHash + { + get { return issuerNameHash; } + } + + public Asn1OctetString IssuerKeyHash + { + get { return issuerKeyHash; } + } + + public DerInteger SerialNumber + { + get { return serialNumber; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * CertID          ::=     Sequence {
+         *     hashAlgorithm       AlgorithmIdentifier,
+         *     issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+         *     issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+         *     serialNumber        CertificateSerialNumber }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber); + } + } +} diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs new file mode 100644 index 000000000..d5b1a94a2 --- /dev/null +++ b/crypto/src/asn1/ocsp/CertStatus.cs @@ -0,0 +1,94 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class CertStatus + : Asn1Encodable, IAsn1Choice + { + private readonly int tagNo; + private readonly 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.TagNo; + + switch (choice.TagNo) + { + case 1: + value = RevokedInfo.GetInstance(choice, false); + break; + case 0: + case 2: + value = DerNull.Instance; + break; + } + } + + public static CertStatus GetInstance( + object obj) + { + if (obj == null || obj is CertStatus) + { + return (CertStatus)obj; + } + + if (obj is Asn1TaggedObject) + { + return new CertStatus((Asn1TaggedObject)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public int TagNo + { + get { return tagNo; } + } + + public Asn1Encodable Status + { + get { return value; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  CertStatus ::= CHOICE {
+         *                  good        [0]     IMPLICIT Null,
+         *                  revoked     [1]     IMPLICIT RevokedInfo,
+         *                  unknown     [2]     IMPLICIT UnknownInfo }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerTaggedObject(false, tagNo, value); + } + } +} diff --git a/crypto/src/asn1/ocsp/CrlID.cs b/crypto/src/asn1/ocsp/CrlID.cs new file mode 100644 index 000000000..cfb3d6fcb --- /dev/null +++ b/crypto/src/asn1/ocsp/CrlID.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class CrlID + : Asn1Encodable + { + private readonly DerIA5String crlUrl; + private readonly DerInteger crlNum; + private readonly DerGeneralizedTime crlTime; + + // TODO Add GetInstance method(s) and amke this private? + public CrlID( + Asn1Sequence seq) + { + foreach (Asn1TaggedObject o in seq) + { + switch (o.TagNo) + { + case 0: + crlUrl = DerIA5String.GetInstance(o, true); + break; + case 1: + crlNum = DerInteger.GetInstance(o, true); + break; + case 2: + crlTime = DerGeneralizedTime.GetInstance(o, true); + break; + default: + throw new ArgumentException("unknown tag number: " + o.TagNo); + } + } + } + + public DerIA5String CrlUrl + { + get { return crlUrl; } + } + + public DerInteger CrlNum + { + get { return crlNum; } + } + + public DerGeneralizedTime CrlTime + { + get { return crlTime; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * CrlID ::= Sequence {
+         *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+         *     crlNum               [1]     EXPLICIT Integer OPTIONAL,
+         *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs b/crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs new file mode 100644 index 000000000..a37c8552d --- /dev/null +++ b/crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs @@ -0,0 +1,23 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public abstract class OcspObjectIdentifiers + { + internal const string PkixOcspId = "1.3.6.1.5.5.7.48.1"; + + public static readonly DerObjectIdentifier PkixOcsp = new DerObjectIdentifier(PkixOcspId); + public static readonly DerObjectIdentifier PkixOcspBasic = new DerObjectIdentifier(PkixOcspId + ".1"); + + // + // extensions + // + public static readonly DerObjectIdentifier PkixOcspNonce = new DerObjectIdentifier(PkixOcsp + ".2"); + public static readonly DerObjectIdentifier PkixOcspCrl = new DerObjectIdentifier(PkixOcsp + ".3"); + + public static readonly DerObjectIdentifier PkixOcspResponse = new DerObjectIdentifier(PkixOcsp + ".4"); + public static readonly DerObjectIdentifier PkixOcspNocheck = new DerObjectIdentifier(PkixOcsp + ".5"); + public static readonly DerObjectIdentifier PkixOcspArchiveCutoff = new DerObjectIdentifier(PkixOcsp + ".6"); + public static readonly DerObjectIdentifier PkixOcspServiceLocator = new DerObjectIdentifier(PkixOcsp + ".7"); + } +} diff --git a/crypto/src/asn1/ocsp/OCSPRequest.cs b/crypto/src/asn1/ocsp/OCSPRequest.cs new file mode 100644 index 000000000..1e804d78e --- /dev/null +++ b/crypto/src/asn1/ocsp/OCSPRequest.cs @@ -0,0 +1,89 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class OcspRequest + : Asn1Encodable + { + private readonly TbsRequest tbsRequest; + private readonly Signature optionalSignature; + + public static OcspRequest GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static OcspRequest GetInstance( + object obj) + { + if (obj == null || obj is OcspRequest) + { + return (OcspRequest)obj; + } + + if (obj is Asn1Sequence) + { + return new OcspRequest((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public OcspRequest( + TbsRequest tbsRequest, + Signature optionalSignature) + { + if (tbsRequest == null) + throw new ArgumentNullException("tbsRequest"); + + this.tbsRequest = tbsRequest; + this.optionalSignature = optionalSignature; + } + + private OcspRequest( + Asn1Sequence seq) + { + tbsRequest = TbsRequest.GetInstance(seq[0]); + + if (seq.Count == 2) + { + optionalSignature = Signature.GetInstance( + (Asn1TaggedObject)seq[1], true); + } + } + + public TbsRequest TbsRequest + { + get { return tbsRequest; } + } + + public Signature OptionalSignature + { + get { return optionalSignature; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OcspRequest     ::=     Sequence {
+         *     tbsRequest                  TBSRequest,
+         *     optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(tbsRequest); + + if (optionalSignature != null) + { + v.Add(new DerTaggedObject(true, 0, optionalSignature)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/OCSPResponse.cs b/crypto/src/asn1/ocsp/OCSPResponse.cs new file mode 100644 index 000000000..e9aad8100 --- /dev/null +++ b/crypto/src/asn1/ocsp/OCSPResponse.cs @@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class OcspResponse + : Asn1Encodable + { + private readonly OcspResponseStatus responseStatus; + private readonly ResponseBytes responseBytes; + + public static OcspResponse GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static OcspResponse GetInstance( + object obj) + { + if (obj == null || obj is OcspResponse) + { + return (OcspResponse)obj; + } + + if (obj is Asn1Sequence) + { + return new OcspResponse((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public OcspResponse( + OcspResponseStatus responseStatus, + ResponseBytes responseBytes) + { + if (responseStatus == null) + throw new ArgumentNullException("responseStatus"); + + this.responseStatus = responseStatus; + this.responseBytes = responseBytes; + } + + private OcspResponse( + Asn1Sequence seq) + { + responseStatus = new OcspResponseStatus( + DerEnumerated.GetInstance(seq[0])); + + if (seq.Count == 2) + { + responseBytes = ResponseBytes.GetInstance( + (Asn1TaggedObject)seq[1], true); + } + } + + public OcspResponseStatus ResponseStatus + { + get { return responseStatus; } + } + + public ResponseBytes ResponseBytes + { + get { return responseBytes; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * OcspResponse ::= Sequence {
+         *     responseStatus         OcspResponseStatus,
+         *     responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(responseStatus); + + if (responseBytes != null) + { + v.Add(new DerTaggedObject(true, 0, responseBytes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/OCSPResponseStatus.cs b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs new file mode 100644 index 000000000..653317e33 --- /dev/null +++ b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs @@ -0,0 +1,41 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class OcspResponseStatus + : DerEnumerated + { + public const int Successful = 0; + public const int MalformedRequest = 1; + public const int InternalError = 2; + public const int TryLater = 3; + public const int SignatureRequired = 5; + public const int Unauthorized = 6; + + /** + * The OcspResponseStatus enumeration. + *
+         * 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
+         * }
+         * 
+ */ + public OcspResponseStatus(int value) + : base(value) + { + } + + public OcspResponseStatus(DerEnumerated value) + : base(value.Value.IntValue) + { + } + } +} diff --git a/crypto/src/asn1/ocsp/Request.cs b/crypto/src/asn1/ocsp/Request.cs new file mode 100644 index 000000000..116c15e73 --- /dev/null +++ b/crypto/src/asn1/ocsp/Request.cs @@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class Request + : Asn1Encodable + { + private readonly CertID reqCert; + private readonly X509Extensions singleRequestExtensions; + + public static Request GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static Request GetInstance( + object obj) + { + if (obj == null || obj is Request) + { + return (Request)obj; + } + + if (obj is Asn1Sequence) + { + return new Request((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public Request( + CertID reqCert, + X509Extensions singleRequestExtensions) + { + if (reqCert == null) + throw new ArgumentNullException("reqCert"); + + this.reqCert = reqCert; + this.singleRequestExtensions = singleRequestExtensions; + } + + private Request( + Asn1Sequence seq) + { + reqCert = CertID.GetInstance(seq[0]); + + if (seq.Count == 2) + { + singleRequestExtensions = X509Extensions.GetInstance( + (Asn1TaggedObject)seq[1], true); + } + } + + public CertID ReqCert + { + get { return reqCert; } + } + + public X509Extensions SingleRequestExtensions + { + get { return singleRequestExtensions; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Request         ::=     Sequence {
+         *     reqCert                     CertID,
+         *     singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(reqCert); + + if (singleRequestExtensions != null) + { + v.Add(new DerTaggedObject(true, 0, singleRequestExtensions)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/ResponderID.cs b/crypto/src/asn1/ocsp/ResponderID.cs new file mode 100644 index 000000000..143b17339 --- /dev/null +++ b/crypto/src/asn1/ocsp/ResponderID.cs @@ -0,0 +1,107 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class ResponderID + : Asn1Encodable, IAsn1Choice + { + private readonly Asn1Encodable id; + + public static ResponderID GetInstance( + object obj) + { + if (obj == null || obj is ResponderID) + { + return (ResponderID)obj; + } + + if (obj is DerOctetString) + { + return new ResponderID((DerOctetString)obj); + } + + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject o = (Asn1TaggedObject)obj; + + if (o.TagNo == 1) + { + return new ResponderID(X509Name.GetInstance(o, true)); + } + + return new ResponderID(Asn1OctetString.GetInstance(o, true)); + } + + return new ResponderID(X509Name.GetInstance(obj)); + } + + public ResponderID( + Asn1OctetString id) + { + if (id == null) + throw new ArgumentNullException("id"); + + this.id = id; + } + + public ResponderID( + X509Name id) + { + if (id == null) + throw new ArgumentNullException("id"); + + this.id = id; + } + + public static ResponderID GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(obj.GetObject()); // must be explicitly tagged + } + + public virtual byte[] GetKeyHash() + { + if (id is Asn1OctetString) + { + return ((Asn1OctetString)id).GetOctets(); + } + + return null; + } + + public virtual X509Name Name + { + get + { + if (id is Asn1OctetString) + { + return null; + } + + return X509Name.GetInstance(id); + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ResponderID ::= CHOICE {
+         *      byName          [1] Name,
+         *      byKey           [2] KeyHash }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + if (id is Asn1OctetString) + { + return new DerTaggedObject(true, 2, id); + } + + return new DerTaggedObject(true, 1, id); + } + } +} diff --git a/crypto/src/asn1/ocsp/ResponseBytes.cs b/crypto/src/asn1/ocsp/ResponseBytes.cs new file mode 100644 index 000000000..2ce59faea --- /dev/null +++ b/crypto/src/asn1/ocsp/ResponseBytes.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class ResponseBytes + : Asn1Encodable + { + private readonly DerObjectIdentifier responseType; + private readonly Asn1OctetString response; + + public static ResponseBytes GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static ResponseBytes GetInstance( + object obj) + { + if (obj == null || obj is ResponseBytes) + { + return (ResponseBytes)obj; + } + + if (obj is Asn1Sequence) + { + return new ResponseBytes((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public ResponseBytes( + DerObjectIdentifier responseType, + Asn1OctetString response) + { + if (responseType == null) + throw new ArgumentNullException("responseType"); + if (response == null) + throw new ArgumentNullException("response"); + + this.responseType = responseType; + this.response = response; + } + + private ResponseBytes( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.responseType = DerObjectIdentifier.GetInstance(seq[0]); + this.response = Asn1OctetString.GetInstance(seq[1]); + } + + public DerObjectIdentifier ResponseType + { + get { return responseType; } + } + + public Asn1OctetString Response + { + get { return response; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ResponseBytes ::=       Sequence {
+         *     responseType   OBJECT IDENTIFIER,
+         *     response       OCTET STRING }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(responseType, response); + } + } +} diff --git a/crypto/src/asn1/ocsp/ResponseData.cs b/crypto/src/asn1/ocsp/ResponseData.cs new file mode 100644 index 000000000..173829db8 --- /dev/null +++ b/crypto/src/asn1/ocsp/ResponseData.cs @@ -0,0 +1,158 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class ResponseData + : Asn1Encodable + { + private static readonly DerInteger V1 = new DerInteger(0); + + private readonly bool versionPresent; + private readonly DerInteger version; + private readonly ResponderID responderID; + private readonly DerGeneralizedTime producedAt; + private readonly Asn1Sequence responses; + private readonly X509Extensions responseExtensions; + + public static ResponseData GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static ResponseData GetInstance( + object obj) + { + if (obj == null || obj is ResponseData) + { + return (ResponseData)obj; + } + + if (obj is Asn1Sequence) + { + return new ResponseData((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public ResponseData( + DerInteger version, + ResponderID responderID, + DerGeneralizedTime producedAt, + Asn1Sequence responses, + X509Extensions responseExtensions) + { + this.version = version; + this.responderID = responderID; + this.producedAt = producedAt; + this.responses = responses; + this.responseExtensions = responseExtensions; + } + + public ResponseData( + ResponderID responderID, + DerGeneralizedTime producedAt, + Asn1Sequence responses, + X509Extensions responseExtensions) + : this(V1, responderID, producedAt, responses, responseExtensions) + { + } + + private ResponseData( + Asn1Sequence seq) + { + int index = 0; + + Asn1Encodable enc = seq[0]; + if (enc is Asn1TaggedObject) + { + Asn1TaggedObject o = (Asn1TaggedObject)enc; + + if (o.TagNo == 0) + { + this.versionPresent = true; + this.version = DerInteger.GetInstance(o, true); + index++; + } + else + { + this.version = V1; + } + } + else + { + this.version = V1; + } + + this.responderID = ResponderID.GetInstance(seq[index++]); + this.producedAt = (DerGeneralizedTime)seq[index++]; + this.responses = (Asn1Sequence)seq[index++]; + + if (seq.Count > index) + { + this.responseExtensions = X509Extensions.GetInstance( + (Asn1TaggedObject)seq[index], true); + } + } + + public DerInteger Version + { + get { return version; } + } + + public ResponderID ResponderID + { + get { return responderID; } + } + + public DerGeneralizedTime ProducedAt + { + get { return producedAt; } + } + + public Asn1Sequence Responses + { + get { return responses; } + } + + public X509Extensions ResponseExtensions + { + get { return responseExtensions; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ResponseData ::= Sequence {
+         *     version              [0] EXPLICIT Version DEFAULT v1,
+         *     responderID              ResponderID,
+         *     producedAt               GeneralizedTime,
+         *     responses                Sequence OF SingleResponse,
+         *     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (versionPresent || !version.Equals(V1)) + { + v.Add(new DerTaggedObject(true, 0, version)); + } + + v.Add(responderID, producedAt, responses); + + if (responseExtensions != null) + { + v.Add(new DerTaggedObject(true, 1, responseExtensions)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/RevokedInfo.cs b/crypto/src/asn1/ocsp/RevokedInfo.cs new file mode 100644 index 000000000..7d9d590e3 --- /dev/null +++ b/crypto/src/asn1/ocsp/RevokedInfo.cs @@ -0,0 +1,96 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class RevokedInfo + : Asn1Encodable + { + private readonly DerGeneralizedTime revocationTime; + private readonly CrlReason revocationReason; + + public static RevokedInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static RevokedInfo GetInstance( + object obj) + { + if (obj == null || obj is RevokedInfo) + { + return (RevokedInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new RevokedInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public RevokedInfo( + DerGeneralizedTime revocationTime) + : this(revocationTime, null) + { + } + + public RevokedInfo( + DerGeneralizedTime revocationTime, + CrlReason revocationReason) + { + if (revocationTime == null) + throw new ArgumentNullException("revocationTime"); + + this.revocationTime = revocationTime; + this.revocationReason = revocationReason; + } + + private RevokedInfo( + Asn1Sequence seq) + { + this.revocationTime = (DerGeneralizedTime) seq[0]; + + if (seq.Count > 1) + { + this.revocationReason = new CrlReason( + DerEnumerated.GetInstance((Asn1TaggedObject) seq[1], true)); + } + } + + public DerGeneralizedTime RevocationTime + { + get { return revocationTime; } + } + + public CrlReason RevocationReason + { + get { return revocationReason; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * RevokedInfo ::= Sequence {
+         *      revocationTime              GeneralizedTime,
+         *      revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(revocationTime); + + if (revocationReason != null) + { + v.Add(new DerTaggedObject(true, 0, revocationReason)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/ServiceLocator.cs b/crypto/src/asn1/ocsp/ServiceLocator.cs new file mode 100644 index 000000000..56bc49ded --- /dev/null +++ b/crypto/src/asn1/ocsp/ServiceLocator.cs @@ -0,0 +1,95 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class ServiceLocator + : Asn1Encodable + { + private readonly X509Name issuer; + private readonly Asn1Object locator; + + public static ServiceLocator GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static ServiceLocator GetInstance( + object obj) + { + if (obj == null || obj is ServiceLocator) + { + return (ServiceLocator) obj; + } + + if (obj is Asn1Sequence) + { + return new ServiceLocator((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public ServiceLocator( + X509Name issuer) + : this(issuer, null) + { + } + + public ServiceLocator( + X509Name issuer, + Asn1Object locator) + { + if (issuer == null) + throw new ArgumentNullException("issuer"); + + this.issuer = issuer; + this.locator = locator; + } + + private ServiceLocator( + Asn1Sequence seq) + { + this.issuer = X509Name.GetInstance(seq[0]); + + if (seq.Count > 1) + { + this.locator = seq[1].ToAsn1Object(); + } + } + + public X509Name Issuer + { + get { return issuer; } + } + + public Asn1Object Locator + { + get { return locator; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ServiceLocator ::= Sequence {
+         *     issuer    Name,
+         *     locator   AuthorityInfoAccessSyntax OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(issuer); + + if (locator != null) + { + v.Add(locator); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/Signature.cs b/crypto/src/asn1/ocsp/Signature.cs new file mode 100644 index 000000000..a07e7a709 --- /dev/null +++ b/crypto/src/asn1/ocsp/Signature.cs @@ -0,0 +1,110 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class Signature + : Asn1Encodable + { + internal AlgorithmIdentifier signatureAlgorithm; + internal DerBitString signatureValue; + internal Asn1Sequence certs; + + public static Signature GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static Signature GetInstance( + object obj) + { + if (obj == null || obj is Signature) + { + return (Signature)obj; + } + + if (obj is Asn1Sequence) + { + return new Signature((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public Signature( + AlgorithmIdentifier signatureAlgorithm, + DerBitString signatureValue) + : this(signatureAlgorithm, signatureValue, null) + { + } + + public Signature( + AlgorithmIdentifier signatureAlgorithm, + DerBitString signatureValue, + Asn1Sequence certs) + { + if (signatureAlgorithm == null) + throw new ArgumentException("signatureAlgorithm"); + if (signatureValue == null) + throw new ArgumentException("signatureValue"); + + this.signatureAlgorithm = signatureAlgorithm; + this.signatureValue = signatureValue; + this.certs = certs; + } + + private Signature( + Asn1Sequence seq) + { + signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); + signatureValue = (DerBitString)seq[1]; + + if (seq.Count == 3) + { + certs = Asn1Sequence.GetInstance( + (Asn1TaggedObject)seq[2], true); + } + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return signatureAlgorithm; } + } + + public DerBitString SignatureValue + { + get { return signatureValue; } + } + + public Asn1Sequence Certs + { + get { return certs; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Signature       ::=     Sequence {
+         *     signatureAlgorithm      AlgorithmIdentifier,
+         *     signature               BIT STRING,
+         *     certs               [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + signatureAlgorithm, signatureValue); + + if (certs != null) + { + v.Add(new DerTaggedObject(true, 0, certs)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/ocsp/SingleResponse.cs b/crypto/src/asn1/ocsp/SingleResponse.cs new file mode 100644 index 000000000..93d4c21d6 --- /dev/null +++ b/crypto/src/asn1/ocsp/SingleResponse.cs @@ -0,0 +1,137 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +using System; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class SingleResponse + : Asn1Encodable + { + private readonly CertID certID; + private readonly CertStatus certStatus; + private readonly DerGeneralizedTime thisUpdate; + private readonly DerGeneralizedTime nextUpdate; + private readonly X509Extensions singleExtensions; + + public SingleResponse( + CertID certID, + CertStatus certStatus, + DerGeneralizedTime thisUpdate, + DerGeneralizedTime nextUpdate, + X509Extensions singleExtensions) + { + this.certID = certID; + this.certStatus = certStatus; + this.thisUpdate = thisUpdate; + this.nextUpdate = nextUpdate; + this.singleExtensions = singleExtensions; + } + + public SingleResponse( + Asn1Sequence seq) + { + this.certID = CertID.GetInstance(seq[0]); + this.certStatus = CertStatus.GetInstance(seq[1]); + this.thisUpdate = (DerGeneralizedTime)seq[2]; + + if (seq.Count > 4) + { + this.nextUpdate = DerGeneralizedTime.GetInstance( + (Asn1TaggedObject) seq[3], true); + this.singleExtensions = X509Extensions.GetInstance( + (Asn1TaggedObject) seq[4], true); + } + else if (seq.Count > 3) + { + Asn1TaggedObject o = (Asn1TaggedObject) seq[3]; + + if (o.TagNo == 0) + { + this.nextUpdate = DerGeneralizedTime.GetInstance(o, true); + } + else + { + this.singleExtensions = X509Extensions.GetInstance(o, true); + } + } + } + + public static SingleResponse GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static SingleResponse GetInstance( + object obj) + { + if (obj == null || obj is SingleResponse) + { + return (SingleResponse)obj; + } + + if (obj is Asn1Sequence) + { + return new SingleResponse((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public CertID CertId + { + get { return certID; } + } + + public CertStatus CertStatus + { + get { return certStatus; } + } + + public DerGeneralizedTime ThisUpdate + { + get { return thisUpdate; } + } + + public DerGeneralizedTime NextUpdate + { + get { return nextUpdate; } + } + + public X509Extensions SingleExtensions + { + get { return singleExtensions; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  SingleResponse ::= Sequence {
+         *          certID                       CertID,
+         *          certStatus                   CertStatus,
+         *          thisUpdate                   GeneralizedTime,
+         *          nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
+         *          singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + certID, certStatus, 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/crypto/src/asn1/ocsp/TBSRequest.cs b/crypto/src/asn1/ocsp/TBSRequest.cs new file mode 100644 index 000000000..6bf75eb96 --- /dev/null +++ b/crypto/src/asn1/ocsp/TBSRequest.cs @@ -0,0 +1,151 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +using System; + +namespace Org.BouncyCastle.Asn1.Ocsp +{ + public class TbsRequest + : Asn1Encodable + { + private static readonly DerInteger V1 = new DerInteger(0); + + private readonly DerInteger version; + private readonly GeneralName requestorName; + private readonly Asn1Sequence requestList; + private readonly X509Extensions requestExtensions; + + private bool versionSet; + + public static TbsRequest GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static TbsRequest GetInstance( + object obj) + { + if (obj == null || obj is TbsRequest) + { + return (TbsRequest)obj; + } + + if (obj is Asn1Sequence) + { + return new TbsRequest((Asn1Sequence)obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public TbsRequest( + GeneralName requestorName, + Asn1Sequence requestList, + X509Extensions requestExtensions) + { + this.version = V1; + this.requestorName = requestorName; + this.requestList = requestList; + this.requestExtensions = requestExtensions; + } + + private TbsRequest( + Asn1Sequence seq) + { + int index = 0; + + Asn1Encodable enc = seq[0]; + if (enc is Asn1TaggedObject) + { + Asn1TaggedObject o = (Asn1TaggedObject) enc; + + if (o.TagNo == 0) + { + versionSet = true; + version = DerInteger.GetInstance(o, true); + index++; + } + else + { + version = V1; + } + } + else + { + version = V1; + } + + if (seq[index] is Asn1TaggedObject) + { + requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true); + } + + requestList = (Asn1Sequence) seq[index++]; + + if (seq.Count == (index + 1)) + { + requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true); + } + } + + public DerInteger Version + { + get { return version; } + } + + public GeneralName RequestorName + { + get { return requestorName; } + } + + public Asn1Sequence RequestList + { + get { return requestList; } + } + + public X509Extensions RequestExtensions + { + get { return requestExtensions; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * TBSRequest      ::=     Sequence {
+         *     version             [0]     EXPLICIT Version DEFAULT v1,
+         *     requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+         *     requestList                 Sequence OF Request,
+         *     requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/oiw/ElGamalParameter.cs b/crypto/src/asn1/oiw/ElGamalParameter.cs new file mode 100644 index 000000000..3e020f059 --- /dev/null +++ b/crypto/src/asn1/oiw/ElGamalParameter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Oiw +{ + public class ElGamalParameter + : Asn1Encodable + { + internal DerInteger p, g; + + public ElGamalParameter( + BigInteger p, + BigInteger g) + { + this.p = new DerInteger(p); + this.g = new DerInteger(g); + } + + public ElGamalParameter( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + p = DerInteger.GetInstance(seq[0]); + g = DerInteger.GetInstance(seq[1]); + } + + public BigInteger P + { + get { return p.PositiveValue; } + } + + public BigInteger G + { + get { return g.PositiveValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(p, g); + } + } +} diff --git a/crypto/src/asn1/oiw/OIWObjectIdentifiers.cs b/crypto/src/asn1/oiw/OIWObjectIdentifiers.cs new file mode 100644 index 000000000..3da226301 --- /dev/null +++ b/crypto/src/asn1/oiw/OIWObjectIdentifiers.cs @@ -0,0 +1,29 @@ +namespace Org.BouncyCastle.Asn1.Oiw +{ + public abstract class OiwObjectIdentifiers + { + public static readonly DerObjectIdentifier MD4WithRsa = new DerObjectIdentifier("1.3.14.3.2.2"); + public static readonly DerObjectIdentifier MD5WithRsa = new DerObjectIdentifier("1.3.14.3.2.3"); + public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier("1.3.14.3.2.4"); + + public static readonly DerObjectIdentifier DesEcb = new DerObjectIdentifier("1.3.14.3.2.6"); + public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7"); + public static readonly DerObjectIdentifier DesOfb = new DerObjectIdentifier("1.3.14.3.2.8"); + public static readonly DerObjectIdentifier DesCfb = new DerObjectIdentifier("1.3.14.3.2.9"); + + public static readonly DerObjectIdentifier DesEde = new DerObjectIdentifier("1.3.14.3.2.17"); + + // id-SHA1 OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } // + public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26"); + + public static readonly DerObjectIdentifier DsaWithSha1 = new DerObjectIdentifier("1.3.14.3.2.27"); + + public static readonly DerObjectIdentifier Sha1WithRsa = new DerObjectIdentifier("1.3.14.3.2.29"); + + // ElGamal Algorithm OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 } + // + public static readonly DerObjectIdentifier ElGamalAlgorithm = new DerObjectIdentifier("1.3.14.7.2.1.1"); + } +} diff --git a/crypto/src/asn1/pkcs/Attribute.cs b/crypto/src/asn1/pkcs/Attribute.cs new file mode 100644 index 000000000..ceec115bd --- /dev/null +++ b/crypto/src/asn1/pkcs/Attribute.cs @@ -0,0 +1,79 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class AttributePkcs + : Asn1Encodable + { + private readonly DerObjectIdentifier attrType; + private readonly Asn1Set attrValues; + + /** + * return an Attribute object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static AttributePkcs GetInstance( + object obj) + { + AttributePkcs attr = obj as AttributePkcs; + if (obj == null || attr != null) + { + return attr; + } + + Asn1Sequence seq = obj as Asn1Sequence; + if (seq != null) + { + return new AttributePkcs(seq); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + private AttributePkcs( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + attrType = DerObjectIdentifier.GetInstance(seq[0]); + attrValues = Asn1Set.GetInstance(seq[1]); + } + + public AttributePkcs( + DerObjectIdentifier attrType, + Asn1Set attrValues) + { + this.attrType = attrType; + this.attrValues = attrValues; + } + + public DerObjectIdentifier AttrType + { + get { return attrType; } + } + + public Asn1Set AttrValues + { + get { return attrValues; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Attr ::= Sequence {
+         *     attrType OBJECT IDENTIFIER,
+         *     attrValues Set OF AttributeValue
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(attrType, attrValues); + } + } +} diff --git a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs new file mode 100644 index 000000000..f3dabb89c --- /dev/null +++ b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs @@ -0,0 +1,37 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class AuthenticatedSafe + : Asn1Encodable + { + private readonly ContentInfo[] info; + + public AuthenticatedSafe( + Asn1Sequence seq) + { + info = new ContentInfo[seq.Count]; + + for (int i = 0; i != info.Length; i++) + { + info[i] = ContentInfo.GetInstance(seq[i]); + } + } + + public AuthenticatedSafe( + ContentInfo[] info) + { + this.info = (ContentInfo[]) info.Clone(); + } + + public ContentInfo[] GetContentInfo() + { + return (ContentInfo[]) info.Clone(); + } + + public override Asn1Object ToAsn1Object() + { + return new BerSequence(info); + } + } +} diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs new file mode 100644 index 000000000..b6f4c8a30 --- /dev/null +++ b/crypto/src/asn1/pkcs/CertBag.cs @@ -0,0 +1,46 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class CertBag + : Asn1Encodable + { +// private readonly Asn1Sequence seq; + private readonly DerObjectIdentifier certID; + private readonly Asn1Object certValue; + + public CertBag( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + +// this.seq = seq; + this.certID = DerObjectIdentifier.GetInstance(seq[0]); + this.certValue = DerTaggedObject.GetInstance(seq[1]).GetObject(); + } + + public CertBag( + DerObjectIdentifier certID, + Asn1Object certValue) + { + this.certID = certID; + this.certValue = certValue; + } + + public DerObjectIdentifier CertID + { + get { return certID; } + } + + public Asn1Object CertValue + { + get { return certValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(certID, new DerTaggedObject(0, certValue)); + } + } +} diff --git a/crypto/src/asn1/pkcs/CertificationRequest.cs b/crypto/src/asn1/pkcs/CertificationRequest.cs new file mode 100644 index 000000000..32b1612d2 --- /dev/null +++ b/crypto/src/asn1/pkcs/CertificationRequest.cs @@ -0,0 +1,81 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * Pkcs10 Certfication request object. + *
+     * CertificationRequest ::= Sequence {
+     *   certificationRequestInfo  CertificationRequestInfo,
+     *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+     *   signature                 BIT STRING
+     * }
+     * 
+ */ + public class CertificationRequest + : Asn1Encodable + { + protected CertificationRequestInfo reqInfo; + protected AlgorithmIdentifier sigAlgId; + protected DerBitString sigBits; + + public static CertificationRequest GetInstance( + object obj) + { + if (obj is CertificationRequest) + return (CertificationRequest)obj; + + if (obj != null) + return new CertificationRequest((Asn1Sequence)obj); + + 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) + { + if (seq.Count != 3) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + reqInfo = CertificationRequestInfo.GetInstance(seq[0]); + sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]); + sigBits = DerBitString.GetInstance(seq[2]); + } + + public CertificationRequestInfo GetCertificationRequestInfo() + { + return reqInfo; + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return sigAlgId; } + } + + public DerBitString Signature + { + get { return sigBits; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(reqInfo, sigAlgId, sigBits); + } + } +} diff --git a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs new file mode 100644 index 000000000..690d06878 --- /dev/null +++ b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs @@ -0,0 +1,123 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * Pkcs10 CertificationRequestInfo object. + *
+     *  CertificationRequestInfo ::= Sequence {
+     *   version             Integer { v1(0) } (v1,...),
+     *   subject             Name,
+     *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+     *   attributes          [0] Attributes{{ CRIAttributes }}
+     *  }
+     *
+     *  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+     *
+     *  Attr { ATTRIBUTE:IOSet } ::= Sequence {
+     *    type    ATTRIBUTE.&id({IOSet}),
+     *    values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+     *  }
+     * 
+ */ + public class CertificationRequestInfo + : Asn1Encodable + { + internal DerInteger version = new DerInteger(0); + internal X509Name subject; + internal SubjectPublicKeyInfo subjectPKInfo; + internal Asn1Set attributes; + + public static CertificationRequestInfo GetInstance( + object obj) + { + if (obj is CertificationRequestInfo) + { + return (CertificationRequestInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new CertificationRequestInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public CertificationRequestInfo( + X509Name subject, + SubjectPublicKeyInfo pkInfo, + Asn1Set attributes) + { + this.subject = subject; + this.subjectPKInfo = pkInfo; + this.attributes = attributes; + + if (subject == null || version == null || subjectPKInfo == null) + { + throw new ArgumentException( + "Not all mandatory fields set in CertificationRequestInfo generator."); + } + } + + private CertificationRequestInfo( + Asn1Sequence seq) + { + version = (DerInteger) seq[0]; + + subject = X509Name.GetInstance(seq[1]); + subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[2]); + + // + // some CertificationRequestInfo objects seem to treat this field + // as optional. + // + if (seq.Count > 3) + { + DerTaggedObject tagobj = (DerTaggedObject) seq[3]; + attributes = Asn1Set.GetInstance(tagobj, false); + } + + if (subject == null || version == null || subjectPKInfo == null) + { + throw new ArgumentException( + "Not all mandatory fields set in CertificationRequestInfo generator."); + } + } + + public DerInteger Version + { + get { return version; } + } + + public X509Name Subject + { + get { return subject; } + } + + public SubjectPublicKeyInfo SubjectPublicKeyInfo + { + get { return subjectPKInfo; } + } + + public Asn1Set Attributes + { + get { return attributes; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, subject, subjectPKInfo); + + if (attributes != null) + { + v.Add(new DerTaggedObject(false, 0, attributes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/ContentInfo.cs b/crypto/src/asn1/pkcs/ContentInfo.cs new file mode 100644 index 000000000..526a3c48e --- /dev/null +++ b/crypto/src/asn1/pkcs/ContentInfo.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class ContentInfo + : Asn1Encodable + { + private readonly DerObjectIdentifier contentType; + private readonly Asn1Encodable content; + + public static ContentInfo GetInstance(object obj) + { + if (obj == null) + return null; + ContentInfo existing = obj as ContentInfo; + if (existing != null) + return existing; + return new ContentInfo(Asn1Sequence.GetInstance(obj)); + } + + private ContentInfo( + Asn1Sequence seq) + { + contentType = (DerObjectIdentifier) seq[0]; + + if (seq.Count > 1) + { + content = ((Asn1TaggedObject) seq[1]).GetObject(); + } + } + + public ContentInfo( + DerObjectIdentifier contentType, + Asn1Encodable content) + { + this.contentType = contentType; + this.content = content; + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public Asn1Encodable Content + { + get { return content; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * ContentInfo ::= Sequence {
+         *          contentType ContentType,
+         *          content
+         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(contentType); + + if (content != null) + { + v.Add(new BerTaggedObject(0, content)); + } + + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/DHParameter.cs b/crypto/src/asn1/pkcs/DHParameter.cs new file mode 100644 index 000000000..25a091a97 --- /dev/null +++ b/crypto/src/asn1/pkcs/DHParameter.cs @@ -0,0 +1,72 @@ +using Org.BouncyCastle.Asn1; +using System; +using System.Collections; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class DHParameter + : Asn1Encodable + { + internal DerInteger p, g, l; + + public DHParameter( + BigInteger p, + BigInteger g, + int l) + { + this.p = new DerInteger(p); + this.g = new DerInteger(g); + + if (l != 0) + { + this.l = new DerInteger(l); + } + } + + public DHParameter( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + p = (DerInteger)e.Current; + + e.MoveNext(); + g = (DerInteger)e.Current; + + if (e.MoveNext()) + { + l = (DerInteger) e.Current; + } + } + + public BigInteger P + { + get { return p.PositiveValue; } + } + + public BigInteger G + { + get { return g.PositiveValue; } + } + + public BigInteger L + { + get { return l == null ? null : l.PositiveValue; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(p, g); + + if (this.l != null) + { + v.Add(l); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/EncryptedData.cs b/crypto/src/asn1/pkcs/EncryptedData.cs new file mode 100644 index 000000000..912064ace --- /dev/null +++ b/crypto/src/asn1/pkcs/EncryptedData.cs @@ -0,0 +1,104 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * The EncryptedData object. + *
+     *      EncryptedData ::= Sequence {
+     *           version Version,
+     *           encryptedContentInfo EncryptedContentInfo
+     *      }
+     *
+     *
+     *      EncryptedContentInfo ::= Sequence {
+     *          contentType ContentType,
+     *          contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
+     *          encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+     *    }
+     *
+     *    EncryptedContent ::= OCTET STRING
+     * 
+ */ + public class EncryptedData + : Asn1Encodable + { + private readonly Asn1Sequence data; +// private readonly DerObjectIdentifier bagId; +// private readonly Asn1Object bagValue; + + public static EncryptedData GetInstance( + object obj) + { + if (obj is EncryptedData) + { + return (EncryptedData) obj; + } + + if (obj is Asn1Sequence) + { + return new EncryptedData((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + private EncryptedData( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + int version = ((DerInteger) seq[0]).Value.IntValue; + if (version != 0) + { + throw new ArgumentException("sequence not version 0"); + } + + this.data = (Asn1Sequence) seq[1]; + } + + public EncryptedData( + DerObjectIdentifier contentType, + AlgorithmIdentifier encryptionAlgorithm, + Asn1Encodable content) + { + data = new BerSequence( + contentType, + encryptionAlgorithm.ToAsn1Object(), + new BerTaggedObject(false, 0, content)); + } + + public DerObjectIdentifier ContentType + { + get { return (DerObjectIdentifier) data[0]; } + } + + public AlgorithmIdentifier EncryptionAlgorithm + { + get { return AlgorithmIdentifier.GetInstance(data[1]); } + } + + public Asn1OctetString Content + { + get + { + if (data.Count == 3) + { + DerTaggedObject o = (DerTaggedObject) data[2]; + + return Asn1OctetString.GetInstance(o, false); + } + + return null; + } + } + + public override Asn1Object ToAsn1Object() + { + return new BerSequence(new DerInteger(0), data); + } + } +} diff --git a/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs b/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs new file mode 100644 index 000000000..b97b8f5ea --- /dev/null +++ b/crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class EncryptedPrivateKeyInfo + : Asn1Encodable + { + private readonly AlgorithmIdentifier algId; + private readonly Asn1OctetString data; + + private EncryptedPrivateKeyInfo( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + algId = AlgorithmIdentifier.GetInstance(seq[0]); + data = Asn1OctetString.GetInstance(seq[1]); + } + + public EncryptedPrivateKeyInfo( + AlgorithmIdentifier algId, + byte[] encoding) + { + this.algId = algId; + this.data = new DerOctetString(encoding); + } + + public static EncryptedPrivateKeyInfo GetInstance( + object obj) + { + if (obj is EncryptedPrivateKeyInfo) + { + return (EncryptedPrivateKeyInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new EncryptedPrivateKeyInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public AlgorithmIdentifier EncryptionAlgorithm + { + get { return algId; } + } + + public byte[] GetEncryptedData() + { + return data.GetOctets(); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * EncryptedPrivateKeyInfo ::= Sequence {
+         *      encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+         *      encryptedData EncryptedData
+         * }
+         *
+         * EncryptedData ::= OCTET STRING
+         *
+         * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+         *          ... -- For local profiles
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algId, data); + } + } +} diff --git a/crypto/src/asn1/pkcs/EncryptionScheme.cs b/crypto/src/asn1/pkcs/EncryptionScheme.cs new file mode 100644 index 000000000..5b64d6f67 --- /dev/null +++ b/crypto/src/asn1/pkcs/EncryptionScheme.cs @@ -0,0 +1,49 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class EncryptionScheme + : AlgorithmIdentifier + { + public EncryptionScheme( + DerObjectIdentifier objectID, + Asn1Encodable parameters) + : base(objectID, parameters) + { + } + + internal EncryptionScheme( + Asn1Sequence seq) + : this((DerObjectIdentifier)seq[0], seq[1]) + { + } + + public new static EncryptionScheme GetInstance(object obj) + { + if (obj is EncryptionScheme) + { + return (EncryptionScheme)obj; + } + + if (obj is Asn1Sequence) + { + return new EncryptionScheme((Asn1Sequence)obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public Asn1Object Asn1Object + { + get { return Parameters.ToAsn1Object(); } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(ObjectID, Parameters); + } + } +} diff --git a/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs b/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs new file mode 100644 index 000000000..ff608f15b --- /dev/null +++ b/crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs @@ -0,0 +1,71 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class IssuerAndSerialNumber + : Asn1Encodable + { + private readonly X509Name name; + private readonly DerInteger certSerialNumber; + + public static IssuerAndSerialNumber GetInstance( + object obj) + { + if (obj is IssuerAndSerialNumber) + { + return (IssuerAndSerialNumber) obj; + } + + if (obj is Asn1Sequence) + { + return new IssuerAndSerialNumber((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + private IssuerAndSerialNumber( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.name = X509Name.GetInstance(seq[0]); + this.certSerialNumber = DerInteger.GetInstance(seq[1]); + } + + public IssuerAndSerialNumber( + X509Name name, + BigInteger certSerialNumber) + { + this.name = name; + this.certSerialNumber = new DerInteger(certSerialNumber); + } + + public IssuerAndSerialNumber( + X509Name name, + DerInteger certSerialNumber) + { + this.name = name; + this.certSerialNumber = certSerialNumber; + } + + public X509Name Name + { + get { return name; } + } + + public DerInteger CertificateSerialNumber + { + get { return certSerialNumber; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(name, certSerialNumber); + } + } +} diff --git a/crypto/src/asn1/pkcs/KeyDerivationFunc.cs b/crypto/src/asn1/pkcs/KeyDerivationFunc.cs new file mode 100644 index 000000000..9fc89853b --- /dev/null +++ b/crypto/src/asn1/pkcs/KeyDerivationFunc.cs @@ -0,0 +1,21 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class KeyDerivationFunc + : AlgorithmIdentifier + { + internal KeyDerivationFunc(Asn1Sequence seq) + : base(seq) + { + } + + public KeyDerivationFunc( + DerObjectIdentifier id, + Asn1Encodable parameters) + : base(id, parameters) + { + } + } +} \ No newline at end of file diff --git a/crypto/src/asn1/pkcs/MacData.cs b/crypto/src/asn1/pkcs/MacData.cs new file mode 100644 index 000000000..780b24153 --- /dev/null +++ b/crypto/src/asn1/pkcs/MacData.cs @@ -0,0 +1,96 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class MacData + : Asn1Encodable + { + internal DigestInfo digInfo; + internal byte[] salt; + internal BigInteger iterationCount; + + public static MacData GetInstance( + object obj) + { + if (obj is MacData) + { + return (MacData) obj; + } + + if (obj is Asn1Sequence) + { + return new MacData((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + private MacData( + Asn1Sequence seq) + { + this.digInfo = DigestInfo.GetInstance(seq[0]); + this.salt = ((Asn1OctetString) seq[1]).GetOctets(); + + if (seq.Count == 3) + { + this.iterationCount = ((DerInteger) seq[2]).Value; + } + else + { + this.iterationCount = BigInteger.One; + } + } + + public MacData( + DigestInfo digInfo, + byte[] salt, + int iterationCount) + { + this.digInfo = digInfo; + this.salt = (byte[]) salt.Clone(); + this.iterationCount = BigInteger.ValueOf(iterationCount); + } + + public DigestInfo Mac + { + get { return digInfo; } + } + + public byte[] GetSalt() + { + return (byte[]) salt.Clone(); + } + + public BigInteger IterationCount + { + get { return iterationCount; } + } + + /** + *
+		 * 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.
+		 * 
+ * @return the basic DERObject construction. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(digInfo, new DerOctetString(salt)); + + if (!iterationCount.Equals(BigInteger.One)) + { + v.Add(new DerInteger(iterationCount)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/PBEParameter.cs b/crypto/src/asn1/pkcs/PBEParameter.cs new file mode 100644 index 000000000..80d5ec3e1 --- /dev/null +++ b/crypto/src/asn1/pkcs/PBEParameter.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class PbeParameter + : Asn1Encodable + { + private readonly Asn1OctetString salt; + private readonly DerInteger iterationCount; + + public static PbeParameter GetInstance(object obj) + { + if (obj is PbeParameter || obj == null) + { + return (PbeParameter) obj; + } + + if (obj is Asn1Sequence) + { + return new PbeParameter((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + private PbeParameter(Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + salt = Asn1OctetString.GetInstance(seq[0]); + iterationCount = DerInteger.GetInstance(seq[1]); + } + + public PbeParameter(byte[] salt, int iterationCount) + { + this.salt = new DerOctetString(salt); + this.iterationCount = new DerInteger(iterationCount); + } + + public byte[] GetSalt() + { + return salt.GetOctets(); + } + + public BigInteger IterationCount + { + get { return iterationCount.Value; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(salt, iterationCount); + } + } +} diff --git a/crypto/src/asn1/pkcs/PBES2Parameters.cs b/crypto/src/asn1/pkcs/PBES2Parameters.cs new file mode 100644 index 000000000..fc6904eed --- /dev/null +++ b/crypto/src/asn1/pkcs/PBES2Parameters.cs @@ -0,0 +1,65 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class PbeS2Parameters + : Asn1Encodable + { + private readonly KeyDerivationFunc func; + private readonly EncryptionScheme scheme; + + public static PbeS2Parameters GetInstance(object obj) + { + if (obj == null) + return null; + PbeS2Parameters existing = obj as PbeS2Parameters; + if (existing != null) + return existing; + return new PbeS2Parameters(Asn1Sequence.GetInstance(obj)); + } + + public PbeS2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme) + { + this.func = keyDevFunc; + this.scheme = encScheme; + } + + [Obsolete("Use GetInstance() instead")] + public PbeS2Parameters( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + Asn1Sequence funcSeq = (Asn1Sequence)seq[0].ToAsn1Object(); + + // TODO Not sure if this special case is really necessary/appropriate + if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2)) + { + func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2, + Pbkdf2Params.GetInstance(funcSeq[1])); + } + else + { + func = new KeyDerivationFunc(funcSeq); + } + + scheme = EncryptionScheme.GetInstance(seq[1].ToAsn1Object()); + } + + public KeyDerivationFunc KeyDerivationFunc + { + get { return func; } + } + + public EncryptionScheme EncryptionScheme + { + get { return scheme; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(func, scheme); + } + } +} diff --git a/crypto/src/asn1/pkcs/PBKDF2Params.cs b/crypto/src/asn1/pkcs/PBKDF2Params.cs new file mode 100644 index 000000000..1351b94cf --- /dev/null +++ b/crypto/src/asn1/pkcs/PBKDF2Params.cs @@ -0,0 +1,86 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class Pbkdf2Params + : Asn1Encodable + { + private readonly Asn1OctetString octStr; + private readonly DerInteger iterationCount; + private readonly DerInteger keyLength; + + public static Pbkdf2Params GetInstance( + object obj) + { + if (obj == null || obj is Pbkdf2Params) + return (Pbkdf2Params)obj; + + if (obj is Asn1Sequence) + return new Pbkdf2Params((Asn1Sequence)obj); + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public Pbkdf2Params( + Asn1Sequence seq) + { + if (seq.Count < 2 || seq.Count > 3) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + octStr = (Asn1OctetString)seq[0]; + iterationCount = (DerInteger)seq[1]; + + if (seq.Count > 2) + { + keyLength = (DerInteger)seq[2]; + } + } + + public Pbkdf2Params( + byte[] salt, + int iterationCount) + { + this.octStr = new DerOctetString(salt); + this.iterationCount = new DerInteger(iterationCount); + } + + public Pbkdf2Params( + byte[] salt, + int iterationCount, + int keyLength) + : this(salt, iterationCount) + { + this.keyLength = new DerInteger(keyLength); + } + + public byte[] GetSalt() + { + return octStr.GetOctets(); + } + + public BigInteger IterationCount + { + get { return iterationCount.Value; } + } + + public BigInteger KeyLength + { + get { return keyLength == null ? null : keyLength.Value; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + octStr, iterationCount); + + if (keyLength != null) + { + v.Add(keyLength); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/PKCS12PBEParams.cs b/crypto/src/asn1/pkcs/PKCS12PBEParams.cs new file mode 100644 index 000000000..7521f93ea --- /dev/null +++ b/crypto/src/asn1/pkcs/PKCS12PBEParams.cs @@ -0,0 +1,63 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class Pkcs12PbeParams + : Asn1Encodable + { + private readonly DerInteger iterations; + private readonly Asn1OctetString iv; + + public Pkcs12PbeParams( + byte[] salt, + int iterations) + { + this.iv = new DerOctetString(salt); + this.iterations = new DerInteger(iterations); + } + + private Pkcs12PbeParams( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + iv = Asn1OctetString.GetInstance(seq[0]); + iterations = DerInteger.GetInstance(seq[1]); + } + + public static Pkcs12PbeParams GetInstance( + object obj) + { + if (obj is Pkcs12PbeParams) + { + return (Pkcs12PbeParams) obj; + } + + if (obj is Asn1Sequence) + { + return new Pkcs12PbeParams((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public BigInteger Iterations + { + get { return iterations.Value; } + } + + public byte[] GetIV() + { + return iv.GetOctets(); + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(iv, iterations); + } + } +} diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs new file mode 100644 index 000000000..0b2ffa0d1 --- /dev/null +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -0,0 +1,256 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public abstract class PkcsObjectIdentifiers + { + // + // pkcs-1 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } + // + public const string Pkcs1 = "1.2.840.113549.1.1"; + + public static readonly DerObjectIdentifier RsaEncryption = new DerObjectIdentifier(Pkcs1 + ".1"); + public static readonly DerObjectIdentifier MD2WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".2"); + public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".3"); + public static readonly DerObjectIdentifier MD5WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".4"); + public static readonly DerObjectIdentifier Sha1WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".5"); + public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = new DerObjectIdentifier(Pkcs1 + ".6"); + public static readonly DerObjectIdentifier IdRsaesOaep = new DerObjectIdentifier(Pkcs1 + ".7"); + public static readonly DerObjectIdentifier IdMgf1 = new DerObjectIdentifier(Pkcs1 + ".8"); + public static readonly DerObjectIdentifier IdPSpecified = new DerObjectIdentifier(Pkcs1 + ".9"); + public static readonly DerObjectIdentifier IdRsassaPss = new DerObjectIdentifier(Pkcs1 + ".10"); + public static readonly DerObjectIdentifier Sha256WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".11"); + public static readonly DerObjectIdentifier Sha384WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".12"); + public static readonly DerObjectIdentifier Sha512WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".13"); + public static readonly DerObjectIdentifier Sha224WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".14"); + + // + // pkcs-3 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 } + // + public const string Pkcs3 = "1.2.840.113549.1.3"; + + public static readonly DerObjectIdentifier DhKeyAgreement = new DerObjectIdentifier(Pkcs3 + ".1"); + + // + // pkcs-5 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } + // + public const string Pkcs5 = "1.2.840.113549.1.5"; + + public static readonly DerObjectIdentifier PbeWithMD2AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".1"); + public static readonly DerObjectIdentifier PbeWithMD2AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".4"); + public static readonly DerObjectIdentifier PbeWithMD5AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".3"); + public static readonly DerObjectIdentifier PbeWithMD5AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".6"); + public static readonly DerObjectIdentifier PbeWithSha1AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".10"); + public static readonly DerObjectIdentifier PbeWithSha1AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".11"); + + public static readonly DerObjectIdentifier IdPbeS2 = new DerObjectIdentifier(Pkcs5 + ".13"); + public static readonly DerObjectIdentifier IdPbkdf2 = new DerObjectIdentifier(Pkcs5 + ".12"); + + // + // encryptionAlgorithm OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) 3 } + // + public const string EncryptionAlgorithm = "1.2.840.113549.3"; + + public static readonly DerObjectIdentifier DesEde3Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".7"); + public static readonly DerObjectIdentifier RC2Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".2"); + + // + // object identifiers for digests + // + public const string DigestAlgorithm = "1.2.840.113549.2"; + + // + // md2 OBJECT IDENTIFIER ::= + // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2} + // + public static readonly DerObjectIdentifier MD2 = new DerObjectIdentifier(DigestAlgorithm + ".2"); + + // + // md4 OBJECT IDENTIFIER ::= + // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 4} + // + public static readonly DerObjectIdentifier MD4 = new DerObjectIdentifier(DigestAlgorithm + ".4"); + + // + // md5 OBJECT IDENTIFIER ::= + // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 5} + // + public static readonly DerObjectIdentifier MD5 = new DerObjectIdentifier(DigestAlgorithm + ".5"); + + public static readonly DerObjectIdentifier IdHmacWithSha1 = new DerObjectIdentifier(DigestAlgorithm + ".7"); + public static readonly DerObjectIdentifier IdHmacWithSha224 = new DerObjectIdentifier(DigestAlgorithm + ".8"); + public static readonly DerObjectIdentifier IdHmacWithSha256 = new DerObjectIdentifier(DigestAlgorithm + ".9"); + public static readonly DerObjectIdentifier IdHmacWithSha384 = new DerObjectIdentifier(DigestAlgorithm + ".10"); + public static readonly DerObjectIdentifier IdHmacWithSha512 = new DerObjectIdentifier(DigestAlgorithm + ".11"); + + // + // pkcs-7 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } + // + public const string Pkcs7 = "1.2.840.113549.1.7"; + + public static readonly DerObjectIdentifier Data = new DerObjectIdentifier(Pkcs7 + ".1"); + public static readonly DerObjectIdentifier SignedData = new DerObjectIdentifier(Pkcs7 + ".2"); + public static readonly DerObjectIdentifier EnvelopedData = new DerObjectIdentifier(Pkcs7 + ".3"); + public static readonly DerObjectIdentifier SignedAndEnvelopedData = new DerObjectIdentifier(Pkcs7 + ".4"); + public static readonly DerObjectIdentifier DigestedData = new DerObjectIdentifier(Pkcs7 + ".5"); + public static readonly DerObjectIdentifier EncryptedData = new DerObjectIdentifier(Pkcs7 + ".6"); + + // + // pkcs-9 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } + // + public const string Pkcs9 = "1.2.840.113549.1.9"; + + public static readonly DerObjectIdentifier Pkcs9AtEmailAddress = new DerObjectIdentifier(Pkcs9 + ".1"); + public static readonly DerObjectIdentifier Pkcs9AtUnstructuredName = new DerObjectIdentifier(Pkcs9 + ".2"); + public static readonly DerObjectIdentifier Pkcs9AtContentType = new DerObjectIdentifier(Pkcs9 + ".3"); + public static readonly DerObjectIdentifier Pkcs9AtMessageDigest = new DerObjectIdentifier(Pkcs9 + ".4"); + public static readonly DerObjectIdentifier Pkcs9AtSigningTime = new DerObjectIdentifier(Pkcs9 + ".5"); + public static readonly DerObjectIdentifier Pkcs9AtCounterSignature = new DerObjectIdentifier(Pkcs9 + ".6"); + public static readonly DerObjectIdentifier Pkcs9AtChallengePassword = new DerObjectIdentifier(Pkcs9 + ".7"); + public static readonly DerObjectIdentifier Pkcs9AtUnstructuredAddress = new DerObjectIdentifier(Pkcs9 + ".8"); + public static readonly DerObjectIdentifier Pkcs9AtExtendedCertificateAttributes = new DerObjectIdentifier(Pkcs9 + ".9"); + public static readonly DerObjectIdentifier Pkcs9AtSigningDescription = new DerObjectIdentifier(Pkcs9 + ".13"); + public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest = new DerObjectIdentifier(Pkcs9 + ".14"); + public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities = new DerObjectIdentifier(Pkcs9 + ".15"); + public static readonly DerObjectIdentifier Pkcs9AtFriendlyName = new DerObjectIdentifier(Pkcs9 + ".20"); + public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID = new DerObjectIdentifier(Pkcs9 + ".21"); + + [Obsolete("Use X509Certificate instead")] + public static readonly DerObjectIdentifier X509CertType = new DerObjectIdentifier(Pkcs9 + ".22.1"); + + public const string CertTypes = Pkcs9 + ".22"; + public static readonly DerObjectIdentifier X509Certificate = new DerObjectIdentifier(CertTypes + ".1"); + public static readonly DerObjectIdentifier SdsiCertificate = new DerObjectIdentifier(CertTypes + ".2"); + + public const string CrlTypes = Pkcs9 + ".23"; + public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1"); + + public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9"); + + // + // SMIME capability sub oids. + // + public static readonly DerObjectIdentifier PreferSignedData = new DerObjectIdentifier(Pkcs9 + ".15.1"); + public static readonly DerObjectIdentifier CannotDecryptAny = new DerObjectIdentifier(Pkcs9 + ".15.2"); + public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = new DerObjectIdentifier(Pkcs9 + ".15.3"); + + // + // other SMIME attributes + // + public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1"); + + // + // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) + // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)} + // + public const string IdCT = "1.2.840.113549.1.9.16.1"; + + public static readonly DerObjectIdentifier IdCTAuthData = new DerObjectIdentifier(IdCT + ".2"); + public static readonly DerObjectIdentifier IdCTTstInfo = new DerObjectIdentifier(IdCT + ".4"); + public static readonly DerObjectIdentifier IdCTCompressedData = new DerObjectIdentifier(IdCT + ".9"); + public static readonly DerObjectIdentifier IdCTAuthEnvelopedData = new DerObjectIdentifier(IdCT + ".23"); + public static readonly DerObjectIdentifier IdCTTimestampedData = new DerObjectIdentifier(IdCT + ".31"); + + // + // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) + // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)} + // + public const string IdCti = "1.2.840.113549.1.9.16.6"; + + public static readonly DerObjectIdentifier IdCtiEtsProofOfOrigin = new DerObjectIdentifier(IdCti + ".1"); + public static readonly DerObjectIdentifier IdCtiEtsProofOfReceipt = new DerObjectIdentifier(IdCti + ".2"); + public static readonly DerObjectIdentifier IdCtiEtsProofOfDelivery = new DerObjectIdentifier(IdCti + ".3"); + public static readonly DerObjectIdentifier IdCtiEtsProofOfSender = new DerObjectIdentifier(IdCti + ".4"); + public static readonly DerObjectIdentifier IdCtiEtsProofOfApproval = new DerObjectIdentifier(IdCti + ".5"); + public static readonly DerObjectIdentifier IdCtiEtsProofOfCreation = new DerObjectIdentifier(IdCti + ".6"); + + // + // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) + // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)} + // + public const string IdAA = "1.2.840.113549.1.9.16.2"; + + public static readonly DerObjectIdentifier IdAAContentHint = new DerObjectIdentifier(IdAA + ".4"); // See RFC 2634 + public static readonly DerObjectIdentifier IdAAMsgSigDigest = new DerObjectIdentifier(IdAA + ".5"); + public static readonly DerObjectIdentifier IdAAContentReference = new DerObjectIdentifier(IdAA + ".10"); + + /* + * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11} + * + */ + public static readonly DerObjectIdentifier IdAAEncrypKeyPref = new DerObjectIdentifier(IdAA + ".11"); + public static readonly DerObjectIdentifier IdAASigningCertificate = new DerObjectIdentifier(IdAA + ".12"); + public static readonly DerObjectIdentifier IdAASigningCertificateV2 = new DerObjectIdentifier(IdAA + ".47"); + + public static readonly DerObjectIdentifier IdAAContentIdentifier = new DerObjectIdentifier(IdAA + ".7"); // See RFC 2634 + + /* + * RFC 3126 + */ + public static readonly DerObjectIdentifier IdAASignatureTimeStampToken = new DerObjectIdentifier(IdAA + ".14"); + + public static readonly DerObjectIdentifier IdAAEtsSigPolicyID = new DerObjectIdentifier(IdAA + ".15"); + public static readonly DerObjectIdentifier IdAAEtsCommitmentType = new DerObjectIdentifier(IdAA + ".16"); + public static readonly DerObjectIdentifier IdAAEtsSignerLocation = new DerObjectIdentifier(IdAA + ".17"); + public static readonly DerObjectIdentifier IdAAEtsSignerAttr = new DerObjectIdentifier(IdAA + ".18"); + public static readonly DerObjectIdentifier IdAAEtsOtherSigCert = new DerObjectIdentifier(IdAA + ".19"); + public static readonly DerObjectIdentifier IdAAEtsContentTimestamp = new DerObjectIdentifier(IdAA + ".20"); + public static readonly DerObjectIdentifier IdAAEtsCertificateRefs = new DerObjectIdentifier(IdAA + ".21"); + public static readonly DerObjectIdentifier IdAAEtsRevocationRefs = new DerObjectIdentifier(IdAA + ".22"); + public static readonly DerObjectIdentifier IdAAEtsCertValues = new DerObjectIdentifier(IdAA + ".23"); + public static readonly DerObjectIdentifier IdAAEtsRevocationValues = new DerObjectIdentifier(IdAA + ".24"); + public static readonly DerObjectIdentifier IdAAEtsEscTimeStamp = new DerObjectIdentifier(IdAA + ".25"); + public static readonly DerObjectIdentifier IdAAEtsCertCrlTimestamp = new DerObjectIdentifier(IdAA + ".26"); + public static readonly DerObjectIdentifier IdAAEtsArchiveTimestamp = new DerObjectIdentifier(IdAA + ".27"); + + [Obsolete("Use 'IdAAEtsSigPolicyID' instead")] + public static readonly DerObjectIdentifier IdAASigPolicyID = IdAAEtsSigPolicyID; + [Obsolete("Use 'IdAAEtsCommitmentType' instead")] + public static readonly DerObjectIdentifier IdAACommitmentType = IdAAEtsCommitmentType; + [Obsolete("Use 'IdAAEtsSignerLocation' instead")] + public static readonly DerObjectIdentifier IdAASignerLocation = IdAAEtsSignerLocation; + [Obsolete("Use 'IdAAEtsOtherSigCert' instead")] + public static readonly DerObjectIdentifier IdAAOtherSigCert = IdAAEtsOtherSigCert; + + // + // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) + // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)} + // + public const string IdSpq = "1.2.840.113549.1.9.16.5"; + + public static readonly DerObjectIdentifier IdSpqEtsUri = new DerObjectIdentifier(IdSpq + ".1"); + public static readonly DerObjectIdentifier IdSpqEtsUNotice = new DerObjectIdentifier(IdSpq + ".2"); + + // + // pkcs-12 OBJECT IDENTIFIER ::= { + // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } + // + public const string Pkcs12 = "1.2.840.113549.1.12"; + public const string BagTypes = Pkcs12 + ".10.1"; + + public static readonly DerObjectIdentifier KeyBag = new DerObjectIdentifier(BagTypes + ".1"); + public static readonly DerObjectIdentifier Pkcs8ShroudedKeyBag = new DerObjectIdentifier(BagTypes + ".2"); + public static readonly DerObjectIdentifier CertBag = new DerObjectIdentifier(BagTypes + ".3"); + public static readonly DerObjectIdentifier CrlBag = new DerObjectIdentifier(BagTypes + ".4"); + public static readonly DerObjectIdentifier SecretBag = new DerObjectIdentifier(BagTypes + ".5"); + public static readonly DerObjectIdentifier SafeContentsBag = new DerObjectIdentifier(BagTypes + ".6"); + + public const string Pkcs12PbeIds = Pkcs12 + ".1"; + + public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC4 = new DerObjectIdentifier(Pkcs12PbeIds + ".1"); + public static readonly DerObjectIdentifier PbeWithShaAnd40BitRC4 = new DerObjectIdentifier(Pkcs12PbeIds + ".2"); + public static readonly DerObjectIdentifier PbeWithShaAnd3KeyTripleDesCbc = new DerObjectIdentifier(Pkcs12PbeIds + ".3"); + public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc = new DerObjectIdentifier(Pkcs12PbeIds + ".4"); + public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".5"); + public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".6"); + + public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6"); + public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7"); + } +} diff --git a/crypto/src/asn1/pkcs/Pfx.cs b/crypto/src/asn1/pkcs/Pfx.cs new file mode 100644 index 000000000..9676f64fc --- /dev/null +++ b/crypto/src/asn1/pkcs/Pfx.cs @@ -0,0 +1,65 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * the infamous Pfx from Pkcs12 + */ + public class Pfx + : Asn1Encodable + { + private ContentInfo contentInfo; + private MacData macData; + + public Pfx( + Asn1Sequence seq) + { + BigInteger version = ((DerInteger) seq[0]).Value; + if (version.IntValue != 3) + { + throw new ArgumentException("wrong version for PFX PDU"); + } + + contentInfo = ContentInfo.GetInstance(seq[1]); + + if (seq.Count == 3) + { + macData = MacData.GetInstance(seq[2]); + } + } + + public Pfx( + ContentInfo contentInfo, + MacData macData) + { + this.contentInfo = contentInfo; + this.macData = macData; + } + + public ContentInfo AuthSafe + { + get { return contentInfo; } + } + + public MacData MacData + { + get { return macData; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(3), contentInfo); + + if (macData != null) + { + v.Add(macData); + } + + return new BerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs new file mode 100644 index 000000000..91b6fb456 --- /dev/null +++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class PrivateKeyInfo + : Asn1Encodable + { + private readonly Asn1Object privKey; + private readonly AlgorithmIdentifier algID; + private readonly Asn1Set attributes; + + public static PrivateKeyInfo GetInstance( + object obj) + { + if (obj is PrivateKeyInfo) + return (PrivateKeyInfo) obj; + + if (obj != null) + return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public PrivateKeyInfo( + AlgorithmIdentifier algID, + Asn1Object privateKey) + : this(algID, privateKey, null) + { + } + + public PrivateKeyInfo( + AlgorithmIdentifier algID, + Asn1Object privateKey, + Asn1Set attributes) + { + this.privKey = privateKey; + this.algID = algID; + this.attributes = attributes; + } + + private PrivateKeyInfo( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + BigInteger version = ((DerInteger) e.Current).Value; + if (version.IntValue != 0) + { + throw new ArgumentException("wrong version for private key info: " + version.IntValue); + } + + e.MoveNext(); + algID = AlgorithmIdentifier.GetInstance(e.Current); + + try + { + e.MoveNext(); + Asn1OctetString data = (Asn1OctetString) e.Current; + + privKey = Asn1Object.FromByteArray(data.GetOctets()); + } + catch (IOException) + { + throw new ArgumentException("Error recoverying private key from sequence"); + } + + if (e.MoveNext()) + { + attributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false); + } + } + + public AlgorithmIdentifier AlgorithmID + { + get { return algID; } + } + + public Asn1Object PrivateKey + { + get { return privKey; } + } + + public Asn1Set Attributes + { + get { return attributes; } + } + + /** + * write out an RSA private key with its associated information + * as described in Pkcs8. + *
+         *      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 Attr
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(0), + algID, + new DerOctetString(privKey)); + + if (attributes != null) + { + v.Add(new DerTaggedObject(false, 0, attributes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/RC2CBCParameter.cs b/crypto/src/asn1/pkcs/RC2CBCParameter.cs new file mode 100644 index 000000000..f5355d012 --- /dev/null +++ b/crypto/src/asn1/pkcs/RC2CBCParameter.cs @@ -0,0 +1,81 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class RC2CbcParameter + : Asn1Encodable + { + internal DerInteger version; + internal Asn1OctetString iv; + + public static RC2CbcParameter GetInstance( + object obj) + { + if (obj is Asn1Sequence) + { + return new RC2CbcParameter((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public RC2CbcParameter( + byte[] iv) + { + this.iv = new DerOctetString(iv); + } + + public RC2CbcParameter( + int parameterVersion, + byte[] iv) + { + this.version = new DerInteger(parameterVersion); + this.iv = new DerOctetString(iv); + } + + private RC2CbcParameter( + Asn1Sequence seq) + { + if (seq.Count == 1) + { + iv = (Asn1OctetString)seq[0]; + } + else + { + version = (DerInteger)seq[0]; + iv = (Asn1OctetString)seq[1]; + } + } + + public BigInteger RC2ParameterVersion + { + get + { + return version == null ? null : version.Value; + } + } + + public byte[] GetIV() + { + return Arrays.Clone(iv.GetOctets()); + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (version != null) + { + v.Add(version); + } + + v.Add(iv); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/RSAESOAEPparams.cs b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs new file mode 100644 index 000000000..5ecb394fd --- /dev/null +++ b/crypto/src/asn1/pkcs/RSAESOAEPparams.cs @@ -0,0 +1,145 @@ +using System; + +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class RsaesOaepParameters + : Asn1Encodable + { + private AlgorithmIdentifier hashAlgorithm; + private AlgorithmIdentifier maskGenAlgorithm; + private AlgorithmIdentifier pSourceAlgorithm; + + public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); + public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm); + public readonly static AlgorithmIdentifier DefaultPSourceAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0])); + + public static RsaesOaepParameters GetInstance( + object obj) + { + if (obj is RsaesOaepParameters) + { + return (RsaesOaepParameters)obj; + } + else if (obj is Asn1Sequence) + { + return new RsaesOaepParameters((Asn1Sequence)obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + /** + * The default version + */ + public RsaesOaepParameters() + { + hashAlgorithm = DefaultHashAlgorithm; + maskGenAlgorithm = DefaultMaskGenFunction; + pSourceAlgorithm = DefaultPSourceAlgorithm; + } + + public RsaesOaepParameters( + AlgorithmIdentifier hashAlgorithm, + AlgorithmIdentifier maskGenAlgorithm, + AlgorithmIdentifier pSourceAlgorithm) + { + this.hashAlgorithm = hashAlgorithm; + this.maskGenAlgorithm = maskGenAlgorithm; + this.pSourceAlgorithm = pSourceAlgorithm; + } + + public RsaesOaepParameters( + Asn1Sequence seq) + { + hashAlgorithm = DefaultHashAlgorithm; + maskGenAlgorithm = DefaultMaskGenFunction; + pSourceAlgorithm = DefaultPSourceAlgorithm; + + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject o = (Asn1TaggedObject)seq[i]; + + switch (o.TagNo) + { + 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 ArgumentException("unknown tag"); + } + } + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public AlgorithmIdentifier MaskGenAlgorithm + { + get { return maskGenAlgorithm; } + } + + public AlgorithmIdentifier PSourceAlgorithm + { + get { return pSourceAlgorithm; } + } + + /** + *
+		 *  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 --
+		 *  }
+		 * 
+ * @return the asn1 primitive representing the parameters. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (!hashAlgorithm.Equals(DefaultHashAlgorithm)) + { + v.Add(new DerTaggedObject(true, 0, hashAlgorithm)); + } + + if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction)) + { + v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm)); + } + + if (!pSourceAlgorithm.Equals(DefaultPSourceAlgorithm)) + { + v.Add(new DerTaggedObject(true, 2, pSourceAlgorithm)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs new file mode 100644 index 000000000..dbb07c744 --- /dev/null +++ b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class RsaPrivateKeyStructure + : Asn1Encodable + { + private readonly BigInteger modulus; + private readonly BigInteger publicExponent; + private readonly BigInteger privateExponent; + private readonly BigInteger prime1; + private readonly BigInteger prime2; + private readonly BigInteger exponent1; + private readonly BigInteger exponent2; + private readonly BigInteger coefficient; + + public RsaPrivateKeyStructure( + BigInteger modulus, + BigInteger publicExponent, + BigInteger privateExponent, + BigInteger prime1, + BigInteger prime2, + BigInteger exponent1, + BigInteger exponent2, + BigInteger coefficient) + { + 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) + { + BigInteger version = ((DerInteger) seq[0]).Value; + if (version.IntValue != 0) + throw new ArgumentException("wrong version for RSA private key"); + + modulus = ((DerInteger) seq[1]).Value; + publicExponent = ((DerInteger) seq[2]).Value; + privateExponent = ((DerInteger) seq[3]).Value; + prime1 = ((DerInteger) seq[4]).Value; + prime2 = ((DerInteger) seq[5]).Value; + exponent1 = ((DerInteger) seq[6]).Value; + exponent2 = ((DerInteger) seq[7]).Value; + coefficient = ((DerInteger) seq[8]).Value; + } + + public BigInteger Modulus + { + get { return modulus; } + } + + public BigInteger PublicExponent + { + get { return publicExponent; } + } + + public BigInteger PrivateExponent + { + get { return privateExponent; } + } + + public BigInteger Prime1 + { + get { return prime1; } + } + + public BigInteger Prime2 + { + get { return prime2; } + } + + public BigInteger Exponent1 + { + get { return exponent1; } + } + + public BigInteger Exponent2 + { + get { return exponent2; } + } + + public BigInteger Coefficient + { + get { return coefficient; } + } + + /** + * This outputs the key in Pkcs1v2 format. + *
+         *      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
+         *                      }
+         *
+         *      Version ::= Integer
+         * 
+ *

This routine is written to output Pkcs1 version 0, private keys.

+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence( + new DerInteger(0), // version + new DerInteger(Modulus), + new DerInteger(PublicExponent), + new DerInteger(PrivateExponent), + new DerInteger(Prime1), + new DerInteger(Prime2), + new DerInteger(Exponent1), + new DerInteger(Exponent2), + new DerInteger(Coefficient)); + } + } +} diff --git a/crypto/src/asn1/pkcs/RSASSAPSSparams.cs b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs new file mode 100644 index 000000000..941620761 --- /dev/null +++ b/crypto/src/asn1/pkcs/RSASSAPSSparams.cs @@ -0,0 +1,165 @@ +using System; + +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class RsassaPssParameters + : Asn1Encodable + { + private AlgorithmIdentifier hashAlgorithm; + private AlgorithmIdentifier maskGenAlgorithm; + private DerInteger saltLength; + private DerInteger trailerField; + + public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); + public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm); + public readonly static DerInteger DefaultSaltLength = new DerInteger(20); + public readonly static DerInteger DefaultTrailerField = new DerInteger(1); + + public static RsassaPssParameters GetInstance( + object obj) + { + if (obj == null || obj is RsassaPssParameters) + { + return (RsassaPssParameters)obj; + } + + if (obj is Asn1Sequence) + { + return new RsassaPssParameters((Asn1Sequence)obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + /** + * The default version + */ + public RsassaPssParameters() + { + hashAlgorithm = DefaultHashAlgorithm; + maskGenAlgorithm = DefaultMaskGenFunction; + saltLength = DefaultSaltLength; + trailerField = DefaultTrailerField; + } + + public RsassaPssParameters( + AlgorithmIdentifier hashAlgorithm, + AlgorithmIdentifier maskGenAlgorithm, + DerInteger saltLength, + DerInteger trailerField) + { + this.hashAlgorithm = hashAlgorithm; + this.maskGenAlgorithm = maskGenAlgorithm; + this.saltLength = saltLength; + this.trailerField = trailerField; + } + + public RsassaPssParameters( + Asn1Sequence seq) + { + hashAlgorithm = DefaultHashAlgorithm; + maskGenAlgorithm = DefaultMaskGenFunction; + saltLength = DefaultSaltLength; + trailerField = DefaultTrailerField; + + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject o = (Asn1TaggedObject)seq[i]; + + switch (o.TagNo) + { + case 0: + hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true); + break; + case 1: + maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true); + break; + case 2: + saltLength = DerInteger.GetInstance(o, true); + break; + case 3: + trailerField = DerInteger.GetInstance(o, true); + break; + default: + throw new ArgumentException("unknown tag"); + } + } + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public AlgorithmIdentifier MaskGenAlgorithm + { + get { return maskGenAlgorithm; } + } + + public DerInteger SaltLength + { + get { return saltLength; } + } + + public DerInteger TrailerField + { + get { return trailerField; } + } + + /** + *
+		 * 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) }
+		 * 
+ * @return the asn1 primitive representing the parameters. + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (!hashAlgorithm.Equals(DefaultHashAlgorithm)) + { + v.Add(new DerTaggedObject(true, 0, hashAlgorithm)); + } + + if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction)) + { + v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm)); + } + + if (!saltLength.Equals(DefaultSaltLength)) + { + v.Add(new DerTaggedObject(true, 2, saltLength)); + } + + if (!trailerField.Equals(DefaultTrailerField)) + { + v.Add(new DerTaggedObject(true, 3, trailerField)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/SafeBag.cs b/crypto/src/asn1/pkcs/SafeBag.cs new file mode 100644 index 000000000..4b9350bac --- /dev/null +++ b/crypto/src/asn1/pkcs/SafeBag.cs @@ -0,0 +1,70 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + public class SafeBag + : Asn1Encodable + { + private readonly DerObjectIdentifier bagID; + private readonly Asn1Object bagValue; + private readonly Asn1Set bagAttributes; + + public SafeBag( + DerObjectIdentifier oid, + Asn1Object obj) + { + this.bagID = oid; + this.bagValue = obj; + this.bagAttributes = null; + } + + public SafeBag( + DerObjectIdentifier oid, + Asn1Object obj, + Asn1Set bagAttributes) + { + this.bagID = oid; + this.bagValue = obj; + this.bagAttributes = bagAttributes; + } + + public SafeBag( + Asn1Sequence seq) + { + this.bagID = (DerObjectIdentifier) seq[0]; + this.bagValue = ((DerTaggedObject) seq[1]).GetObject(); + if (seq.Count == 3) + { + this.bagAttributes = (Asn1Set) seq[2]; + } + } + + public DerObjectIdentifier BagID + { + get { return bagID; } + } + + public Asn1Object BagValue + { + get { return bagValue; } + } + + public Asn1Set BagAttributes + { + get { return bagAttributes; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + bagID, new DerTaggedObject(0, bagValue)); + + if (bagAttributes != null) + { + v.Add(bagAttributes); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/pkcs/SignedData.cs b/crypto/src/asn1/pkcs/SignedData.cs new file mode 100644 index 000000000..6e72bd0a9 --- /dev/null +++ b/crypto/src/asn1/pkcs/SignedData.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * a Pkcs#7 signed data object. + */ + public class SignedData + : Asn1Encodable + { + private readonly DerInteger version; + private readonly Asn1Set digestAlgorithms; + private readonly ContentInfo contentInfo; + private readonly Asn1Set certificates; + private readonly Asn1Set crls; + private readonly Asn1Set signerInfos; + + public static SignedData GetInstance(object obj) + { + if (obj == null) + return null; + SignedData existing = obj as SignedData; + if (existing != null) + return existing; + return new SignedData(Asn1Sequence.GetInstance(obj)); + } + + public SignedData( + DerInteger _version, + Asn1Set _digestAlgorithms, + ContentInfo _contentInfo, + Asn1Set _certificates, + Asn1Set _crls, + Asn1Set _signerInfos) + { + version = _version; + digestAlgorithms = _digestAlgorithms; + contentInfo = _contentInfo; + certificates = _certificates; + crls = _crls; + signerInfos = _signerInfos; + } + + private SignedData( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + version = (DerInteger) e.Current; + + e.MoveNext(); + digestAlgorithms = (Asn1Set) e.Current; + + e.MoveNext(); + contentInfo = ContentInfo.GetInstance(e.Current); + + while (e.MoveNext()) + { + Asn1Object o = (Asn1Object) e.Current; + + // + // 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 is DerTaggedObject) + { + DerTaggedObject tagged = (DerTaggedObject) o; + + switch (tagged.TagNo) + { + case 0: + certificates = Asn1Set.GetInstance(tagged, false); + break; + case 1: + crls = Asn1Set.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("unknown tag value " + tagged.TagNo); + } + } + else + { + signerInfos = (Asn1Set) o; + } + } + } + + public DerInteger Version + { + get { return version; } + } + + public Asn1Set DigestAlgorithms + { + get { return digestAlgorithms; } + } + + public ContentInfo ContentInfo + { + get { return contentInfo; } + } + + public Asn1Set Certificates + { + get { return certificates; } + } + + public Asn1Set Crls + { + get { return crls; } + } + + public Asn1Set SignerInfos + { + get { return signerInfos; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  SignedData ::= Sequence {
+         *      version Version,
+         *      digestAlgorithms DigestAlgorithmIdentifiers,
+         *      contentInfo ContentInfo,
+         *      certificates
+         *          [0] IMPLICIT ExtendedCertificatesAndCertificates
+         *                   OPTIONAL,
+         *      crls
+         *          [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+         *      signerInfos SignerInfos }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, digestAlgorithms, 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/crypto/src/asn1/pkcs/SignerInfo.cs b/crypto/src/asn1/pkcs/SignerInfo.cs new file mode 100644 index 000000000..1e4694547 --- /dev/null +++ b/crypto/src/asn1/pkcs/SignerInfo.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Pkcs +{ + /** + * a Pkcs#7 signer info object. + */ + public class SignerInfo + : Asn1Encodable + { + private DerInteger version; + private IssuerAndSerialNumber issuerAndSerialNumber; + private AlgorithmIdentifier digAlgorithm; + private Asn1Set authenticatedAttributes; + private AlgorithmIdentifier digEncryptionAlgorithm; + private Asn1OctetString encryptedDigest; + private Asn1Set unauthenticatedAttributes; + + public static SignerInfo GetInstance( + object obj) + { + if (obj is SignerInfo) + { + return (SignerInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new SignerInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj"); + } + + public SignerInfo( + DerInteger 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) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + version = (DerInteger) e.Current; + + e.MoveNext(); + issuerAndSerialNumber = IssuerAndSerialNumber.GetInstance(e.Current); + + e.MoveNext(); + digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current); + + e.MoveNext(); + object obj = e.Current; + + if (obj is Asn1TaggedObject) + { + authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false); + + e.MoveNext(); + digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current); + } + else + { + authenticatedAttributes = null; + digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj); + } + + e.MoveNext(); + encryptedDigest = DerOctetString.GetInstance(e.Current); + + if (e.MoveNext()) + { + unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false); + } + else + { + unauthenticatedAttributes = null; + } + } + + public DerInteger Version { get { return version; } } + + public IssuerAndSerialNumber IssuerAndSerialNumber { get { return issuerAndSerialNumber; } } + + public Asn1Set AuthenticatedAttributes { get { return authenticatedAttributes; } } + + public AlgorithmIdentifier DigestAlgorithm { get { return digAlgorithm; } } + + public Asn1OctetString EncryptedDigest { get { return encryptedDigest; } } + + public AlgorithmIdentifier DigestEncryptionAlgorithm { get { return digEncryptionAlgorithm; } } + + public Asn1Set UnauthenticatedAttributes { get { return unauthenticatedAttributes; } } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  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
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, issuerAndSerialNumber, digAlgorithm); + + if (authenticatedAttributes != null) + { + v.Add(new DerTaggedObject(false, 0, authenticatedAttributes)); + } + + v.Add(digEncryptionAlgorithm, encryptedDigest); + + if (unauthenticatedAttributes != null) + { + v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs new file mode 100644 index 000000000..2e9c27fd2 --- /dev/null +++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs @@ -0,0 +1,118 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Sec +{ + /** + * the elliptic curve private key object from SEC 1 + */ + public class ECPrivateKeyStructure + : Asn1Encodable + { + private readonly Asn1Sequence seq; + + public ECPrivateKeyStructure( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + this.seq = seq; + } + + public ECPrivateKeyStructure( + BigInteger key) + { + if (key == null) + throw new ArgumentNullException("key"); + + this.seq = new DerSequence( + new DerInteger(1), + new DerOctetString(key.ToByteArrayUnsigned())); + } + + public ECPrivateKeyStructure( + BigInteger key, + Asn1Encodable parameters) + : this(key, null, parameters) + { + } + + public ECPrivateKeyStructure( + BigInteger key, + DerBitString publicKey, + Asn1Encodable parameters) + { + if (key == null) + throw new ArgumentNullException("key"); + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(1), + new DerOctetString(key.ToByteArrayUnsigned())); + + if (parameters != null) + { + v.Add(new DerTaggedObject(true, 0, parameters)); + } + + if (publicKey != null) + { + v.Add(new DerTaggedObject(true, 1, publicKey)); + } + + this.seq = new DerSequence(v); + } + + public BigInteger GetKey() + { + Asn1OctetString octs = (Asn1OctetString) seq[1]; + + return new BigInteger(1, octs.GetOctets()); + } + + public DerBitString GetPublicKey() + { + return (DerBitString) GetObjectInTag(1); + } + + public Asn1Object GetParameters() + { + return GetObjectInTag(0); + } + + private Asn1Object GetObjectInTag( + int tagNo) + { + foreach (Asn1Encodable ae in seq) + { + Asn1Object obj = ae.ToAsn1Object(); + + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tag = (Asn1TaggedObject) obj; + if (tag.TagNo == tagNo) + { + return tag.GetObject(); + } + } + } + + return null; + } + + /** + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] Parameters OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL } + */ + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/sec/SECNamedCurves.cs b/crypto/src/asn1/sec/SECNamedCurves.cs new file mode 100644 index 000000000..c8d952b2e --- /dev/null +++ b/crypto/src/asn1/sec/SECNamedCurves.cs @@ -0,0 +1,1191 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.Sec +{ + public sealed class SecNamedCurves + { + private SecNamedCurves() + { + } + + private static BigInteger FromHex( + string hex) + { + return new BigInteger(1, Hex.Decode(hex)); + } + + /* + * secp112r1 + */ + internal class Secp112r1Holder + : X9ECParametersHolder + { + private Secp112r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp112r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = (2^128 - 3) / 76439 + BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B"); + BigInteger a = FromHex("DB7C2ABF62E35E668076BEAD2088"); + BigInteger b = FromHex("659EF8BA043916EEDE8911702B22"); + byte[] S = Hex.Decode("00F50B028E4D696E676875615175290472783FB1"); + BigInteger n = FromHex("DB7C2ABF62E35E7628DFAC6561C5"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "09487239995A5EE76B55F9C2F098")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "09487239995A5EE76B55F9C2F098" + + "A89CE5AF8724C0A23E0E0FF77500")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp112r2 + */ + internal class Secp112r2Holder + : X9ECParametersHolder + { + private Secp112r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp112r2Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = (2^128 - 3) / 76439 + BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B"); + BigInteger a = FromHex("6127C24C05F38A0AAAF65C0EF02C"); + BigInteger b = FromHex("51DEF1815DB5ED74FCC34C85D709"); + byte[] S = Hex.Decode("002757A1114D696E6768756151755316C05E0BD4"); + BigInteger n = FromHex("36DF0AAFD8B8D7597CA10520D04B"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "4BA30AB5E892B4E1649DD0928643")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "4BA30AB5E892B4E1649DD0928643" + + "ADCD46F5882E3747DEF36E956E97")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp128r1 + */ + internal class Secp128r1Holder + : X9ECParametersHolder + { + private Secp128r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp128r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^128 - 2^97 - 1 + BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = FromHex("E87579C11079F43DD824993C2CEE5ED3"); + byte[] S = Hex.Decode("000E0D4D696E6768756151750CC03A4473D03679"); + BigInteger n = FromHex("FFFFFFFE0000000075A30D1B9038A115"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "161FF7528B899B2D0C28607CA52C5B86")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "161FF7528B899B2D0C28607CA52C5B86" + + "CF5AC8395BAFEB13C02DA292DDED7A83")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp128r2 + */ + internal class Secp128r2Holder + : X9ECParametersHolder + { + private Secp128r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp128r2Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^128 - 2^97 - 1 + BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = FromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1"); + BigInteger b = FromHex("5EEEFCA380D02919DC2C6558BB6D8A5D"); + byte[] S = Hex.Decode("004D696E67687561517512D8F03431FCE63B88F4"); + BigInteger n = FromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "7B6AA5D85E572983E6FB32A7CDEBC140")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "7B6AA5D85E572983E6FB32A7CDEBC140" + + "27B6916A894D3AEE7106FE805FC34B44")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp160k1 + */ + internal class Secp160k1Holder + : X9ECParametersHolder + { + private Secp160k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp160k1Holder(); + + protected override 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 = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(7); + byte[] S = null; + BigInteger n = FromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" + + "938CF935318FDCED6BC28286531733C3F03C4FEE")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp160r1 + */ + internal class Secp160r1Holder + : X9ECParametersHolder + { + private Secp160r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp160r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^160 - 2^31 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"); + BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"); + BigInteger b = FromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"); + byte[] S = Hex.Decode("1053CDE42C14D696E67687561517533BF3F83345"); + BigInteger n = FromHex("0100000000000000000001F4C8F927AED3CA752257"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "4A96B5688EF573284664698968C38BB913CBFC82")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "4A96B5688EF573284664698968C38BB913CBFC82" + + "23A628553168947D59DCC912042351377AC5FB32")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp160r2 + */ + internal class Secp160r2Holder + : X9ECParametersHolder + { + private Secp160r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp160r2Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); + BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70"); + BigInteger b = FromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA"); + byte[] S = Hex.Decode("B99B99B099B323E02709A4D696E6768756151751"); + BigInteger n = FromHex("0100000000000000000000351EE786A818F3A1A16B"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "52DCB034293A117E1F4FF11B30F7199D3144CE6D" + + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp192k1 + */ + internal class Secp192k1Holder + : X9ECParametersHolder + { + private Secp192k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp192k1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"); + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(3); + byte[] S = null; + BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp192r1 + */ + internal class Secp192r1Holder + : X9ECParametersHolder + { + private Secp192r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp192r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^192 - 2^64 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); + BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + BigInteger b = FromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); + byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); + BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp224k1 + */ + internal class Secp224k1Holder + : X9ECParametersHolder + { + private Secp224k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp224k1Holder(); + + protected override 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 = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(5); + byte[] S = null; + BigInteger n = FromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C" + + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp224r1 + */ + internal class Secp224r1Holder + : X9ECParametersHolder + { + private Secp224r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp224r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^224 - 2^96 + 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); + BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"); + BigInteger b = FromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"); + byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); + BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp256k1 + */ + internal class Secp256k1Holder + : X9ECParametersHolder + { + private Secp256k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp256k1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(7); + byte[] S = null; + BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp256r1 + */ + internal class Secp256r1Holder + : X9ECParametersHolder + { + private Secp256r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp256r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 + BigInteger p = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = FromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); + byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90"); + BigInteger n = FromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp384r1 + */ + internal class Secp384r1Holder + : X9ECParametersHolder + { + private Secp384r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp384r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^384 - 2^128 - 2^96 + 2^32 - 1 + BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"); + BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"); + BigInteger b = FromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"); + byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73"); + BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("03" + //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" + + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * secp521r1 + */ + internal class Secp521r1Holder + : X9ECParametersHolder + { + private Secp521r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Secp521r1Holder(); + + protected override X9ECParameters CreateParameters() + { + // p = 2^521 - 1 + BigInteger p = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = FromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"); + byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA"); + BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); + BigInteger h = BigInteger.ValueOf(1); + + ECCurve curve = new FpCurve(p, a, b); + //ECPoint G = curve.DecodePoint(Hex.Decode("02" + //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" + + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); + + return new X9ECParameters(curve, G, n, h, S); + } + } + + /* + * sect113r1 + */ + internal class Sect113r1Holder + : X9ECParametersHolder + { + private Sect113r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect113r1Holder(); + + private const int m = 113; + private const int k = 9; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("003088250CA6E7C7FE649CE85820F7"); + BigInteger b = FromHex("00E8BEE4D3E2260744188BE0E9C723"); + byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9"); + BigInteger n = FromHex("0100000000000000D9CCEC8A39E56F"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect113r2Holder + : X9ECParametersHolder + { + private Sect113r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect113r2Holder(); + + private const int m = 113; + private const int k = 9; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("00689918DBEC7E5A0DD6DFC0AA55C7"); + BigInteger b = FromHex("0095E9A9EC9B297BD4BF36E059184F"); + byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D"); + BigInteger n = FromHex("010000000000000108789B2496AF93"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect131r1Holder + : X9ECParametersHolder + { + private Sect131r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect131r1Holder(); + + private const int m = 131; + private const int k1 = 2; + private const int k2 = 3; + private const int k3 = 8; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("07A11B09A76B562144418FF3FF8C2570B8"); + BigInteger b = FromHex("0217C05610884B63B9C6C7291678F9D341"); + byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2"); + BigInteger n = FromHex("0400000000000000023123953A9464B54D"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect131r2Holder + : X9ECParametersHolder + { + private Sect131r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect131r2Holder(); + + private const int m = 131; + private const int k1 = 2; + private const int k2 = 3; + private const int k3 = 8; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("03E5A88919D7CAFCBF415F07C2176573B2"); + BigInteger b = FromHex("04B8266A46C55657AC734CE38F018F2192"); + byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3"); + BigInteger n = FromHex("0400000000000000016954A233049BA98F"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect163k1Holder + : X9ECParametersHolder + { + private Sect163k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect163k1Holder(); + + private const int m = 163; + private const int k1 = 3; + private const int k2 = 6; + private const int k3 = 7; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("04000000000000000000020108A2E0CC0D99F8A5EF"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect163r1Holder + : X9ECParametersHolder + { + private Sect163r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect163r1Holder(); + + private const int m = 163; + private const int k1 = 3; + private const int k2 = 6; + private const int k3 = 7; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2"); + BigInteger b = FromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9"); + byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C"); + BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect163r2Holder + : X9ECParametersHolder + { + private Sect163r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect163r2Holder(); + + private const int m = 163; + private const int k1 = 3; + private const int k2 = 6; + private const int k3 = 7; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = FromHex("020A601907B8C953CA1481EB10512F78744A3205FD"); + byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268"); + BigInteger n = FromHex("040000000000000000000292FE77E70C12A4234C33"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect193r1Holder + : X9ECParametersHolder + { + private Sect193r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect193r1Holder(); + + private const int m = 193; + private const int k = 15; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01"); + BigInteger b = FromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814"); + byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30"); + BigInteger n = FromHex("01000000000000000000000000C7F34A778F443ACC920EBA49"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect193r2Holder + : X9ECParametersHolder + { + private Sect193r2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect193r2Holder(); + + private const int m = 193; + private const int k = 15; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = FromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B"); + BigInteger b = FromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE"); + byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211"); + BigInteger n = FromHex("010000000000000000000000015AAB561B005413CCD4EE99D5"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect233k1Holder + : X9ECParametersHolder + { + private Sect233k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect233k1Holder(); + + private const int m = 233; + private const int k = 74; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect233r1Holder + : X9ECParametersHolder + { + private Sect233r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect233r1Holder(); + + private const int m = 233; + private const int k = 74; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = FromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD"); + byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3"); + BigInteger n = FromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect239k1Holder + : X9ECParametersHolder + { + private Sect239k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect239k1Holder(); + + private const int m = 239; + private const int k = 158; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect283k1Holder + : X9ECParametersHolder + { + private Sect283k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect283k1Holder(); + + private const int m = 283; + private const int k1 = 5; + private const int k2 = 7; + private const int k3 = 12; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect283r1Holder + : X9ECParametersHolder + { + private Sect283r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect283r1Holder(); + + private const int m = 283; + private const int k1 = 5; + private const int k2 = 7; + private const int k3 = 12; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = FromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5"); + byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE"); + BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect409k1Holder + : X9ECParametersHolder + { + private Sect409k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect409k1Holder(); + + private const int m = 409; + private const int k = 87; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect409r1Holder + : X9ECParametersHolder + { + private Sect409r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect409r1Holder(); + + private const int m = 409; + private const int k = 87; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = FromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F"); + byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B"); + BigInteger n = FromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect571k1Holder + : X9ECParametersHolder + { + private Sect571k1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect571k1Holder(); + + private const int m = 571; + private const int k1 = 2; + private const int k2 = 5; + private const int k3 = 10; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.Zero; + BigInteger b = BigInteger.ValueOf(1); + byte[] S = null; + BigInteger n = FromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001"); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve curve = new F2mCurve(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 + */ + internal class Sect571r1Holder + : X9ECParametersHolder + { + private Sect571r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Sect571r1Holder(); + + private const int m = 571; + private const int k1 = 2; + private const int k2 = 5; + private const int k3 = 10; + + protected override X9ECParameters CreateParameters() + { + BigInteger a = BigInteger.ValueOf(1); + BigInteger b = FromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A"); + byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310"); + BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47"); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve curve = new F2mCurve(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); + } + } + + + private static readonly IDictionary objIds = Platform.CreateHashtable(); + private static readonly IDictionary curves = Platform.CreateHashtable(); + private static readonly IDictionary names = Platform.CreateHashtable(); + + private static void DefineCurve( + string name, + DerObjectIdentifier oid, + X9ECParametersHolder holder) + { + objIds.Add(name, oid); + names.Add(oid, name); + curves.Add(oid, holder); + } + + static SecNamedCurves() + { + DefineCurve("secp112r1", SecObjectIdentifiers.SecP112r1, Secp112r1Holder.Instance); + DefineCurve("secp112r2", SecObjectIdentifiers.SecP112r2, Secp112r2Holder.Instance); + DefineCurve("secp128r1", SecObjectIdentifiers.SecP128r1, Secp128r1Holder.Instance); + DefineCurve("secp128r2", SecObjectIdentifiers.SecP128r2, Secp128r2Holder.Instance); + DefineCurve("secp160k1", SecObjectIdentifiers.SecP160k1, Secp160k1Holder.Instance); + DefineCurve("secp160r1", SecObjectIdentifiers.SecP160r1, Secp160r1Holder.Instance); + DefineCurve("secp160r2", SecObjectIdentifiers.SecP160r2, Secp160r2Holder.Instance); + DefineCurve("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance); + DefineCurve("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance); + DefineCurve("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance); + DefineCurve("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance); + DefineCurve("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance); + DefineCurve("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance); + DefineCurve("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance); + DefineCurve("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance); + + DefineCurve("sect113r1", SecObjectIdentifiers.SecT113r1, Sect113r1Holder.Instance); + DefineCurve("sect113r2", SecObjectIdentifiers.SecT113r2, Sect113r2Holder.Instance); + DefineCurve("sect131r1", SecObjectIdentifiers.SecT131r1, Sect131r1Holder.Instance); + DefineCurve("sect131r2", SecObjectIdentifiers.SecT131r2, Sect131r2Holder.Instance); + DefineCurve("sect163k1", SecObjectIdentifiers.SecT163k1, Sect163k1Holder.Instance); + DefineCurve("sect163r1", SecObjectIdentifiers.SecT163r1, Sect163r1Holder.Instance); + DefineCurve("sect163r2", SecObjectIdentifiers.SecT163r2, Sect163r2Holder.Instance); + DefineCurve("sect193r1", SecObjectIdentifiers.SecT193r1, Sect193r1Holder.Instance); + DefineCurve("sect193r2", SecObjectIdentifiers.SecT193r2, Sect193r2Holder.Instance); + DefineCurve("sect233k1", SecObjectIdentifiers.SecT233k1, Sect233k1Holder.Instance); + DefineCurve("sect233r1", SecObjectIdentifiers.SecT233r1, Sect233r1Holder.Instance); + DefineCurve("sect239k1", SecObjectIdentifiers.SecT239k1, Sect239k1Holder.Instance); + DefineCurve("sect283k1", SecObjectIdentifiers.SecT283k1, Sect283k1Holder.Instance); + DefineCurve("sect283r1", SecObjectIdentifiers.SecT283r1, Sect283r1Holder.Instance); + DefineCurve("sect409k1", SecObjectIdentifiers.SecT409k1, Sect409k1Holder.Instance); + DefineCurve("sect409r1", SecObjectIdentifiers.SecT409r1, Sect409r1Holder.Instance); + DefineCurve("sect571k1", SecObjectIdentifiers.SecT571k1, Sect571k1Holder.Instance); + DefineCurve("sect571r1", SecObjectIdentifiers.SecT571r1, Sect571r1Holder.Instance); + } + + public static X9ECParameters GetByName( + string name) + { + DerObjectIdentifier oid = (DerObjectIdentifier) + objIds[Platform.ToLowerInvariant(name)]; + + return oid == null ? null : GetByOid(oid); + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters GetByOid( + DerObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid]; + + return holder == null ? null : holder.Parameters; + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)]; + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static string GetName( + DerObjectIdentifier oid) + { + return (string) names[oid]; + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + } +} diff --git a/crypto/src/asn1/sec/SECObjectIdentifiers.cs b/crypto/src/asn1/sec/SECObjectIdentifiers.cs new file mode 100644 index 000000000..afc10e1d6 --- /dev/null +++ b/crypto/src/asn1/sec/SECObjectIdentifiers.cs @@ -0,0 +1,52 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X9; + +namespace Org.BouncyCastle.Asn1.Sec +{ + public abstract class SecObjectIdentifiers + { + /** + * EllipticCurve OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) + * } + */ + public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier("1.3.132.0"); + + public static readonly DerObjectIdentifier SecT163k1 = new DerObjectIdentifier(EllipticCurve + ".1"); + public static readonly DerObjectIdentifier SecT163r1 = new DerObjectIdentifier(EllipticCurve + ".2"); + public static readonly DerObjectIdentifier SecT239k1 = new DerObjectIdentifier(EllipticCurve + ".3"); + public static readonly DerObjectIdentifier SecT113r1 = new DerObjectIdentifier(EllipticCurve + ".4"); + public static readonly DerObjectIdentifier SecT113r2 = new DerObjectIdentifier(EllipticCurve + ".5"); + public static readonly DerObjectIdentifier SecP112r1 = new DerObjectIdentifier(EllipticCurve + ".6"); + public static readonly DerObjectIdentifier SecP112r2 = new DerObjectIdentifier(EllipticCurve + ".7"); + public static readonly DerObjectIdentifier SecP160r1 = new DerObjectIdentifier(EllipticCurve + ".8"); + public static readonly DerObjectIdentifier SecP160k1 = new DerObjectIdentifier(EllipticCurve + ".9"); + public static readonly DerObjectIdentifier SecP256k1 = new DerObjectIdentifier(EllipticCurve + ".10"); + public static readonly DerObjectIdentifier SecT163r2 = new DerObjectIdentifier(EllipticCurve + ".15"); + public static readonly DerObjectIdentifier SecT283k1 = new DerObjectIdentifier(EllipticCurve + ".16"); + public static readonly DerObjectIdentifier SecT283r1 = new DerObjectIdentifier(EllipticCurve + ".17"); + public static readonly DerObjectIdentifier SecT131r1 = new DerObjectIdentifier(EllipticCurve + ".22"); + public static readonly DerObjectIdentifier SecT131r2 = new DerObjectIdentifier(EllipticCurve + ".23"); + public static readonly DerObjectIdentifier SecT193r1 = new DerObjectIdentifier(EllipticCurve + ".24"); + public static readonly DerObjectIdentifier SecT193r2 = new DerObjectIdentifier(EllipticCurve + ".25"); + public static readonly DerObjectIdentifier SecT233k1 = new DerObjectIdentifier(EllipticCurve + ".26"); + public static readonly DerObjectIdentifier SecT233r1 = new DerObjectIdentifier(EllipticCurve + ".27"); + public static readonly DerObjectIdentifier SecP128r1 = new DerObjectIdentifier(EllipticCurve + ".28"); + public static readonly DerObjectIdentifier SecP128r2 = new DerObjectIdentifier(EllipticCurve + ".29"); + public static readonly DerObjectIdentifier SecP160r2 = new DerObjectIdentifier(EllipticCurve + ".30"); + public static readonly DerObjectIdentifier SecP192k1 = new DerObjectIdentifier(EllipticCurve + ".31"); + public static readonly DerObjectIdentifier SecP224k1 = new DerObjectIdentifier(EllipticCurve + ".32"); + public static readonly DerObjectIdentifier SecP224r1 = new DerObjectIdentifier(EllipticCurve + ".33"); + public static readonly DerObjectIdentifier SecP384r1 = new DerObjectIdentifier(EllipticCurve + ".34"); + public static readonly DerObjectIdentifier SecP521r1 = new DerObjectIdentifier(EllipticCurve + ".35"); + public static readonly DerObjectIdentifier SecT409k1 = new DerObjectIdentifier(EllipticCurve + ".36"); + public static readonly DerObjectIdentifier SecT409r1 = new DerObjectIdentifier(EllipticCurve + ".37"); + public static readonly DerObjectIdentifier SecT571k1 = new DerObjectIdentifier(EllipticCurve + ".38"); + public static readonly DerObjectIdentifier SecT571r1 = new DerObjectIdentifier(EllipticCurve + ".39"); + + public static readonly DerObjectIdentifier SecP192r1 = X9ObjectIdentifiers.Prime192v1; + public static readonly DerObjectIdentifier SecP256r1 = X9ObjectIdentifiers.Prime256v1; + } +} \ No newline at end of file diff --git a/crypto/src/asn1/smime/SMIMEAttributes.cs b/crypto/src/asn1/smime/SMIMEAttributes.cs new file mode 100644 index 000000000..e154e5e74 --- /dev/null +++ b/crypto/src/asn1/smime/SMIMEAttributes.cs @@ -0,0 +1,11 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Smime +{ + public abstract class SmimeAttributes + { + public static readonly DerObjectIdentifier SmimeCapabilities = PkcsObjectIdentifiers.Pkcs9AtSmimeCapabilities; + public static readonly DerObjectIdentifier EncrypKeyPref = PkcsObjectIdentifiers.IdAAEncrypKeyPref; + } +} diff --git a/crypto/src/asn1/smime/SMIMECapabilities.cs b/crypto/src/asn1/smime/SMIMECapabilities.cs new file mode 100644 index 000000000..ca3c3af7d --- /dev/null +++ b/crypto/src/asn1/smime/SMIMECapabilities.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Smime +{ + /** + * Handler class for dealing with S/MIME Capabilities + */ + public class SmimeCapabilities + : Asn1Encodable + { + /** + * general preferences + */ + public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData; + public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny; + public static readonly DerObjectIdentifier SmimeCapabilitesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions; + + /** + * encryption algorithms preferences + */ + public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7"); + public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc; + public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc; + + private Asn1Sequence capabilities; + + /** + * return an Attr object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static SmimeCapabilities GetInstance( + object obj) + { + if (obj == null || obj is SmimeCapabilities) + { + return (SmimeCapabilities) obj; + } + + if (obj is Asn1Sequence) + { + return new SmimeCapabilities((Asn1Sequence) obj); + } + + if (obj is AttributeX509) + { + return new SmimeCapabilities( + (Asn1Sequence)(((AttributeX509) obj).AttrValues[0])); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public SmimeCapabilities( + Asn1Sequence seq) + { + capabilities = seq; + } + +#if !SILVERLIGHT + [Obsolete("Use 'GetCapabilitiesForOid' instead")] + public ArrayList GetCapabilities( + DerObjectIdentifier capability) + { + ArrayList list = new ArrayList(); + DoGetCapabilitiesForOid(capability, list); + return list; + } +#endif + + /** + * returns an ArrayList 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 IList GetCapabilitiesForOid( + DerObjectIdentifier capability) + { + IList list = Platform.CreateArrayList(); + DoGetCapabilitiesForOid(capability, list); + return list; + } + + private void DoGetCapabilitiesForOid(DerObjectIdentifier capability, IList list) + { + if (capability == null) + { + foreach (object o in capabilities) + { + SmimeCapability cap = SmimeCapability.GetInstance(o); + + list.Add(cap); + } + } + else + { + foreach (object o in capabilities) + { + SmimeCapability cap = SmimeCapability.GetInstance(o); + + if (capability.Equals(cap.CapabilityID)) + { + list.Add(cap); + } + } + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * SMIMECapabilities ::= Sequence OF SMIMECapability
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return capabilities; + } + } +} diff --git a/crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs b/crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs new file mode 100644 index 000000000..310c478fe --- /dev/null +++ b/crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs @@ -0,0 +1,16 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Smime +{ + public class SmimeCapabilitiesAttribute + : AttributeX509 + { + public SmimeCapabilitiesAttribute( + SmimeCapabilityVector capabilities) + : base(SmimeAttributes.SmimeCapabilities, + new DerSet(new DerSequence(capabilities.ToAsn1EncodableVector()))) + { + } + } +} diff --git a/crypto/src/asn1/smime/SMIMECapability.cs b/crypto/src/asn1/smime/SMIMECapability.cs new file mode 100644 index 000000000..5709cb815 --- /dev/null +++ b/crypto/src/asn1/smime/SMIMECapability.cs @@ -0,0 +1,101 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.Smime +{ + public class SmimeCapability + : Asn1Encodable + { + /** + * general preferences + */ + public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData; + public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny; + public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions; + + /** + * encryption algorithms preferences + */ + public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7"); + public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc; + public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc; + + private DerObjectIdentifier capabilityID; + private Asn1Object parameters; + + public SmimeCapability( + Asn1Sequence seq) + { + capabilityID = (DerObjectIdentifier) seq[0].ToAsn1Object(); + + if (seq.Count > 1) + { + parameters = seq[1].ToAsn1Object(); + } + } + + public SmimeCapability( + DerObjectIdentifier capabilityID, + Asn1Encodable parameters) + { + if (capabilityID == null) + throw new ArgumentNullException("capabilityID"); + + this.capabilityID = capabilityID; + + if (parameters != null) + { + this.parameters = parameters.ToAsn1Object(); + } + } + + public static SmimeCapability GetInstance( + object obj) + { + if (obj == null || obj is SmimeCapability) + { + return (SmimeCapability) obj; + } + + if (obj is Asn1Sequence) + { + return new SmimeCapability((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid SmimeCapability"); + } + + public DerObjectIdentifier CapabilityID + { + get { return capabilityID; } + } + + public Asn1Object Parameters + { + get { return parameters; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * SMIMECapability ::= Sequence {
+         *     capabilityID OBJECT IDENTIFIER,
+         *     parameters ANY DEFINED BY capabilityID OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(capabilityID); + + if (parameters != null) + { + v.Add(parameters); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/smime/SMIMECapabilityVector.cs b/crypto/src/asn1/smime/SMIMECapabilityVector.cs new file mode 100644 index 000000000..842825b88 --- /dev/null +++ b/crypto/src/asn1/smime/SMIMECapabilityVector.cs @@ -0,0 +1,37 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.Smime +{ + /** + * Handler for creating a vector S/MIME Capabilities + */ + public class SmimeCapabilityVector + { + private readonly Asn1EncodableVector capabilities = new Asn1EncodableVector(); + + public void AddCapability( + DerObjectIdentifier capability) + { + capabilities.Add(new DerSequence(capability)); + } + + public void AddCapability( + DerObjectIdentifier capability, + int value) + { + capabilities.Add(new DerSequence(capability, new DerInteger(value))); + } + + public void AddCapability( + DerObjectIdentifier capability, + Asn1Encodable parameters) + { + capabilities.Add(new DerSequence(capability, parameters)); + } + + public Asn1EncodableVector ToAsn1EncodableVector() + { + return capabilities; + } + } +} diff --git a/crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs b/crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs new file mode 100644 index 000000000..19c5fd78a --- /dev/null +++ b/crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs @@ -0,0 +1,44 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Smime +{ + /** + * The SmimeEncryptionKeyPreference object. + *
+     * SmimeEncryptionKeyPreference ::= CHOICE {
+     *     issuerAndSerialNumber   [0] IssuerAndSerialNumber,
+     *     receipentKeyId          [1] RecipientKeyIdentifier,
+     *     subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+     * }
+     * 
+ */ + public class SmimeEncryptionKeyPreferenceAttribute + : AttributeX509 + { + public SmimeEncryptionKeyPreferenceAttribute( + IssuerAndSerialNumber issAndSer) + : base(SmimeAttributes.EncrypKeyPref, + new DerSet(new DerTaggedObject(false, 0, issAndSer))) + { + } + + public SmimeEncryptionKeyPreferenceAttribute( + RecipientKeyIdentifier rKeyID) + : base(SmimeAttributes.EncrypKeyPref, + new DerSet(new DerTaggedObject(false, 1, rKeyID))) + { + } + + /** + * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one) + */ + public SmimeEncryptionKeyPreferenceAttribute( + Asn1OctetString sKeyID) + : base(SmimeAttributes.EncrypKeyPref, + new DerSet(new DerTaggedObject(false, 2, sKeyID))) + { + } + } +} diff --git a/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs new file mode 100644 index 000000000..b83f0ad0e --- /dev/null +++ b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs @@ -0,0 +1,427 @@ +using System.Collections; + +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.TeleTrust +{ + /** + * 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 + { + internal class BrainpoolP160r1Holder + : X9ECParametersHolder + { + private BrainpoolP160r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP160r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q + new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a + new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G + new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP160t1Holder + : X9ECParametersHolder + { + private BrainpoolP160t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP160t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + // new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z + new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q + new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a' + new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G + new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP192r1Holder + : X9ECParametersHolder + { + private BrainpoolP192r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP192r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q + new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a + new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G + new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP192t1Holder + : X9ECParametersHolder + { + private BrainpoolP192t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP192t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z + new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q + new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a' + new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G' + new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP224r1Holder + : X9ECParametersHolder + { + private BrainpoolP224r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP224r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q + new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a + new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G + new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n + new BigInteger("01", 16)); // n + } + } + + internal class BrainpoolP224t1Holder + : X9ECParametersHolder + { + private BrainpoolP224t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP224t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z + new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q + new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a' + new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G' + new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP256r1Holder + : X9ECParametersHolder + { + private BrainpoolP256r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP256r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q + new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a + new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP256t1Holder + : X9ECParametersHolder + { + private BrainpoolP256t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP256t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a' + new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G' + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP320r1Holder + : X9ECParametersHolder + { + private BrainpoolP320r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP320r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q + new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a + new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G + new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP320t1Holder + : X9ECParametersHolder + { + private BrainpoolP320t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP320t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z + new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q + new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a' + new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G' + new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP384r1Holder + : X9ECParametersHolder + { + private BrainpoolP384r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP384r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q + new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a + new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G + new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP384t1Holder + : X9ECParametersHolder + { + private BrainpoolP384t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP384t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z + new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q + new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a' + new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G' + new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP512r1Holder + : X9ECParametersHolder + { + private BrainpoolP512r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP512r1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q + new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a + new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16)); // b + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G + new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n + new BigInteger("01", 16)); // h + } + } + + internal class BrainpoolP512t1Holder + : X9ECParametersHolder + { + private BrainpoolP512t1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new BrainpoolP512t1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve curve = new FpCurve( + //new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z + new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q + new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a' + new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)); // b' + + return new X9ECParameters( + curve, + curve.DecodePoint(Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G' + new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n + new BigInteger("01", 16)); // h + } + } + + + private static readonly IDictionary objIds = Platform.CreateHashtable(); + private static readonly IDictionary curves = Platform.CreateHashtable(); + private static readonly IDictionary names = Platform.CreateHashtable(); + + private static void DefineCurve( + string name, + DerObjectIdentifier oid, + X9ECParametersHolder holder) + { + objIds.Add(name, oid); + names.Add(oid, name); + curves.Add(oid, holder); + } + + static TeleTrusTNamedCurves() + { + DefineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.BrainpoolP160R1, BrainpoolP160r1Holder.Instance); + DefineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.BrainpoolP160T1, BrainpoolP160t1Holder.Instance); + DefineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.BrainpoolP192R1, BrainpoolP192r1Holder.Instance); + DefineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.BrainpoolP192T1, BrainpoolP192t1Holder.Instance); + DefineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.BrainpoolP224R1, BrainpoolP224r1Holder.Instance); + DefineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.BrainpoolP224T1, BrainpoolP224t1Holder.Instance); + DefineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.BrainpoolP256R1, BrainpoolP256r1Holder.Instance); + DefineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.BrainpoolP256T1, BrainpoolP256t1Holder.Instance); + DefineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.BrainpoolP320R1, BrainpoolP320r1Holder.Instance); + DefineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.BrainpoolP320T1, BrainpoolP320t1Holder.Instance); + DefineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.BrainpoolP384R1, BrainpoolP384r1Holder.Instance); + DefineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.BrainpoolP384T1, BrainpoolP384t1Holder.Instance); + DefineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.BrainpoolP512R1, BrainpoolP512r1Holder.Instance); + DefineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.BrainpoolP512T1, BrainpoolP512t1Holder.Instance); + } + + public static X9ECParameters GetByName( + string name) + { + DerObjectIdentifier oid = (DerObjectIdentifier) + objIds[Platform.ToLowerInvariant(name)]; + + return oid == null ? null : GetByOid(oid); + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters GetByOid( + DerObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid]; + + return holder == null ? null : holder.Parameters; + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)]; + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static string GetName( + DerObjectIdentifier oid) + { + return (string) names[oid]; + } + + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + + public static DerObjectIdentifier GetOid( + short curvesize, + bool twisted) + { + return GetOid("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1"); + } + } +} diff --git a/crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs b/crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs new file mode 100644 index 000000000..56e70842a --- /dev/null +++ b/crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs @@ -0,0 +1,45 @@ +namespace Org.BouncyCastle.Asn1.TeleTrust +{ + public sealed class TeleTrusTObjectIdentifiers + { + private TeleTrusTObjectIdentifiers() + { + } + + public static readonly DerObjectIdentifier TeleTrusTAlgorithm = new DerObjectIdentifier("1.3.36.3"); + + public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.1"); + public static readonly DerObjectIdentifier RipeMD128 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.2"); + public static readonly DerObjectIdentifier RipeMD256 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.3"); + + public static readonly DerObjectIdentifier TeleTrusTRsaSignatureAlgorithm = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.1"); + + public static readonly DerObjectIdentifier RsaSignatureWithRipeMD160 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".2"); + public static readonly DerObjectIdentifier RsaSignatureWithRipeMD128 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".3"); + public static readonly DerObjectIdentifier RsaSignatureWithRipeMD256 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".4"); + + public static readonly DerObjectIdentifier ECSign = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2"); + + public static readonly DerObjectIdentifier ECSignWithSha1 = new DerObjectIdentifier(ECSign + ".1"); + public static readonly DerObjectIdentifier ECSignWithRipeMD160 = new DerObjectIdentifier(ECSign + ".2"); + + public static readonly DerObjectIdentifier EccBrainpool = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2.8"); + public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier(EccBrainpool + ".1"); + public static readonly DerObjectIdentifier VersionOne = new DerObjectIdentifier(EllipticCurve + ".1"); + + public static readonly DerObjectIdentifier BrainpoolP160R1 = new DerObjectIdentifier(VersionOne + ".1"); + public static readonly DerObjectIdentifier BrainpoolP160T1 = new DerObjectIdentifier(VersionOne + ".2"); + public static readonly DerObjectIdentifier BrainpoolP192R1 = new DerObjectIdentifier(VersionOne + ".3"); + public static readonly DerObjectIdentifier BrainpoolP192T1 = new DerObjectIdentifier(VersionOne + ".4"); + public static readonly DerObjectIdentifier BrainpoolP224R1 = new DerObjectIdentifier(VersionOne + ".5"); + public static readonly DerObjectIdentifier BrainpoolP224T1 = new DerObjectIdentifier(VersionOne + ".6"); + public static readonly DerObjectIdentifier BrainpoolP256R1 = new DerObjectIdentifier(VersionOne + ".7"); + public static readonly DerObjectIdentifier BrainpoolP256T1 = new DerObjectIdentifier(VersionOne + ".8"); + public static readonly DerObjectIdentifier BrainpoolP320R1 = new DerObjectIdentifier(VersionOne + ".9"); + public static readonly DerObjectIdentifier BrainpoolP320T1 = new DerObjectIdentifier(VersionOne + ".10"); + public static readonly DerObjectIdentifier BrainpoolP384R1 = new DerObjectIdentifier(VersionOne + ".11"); + public static readonly DerObjectIdentifier BrainpoolP384T1 = new DerObjectIdentifier(VersionOne + ".12"); + public static readonly DerObjectIdentifier BrainpoolP512R1 = new DerObjectIdentifier(VersionOne + ".13"); + public static readonly DerObjectIdentifier BrainpoolP512T1 = new DerObjectIdentifier(VersionOne + ".14"); + } +} diff --git a/crypto/src/asn1/tsp/Accuracy.cs b/crypto/src/asn1/tsp/Accuracy.cs new file mode 100644 index 000000000..a193f52ff --- /dev/null +++ b/crypto/src/asn1/tsp/Accuracy.cs @@ -0,0 +1,149 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + public class Accuracy + : Asn1Encodable + { + private readonly DerInteger seconds; + private readonly DerInteger millis; + private readonly DerInteger micros; + + // constants + protected const int MinMillis = 1; + protected const int MaxMillis = 999; + protected const int MinMicros = 1; + protected const int MaxMicros = 999; + + public Accuracy( + DerInteger seconds, + DerInteger millis, + DerInteger micros) + { + //Verifications + if (millis != null + && (millis.Value.IntValue < MinMillis + || millis.Value.IntValue > MaxMillis)) + { + throw new ArgumentException( + "Invalid millis field : not in (1..999)"); + } + + if (micros != null + && (micros.Value.IntValue < MinMicros + || micros.Value.IntValue > MaxMicros)) + { + throw new ArgumentException( + "Invalid micros field : not in (1..999)"); + } + + this.seconds = seconds; + this.millis = millis; + this.micros = micros; + } + + private Accuracy( + Asn1Sequence seq) + { + for (int i = 0; i < seq.Count; ++i) + { + // seconds + if (seq[i] is DerInteger) + { + seconds = (DerInteger) seq[i]; + } + else if (seq[i] is DerTaggedObject) + { + DerTaggedObject extra = (DerTaggedObject) seq[i]; + + switch (extra.TagNo) + { + case 0: + millis = DerInteger.GetInstance(extra, false); + if (millis.Value.IntValue < MinMillis + || millis.Value.IntValue > MaxMillis) + { + throw new ArgumentException( + "Invalid millis field : not in (1..999)."); + } + break; + case 1: + micros = DerInteger.GetInstance(extra, false); + if (micros.Value.IntValue < MinMicros + || micros.Value.IntValue > MaxMicros) + { + throw new ArgumentException( + "Invalid micros field : not in (1..999)."); + } + break; + default: + throw new ArgumentException("Invalig tag number"); + } + } + } + } + + public static Accuracy GetInstance( + object o) + { + if (o == null || o is Accuracy) + { + return (Accuracy) o; + } + + if (o is Asn1Sequence) + { + return new Accuracy((Asn1Sequence) o); + } + + throw new ArgumentException( + "Unknown object in 'Accuracy' factory: " + o.GetType().FullName); + } + + public DerInteger Seconds + { + get { return seconds; } + } + + public DerInteger Millis + { + get { return millis; } + } + + public DerInteger Micros + { + get { return micros; } + } + + /** + *
+		 * Accuracy ::= SEQUENCE {
+		 *             seconds        INTEGER              OPTIONAL,
+		 *             millis     [0] INTEGER  (1..999)    OPTIONAL,
+		 *             micros     [1] INTEGER  (1..999)    OPTIONAL
+		 *             }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/tsp/MessageImprint.cs b/crypto/src/asn1/tsp/MessageImprint.cs new file mode 100644 index 000000000..0933bae21 --- /dev/null +++ b/crypto/src/asn1/tsp/MessageImprint.cs @@ -0,0 +1,74 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + public class MessageImprint + : Asn1Encodable + { + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly byte[] hashedMessage; + + /** + * @param o + * @return a MessageImprint object. + */ + public static MessageImprint GetInstance( + object o) + { + if (o == null || o is MessageImprint) + { + return (MessageImprint) o; + } + + if (o is Asn1Sequence) + { + return new MessageImprint((Asn1Sequence) o); + } + + throw new ArgumentException( + "Unknown object in 'MessageImprint' factory: " + o.GetType().FullName); + } + + private MessageImprint( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); + this.hashedMessage = Asn1OctetString.GetInstance(seq[1]).GetOctets(); + } + + public MessageImprint( + AlgorithmIdentifier hashAlgorithm, + byte[] hashedMessage) + { + this.hashAlgorithm = hashAlgorithm; + this.hashedMessage = hashedMessage; + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public byte[] GetHashedMessage() + { + return hashedMessage; + } + + /** + *
+		 *    MessageImprint ::= SEQUENCE  {
+		 *       hashAlgorithm                AlgorithmIdentifier,
+		 *       hashedMessage                OCTET STRING  }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(hashAlgorithm, new DerOctetString(hashedMessage)); + } + } +} diff --git a/crypto/src/asn1/tsp/TSTInfo.cs b/crypto/src/asn1/tsp/TSTInfo.cs new file mode 100644 index 000000000..61d5399c7 --- /dev/null +++ b/crypto/src/asn1/tsp/TSTInfo.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + public class TstInfo + : Asn1Encodable + { + private readonly DerInteger version; + private readonly DerObjectIdentifier tsaPolicyId; + private readonly MessageImprint messageImprint; + private readonly DerInteger serialNumber; + private readonly DerGeneralizedTime genTime; + private readonly Accuracy accuracy; + private readonly DerBoolean ordering; + private readonly DerInteger nonce; + private readonly GeneralName tsa; + private readonly X509Extensions extensions; + + public static TstInfo GetInstance( + object o) + { + if (o == null || o is TstInfo) + { + return (TstInfo) o; + } + + if (o is Asn1Sequence) + { + return new TstInfo((Asn1Sequence) o); + } + + if (o is Asn1OctetString) + { + try + { + byte[] octets = ((Asn1OctetString)o).GetOctets(); + return GetInstance(Asn1Object.FromByteArray(octets)); + } + catch (IOException) + { + throw new ArgumentException( + "Bad object format in 'TstInfo' factory."); + } + } + + throw new ArgumentException( + "Unknown object in 'TstInfo' factory: " + o.GetType().FullName); + } + + private TstInfo( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + // version + e.MoveNext(); + version = DerInteger.GetInstance(e.Current); + + // tsaPolicy + e.MoveNext(); + tsaPolicyId = DerObjectIdentifier.GetInstance(e.Current); + + // messageImprint + e.MoveNext(); + messageImprint = MessageImprint.GetInstance(e.Current); + + // serialNumber + e.MoveNext(); + serialNumber = DerInteger.GetInstance(e.Current); + + // genTime + e.MoveNext(); + genTime = DerGeneralizedTime.GetInstance(e.Current); + + // default for ordering + ordering = DerBoolean.False; + + while (e.MoveNext()) + { + Asn1Object o = (Asn1Object) e.Current; + + if (o is Asn1TaggedObject) + { + DerTaggedObject tagged = (DerTaggedObject) o; + + switch (tagged.TagNo) + { + case 0: + tsa = GeneralName.GetInstance(tagged, true); + break; + case 1: + extensions = X509Extensions.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("Unknown tag value " + tagged.TagNo); + } + } + + if (o is DerSequence) + { + accuracy = Accuracy.GetInstance(o); + } + + if (o is DerBoolean) + { + ordering = DerBoolean.GetInstance(o); + } + + if (o is DerInteger) + { + nonce = DerInteger.GetInstance(o); + } + } + } + + public TstInfo( + DerObjectIdentifier tsaPolicyId, + MessageImprint messageImprint, + DerInteger serialNumber, + DerGeneralizedTime genTime, + Accuracy accuracy, + DerBoolean ordering, + DerInteger nonce, + GeneralName tsa, + X509Extensions extensions) + { + this.version = new DerInteger(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 DerInteger Version + { + get { return version; } + } + + public MessageImprint MessageImprint + { + get { return messageImprint; } + } + + public DerObjectIdentifier Policy + { + get { return tsaPolicyId; } + } + + public DerInteger SerialNumber + { + get { return serialNumber; } + } + + public Accuracy Accuracy + { + get { return accuracy; } + } + + public DerGeneralizedTime GenTime + { + get { return genTime; } + } + + public DerBoolean Ordering + { + get { return ordering; } + } + + public DerInteger Nonce + { + get { return nonce; } + } + + public GeneralName Tsa + { + get { return tsa; } + } + + public X509Extensions Extensions + { + get { return extensions; } + } + + /** + *
+		 *
+		 *     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  }
+		 *
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, tsaPolicyId, messageImprint, serialNumber, genTime); + + if (accuracy != null) + { + v.Add(accuracy); + } + + if (ordering != null && ordering.IsTrue) + { + v.Add(ordering); + } + + if (nonce != null) + { + v.Add(nonce); + } + + if (tsa != null) + { + v.Add(new DerTaggedObject(true, 0, tsa)); + } + + if (extensions != null) + { + v.Add(new DerTaggedObject(false, 1, extensions)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/tsp/TimeStampReq.cs b/crypto/src/asn1/tsp/TimeStampReq.cs new file mode 100644 index 000000000..55e973e76 --- /dev/null +++ b/crypto/src/asn1/tsp/TimeStampReq.cs @@ -0,0 +1,164 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + public class TimeStampReq + : Asn1Encodable + { + private readonly DerInteger version; + private readonly MessageImprint messageImprint; + private readonly DerObjectIdentifier tsaPolicy; + private readonly DerInteger nonce; + private readonly DerBoolean certReq; + private readonly X509Extensions extensions; + + public static TimeStampReq GetInstance( + object o) + { + if (o == null || o is TimeStampReq) + { + return (TimeStampReq) o; + } + + if (o is Asn1Sequence) + { + return new TimeStampReq((Asn1Sequence) o); + } + + throw new ArgumentException( + "Unknown object in 'TimeStampReq' factory: " + o.GetType().FullName); + } + + private TimeStampReq( + Asn1Sequence seq) + { + int nbObjects = seq.Count; + int seqStart = 0; + + // version + version = DerInteger.GetInstance(seq[seqStart++]); + + // messageImprint + messageImprint = MessageImprint.GetInstance(seq[seqStart++]); + + for (int opt = seqStart; opt < nbObjects; opt++) + { + // tsaPolicy + if (seq[opt] is DerObjectIdentifier) + { + tsaPolicy = DerObjectIdentifier.GetInstance(seq[opt]); + } + // nonce + else if (seq[opt] is DerInteger) + { + nonce = DerInteger.GetInstance(seq[opt]); + } + // certReq + else if (seq[opt] is DerBoolean) + { + certReq = DerBoolean.GetInstance(seq[opt]); + } + // extensions + else if (seq[opt] is Asn1TaggedObject) + { + Asn1TaggedObject tagged = (Asn1TaggedObject) seq[opt]; + if (tagged.TagNo == 0) + { + extensions = X509Extensions.GetInstance(tagged, false); + } + } + } + } + + public TimeStampReq( + MessageImprint messageImprint, + DerObjectIdentifier tsaPolicy, + DerInteger nonce, + DerBoolean certReq, + X509Extensions extensions) + { + // default + this.version = new DerInteger(1); + + this.messageImprint = messageImprint; + this.tsaPolicy = tsaPolicy; + this.nonce = nonce; + this.certReq = certReq; + this.extensions = extensions; + } + + public DerInteger Version + { + get { return version; } + } + + public MessageImprint MessageImprint + { + get { return messageImprint; } + } + + public DerObjectIdentifier ReqPolicy + { + get { return tsaPolicy; } + } + + public DerInteger Nonce + { + get { return nonce; } + } + + public DerBoolean CertReq + { + get { return certReq; } + } + + public X509Extensions Extensions + { + get { return extensions; } + } + + /** + *
+		 * 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
+		 * }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, 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/crypto/src/asn1/tsp/TimeStampResp.cs b/crypto/src/asn1/tsp/TimeStampResp.cs new file mode 100644 index 000000000..f26fb30bd --- /dev/null +++ b/crypto/src/asn1/tsp/TimeStampResp.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + public class TimeStampResp + : Asn1Encodable + { + private readonly PkiStatusInfo pkiStatusInfo; + private readonly ContentInfo timeStampToken; + + public static TimeStampResp GetInstance( + object o) + { + if (o == null || o is TimeStampResp) + { + return (TimeStampResp) o; + } + + if (o is Asn1Sequence) + { + return new TimeStampResp((Asn1Sequence) o); + } + + throw new ArgumentException( + "Unknown object in 'TimeStampResp' factory: " + o.GetType().FullName); + } + + private TimeStampResp( + Asn1Sequence seq) + { + this.pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]); + + if (seq.Count > 1) + { + this.timeStampToken = ContentInfo.GetInstance(seq[1]); + } + } + + public TimeStampResp( + PkiStatusInfo pkiStatusInfo, + ContentInfo timeStampToken) + { + this.pkiStatusInfo = pkiStatusInfo; + this.timeStampToken = timeStampToken; + } + + public PkiStatusInfo Status + { + get { return pkiStatusInfo; } + } + + public ContentInfo TimeStampToken + { + get { return timeStampToken; } + } + + /** + *
+		 * TimeStampResp ::= SEQUENCE  {
+		 *   status                  PkiStatusInfo,
+		 *   timeStampToken          TimeStampToken     OPTIONAL  }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo); + + if (timeStampToken != null) + { + v.Add(timeStampToken); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs new file mode 100644 index 000000000..43d485500 --- /dev/null +++ b/crypto/src/asn1/util/Asn1Dump.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.Utilities +{ + public sealed class Asn1Dump + { + private static readonly string NewLine = Platform.NewLine; + + private Asn1Dump() + { + } + + private const string Tab = " "; + private const int SampleSize = 32; + + /** + * dump a Der object as a formatted string with indentation + * + * @param obj the Asn1Object to be dumped out. + */ + private static void AsString( + string indent, + bool verbose, + Asn1Object obj, + StringBuilder buf) + { + if (obj is Asn1Sequence) + { + string tab = indent + Tab; + buf.Append(indent); + if (obj is BerSequence) + { + buf.Append("BER Sequence"); + } + else if (obj is DerSequence) + { + buf.Append("DER Sequence"); + } + else + { + buf.Append("Sequence"); + } + + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Sequence)obj)) + { + if (o == null || o is Asn1Null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerTaggedObject) + { + string tab = indent + Tab; + buf.Append(indent); + if (obj is BerTaggedObject) + { + buf.Append("BER Tagged ["); + } + else + { + buf.Append("Tagged ["); + } + + DerTaggedObject o = (DerTaggedObject)obj; + + buf.Append(((int)o.TagNo).ToString()); + buf.Append(']'); + + if (!o.IsExplicit()) + { + buf.Append(" IMPLICIT "); + } + + buf.Append(NewLine); + + if (o.IsEmpty()) + { + buf.Append(tab); + buf.Append("EMPTY"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.GetObject(), buf); + } + } + else if (obj is BerSet) + { + string tab = indent + Tab; + + buf.Append(indent); + buf.Append("BER Set"); + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { + if (o == null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerSet) + { + string tab = indent + Tab; + + buf.Append(indent); + buf.Append("DER Set"); + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { + if (o == null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerObjectIdentifier) + { + buf.Append(indent + "ObjectIdentifier(" + ((DerObjectIdentifier)obj).Id + ")" + NewLine); + } + else if (obj is DerBoolean) + { + buf.Append(indent + "Boolean(" + ((DerBoolean)obj).IsTrue + ")" + NewLine); + } + else if (obj is DerInteger) + { + buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine); + } + else if (obj is BerOctetString) + { + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } + else if (obj is DerOctetString) + { + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } + else if (obj is DerBitString) + { + DerBitString bt = (DerBitString)obj; + byte[] bytes = bt.GetBytes(); + string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : ""; + buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine); + } + else if (obj is DerIA5String) + { + buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerUtf8String) + { + buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerPrintableString) + { + buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerVisibleString) + { + buf.Append(indent + "VisibleString(" + ((DerVisibleString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerBmpString) + { + buf.Append(indent + "BMPString(" + ((DerBmpString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerT61String) + { + buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerUtcTime) + { + buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine); + } + else if (obj is DerGeneralizedTime) + { + buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine); + } + else if (obj is DerUnknownTag) + { + string hex = Hex.ToHexString(((DerUnknownTag)obj).GetData()); + buf.Append(indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " " + hex + NewLine); + } + else if (obj is BerApplicationSpecific) + { + buf.Append(outputApplicationSpecific("BER", indent, verbose, (BerApplicationSpecific)obj)); + } + else if (obj is DerApplicationSpecific) + { + buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj)); + } + else if (obj is DerEnumerated) + { + DerEnumerated en = (DerEnumerated)obj; + buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine); + } + else if (obj is DerExternal) + { + DerExternal ext = (DerExternal)obj; + buf.Append(indent + "External " + NewLine); + string tab = indent + Tab; + + if (ext.DirectReference != null) + { + buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine); + } + if (ext.IndirectReference != null) + { + buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine); + } + if (ext.DataValueDescriptor != null) + { + AsString(tab, verbose, ext.DataValueDescriptor, buf); + } + buf.Append(tab + "Encoding: " + ext.Encoding + NewLine); + AsString(tab, verbose, ext.ExternalContent, buf); + } + else + { + buf.Append(indent + obj.ToString() + NewLine); + } + } + + private static string outputApplicationSpecific( + string type, + string indent, + bool verbose, + DerApplicationSpecific app) + { + StringBuilder buf = new StringBuilder(); + + if (app.IsConstructed()) + { + try + { + Asn1Sequence s = Asn1Sequence.GetInstance(app.GetObject(Asn1Tags.Sequence)); + buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine); + foreach (Asn1Encodable ae in s) + { + AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf); + } + } + catch (IOException e) + { + buf.Append(e); + } + return buf.ToString(); + } + + return indent + type + " ApplicationSpecific[" + app.ApplicationTag + "] (" + + Hex.ToHexString(app.GetContents()) + ")" + NewLine; + } + + [Obsolete("Use version accepting Asn1Encodable")] + public static string DumpAsString( + object obj) + { + if (obj is Asn1Encodable) + { + StringBuilder buf = new StringBuilder(); + AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf); + return buf.ToString(); + } + + return "unknown object type " + obj.ToString(); + } + + /** + * dump out a DER object as a formatted string, in non-verbose mode + * + * @param obj the Asn1Encodable to be dumped out. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj) + { + return DumpAsString(obj, false); + } + + /** + * Dump out the object as a string + * + * @param obj the Asn1Encodable to be dumped out. + * @param verbose if true, dump out the contents of octet and bit strings. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj, + bool verbose) + { + StringBuilder buf = new StringBuilder(); + AsString("", verbose, obj.ToAsn1Object(), buf); + return buf.ToString(); + } + + private static string dumpBinaryDataAsString(string indent, byte[] bytes) + { + indent += Tab; + + StringBuilder buf = new StringBuilder(NewLine); + + for (int i = 0; i < bytes.Length; i += SampleSize) + { + if (bytes.Length - i > SampleSize) + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, SampleSize)); + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, SampleSize)); + buf.Append(NewLine); + } + else + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i)); + for (int j = bytes.Length - i; j != SampleSize; j++) + { + buf.Append(" "); + } + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, bytes.Length - i)); + buf.Append(NewLine); + } + } + + return buf.ToString(); + } + + private static string calculateAscString( + byte[] bytes, + int off, + int len) + { + StringBuilder buf = new StringBuilder(); + + for (int i = off; i != off + len; i++) + { + char c = (char)bytes[i]; + if (c >= ' ' && c <= '~') + { + buf.Append(c); + } + } + + return buf.ToString(); + } + } +} diff --git a/crypto/src/asn1/util/Dump.cs b/crypto/src/asn1/util/Dump.cs new file mode 100644 index 000000000..27c87f127 --- /dev/null +++ b/crypto/src/asn1/util/Dump.cs @@ -0,0 +1,28 @@ +using Org.BouncyCastle.Asn1; + +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1.Utilities +{ + public sealed class Dump + { + private Dump() + { + } + + public static void Main(string[] args) + { + FileStream fIn = File.OpenRead(args[0]); + Asn1InputStream bIn = new Asn1InputStream(fIn); + + Asn1Object obj; + while ((obj = bIn.ReadObject()) != null) + { + Console.WriteLine(Asn1Dump.DumpAsString(obj)); + } + + bIn.Close(); + } + } +} diff --git a/crypto/src/asn1/util/FilterStream.cs b/crypto/src/asn1/util/FilterStream.cs new file mode 100644 index 000000000..2b0494b78 --- /dev/null +++ b/crypto/src/asn1/util/FilterStream.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1.Utilities +{ + public class FilterStream : Stream + { + public FilterStream(Stream s) + { + this.s = s; + } + public override bool CanRead + { + get { return s.CanRead; } + } + public override bool CanSeek + { + get { return s.CanSeek; } + } + public override bool CanWrite + { + get { return s.CanWrite; } + } + public override long Length + { + get { return s.Length; } + } + public override long Position + { + get { return s.Position; } + set { s.Position = value; } + } + public override void Close() + { + s.Close(); + } + public override void Flush() + { + s.Flush(); + } + public override long Seek(long offset, SeekOrigin origin) + { + return s.Seek(offset, origin); + } + public override void SetLength(long value) + { + s.SetLength(value); + } + public override int Read(byte[] buffer, int offset, int count) + { + return s.Read(buffer, offset, count); + } + public override int ReadByte() + { + return s.ReadByte(); + } + public override void Write(byte[] buffer, int offset, int count) + { + s.Write(buffer, offset, count); + } + public override void WriteByte(byte value) + { + s.WriteByte(value); + } + protected readonly Stream s; + } +} diff --git a/crypto/src/asn1/x500/DirectoryString.cs b/crypto/src/asn1/x500/DirectoryString.cs new file mode 100644 index 000000000..78ecc2663 --- /dev/null +++ b/crypto/src/asn1/x500/DirectoryString.cs @@ -0,0 +1,75 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X500 +{ + public class DirectoryString + : Asn1Encodable, IAsn1Choice, IAsn1String + { + private readonly DerStringBase str; + + public static DirectoryString GetInstance( + object obj) + { + if (obj is DirectoryString) + { + return (DirectoryString) obj; + } + + if (obj is DerStringBase) + { + if (obj is DerT61String + || obj is DerPrintableString + || obj is DerUniversalString + || obj is DerUtf8String + || obj is DerBmpString) + { + return new DirectoryString((DerStringBase) obj); + } + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static DirectoryString GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + if (!isExplicit) + throw new ArgumentException("choice item must be explicitly tagged"); + + return GetInstance(obj.GetObject()); + } + + private DirectoryString( + DerStringBase str) + { + this.str = str; + } + + public DirectoryString( + string str) + { + this.str = new DerUtf8String(str); + } + + public string GetString() + { + return str.GetString(); + } + + /** + *
+		 *  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))  }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + return str.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/x509/AccessDescription.cs b/crypto/src/asn1/x509/AccessDescription.cs new file mode 100644 index 000000000..09b5b5920 --- /dev/null +++ b/crypto/src/asn1/x509/AccessDescription.cs @@ -0,0 +1,83 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The AccessDescription object. + *
+	 * AccessDescription  ::=  SEQUENCE {
+	 *       accessMethod          OBJECT IDENTIFIER,
+	 *       accessLocation        GeneralName  }
+	 * 
+ */ + public class AccessDescription + : Asn1Encodable + { + public readonly static DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier("1.3.6.1.5.5.7.48.2"); + public readonly static DerObjectIdentifier IdADOcsp = new DerObjectIdentifier("1.3.6.1.5.5.7.48.1"); + + private readonly DerObjectIdentifier accessMethod; + private readonly GeneralName accessLocation; + + public static AccessDescription GetInstance( + object obj) + { + if (obj is AccessDescription) + return (AccessDescription) obj; + + if (obj is Asn1Sequence) + return new AccessDescription((Asn1Sequence) obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private AccessDescription( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("wrong number of elements in sequence"); + + accessMethod = DerObjectIdentifier.GetInstance(seq[0]); + accessLocation = GeneralName.GetInstance(seq[1]); + } + + /** + * create an AccessDescription with the oid and location provided. + */ + public AccessDescription( + DerObjectIdentifier oid, + GeneralName location) + { + accessMethod = oid; + accessLocation = location; + } + + /** + * + * @return the access method. + */ + public DerObjectIdentifier AccessMethod + { + get { return accessMethod; } + } + + /** + * + * @return the access location + */ + public GeneralName AccessLocation + { + get { return accessLocation; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(accessMethod, accessLocation); + } + + public override string ToString() + { + return "AccessDescription: Oid(" + this.accessMethod.Id + ")"; + } + } +} diff --git a/crypto/src/asn1/x509/AlgorithmIdentifier.cs b/crypto/src/asn1/x509/AlgorithmIdentifier.cs new file mode 100644 index 000000000..4ed3a400d --- /dev/null +++ b/crypto/src/asn1/x509/AlgorithmIdentifier.cs @@ -0,0 +1,109 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AlgorithmIdentifier + : Asn1Encodable + { + private readonly DerObjectIdentifier objectID; + private readonly Asn1Encodable parameters; + private readonly bool parametersDefined; + + public static AlgorithmIdentifier GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static AlgorithmIdentifier GetInstance( + object obj) + { + if (obj == null || obj is AlgorithmIdentifier) + return (AlgorithmIdentifier) obj; + + // TODO: delete + if (obj is DerObjectIdentifier) + return new AlgorithmIdentifier((DerObjectIdentifier) obj); + + // TODO: delete + if (obj is string) + return new AlgorithmIdentifier((string) obj); + + return new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj)); + } + + public AlgorithmIdentifier( + DerObjectIdentifier objectID) + { + this.objectID = objectID; + } + + public AlgorithmIdentifier( + string objectID) + { + this.objectID = new DerObjectIdentifier(objectID); + } + + public AlgorithmIdentifier( + DerObjectIdentifier objectID, + Asn1Encodable parameters) + { + this.objectID = objectID; + this.parameters = parameters; + this.parametersDefined = true; + } + + internal AlgorithmIdentifier( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + this.objectID = DerObjectIdentifier.GetInstance(seq[0]); + this.parametersDefined = (seq.Count == 2); + + if (parametersDefined) + { + this.parameters = seq[1]; + } + } + + public virtual DerObjectIdentifier ObjectID + { + get { return objectID; } + } + + public Asn1Encodable Parameters + { + get { return parameters; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *      AlgorithmIdentifier ::= Sequence {
+         *                            algorithm OBJECT IDENTIFIER,
+         *                            parameters ANY DEFINED BY algorithm OPTIONAL }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(objectID); + + if (parametersDefined) + { + if (parameters != null) + { + v.Add(parameters); + } + else + { + v.Add(DerNull.Instance); + } + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/AttCertIssuer.cs b/crypto/src/asn1/x509/AttCertIssuer.cs new file mode 100644 index 000000000..e9314fa92 --- /dev/null +++ b/crypto/src/asn1/x509/AttCertIssuer.cs @@ -0,0 +1,86 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttCertIssuer + : Asn1Encodable, IAsn1Choice + { + internal readonly Asn1Encodable obj; + internal readonly Asn1Object choiceObj; + + public static AttCertIssuer GetInstance( + object obj) + { + if (obj is AttCertIssuer) + { + return (AttCertIssuer)obj; + } + else if (obj is V2Form) + { + return new AttCertIssuer(V2Form.GetInstance(obj)); + } + else if (obj is GeneralNames) + { + return new AttCertIssuer((GeneralNames)obj); + } + else if (obj is Asn1TaggedObject) + { + return new AttCertIssuer(V2Form.GetInstance((Asn1TaggedObject)obj, false)); + } + else if (obj is Asn1Sequence) + { + return new AttCertIssuer(GeneralNames.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static AttCertIssuer GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(obj.GetObject()); // must be explictly tagged + } + + /// + /// Don't use this one if you are trying to be RFC 3281 compliant. + /// Use it for v1 attribute certificates only. + /// + /// Our GeneralNames structure + public AttCertIssuer( + GeneralNames names) + { + obj = names; + choiceObj = obj.ToAsn1Object(); + } + + public AttCertIssuer( + V2Form v2Form) + { + obj = v2Form; + choiceObj = new DerTaggedObject(false, 0, obj); + } + + public Asn1Encodable Issuer + { + get { return obj; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  AttCertIssuer ::= CHOICE {
+         *       v1Form   GeneralNames,  -- MUST NOT be used in this
+         *                               -- profile
+         *       v2Form   [0] V2Form     -- v2 only
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return choiceObj; + } + } +} diff --git a/crypto/src/asn1/x509/AttCertValidityPeriod.cs b/crypto/src/asn1/x509/AttCertValidityPeriod.cs new file mode 100644 index 000000000..7f86cd0b8 --- /dev/null +++ b/crypto/src/asn1/x509/AttCertValidityPeriod.cs @@ -0,0 +1,78 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttCertValidityPeriod + : Asn1Encodable + { + private readonly DerGeneralizedTime notBeforeTime; + private readonly DerGeneralizedTime notAfterTime; + + public static AttCertValidityPeriod GetInstance( + object obj) + { + if (obj is AttCertValidityPeriod || obj == null) + { + return (AttCertValidityPeriod) obj; + } + + if (obj is Asn1Sequence) + { + return new AttCertValidityPeriod((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static AttCertValidityPeriod GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + private AttCertValidityPeriod( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + notBeforeTime = DerGeneralizedTime.GetInstance(seq[0]); + notAfterTime = DerGeneralizedTime.GetInstance(seq[1]); + } + + public AttCertValidityPeriod( + DerGeneralizedTime notBeforeTime, + DerGeneralizedTime notAfterTime) + { + this.notBeforeTime = notBeforeTime; + this.notAfterTime = notAfterTime; + } + + public DerGeneralizedTime NotBeforeTime + { + get { return notBeforeTime; } + } + + public DerGeneralizedTime NotAfterTime + { + get { return notAfterTime; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  AttCertValidityPeriod  ::= Sequence {
+         *       notBeforeTime  GeneralizedTime,
+         *       notAfterTime   GeneralizedTime
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(notBeforeTime, notAfterTime); + } + } +} diff --git a/crypto/src/asn1/x509/Attribute.cs b/crypto/src/asn1/x509/Attribute.cs new file mode 100644 index 000000000..d26db93e9 --- /dev/null +++ b/crypto/src/asn1/x509/Attribute.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttributeX509 + : Asn1Encodable + { + private readonly DerObjectIdentifier attrType; + private readonly Asn1Set attrValues; + + /** + * return an Attr object from the given object. + * + * @param o the object we want converted. + * @exception ArgumentException if the object cannot be converted. + */ + public static AttributeX509 GetInstance( + object obj) + { + if (obj == null || obj is AttributeX509) + { + return (AttributeX509) obj; + } + + if (obj is Asn1Sequence) + { + return new AttributeX509((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private AttributeX509( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + attrType = DerObjectIdentifier.GetInstance(seq[0]); + attrValues = Asn1Set.GetInstance(seq[1]); + } + + public AttributeX509( + DerObjectIdentifier attrType, + Asn1Set attrValues) + { + this.attrType = attrType; + this.attrValues = attrValues; + } + + public DerObjectIdentifier AttrType + { + get { return attrType; } + } + + public Asn1Encodable[] GetAttributeValues() + { + return attrValues.ToArray(); + } + + public Asn1Set AttrValues + { + get { return attrValues; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Attr ::= Sequence {
+         *     attrType OBJECT IDENTIFIER,
+         *     attrValues Set OF AttributeValue
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(attrType, attrValues); + } + } +} diff --git a/crypto/src/asn1/x509/AttributeCertificate.cs b/crypto/src/asn1/x509/AttributeCertificate.cs new file mode 100644 index 000000000..5f85910da --- /dev/null +++ b/crypto/src/asn1/x509/AttributeCertificate.cs @@ -0,0 +1,81 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttributeCertificate + : Asn1Encodable + { + private readonly AttributeCertificateInfo acinfo; + private readonly AlgorithmIdentifier signatureAlgorithm; + private readonly DerBitString signatureValue; + + /** + * @param obj + * @return + */ + public static AttributeCertificate GetInstance( + object obj) + { + if (obj is AttributeCertificate) + return (AttributeCertificate) obj; + + 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; + } + + private AttributeCertificate( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + this.acinfo = AttributeCertificateInfo.GetInstance(seq[0]); + this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + this.signatureValue = DerBitString.GetInstance(seq[2]); + } + + public AttributeCertificateInfo ACInfo + { + get { return acinfo; } + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return signatureAlgorithm; } + } + + public DerBitString SignatureValue + { + get { return signatureValue; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  AttributeCertificate ::= Sequence {
+         *       acinfo               AttributeCertificateInfo,
+         *       signatureAlgorithm   AlgorithmIdentifier,
+         *       signatureValue       BIT STRING
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(acinfo, signatureAlgorithm, signatureValue); + } + } +} diff --git a/crypto/src/asn1/x509/AttributeCertificateInfo.cs b/crypto/src/asn1/x509/AttributeCertificateInfo.cs new file mode 100644 index 000000000..dcef3d472 --- /dev/null +++ b/crypto/src/asn1/x509/AttributeCertificateInfo.cs @@ -0,0 +1,156 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttributeCertificateInfo + : Asn1Encodable + { + internal readonly DerInteger version; + internal readonly Holder holder; + internal readonly AttCertIssuer issuer; + internal readonly AlgorithmIdentifier signature; + internal readonly DerInteger serialNumber; + internal readonly AttCertValidityPeriod attrCertValidityPeriod; + internal readonly Asn1Sequence attributes; + internal readonly DerBitString issuerUniqueID; + internal readonly X509Extensions extensions; + + public static AttributeCertificateInfo GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public static AttributeCertificateInfo GetInstance( + object obj) + { + if (obj is AttributeCertificateInfo) + { + return (AttributeCertificateInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new AttributeCertificateInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private AttributeCertificateInfo( + Asn1Sequence seq) + { + if (seq.Count < 7 || seq.Count > 9) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + this.version = DerInteger.GetInstance(seq[0]); + this.holder = Holder.GetInstance(seq[1]); + this.issuer = AttCertIssuer.GetInstance(seq[2]); + this.signature = AlgorithmIdentifier.GetInstance(seq[3]); + this.serialNumber = DerInteger.GetInstance(seq[4]); + this.attrCertValidityPeriod = AttCertValidityPeriod.GetInstance(seq[5]); + this.attributes = Asn1Sequence.GetInstance(seq[6]); + + for (int i = 7; i < seq.Count; i++) + { + Asn1Encodable obj = (Asn1Encodable) seq[i]; + + if (obj is DerBitString) + { + this.issuerUniqueID = DerBitString.GetInstance(seq[i]); + } + else if (obj is Asn1Sequence || obj is X509Extensions) + { + this.extensions = X509Extensions.GetInstance(seq[i]); + } + } + } + + public DerInteger Version + { + get { return version; } + } + + public Holder Holder + { + get { return holder; } + } + + public AttCertIssuer Issuer + { + get { return issuer; } + } + + public AlgorithmIdentifier Signature + { + get { return signature; } + } + + public DerInteger SerialNumber + { + get { return serialNumber; } + } + + public AttCertValidityPeriod AttrCertValidityPeriod + { + get { return attrCertValidityPeriod; } + } + + public Asn1Sequence Attributes + { + get { return attributes; } + } + + public DerBitString IssuerUniqueID + { + get { return issuerUniqueID; } + } + + public X509Extensions Extensions + { + get { return extensions; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  AttributeCertificateInfo ::= Sequence {
+         *       version              AttCertVersion -- version is v2,
+         *       holder               Holder,
+         *       issuer               AttCertIssuer,
+         *       signature            AlgorithmIdentifier,
+         *       serialNumber         CertificateSerialNumber,
+         *       attrCertValidityPeriod   AttCertValidityPeriod,
+         *       attributes           Sequence OF Attr,
+         *       issuerUniqueID       UniqueIdentifier OPTIONAL,
+         *       extensions           Extensions OPTIONAL
+         *  }
+         *
+         *  AttCertVersion ::= Integer { v2(1) }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + version, holder, issuer, signature, serialNumber, + attrCertValidityPeriod, attributes); + + if (issuerUniqueID != null) + { + v.Add(issuerUniqueID); + } + + if (extensions != null) + { + v.Add(extensions); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/AttributeTable.cs b/crypto/src/asn1/x509/AttributeTable.cs new file mode 100644 index 000000000..ffe0ea935 --- /dev/null +++ b/crypto/src/asn1/x509/AttributeTable.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class AttributeTable + { + private readonly IDictionary attributes; + + public AttributeTable( + IDictionary attrs) + { + this.attributes = Platform.CreateHashtable(attrs); + } + +#if !SILVERLIGHT + [Obsolete] + public AttributeTable( + Hashtable attrs) + { + this.attributes = Platform.CreateHashtable(attrs); + } +#endif + + public AttributeTable( + Asn1EncodableVector v) + { + this.attributes = Platform.CreateHashtable(v.Count); + + for (int i = 0; i != v.Count; i++) + { + AttributeX509 a = AttributeX509.GetInstance(v[i]); + + attributes.Add(a.AttrType, a); + } + } + + public AttributeTable( + Asn1Set s) + { + this.attributes = Platform.CreateHashtable(s.Count); + + for (int i = 0; i != s.Count; i++) + { + AttributeX509 a = AttributeX509.GetInstance(s[i]); + + attributes.Add(a.AttrType, a); + } + } + + public AttributeX509 Get( + DerObjectIdentifier oid) + { + return (AttributeX509) attributes[oid]; + } + +#if !SILVERLIGHT + [Obsolete("Use 'ToDictionary' instead")] + public Hashtable ToHashtable() + { + return new Hashtable(attributes); + } +#endif + + public IDictionary ToDictionary() + { + return Platform.CreateHashtable(attributes); + } + } +} diff --git a/crypto/src/asn1/x509/AuthorityInformationAccess.cs b/crypto/src/asn1/x509/AuthorityInformationAccess.cs new file mode 100644 index 000000000..3eeba8cd2 --- /dev/null +++ b/crypto/src/asn1/x509/AuthorityInformationAccess.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The AuthorityInformationAccess object. + *
+	 * 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 }
+	 * 
+ */ + public class AuthorityInformationAccess + : Asn1Encodable + { + private readonly AccessDescription[] descriptions; + + public static AuthorityInformationAccess GetInstance( + object obj) + { + if (obj is AuthorityInformationAccess) + return (AuthorityInformationAccess) obj; + + if (obj is Asn1Sequence) + return new AuthorityInformationAccess((Asn1Sequence) obj); + + if (obj is X509Extension) + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private AuthorityInformationAccess( + Asn1Sequence seq) + { + if (seq.Count < 1) + throw new ArgumentException("sequence may not be empty"); + + this.descriptions = new AccessDescription[seq.Count]; + + for (int i = 0; i < seq.Count; ++i) + { + descriptions[i] = AccessDescription.GetInstance(seq[i]); + } + } + + /** + * create an AuthorityInformationAccess with the oid and location provided. + */ + [Obsolete("Use version taking an AccessDescription instead")] + public AuthorityInformationAccess( + DerObjectIdentifier oid, + GeneralName location) + { + this.descriptions = new AccessDescription[]{ new AccessDescription(oid, location) }; + } + + public AuthorityInformationAccess( + AccessDescription description) + { + this.descriptions = new AccessDescription[]{ description }; + } + + public AccessDescription[] GetAccessDescriptions() + { + return (AccessDescription[]) descriptions.Clone(); + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(descriptions); + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string sep = Platform.NewLine; + + buf.Append("AuthorityInformationAccess:"); + buf.Append(sep); + + foreach (AccessDescription description in descriptions) + { + buf.Append(" "); + buf.Append(description); + buf.Append(sep); + } + + return buf.ToString(); + } + } +} diff --git a/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs new file mode 100644 index 000000000..12ccacfc7 --- /dev/null +++ b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The AuthorityKeyIdentifier object. + *
+     * 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
+     * 
+ * + */ + public class AuthorityKeyIdentifier + : Asn1Encodable + { + internal readonly Asn1OctetString keyidentifier; + internal readonly GeneralNames certissuer; + internal readonly DerInteger certserno; + + public static AuthorityKeyIdentifier GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static AuthorityKeyIdentifier GetInstance( + object obj) + { + if (obj is AuthorityKeyIdentifier) + { + return (AuthorityKeyIdentifier) obj; + } + + if (obj is Asn1Sequence) + { + return new AuthorityKeyIdentifier((Asn1Sequence) obj); + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + protected internal AuthorityKeyIdentifier( + Asn1Sequence seq) + { + foreach (Asn1TaggedObject o in seq) + { + switch (o.TagNo) + { + case 0: + this.keyidentifier = Asn1OctetString.GetInstance(o, false); + break; + case 1: + this.certissuer = GeneralNames.GetInstance(o, false); + break; + case 2: + this.certserno = DerInteger.GetInstance(o, false); + break; + default: + throw new ArgumentException("illegal tag"); + } + } + } + + /** + * + * Calulates the keyidentifier using a SHA1 hash over the BIT STRING + * from SubjectPublicKeyInfo as defined in RFC2459. + * + * Example of making a AuthorityKeyIdentifier: + *
+	     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+		 *       publicKey.getEncoded()).readObject());
+         *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+         * 
+ * + **/ + public AuthorityKeyIdentifier( + SubjectPublicKeyInfo spki) + { + IDigest digest = new Sha1Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + byte[] bytes = spki.PublicKeyData.GetBytes(); + digest.BlockUpdate(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. + */ + public AuthorityKeyIdentifier( + SubjectPublicKeyInfo spki, + GeneralNames name, + BigInteger serialNumber) + { + IDigest digest = new Sha1Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + byte[] bytes = spki.PublicKeyData.GetBytes(); + digest.BlockUpdate(bytes, 0, bytes.Length); + digest.DoFinal(resBuf, 0); + + this.keyidentifier = new DerOctetString(resBuf); + this.certissuer = name; + this.certserno = new DerInteger(serialNumber); + } + + /** + * create an AuthorityKeyIdentifier with the GeneralNames tag and + * the serial number provided. + */ + public AuthorityKeyIdentifier( + GeneralNames name, + BigInteger serialNumber) + { + this.keyidentifier = null; + this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object()); + this.certserno = new DerInteger(serialNumber); + } + + /** + * create an AuthorityKeyIdentifier with a precomputed key identifier + */ + public AuthorityKeyIdentifier( + byte[] keyIdentifier) + { + this.keyidentifier = new DerOctetString(keyIdentifier); + this.certissuer = null; + this.certserno = null; + } + + /** + * create an AuthorityKeyIdentifier with a precomupted key identifier + * and the GeneralNames tag and the serial number provided as well. + */ + public AuthorityKeyIdentifier( + byte[] keyIdentifier, + GeneralNames name, + BigInteger serialNumber) + { + this.keyidentifier = new DerOctetString(keyIdentifier); + this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object()); + this.certserno = new DerInteger(serialNumber); + } + + public byte[] GetKeyIdentifier() + { + return keyidentifier == null ? null : keyidentifier.GetOctets(); + } + + public GeneralNames AuthorityCertIssuer + { + get { return certissuer; } + } + + public BigInteger AuthorityCertSerialNumber + { + get { return certserno == null ? null : certserno.Value; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + */ + public override Asn1Object ToAsn1Object() + { + 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 override string ToString() + { + return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.GetOctets() + ")"); + } + } +} diff --git a/crypto/src/asn1/x509/BasicConstraints.cs b/crypto/src/asn1/x509/BasicConstraints.cs new file mode 100644 index 000000000..522cb61cc --- /dev/null +++ b/crypto/src/asn1/x509/BasicConstraints.cs @@ -0,0 +1,133 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class BasicConstraints + : Asn1Encodable + { + private readonly DerBoolean cA; + private readonly DerInteger pathLenConstraint; + + public static BasicConstraints GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static BasicConstraints GetInstance( + object obj) + { + if (obj == null || obj is BasicConstraints) + { + return (BasicConstraints) obj; + } + + if (obj is Asn1Sequence) + { + return new BasicConstraints((Asn1Sequence) obj); + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private BasicConstraints( + Asn1Sequence seq) + { + if (seq.Count > 0) + { + if (seq[0] is DerBoolean) + { + this.cA = DerBoolean.GetInstance(seq[0]); + } + else + { + this.pathLenConstraint = DerInteger.GetInstance(seq[0]); + } + + if (seq.Count > 1) + { + if (this.cA == null) + throw new ArgumentException("wrong sequence in constructor", "seq"); + + this.pathLenConstraint = DerInteger.GetInstance(seq[1]); + } + } + } + + public BasicConstraints( + bool cA) + { + if (cA) + { + this.cA = DerBoolean.True; + } + } + + /** + * create a cA=true object for the given path length constraint. + * + * @param pathLenConstraint + */ + public BasicConstraints( + int pathLenConstraint) + { + this.cA = DerBoolean.True; + this.pathLenConstraint = new DerInteger(pathLenConstraint); + } + + public bool IsCA() + { + return cA != null && cA.IsTrue; + } + + public BigInteger PathLenConstraint + { + get { return pathLenConstraint == null ? null : pathLenConstraint.Value; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * BasicConstraints := Sequence {
+         *    cA                  Boolean DEFAULT FALSE,
+         *    pathLenConstraint   Integer (0..MAX) OPTIONAL
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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 override string ToString() + { + if (pathLenConstraint == null) + { + return "BasicConstraints: isCa(" + this.IsCA() + ")"; + } + + return "BasicConstraints: isCa(" + this.IsCA() + "), pathLenConstraint = " + pathLenConstraint.Value; + } + } +} diff --git a/crypto/src/asn1/x509/CRLDistPoint.cs b/crypto/src/asn1/x509/CRLDistPoint.cs new file mode 100644 index 000000000..2b5c19798 --- /dev/null +++ b/crypto/src/asn1/x509/CRLDistPoint.cs @@ -0,0 +1,93 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class CrlDistPoint + : Asn1Encodable + { + internal readonly Asn1Sequence seq; + + public static CrlDistPoint GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static CrlDistPoint GetInstance( + object obj) + { + if (obj is CrlDistPoint || obj == null) + { + return (CrlDistPoint) obj; + } + + if (obj is Asn1Sequence) + { + return new CrlDistPoint((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + private CrlDistPoint( + Asn1Sequence seq) + { + this.seq = seq; + } + + public CrlDistPoint( + DistributionPoint[] points) + { + seq = new DerSequence(points); + } + + /** + * Return the distribution points making up the sequence. + * + * @return DistributionPoint[] + */ + public DistributionPoint[] GetDistributionPoints() + { + DistributionPoint[] dp = new DistributionPoint[seq.Count]; + + for (int i = 0; i != seq.Count; ++i) + { + dp[i] = DistributionPoint.GetInstance(seq[i]); + } + + return dp; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * CrlDistPoint ::= Sequence SIZE {1..MAX} OF DistributionPoint
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return seq; + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string sep = Platform.NewLine; + + 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/crypto/src/asn1/x509/CRLNumber.cs b/crypto/src/asn1/x509/CRLNumber.cs new file mode 100644 index 000000000..d744416a5 --- /dev/null +++ b/crypto/src/asn1/x509/CRLNumber.cs @@ -0,0 +1,30 @@ +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The CRLNumber object. + *
+     * CRLNumber::= Integer(0..MAX)
+     * 
+ */ + public class CrlNumber + : DerInteger + { + public CrlNumber( + BigInteger number) + : base(number) + { + } + + public BigInteger Number + { + get { return PositiveValue; } + } + + public override string ToString() + { + return "CRLNumber: " + Number; + } + } +} diff --git a/crypto/src/asn1/x509/CRLReason.cs b/crypto/src/asn1/x509/CRLReason.cs new file mode 100644 index 000000000..e8eb53a59 --- /dev/null +++ b/crypto/src/asn1/x509/CRLReason.cs @@ -0,0 +1,61 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The CRLReason enumeration. + *
+     * CRLReason ::= Enumerated {
+     *  unspecified             (0),
+     *  keyCompromise           (1),
+     *  cACompromise            (2),
+     *  affiliationChanged      (3),
+     *  superseded              (4),
+     *  cessationOfOperation    (5),
+     *  certificateHold         (6),
+     *  removeFromCRL           (8),
+     *  privilegeWithdrawn      (9),
+     *  aACompromise           (10)
+     * }
+     * 
+ */ + public class CrlReason + : DerEnumerated + { + public const int Unspecified = 0; + public const int KeyCompromise = 1; + public const int CACompromise = 2; + public const int AffiliationChanged = 3; + public const int Superseded = 4; + public const int CessationOfOperation = 5; + public const int CertificateHold = 6; + // 7 -> Unknown + public const int RemoveFromCrl = 8; + public const int PrivilegeWithdrawn = 9; + public const int AACompromise = 10; + + private static readonly string[] ReasonString = new string[] + { + "Unspecified", "KeyCompromise", "CACompromise", "AffiliationChanged", + "Superseded", "CessationOfOperation", "CertificateHold", "Unknown", + "RemoveFromCrl", "PrivilegeWithdrawn", "AACompromise" + }; + + public CrlReason( + int reason) + : base(reason) + { + } + + public CrlReason( + DerEnumerated reason) + : base(reason.Value.IntValue) + { + } + + public override string ToString() + { + int reason = Value.IntValue; + string str = (reason < 0 || reason > 10) ? "Invalid" : ReasonString[reason]; + return "CrlReason: " + str; + } + } +} diff --git a/crypto/src/asn1/x509/CertPolicyId.cs b/crypto/src/asn1/x509/CertPolicyId.cs new file mode 100644 index 000000000..11cebcdd7 --- /dev/null +++ b/crypto/src/asn1/x509/CertPolicyId.cs @@ -0,0 +1,20 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * CertPolicyId, used in the CertificatePolicies and PolicyMappings + * X509V3 Extensions. + * + *
+     *     CertPolicyId ::= OBJECT IDENTIFIER
+     * 
+ */ + public class CertPolicyID + : DerObjectIdentifier + { + public CertPolicyID( + string id) + : base(id) + { + } + } +} diff --git a/crypto/src/asn1/x509/CertificateList.cs b/crypto/src/asn1/x509/CertificateList.cs new file mode 100644 index 000000000..0412e0816 --- /dev/null +++ b/crypto/src/asn1/x509/CertificateList.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * 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. + * + *
+     * CertificateList  ::=  Sequence  {
+     *      tbsCertList          TbsCertList,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     * 
+ */ + public class CertificateList + : Asn1Encodable + { + private readonly TbsCertificateList tbsCertList; + private readonly AlgorithmIdentifier sigAlgID; + private readonly DerBitString sig; + + public static CertificateList GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static CertificateList GetInstance( + object obj) + { + if (obj is CertificateList) + return (CertificateList) obj; + + if (obj != null) + return new CertificateList(Asn1Sequence.GetInstance(obj)); + + return null; + } + + private CertificateList( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("sequence wrong size for CertificateList", "seq"); + + tbsCertList = TbsCertificateList.GetInstance(seq[0]); + sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]); + sig = DerBitString.GetInstance(seq[2]); + } + + public TbsCertificateList TbsCertList + { + get { return tbsCertList; } + } + + public CrlEntry[] GetRevokedCertificates() + { + return tbsCertList.GetRevokedCertificates(); + } + + public IEnumerable GetRevokedCertificateEnumeration() + { + return tbsCertList.GetRevokedCertificateEnumeration(); + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return sigAlgID; } + } + + public DerBitString Signature + { + get { return sig; } + } + + public int Version + { + get { return tbsCertList.Version; } + } + + public X509Name Issuer + { + get { return tbsCertList.Issuer; } + } + + public Time ThisUpdate + { + get { return tbsCertList.ThisUpdate; } + } + + public Time NextUpdate + { + get { return tbsCertList.NextUpdate; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(tbsCertList, sigAlgID, sig); + } + } +} diff --git a/crypto/src/asn1/x509/CertificatePair.cs b/crypto/src/asn1/x509/CertificatePair.cs new file mode 100644 index 000000000..8baa64719 --- /dev/null +++ b/crypto/src/asn1/x509/CertificatePair.cs @@ -0,0 +1,160 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * This class helps to support crossCerfificatePairs in a LDAP directory + * according RFC 2587 + * + *
+	*     crossCertificatePairATTRIBUTE::={
+	*       WITH SYNTAX   CertificatePair
+	*       EQUALITY MATCHING RULE certificatePairExactMatch
+	*       ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+	* 
+ * + *
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.
+ * + *
+	*       CertificatePair ::= SEQUENCE {
+	*         forward		[0]	Certificate OPTIONAL,
+	*         reverse		[1]	Certificate OPTIONAL,
+	*         -- at least one of the pair shall be present -- }
+	* 
+ */ + public class CertificatePair + : Asn1Encodable + { + private X509CertificateStructure forward, reverse; + + public static CertificatePair GetInstance( + object obj) + { + if (obj == null || obj is CertificatePair) + { + return (CertificatePair) obj; + } + + if (obj is Asn1Sequence) + { + return new CertificatePair((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type CertificatePair: + *

+ *

+		*       CertificatePair ::= SEQUENCE {
+		*         forward		[0]	Certificate OPTIONAL,
+		*         reverse		[1]	Certificate OPTIONAL,
+		*         -- at least one of the pair shall be present -- }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private CertificatePair( + Asn1Sequence seq) + { + if (seq.Count != 1 && seq.Count != 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + } + + foreach (object obj in seq) + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(obj); + if (o.TagNo == 0) + { + forward = X509CertificateStructure.GetInstance(o, true); + } + else if (o.TagNo == 1) + { + reverse = X509CertificateStructure.GetInstance(o, true); + } + else + { + throw new ArgumentException("Bad tag number: " + o.TagNo); + } + } + } + + /** + * Constructor from a given details. + * + * @param forward Certificates issued to this CA. + * @param reverse Certificates issued by this CA to other CAs. + */ + public CertificatePair( + X509CertificateStructure forward, + X509CertificateStructure reverse) + { + this.forward = forward; + this.reverse = reverse; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*       CertificatePair ::= SEQUENCE {
+		*         forward		[0]	Certificate OPTIONAL,
+		*         reverse		[1]	Certificate OPTIONAL,
+		*         -- at least one of the pair shall be present -- }
+		* 
+ * + * @return a DERObject + */ + public override Asn1Object ToAsn1Object() + { + 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 X509CertificateStructure Forward + { + get { return forward; } + } + + /** + * @return Returns the reverse. + */ + public X509CertificateStructure Reverse + { + get { return reverse; } + } + } +} diff --git a/crypto/src/asn1/x509/CertificatePolicies.cs b/crypto/src/asn1/x509/CertificatePolicies.cs new file mode 100644 index 000000000..a83565bb2 --- /dev/null +++ b/crypto/src/asn1/x509/CertificatePolicies.cs @@ -0,0 +1,81 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class CertificatePolicies + : Asn1Encodable + { + private readonly PolicyInformation[] policyInformation; + + public static CertificatePolicies GetInstance(object obj) + { + if (obj == null || obj is CertificatePolicies) + return (CertificatePolicies)obj; + + return new CertificatePolicies(Asn1Sequence.GetInstance(obj)); + } + + public static CertificatePolicies GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * 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.Count]; + + for (int i = 0; i < seq.Count; ++i) + { + policyInformation[i] = PolicyInformation.GetInstance(seq[i]); + } + } + + public virtual PolicyInformation[] GetPolicyInformation() + { + return (PolicyInformation[])policyInformation.Clone(); + } + + /** + * Produce an object suitable for an ASN1OutputStream. + *
+         * CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(policyInformation); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder("CertificatePolicies:"); + if (policyInformation != null && policyInformation.Length > 0) + { + sb.Append(' '); + sb.Append(policyInformation[0]); + for (int i = 1; i < policyInformation.Length; ++i) + { + sb.Append(", "); + sb.Append(policyInformation[i]); + } + } + return sb.ToString(); + } + } +} diff --git a/crypto/src/asn1/x509/DSAParameter.cs b/crypto/src/asn1/x509/DSAParameter.cs new file mode 100644 index 000000000..b2b325f4d --- /dev/null +++ b/crypto/src/asn1/x509/DSAParameter.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class DsaParameter + : Asn1Encodable + { + internal readonly DerInteger p, q, g; + + public static DsaParameter GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static DsaParameter GetInstance( + object obj) + { + if(obj == null || obj is DsaParameter) + { + return (DsaParameter) obj; + } + + if(obj is Asn1Sequence) + { + return new DsaParameter((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid DsaParameter: " + obj.GetType().Name); + } + + public DsaParameter( + BigInteger p, + BigInteger q, + BigInteger g) + { + this.p = new DerInteger(p); + this.q = new DerInteger(q); + this.g = new DerInteger(g); + } + + private DsaParameter( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.p = DerInteger.GetInstance(seq[0]); + this.q = DerInteger.GetInstance(seq[1]); + this.g = DerInteger.GetInstance(seq[2]); + } + + public BigInteger P + { + get { return p.PositiveValue; } + } + + public BigInteger Q + { + get { return q.PositiveValue; } + } + + public BigInteger G + { + get { return g.PositiveValue; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(p, q, g); + } + } +} diff --git a/crypto/src/asn1/x509/DigestInfo.cs b/crypto/src/asn1/x509/DigestInfo.cs new file mode 100644 index 000000000..1dec227fa --- /dev/null +++ b/crypto/src/asn1/x509/DigestInfo.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The DigestInfo object. + *
+     * DigestInfo::=Sequence{
+     *          digestAlgorithm  AlgorithmIdentifier,
+     *          digest OCTET STRING }
+     * 
+ */ + public class DigestInfo + : Asn1Encodable + { + private readonly byte[] digest; + private readonly AlgorithmIdentifier algID; + + public static DigestInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static DigestInfo GetInstance( + object obj) + { + if (obj is DigestInfo) + { + return (DigestInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new DigestInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public DigestInfo( + AlgorithmIdentifier algID, + byte[] digest) + { + this.digest = digest; + this.algID = algID; + } + + private DigestInfo( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", "seq"); + + algID = AlgorithmIdentifier.GetInstance(seq[0]); + digest = Asn1OctetString.GetInstance(seq[1]).GetOctets(); + } + + public AlgorithmIdentifier AlgorithmID + { + get { return algID; } + } + + public byte[] GetDigest() + { + return digest; + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algID, new DerOctetString(digest)); + } + } +} diff --git a/crypto/src/asn1/x509/DisplayText.cs b/crypto/src/asn1/x509/DisplayText.cs new file mode 100644 index 000000000..699f39031 --- /dev/null +++ b/crypto/src/asn1/x509/DisplayText.cs @@ -0,0 +1,172 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * DisplayText class, used in + * CertificatePolicies X509 V3 extensions (in policy qualifiers). + * + *

It stores a string in a chosen encoding. + *

+	 * DisplayText ::= CHOICE {
+	 *      ia5String        IA5String      (SIZE (1..200)),
+	 *      visibleString    VisibleString  (SIZE (1..200)),
+	 *      bmpString        BMPString      (SIZE (1..200)),
+	 *      utf8String       UTF8String     (SIZE (1..200)) }
+	 * 

+ * @see PolicyQualifierInfo + * @see PolicyInformation + */ + public class DisplayText + : Asn1Encodable, IAsn1Choice + { + /** + * Constant corresponding to ia5String encoding. + * + */ + public const int ContentTypeIA5String = 0; + /** + * Constant corresponding to bmpString encoding. + * + */ + public const int ContentTypeBmpString = 1; + /** + * Constant corresponding to utf8String encoding. + * + */ + public const int ContentTypeUtf8String = 2; + /** + * Constant corresponding to visibleString encoding. + * + */ + public const int ContentTypeVisibleString = 3; + /** + * Describe constant DisplayTextMaximumSize here. + * + */ + public const int DisplayTextMaximumSize = 200; + + internal readonly int contentType; + internal readonly IAsn1String contents; + + /** + * Creates a new DisplayText 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 > DisplayTextMaximumSize) + { + // RFC3280 limits these strings to 200 chars + // truncate the string + text = text.Substring(0, DisplayTextMaximumSize); + } + + contentType = type; + switch (type) + { + case ContentTypeIA5String: + contents = (IAsn1String)new DerIA5String (text); + break; + case ContentTypeUtf8String: + contents = (IAsn1String)new DerUtf8String(text); + break; + case ContentTypeVisibleString: + contents = (IAsn1String)new DerVisibleString(text); + break; + case ContentTypeBmpString: + contents = (IAsn1String)new DerBmpString(text); + break; + default: + contents = (IAsn1String)new DerUtf8String(text); + break; + } + } + +// /** +// * return true if the passed in string can be represented without +// * loss as a PrintableString, false otherwise. +// */ +// private bool CanBePrintable( +// string str) +// { +// for (int i = str.Length - 1; i >= 0; i--) +// { +// if (str[i] > 0x007f) +// { +// return false; +// } +// } +// +// return true; +// } + + /** + * Creates a new DisplayText 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 > DisplayTextMaximumSize) + { + text = text.Substring(0, DisplayTextMaximumSize); + } + + contentType = ContentTypeUtf8String; + contents = new DerUtf8String(text); + } + + /** + * Creates a new DisplayText instance. + *

Useful when reading back a DisplayText class + * from it's Asn1Encodable form.

+ * + * @param contents an Asn1Encodable instance. + */ + public DisplayText( + IAsn1String contents) + { + this.contents = contents; + } + + public static DisplayText GetInstance( + object obj) + { + if (obj is IAsn1String) + { + return new DisplayText((IAsn1String) obj); + } + + if (obj is DisplayText) + { + return (DisplayText) obj; + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public override Asn1Object ToAsn1Object() + { + return (Asn1Object) contents; + } + + /** + * Returns the stored string object. + * + * @return the stored text as a string. + */ + public string GetString() + { + return contents.GetString(); + } + } +} diff --git a/crypto/src/asn1/x509/DistributionPoint.cs b/crypto/src/asn1/x509/DistributionPoint.cs new file mode 100644 index 000000000..ad1d3989e --- /dev/null +++ b/crypto/src/asn1/x509/DistributionPoint.cs @@ -0,0 +1,161 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The DistributionPoint object. + *
+     * DistributionPoint ::= Sequence {
+     *      distributionPoint [0] DistributionPointName OPTIONAL,
+     *      reasons           [1] ReasonFlags OPTIONAL,
+     *      cRLIssuer         [2] GeneralNames OPTIONAL
+     * }
+     * 
+ */ + public class DistributionPoint + : Asn1Encodable + { + internal readonly DistributionPointName distributionPoint; + internal readonly ReasonFlags reasons; + internal readonly GeneralNames cRLIssuer; + + public static DistributionPoint GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static DistributionPoint GetInstance( + object obj) + { + if(obj == null || obj is DistributionPoint) + { + return (DistributionPoint) obj; + } + + if(obj is Asn1Sequence) + { + return new DistributionPoint((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid DistributionPoint: " + obj.GetType().Name); + } + + private DistributionPoint( + Asn1Sequence seq) + { + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject t = Asn1TaggedObject.GetInstance(seq[i]); + + switch (t.TagNo) + { + 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); + break; + } + } + } + + public DistributionPoint( + DistributionPointName distributionPointName, + ReasonFlags reasons, + GeneralNames crlIssuer) + { + this.distributionPoint = distributionPointName; + this.reasons = reasons; + this.cRLIssuer = crlIssuer; + } + + public DistributionPointName DistributionPointName + { + get { return distributionPoint; } + } + + public ReasonFlags Reasons + { + get { return reasons; } + } + + public GeneralNames CrlIssuer + { + get { return cRLIssuer; } + } + + public override Asn1Object ToAsn1Object() + { + 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 override string ToString() + { + string sep = Platform.NewLine; + StringBuilder buf = new StringBuilder(); + 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( + StringBuilder buf, + string sep, + string name, + string val) + { + string indent = " "; + + buf.Append(indent); + buf.Append(name); + buf.Append(":"); + buf.Append(sep); + buf.Append(indent); + buf.Append(indent); + buf.Append(val); + buf.Append(sep); + } + } +} diff --git a/crypto/src/asn1/x509/DistributionPointName.cs b/crypto/src/asn1/x509/DistributionPointName.cs new file mode 100644 index 000000000..1a9d24241 --- /dev/null +++ b/crypto/src/asn1/x509/DistributionPointName.cs @@ -0,0 +1,130 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The DistributionPointName object. + *
+     * DistributionPointName ::= CHOICE {
+     *     fullName                 [0] GeneralNames,
+     *     nameRelativeToCRLIssuer  [1] RDN
+     * }
+     * 
+ */ + public class DistributionPointName + : Asn1Encodable, IAsn1Choice + { + internal readonly Asn1Encodable name; + internal readonly int type; + + public const int FullName = 0; + public const int NameRelativeToCrlIssuer = 1; + + public static DistributionPointName GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1TaggedObject.GetInstance(obj, true)); + } + + public static DistributionPointName GetInstance( + object obj) + { + if (obj == null || obj is DistributionPointName) + { + return (DistributionPointName) obj; + } + + if (obj is Asn1TaggedObject) + { + return new DistributionPointName((Asn1TaggedObject) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public DistributionPointName( + int type, + Asn1Encodable name) + { + this.type = type; + this.name = name; + } + + public DistributionPointName( + GeneralNames name) + : this(FullName, name) + { + } + + public int PointType + { + get { return type; } + } + + public Asn1Encodable Name + { + get { return name; } + } + + public DistributionPointName( + Asn1TaggedObject obj) + { + this.type = obj.TagNo; + + if (type == FullName) + { + this.name = GeneralNames.GetInstance(obj, false); + } + else + { + this.name = Asn1Set.GetInstance(obj, false); + } + } + + public override Asn1Object ToAsn1Object() + { + return new DerTaggedObject(false, type, name); + } + + public override string ToString() + { + string sep = Platform.NewLine; + StringBuilder buf = new StringBuilder(); + buf.Append("DistributionPointName: ["); + buf.Append(sep); + if (type == FullName) + { + appendObject(buf, sep, "fullName", name.ToString()); + } + else + { + appendObject(buf, sep, "nameRelativeToCRLIssuer", name.ToString()); + } + buf.Append("]"); + buf.Append(sep); + return buf.ToString(); + } + + private void appendObject( + StringBuilder buf, + string sep, + string name, + string val) + { + string indent = " "; + + buf.Append(indent); + buf.Append(name); + buf.Append(":"); + buf.Append(sep); + buf.Append(indent); + buf.Append(indent); + buf.Append(val); + buf.Append(sep); + } + } +} diff --git a/crypto/src/asn1/x509/ExtendedKeyUsage.cs b/crypto/src/asn1/x509/ExtendedKeyUsage.cs new file mode 100644 index 000000000..b5e4b7f8d --- /dev/null +++ b/crypto/src/asn1/x509/ExtendedKeyUsage.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The extendedKeyUsage object. + *
+     *      extendedKeyUsage ::= Sequence SIZE (1..MAX) OF KeyPurposeId
+     * 
+ */ + public class ExtendedKeyUsage + : Asn1Encodable + { + internal readonly IDictionary usageTable = Platform.CreateHashtable(); + internal readonly Asn1Sequence seq; + + public static ExtendedKeyUsage GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static ExtendedKeyUsage GetInstance( + object obj) + { + if (obj is ExtendedKeyUsage) + { + return (ExtendedKeyUsage) obj; + } + + if (obj is Asn1Sequence) + { + return new ExtendedKeyUsage((Asn1Sequence) obj); + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + throw new ArgumentException("Invalid ExtendedKeyUsage: " + obj.GetType().Name); + } + + private ExtendedKeyUsage( + Asn1Sequence seq) + { + this.seq = seq; + + foreach (object o in seq) + { + if (!(o is DerObjectIdentifier)) + throw new ArgumentException("Only DerObjectIdentifier instances allowed in ExtendedKeyUsage."); + + this.usageTable.Add(o, o); + } + } + + public ExtendedKeyUsage( + params KeyPurposeID[] usages) + { + this.seq = new DerSequence(usages); + + foreach (KeyPurposeID usage in usages) + { + this.usageTable.Add(usage, usage); + } + } + +#if !SILVERLIGHT + [Obsolete] + public ExtendedKeyUsage( + ArrayList usages) + : this((IEnumerable)usages) + { + } +#endif + + public ExtendedKeyUsage( + IEnumerable usages) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + foreach (Asn1Object o in usages) + { + v.Add(o); + + this.usageTable.Add(o, o); + } + + this.seq = new DerSequence(v); + } + + public bool HasKeyPurposeId( + KeyPurposeID keyPurposeId) + { + return usageTable[keyPurposeId] != null; + } + +#if !SILVERLIGHT + [Obsolete("Use 'GetAllUsages'")] + public ArrayList GetUsages() + { + return new ArrayList(usageTable.Values); + } +#endif + + /** + * Returns all extended key usages. + * The returned ArrayList contains DerObjectIdentifier instances. + * @return An ArrayList with all key purposes. + */ + public IList GetAllUsages() + { + return Platform.CreateArrayList(usageTable.Values); + } + + public int Count + { + get { return usageTable.Count; } + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/x509/GeneralName.cs b/crypto/src/asn1/x509/GeneralName.cs new file mode 100644 index 000000000..710ddc922 --- /dev/null +++ b/crypto/src/asn1/x509/GeneralName.cs @@ -0,0 +1,418 @@ +using System; +using System.Collections; +using System.Globalization; +using System.IO; +using System.Text; + +using NetUtils = Org.BouncyCastle.Utilities.Net; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The GeneralName object. + *
+     * 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 }
+     * 
+ */ + public class GeneralName + : Asn1Encodable, IAsn1Choice + { + public const int OtherName = 0; + public const int Rfc822Name = 1; + public const int DnsName = 2; + public const int X400Address = 3; + public const int DirectoryName = 4; + public const int EdiPartyName = 5; + public const int UniformResourceIdentifier = 6; + public const int IPAddress = 7; + public const int RegisteredID = 8; + + internal readonly Asn1Encodable obj; + internal readonly int tag; + + public GeneralName( + X509Name directoryName) + { + this.obj = directoryName; + 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( + Asn1Object name, + int tag) + { + this.obj = name; + this.tag = tag; + } + + public GeneralName( + int tag, + Asn1Encodable name) + { + this.obj = name; + this.tag = tag; + } + + /** + * Create a GeneralName for the given tag from the passed in string. + *

+ * This constructor can handle: + *

    + *
  • rfc822Name
  • + *
  • iPAddress
  • + *
  • directoryName
  • + *
  • dNSName
  • + *
  • uniformResourceIdentifier
  • + *
  • registeredID
  • + *
+ * For x400Address, otherName and ediPartyName there is no common string + * format defined. + *

+ * 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 ArgumentException 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 DerObjectIdentifier(name); + } + else if (tag == DirectoryName) + { + this.obj = new X509Name(name); + } + else if (tag == IPAddress) + { + byte[] enc = toGeneralNameEncoding(name); + if (enc == null) + throw new ArgumentException("IP Address is invalid", "name"); + + this.obj = new DerOctetString(enc); + } + else + { + throw new ArgumentException("can't process string for tag: " + tag, "tag"); + } + } + + public static GeneralName GetInstance( + object obj) + { + if (obj == null || obj is GeneralName) + { + return (GeneralName) obj; + } + + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tagObj = (Asn1TaggedObject) obj; + int tag = tagObj.TagNo; + + 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 ArgumentException("unknown tag: " + tag); + case DirectoryName: + return new GeneralName(tag, X509Name.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, DerObjectIdentifier.GetInstance(tagObj, false)); + } + } + + if (obj is byte[]) + { + try + { + return GetInstance(Asn1Object.FromByteArray((byte[])obj)); + } + catch (IOException) + { + throw new ArgumentException("unable to parse encoded general name"); + } + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public static GeneralName GetInstance( + Asn1TaggedObject tagObj, + bool explicitly) + { + return GetInstance(Asn1TaggedObject.GetInstance(tagObj, true)); + } + + public int TagNo + { + get { return tag; } + } + + public Asn1Encodable Name + { + get { return obj; } + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + buf.Append(tag); + buf.Append(": "); + + switch (tag) + { + case Rfc822Name: + case DnsName: + case UniformResourceIdentifier: + buf.Append(DerIA5String.GetInstance(obj).GetString()); + break; + case DirectoryName: + buf.Append(X509Name.GetInstance(obj).ToString()); + break; + default: + buf.Append(obj.ToString()); + break; + } + + return buf.ToString(); + } + + private byte[] toGeneralNameEncoding( + string ip) + { + if (NetUtils.IPAddress.IsValidIPv6WithNetmask(ip) || NetUtils.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 (NetUtils.IPAddress.IsValidIPv4WithNetmask(ip) || NetUtils.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 = Int32.Parse(mask); + + for (int i = 0; i != maskVal; i++) + { + addr[(i / 8) + offset] |= (byte)(1 << (i % 8)); + } + } + + private void parseIPv4(string ip, byte[] addr, int offset) + { + foreach (string token in ip.Split('.', '/')) + { + addr[offset++] = (byte)Int32.Parse(token); + } + } + + private int[] parseMask(string mask) + { + int[] res = new int[8]; + int maskVal = Int32.Parse(mask); + + for (int i = 0; i != maskVal; i++) + { + res[i / 16] |= 1 << (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) + { + if (ip.StartsWith("::")) + { + ip = ip.Substring(1); + } + else if (ip.EndsWith("::")) + { + ip = ip.Substring(0, ip.Length - 1); + } + + IEnumerator sEnum = ip.Split(':').GetEnumerator(); + + int index = 0; + int[] val = new int[8]; + + int doubleColon = -1; + + while (sEnum.MoveNext()) + { + string e = (string) sEnum.Current; + + if (e.Length == 0) + { + doubleColon = index; + val[index++] = 0; + } + else + { + if (e.IndexOf('.') < 0) + { + val[index++] = Int32.Parse(e, NumberStyles.AllowHexSpecifier); + } + else + { + string[] tokens = e.Split('.'); + + val[index++] = (Int32.Parse(tokens[0]) << 8) | Int32.Parse(tokens[1]); + val[index++] = (Int32.Parse(tokens[2]) << 8) | Int32.Parse(tokens[3]); + } + } + } + + if (index != val.Length) + { + Array.Copy(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 override Asn1Object ToAsn1Object() + { + // Explicitly tagged if DirectoryName + return new DerTaggedObject(tag == DirectoryName, tag, obj); + } + } +} diff --git a/crypto/src/asn1/x509/GeneralNames.cs b/crypto/src/asn1/x509/GeneralNames.cs new file mode 100644 index 000000000..6c5c8e690 --- /dev/null +++ b/crypto/src/asn1/x509/GeneralNames.cs @@ -0,0 +1,95 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class GeneralNames + : Asn1Encodable + { + private readonly GeneralName[] names; + + public static GeneralNames GetInstance( + object obj) + { + if (obj == null || obj is GeneralNames) + { + return (GeneralNames) obj; + } + + if (obj is Asn1Sequence) + { + return new GeneralNames((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static GeneralNames GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + /// Construct a GeneralNames object containing one GeneralName. + /// The name to be contained. + public GeneralNames( + GeneralName name) + { + names = new GeneralName[]{ name }; + } + + public GeneralNames( + GeneralName[] names) + { + this.names = (GeneralName[])names.Clone(); + } + + private GeneralNames( + Asn1Sequence seq) + { + this.names = new GeneralName[seq.Count]; + + for (int i = 0; i != seq.Count; i++) + { + names[i] = GeneralName.GetInstance(seq[i]); + } + } + + public GeneralName[] GetNames() + { + return (GeneralName[]) names.Clone(); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 * GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(names); + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string sep = Platform.NewLine; + + buf.Append("GeneralNames:"); + buf.Append(sep); + + foreach (GeneralName name in names) + { + buf.Append(" "); + buf.Append(name); + buf.Append(sep); + } + + return buf.ToString(); + } + } +} diff --git a/crypto/src/asn1/x509/GeneralSubtree.cs b/crypto/src/asn1/x509/GeneralSubtree.cs new file mode 100644 index 000000000..e918a0277 --- /dev/null +++ b/crypto/src/asn1/x509/GeneralSubtree.cs @@ -0,0 +1,189 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Class for containing a restriction object subtrees in NameConstraints. See + * RFC 3280. + * + *
+	 *
+	 *       GeneralSubtree ::= SEQUENCE
+	 *       {
+	 *         baseName                    GeneralName,
+	 *         minimum         [0]     BaseDistance DEFAULT 0,
+	 *         maximum         [1]     BaseDistance OPTIONAL
+	 *       }
+	 * 
+ * + * @see org.bouncycastle.asn1.x509.NameConstraints + * + */ + public class GeneralSubtree + : Asn1Encodable + { + private readonly GeneralName baseName; + private readonly DerInteger minimum; + private readonly DerInteger maximum; + + private GeneralSubtree( + Asn1Sequence seq) + { + baseName = GeneralName.GetInstance(seq[0]); + + switch (seq.Count) + { + case 1: + break; + case 2: + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[1]); + switch (o.TagNo) + { + case 0: + minimum = DerInteger.GetInstance(o, false); + break; + case 1: + maximum = DerInteger.GetInstance(o, false); + break; + default: + throw new ArgumentException("Bad tag number: " + o.TagNo); + } + break; + } + case 3: + { + { + Asn1TaggedObject oMin = Asn1TaggedObject.GetInstance(seq[1]); + if (oMin.TagNo != 0) + throw new ArgumentException("Bad tag number for 'minimum': " + oMin.TagNo); + minimum = DerInteger.GetInstance(oMin, false); + } + + { + Asn1TaggedObject oMax = Asn1TaggedObject.GetInstance(seq[2]); + if (oMax.TagNo != 1) + throw new ArgumentException("Bad tag number for 'maximum': " + oMax.TagNo); + maximum = DerInteger.GetInstance(oMax, false); + } + + break; + } + default: + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + } + + /** + * 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. + *

+ * If minimum is null, zero is assumed, if + * maximum is null, maximum is absent.

+ * + * @param baseName + * A restriction. + * @param minimum + * Minimum + * + * @param maximum + * Maximum + */ + public GeneralSubtree( + GeneralName baseName, + BigInteger minimum, + BigInteger maximum) + { + this.baseName = baseName; + if (minimum != null) + { + this.minimum = new DerInteger(minimum); + } + if (maximum != null) + { + this.maximum = new DerInteger(maximum); + } + } + + public GeneralSubtree( + GeneralName baseName) + : this(baseName, null, null) + { + } + + public static GeneralSubtree GetInstance( + Asn1TaggedObject o, + bool isExplicit) + { + return new GeneralSubtree(Asn1Sequence.GetInstance(o, isExplicit)); + } + + public static GeneralSubtree GetInstance( + object obj) + { + if (obj == null) + { + return null; + } + + if (obj is GeneralSubtree) + { + return (GeneralSubtree) obj; + } + + return new GeneralSubtree(Asn1Sequence.GetInstance(obj)); + } + + public GeneralName Base + { + get { return baseName; } + } + + public BigInteger Minimum + { + get { return minimum == null ? BigInteger.Zero : minimum.Value; } + } + + public BigInteger Maximum + { + get { return maximum == null ? null : maximum.Value; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + * + * Returns: + * + *
+		 *       GeneralSubtree ::= SEQUENCE
+		 *       {
+		 *         baseName                    GeneralName,
+		 *         minimum         [0]     BaseDistance DEFAULT 0,
+		 *         maximum         [1]     BaseDistance OPTIONAL
+		 *       }
+		 * 
+ * + * @return a DERObject + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(baseName); + + if (minimum != null && minimum.Value.SignValue != 0) + { + v.Add(new DerTaggedObject(false, 0, minimum)); + } + + if (maximum != null) + { + v.Add(new DerTaggedObject(false, 1, maximum)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/Holder.cs b/crypto/src/asn1/x509/Holder.cs new file mode 100644 index 000000000..d04f1cb60 --- /dev/null +++ b/crypto/src/asn1/x509/Holder.cs @@ -0,0 +1,257 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The Holder object. + *

+ * For an v2 attribute certificate this is: + * + *

+	 *            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
+	 *            }
+	 * 
+ *

+ *

+ * For an v1 attribute certificate this is: + * + *

+	 *         subject CHOICE {
+	 *          baseCertificateID [0] IssuerSerial,
+	 *          -- associated with a Public Key Certificate
+	 *          subjectName [1] GeneralNames },
+	 *          -- associated with a name
+	 * 
+ *

+ */ + public class Holder + : Asn1Encodable + { + internal readonly IssuerSerial baseCertificateID; + internal readonly GeneralNames entityName; + internal readonly ObjectDigestInfo objectDigestInfo; + private readonly int version; + + public static Holder GetInstance( + object obj) + { + if (obj is Holder) + { + return (Holder) obj; + } + + if (obj is Asn1Sequence) + { + return new Holder((Asn1Sequence) obj); + } + + if (obj is Asn1TaggedObject) + { + return new Holder((Asn1TaggedObject) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor for a holder for an v1 attribute certificate. + * + * @param tagObj The ASN.1 tagged holder object. + */ + public Holder( + Asn1TaggedObject tagObj) + { + switch (tagObj.TagNo) + { + case 0: + baseCertificateID = IssuerSerial.GetInstance(tagObj, false); + break; + case 1: + entityName = GeneralNames.GetInstance(tagObj, false); + break; + default: + throw new ArgumentException("unknown tag in Holder"); + } + + this.version = 0; + } + + /** + * Constructor for a holder for an v2 attribute certificate. * + * + * @param seq The ASN.1 sequence. + */ + private Holder( + Asn1Sequence seq) + { + if (seq.Count > 3) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[i]); + + switch (tObj.TagNo) + { + 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 ArgumentException("unknown tag in Holder"); + } + } + + this.version = 1; + } + + public Holder( + IssuerSerial baseCertificateID) + : this(baseCertificateID, 1) + { + } + + /** + * Constructs a holder from a IssuerSerial. + * @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 Version + { + get { return version; } + } + + /** + * 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. + */ + public Holder( + GeneralNames entityName) + : this(entityName, 1) + { + } + + /** + * 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; + this.version = 1; + } + + public IssuerSerial BaseCertificateID + { + get { 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 EntityName + { + get { return entityName; } + } + + public ObjectDigestInfo ObjectDigestInfo + { + get { return objectDigestInfo; } + } + + /** + * The Holder object. + *
+         *  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
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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); + } + + if (entityName != null) + { + return new DerTaggedObject(false, 1, entityName); + } + + return new DerTaggedObject(false, 0, baseCertificateID); + } + } +} diff --git a/crypto/src/asn1/x509/IetfAttrSyntax.cs b/crypto/src/asn1/x509/IetfAttrSyntax.cs new file mode 100644 index 000000000..e719865b3 --- /dev/null +++ b/crypto/src/asn1/x509/IetfAttrSyntax.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Implementation of IetfAttrSyntax as specified by RFC3281. + */ + public class IetfAttrSyntax + : Asn1Encodable + { + public const int ValueOctets = 1; + public const int ValueOid = 2; + public const int ValueUtf8 = 3; + + internal readonly GeneralNames policyAuthority; + internal readonly Asn1EncodableVector values = new Asn1EncodableVector(); + + internal int valueChoice = -1; + + /** + * + */ + public IetfAttrSyntax( + Asn1Sequence seq) + { + int i = 0; + + if (seq[0] is Asn1TaggedObject) + { + policyAuthority = GeneralNames.GetInstance(((Asn1TaggedObject)seq[0]), false); + i++; + } + else if (seq.Count == 2) + { // VOMS fix + policyAuthority = GeneralNames.GetInstance(seq[0]); + i++; + } + + if (!(seq[i] is Asn1Sequence)) + { + throw new ArgumentException("Non-IetfAttrSyntax encoding"); + } + + seq = (Asn1Sequence) seq[i]; + + foreach (Asn1Object obj in seq) + { + int type; + + if (obj is DerObjectIdentifier) + { + type = ValueOid; + } + else if (obj is DerUtf8String) + { + type = ValueUtf8; + } + else if (obj is DerOctetString) + { + type = ValueOctets; + } + else + { + throw new ArgumentException("Bad value type encoding IetfAttrSyntax"); + } + + if (valueChoice < 0) + { + valueChoice = type; + } + + if (type != valueChoice) + { + throw new ArgumentException("Mix of value types in IetfAttrSyntax"); + } + + values.Add(obj); + } + } + + public GeneralNames PolicyAuthority + { + get { return policyAuthority; } + } + + public int ValueType + { + get { return valueChoice; } + } + + public object[] GetValues() + { + if (this.ValueType == ValueOctets) + { + Asn1OctetString[] tmp = new Asn1OctetString[values.Count]; + + for (int i = 0; i != tmp.Length; i++) + { + tmp[i] = (Asn1OctetString) values[i]; + } + + return tmp; + } + + if (this.ValueType == ValueOid) + { + DerObjectIdentifier[] tmp = new DerObjectIdentifier[values.Count]; + + for (int i = 0; i != tmp.Length; i++) + { + tmp[i] = (DerObjectIdentifier) values[i]; + } + + return tmp; + } + + { + DerUtf8String[] tmp = new DerUtf8String[values.Count]; + + for (int i = 0; i != tmp.Length; i++) + { + tmp[i] = (DerUtf8String) values[i]; + } + + return tmp; + } + } + + /** + * + *
+         *
+         *  IetfAttrSyntax ::= Sequence {
+         *    policyAuthority [0] GeneralNames OPTIONAL,
+         *    values Sequence OF CHOICE {
+         *      octets OCTET STRING,
+         *      oid OBJECT IDENTIFIER,
+         *      string UTF8String
+         *    }
+         *  }
+         *
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (policyAuthority != null) + { + v.Add(new DerTaggedObject(0, policyAuthority)); + } + + v.Add(new DerSequence(values)); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/IssuerSerial.cs b/crypto/src/asn1/x509/IssuerSerial.cs new file mode 100644 index 000000000..6a24e7333 --- /dev/null +++ b/crypto/src/asn1/x509/IssuerSerial.cs @@ -0,0 +1,98 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class IssuerSerial + : Asn1Encodable + { + internal readonly GeneralNames issuer; + internal readonly DerInteger serial; + internal readonly DerBitString issuerUid; + + public static IssuerSerial GetInstance( + object obj) + { + if (obj == null || obj is IssuerSerial) + { + return (IssuerSerial) obj; + } + + if (obj is Asn1Sequence) + { + return new IssuerSerial((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static IssuerSerial GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + private IssuerSerial( + Asn1Sequence seq) + { + if (seq.Count != 2 && seq.Count != 3) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + issuer = GeneralNames.GetInstance(seq[0]); + serial = DerInteger.GetInstance(seq[1]); + + if (seq.Count == 3) + { + issuerUid = DerBitString.GetInstance(seq[2]); + } + } + + public IssuerSerial( + GeneralNames issuer, + DerInteger serial) + { + this.issuer = issuer; + this.serial = serial; + } + + public GeneralNames Issuer + { + get { return issuer; } + } + + public DerInteger Serial + { + get { return serial; } + } + + public DerBitString IssuerUid + { + get { return issuerUid; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  IssuerSerial  ::=  Sequence {
+         *       issuer         GeneralNames,
+         *       serial         CertificateSerialNumber,
+         *       issuerUid      UniqueIdentifier OPTIONAL
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + issuer, serial); + + if (issuerUid != null) + { + v.Add(issuerUid); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/IssuingDistributionPoint.cs b/crypto/src/asn1/x509/IssuingDistributionPoint.cs new file mode 100644 index 000000000..3af0d565f --- /dev/null +++ b/crypto/src/asn1/x509/IssuingDistributionPoint.cs @@ -0,0 +1,247 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + *
+	 * 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 }
+	 * 
+ */ + public class IssuingDistributionPoint + : Asn1Encodable + { + private readonly DistributionPointName _distributionPoint; + private readonly bool _onlyContainsUserCerts; + private readonly bool _onlyContainsCACerts; + private readonly ReasonFlags _onlySomeReasons; + private readonly bool _indirectCRL; + private readonly bool _onlyContainsAttributeCerts; + + private readonly Asn1Sequence seq; + + public static IssuingDistributionPoint GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static IssuingDistributionPoint GetInstance( + object obj) + { + if (obj == null || obj is IssuingDistributionPoint) + { + return (IssuingDistributionPoint) obj; + } + + if (obj is Asn1Sequence) + { + return new IssuingDistributionPoint((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * 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 true then the CRL contains revocation + * information about certificates ssued by other CAs. + * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates. + */ + public IssuingDistributionPoint( + DistributionPointName distributionPoint, + bool onlyContainsUserCerts, + bool onlyContainsCACerts, + ReasonFlags onlySomeReasons, + bool indirectCRL, + bool 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, DerBoolean.True)); + } + if (onlyContainsCACerts) + { + vec.Add(new DerTaggedObject(false, 2, DerBoolean.True)); + } + if (onlySomeReasons != null) + { + vec.Add(new DerTaggedObject(false, 3, onlySomeReasons)); + } + if (indirectCRL) + { + vec.Add(new DerTaggedObject(false, 4, DerBoolean.True)); + } + if (onlyContainsAttributeCerts) + { + vec.Add(new DerTaggedObject(false, 5, DerBoolean.True)); + } + + seq = new DerSequence(vec); + } + + /** + * Constructor from Asn1Sequence + */ + private IssuingDistributionPoint( + Asn1Sequence seq) + { + this.seq = seq; + + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]); + + switch (o.TagNo) + { + case 0: + // CHOICE so explicit + _distributionPoint = DistributionPointName.GetInstance(o, true); + break; + case 1: + _onlyContainsUserCerts = DerBoolean.GetInstance(o, false).IsTrue; + break; + case 2: + _onlyContainsCACerts = DerBoolean.GetInstance(o, false).IsTrue; + break; + case 3: + _onlySomeReasons = new ReasonFlags(ReasonFlags.GetInstance(o, false)); + break; + case 4: + _indirectCRL = DerBoolean.GetInstance(o, false).IsTrue; + break; + case 5: + _onlyContainsAttributeCerts = DerBoolean.GetInstance(o, false).IsTrue; + break; + default: + throw new ArgumentException("unknown tag in IssuingDistributionPoint"); + } + } + } + + public bool OnlyContainsUserCerts + { + get { return _onlyContainsUserCerts; } + } + + public bool OnlyContainsCACerts + { + get { return _onlyContainsCACerts; } + } + + public bool IsIndirectCrl + { + get { return _indirectCRL; } + } + + public bool OnlyContainsAttributeCerts + { + get { return _onlyContainsAttributeCerts; } + } + + /** + * @return Returns the distributionPoint. + */ + public DistributionPointName DistributionPoint + { + get { return _distributionPoint; } + } + + /** + * @return Returns the onlySomeReasons. + */ + public ReasonFlags OnlySomeReasons + { + get { return _onlySomeReasons; } + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + + public override string ToString() + { + string sep = Platform.NewLine; + StringBuilder buf = new StringBuilder(); + + buf.Append("IssuingDistributionPoint: ["); + buf.Append(sep); + if (_distributionPoint != null) + { + appendObject(buf, sep, "distributionPoint", _distributionPoint.ToString()); + } + if (_onlyContainsUserCerts) + { + appendObject(buf, sep, "onlyContainsUserCerts", _onlyContainsUserCerts.ToString()); + } + if (_onlyContainsCACerts) + { + appendObject(buf, sep, "onlyContainsCACerts", _onlyContainsCACerts.ToString()); + } + if (_onlySomeReasons != null) + { + appendObject(buf, sep, "onlySomeReasons", _onlySomeReasons.ToString()); + } + if (_onlyContainsAttributeCerts) + { + appendObject(buf, sep, "onlyContainsAttributeCerts", _onlyContainsAttributeCerts.ToString()); + } + if (_indirectCRL) + { + appendObject(buf, sep, "indirectCRL", _indirectCRL.ToString()); + } + buf.Append("]"); + buf.Append(sep); + return buf.ToString(); + } + + private void appendObject( + StringBuilder buf, + string sep, + string name, + string val) + { + string indent = " "; + + buf.Append(indent); + buf.Append(name); + buf.Append(":"); + buf.Append(sep); + buf.Append(indent); + buf.Append(indent); + buf.Append(val); + buf.Append(sep); + } + } +} diff --git a/crypto/src/asn1/x509/KeyPurposeId.cs b/crypto/src/asn1/x509/KeyPurposeId.cs new file mode 100644 index 000000000..4b48a9b51 --- /dev/null +++ b/crypto/src/asn1/x509/KeyPurposeId.cs @@ -0,0 +1,36 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The KeyPurposeID object. + *
+     *     KeyPurposeID ::= OBJECT IDENTIFIER
+     * 
+ */ + public sealed class KeyPurposeID + : DerObjectIdentifier + { + private const string IdKP = "1.3.6.1.5.5.7.3"; + + private KeyPurposeID( + string id) + : base(id) + { + } + + public static readonly KeyPurposeID AnyExtendedKeyUsage = new KeyPurposeID(X509Extensions.ExtendedKeyUsage.Id + ".0"); + public static readonly KeyPurposeID IdKPServerAuth = new KeyPurposeID(IdKP + ".1"); + public static readonly KeyPurposeID IdKPClientAuth = new KeyPurposeID(IdKP + ".2"); + public static readonly KeyPurposeID IdKPCodeSigning = new KeyPurposeID(IdKP + ".3"); + public static readonly KeyPurposeID IdKPEmailProtection = new KeyPurposeID(IdKP + ".4"); + public static readonly KeyPurposeID IdKPIpsecEndSystem = new KeyPurposeID(IdKP + ".5"); + public static readonly KeyPurposeID IdKPIpsecTunnel = new KeyPurposeID(IdKP + ".6"); + public static readonly KeyPurposeID IdKPIpsecUser = new KeyPurposeID(IdKP + ".7"); + public static readonly KeyPurposeID IdKPTimeStamping = new KeyPurposeID(IdKP + ".8"); + public static readonly KeyPurposeID IdKPOcspSigning = new KeyPurposeID(IdKP + ".9"); + + // + // microsoft key purpose ids + // + public static readonly KeyPurposeID IdKPSmartCardLogon = new KeyPurposeID("1.3.6.1.4.1.311.20.2.2"); + } +} diff --git a/crypto/src/asn1/x509/KeyUsage.cs b/crypto/src/asn1/x509/KeyUsage.cs new file mode 100644 index 000000000..fef04e8b9 --- /dev/null +++ b/crypto/src/asn1/x509/KeyUsage.cs @@ -0,0 +1,79 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The KeyUsage object. + *
+     *    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) }
+     * 
+ */ + public class KeyUsage + : DerBitString + { + public const int DigitalSignature = (1 << 7); + public const int NonRepudiation = (1 << 6); + public const int KeyEncipherment = (1 << 5); + public const int DataEncipherment = (1 << 4); + public const int KeyAgreement = (1 << 3); + public const int KeyCertSign = (1 << 2); + public const int CrlSign = (1 << 1); + public const int EncipherOnly = (1 << 0); + public const int DecipherOnly = (1 << 15); + + public static new KeyUsage GetInstance( + object obj) + { + if (obj is KeyUsage) + { + return (KeyUsage)obj; + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + return new KeyUsage(DerBitString.GetInstance(obj)); + } + + /** + * 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) + : base(GetBytes(usage), GetPadBits(usage)) + { + } + + private KeyUsage( + DerBitString usage) + : base(usage.GetBytes(), usage.PadBits) + { + } + + public override string ToString() + { + byte[] data = GetBytes(); + if (data.Length == 1) + { + return "KeyUsage: 0x" + (data[0] & 0xff).ToString("X"); + } + + return "KeyUsage: 0x" + ((data[1] & 0xff) << 8 | (data[0] & 0xff)).ToString("X"); + } + } +} diff --git a/crypto/src/asn1/x509/NameConstraints.cs b/crypto/src/asn1/x509/NameConstraints.cs new file mode 100644 index 000000000..8374ff60a --- /dev/null +++ b/crypto/src/asn1/x509/NameConstraints.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class NameConstraints + : Asn1Encodable + { + private Asn1Sequence permitted, excluded; + + public static NameConstraints GetInstance( + object obj) + { + if (obj == null || obj is NameConstraints) + { + return (NameConstraints) obj; + } + + if (obj is Asn1Sequence) + { + return new NameConstraints((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public NameConstraints( + Asn1Sequence seq) + { + foreach (Asn1TaggedObject o in seq) + { + switch (o.TagNo) + { + case 0: + permitted = Asn1Sequence.GetInstance(o, false); + break; + case 1: + excluded = Asn1Sequence.GetInstance(o, false); + break; + } + } + } + +#if !SILVERLIGHT + public NameConstraints( + ArrayList permitted, + ArrayList excluded) + : this((IList)permitted, (IList)excluded) + { + } +#endif + + /** + * Constructor from a given details. + * + *

permitted and excluded are Vectors of GeneralSubtree objects.

+ * + * @param permitted Permitted subtrees + * @param excluded Excluded subtrees + */ + public NameConstraints( + IList permitted, + IList excluded) + { + if (permitted != null) + { + this.permitted = CreateSequence(permitted); + } + + if (excluded != null) + { + this.excluded = CreateSequence(excluded); + } + } + + private DerSequence CreateSequence( + IList subtrees) + { + GeneralSubtree[] gsts = new GeneralSubtree[subtrees.Count]; + for (int i = 0; i < subtrees.Count; ++i) + { + gsts[i] = (GeneralSubtree)subtrees[i]; + } + return new DerSequence(gsts); + } + + public Asn1Sequence PermittedSubtrees + { + get { return permitted; } + } + + public Asn1Sequence ExcludedSubtrees + { + get { return excluded; } + } + + /* + * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees + * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL } + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (permitted != null) + { + v.Add(new DerTaggedObject(false, 0, permitted)); + } + + if (excluded != null) + { + v.Add(new DerTaggedObject(false, 1, excluded)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/NoticeReference.cs b/crypto/src/asn1/x509/NoticeReference.cs new file mode 100644 index 000000000..86a51c5b7 --- /dev/null +++ b/crypto/src/asn1/x509/NoticeReference.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * NoticeReference class, used in + * CertificatePolicies X509 V3 extensions + * (in policy qualifiers). + * + *
+	 *  NoticeReference ::= Sequence {
+	 *      organization     DisplayText,
+	 *      noticeNumbers    Sequence OF Integer }
+	 *
+	 * 
+ * + * @see PolicyQualifierInfo + * @see PolicyInformation + */ + public class NoticeReference + : Asn1Encodable + { + internal readonly DisplayText organization; + internal readonly Asn1Sequence noticeNumbers; + +#if !SILVERLIGHT + [Obsolete] + public NoticeReference( + string orgName, + ArrayList numbers) + : this(orgName, (IList)numbers) + { + } +#endif + + /** + * Creates a new NoticeReference instance. + * + * @param orgName a string value + * @param numbers a ArrayList value + */ + public NoticeReference( + string orgName, + IList numbers) + { + organization = new DisplayText(orgName); + + object o = numbers[0]; + + Asn1EncodableVector av = new Asn1EncodableVector(); + if (o is int) + { + foreach (int nm in numbers) + { + av.Add(new DerInteger(nm)); + } + } + + noticeNumbers = new DerSequence(av); + } + + /** + * Creates a new NoticeReference instance. + * + * @param orgName a string value + * @param numbers an Asn1Sequence value + */ + public NoticeReference( + string orgName, + Asn1Sequence numbers) + { + organization = new DisplayText(orgName); + noticeNumbers = numbers; + } + + /** + * Creates a new NoticeReference instance. + * + * @param displayTextType an int value + * @param orgName a string value + * @param numbers an Asn1Sequence value + */ + public NoticeReference( + int displayTextType, + string orgName, + Asn1Sequence numbers) + { + organization = new DisplayText(displayTextType, orgName); + noticeNumbers = numbers; + } + + /** + * Creates a new NoticeReference instance. + *

Useful for reconstructing a NoticeReference + * instance from its encodable/encoded form.

+ * + * @param as an Asn1Sequence value obtained from either + * calling @{link ToAsn1Object()} for a NoticeReference + * instance or from parsing it from a Der-encoded stream. + */ + private NoticeReference( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + organization = DisplayText.GetInstance(seq[0]); + noticeNumbers = Asn1Sequence.GetInstance(seq[1]); + } + + public static NoticeReference GetInstance( + object obj) + { + if (obj is NoticeReference) + { + return (NoticeReference) obj; + } + + if (obj is Asn1Sequence) + { + return new NoticeReference((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + /** + * Describe ToAsn1Object method here. + * + * @return a Asn1Object value + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(organization, noticeNumbers); + } + } +} diff --git a/crypto/src/asn1/x509/ObjectDigestInfo.cs b/crypto/src/asn1/x509/ObjectDigestInfo.cs new file mode 100644 index 000000000..6d5b9c692 --- /dev/null +++ b/crypto/src/asn1/x509/ObjectDigestInfo.cs @@ -0,0 +1,177 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates. + * + *
+	 *  
+	 *    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
+	 *    }
+	 *   
+	 * 
+ * + */ + public class ObjectDigestInfo + : Asn1Encodable + { + /** + * The public key is hashed. + */ + public const int PublicKey = 0; + + /** + * The public key certificate is hashed. + */ + public const int PublicKeyCert = 1; + + /** + * An other object is hashed. + */ + public const int OtherObjectDigest = 2; + + internal readonly DerEnumerated digestedObjectType; + internal readonly DerObjectIdentifier otherObjectTypeID; + internal readonly AlgorithmIdentifier digestAlgorithm; + internal readonly DerBitString objectDigest; + + public static ObjectDigestInfo GetInstance( + object obj) + { + if (obj == null || obj is ObjectDigestInfo) + { + return (ObjectDigestInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new ObjectDigestInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public static ObjectDigestInfo GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + /** + * Constructor from given details. + *

+ * If digestedObjectType is not {@link #publicKeyCert} or + * {@link #publicKey} otherObjectTypeID must be given, + * otherwise it is ignored.

+ * + * @param digestedObjectType The digest object type. + * @param otherObjectTypeID The object type ID for + * otherObjectDigest. + * @param digestAlgorithm The algorithm identifier for the hash. + * @param objectDigest The hash value. + */ + public ObjectDigestInfo( + int digestedObjectType, + string otherObjectTypeID, + AlgorithmIdentifier digestAlgorithm, + byte[] objectDigest) + { + this.digestedObjectType = new DerEnumerated(digestedObjectType); + + if (digestedObjectType == OtherObjectDigest) + { + this.otherObjectTypeID = new DerObjectIdentifier(otherObjectTypeID); + } + + this.digestAlgorithm = digestAlgorithm; + + this.objectDigest = new DerBitString(objectDigest); + } + + private ObjectDigestInfo( + Asn1Sequence seq) + { + if (seq.Count > 4 || seq.Count < 3) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + digestedObjectType = DerEnumerated.GetInstance(seq[0]); + + int offset = 0; + + if (seq.Count == 4) + { + otherObjectTypeID = DerObjectIdentifier.GetInstance(seq[1]); + offset++; + } + + digestAlgorithm = AlgorithmIdentifier.GetInstance(seq[1 + offset]); + objectDigest = DerBitString.GetInstance(seq[2 + offset]); + } + + public DerEnumerated DigestedObjectType + { + get { return digestedObjectType; } + } + + public DerObjectIdentifier OtherObjectTypeID + { + get { return otherObjectTypeID; } + } + + public AlgorithmIdentifier DigestAlgorithm + { + get { return digestAlgorithm; } + } + + public DerBitString ObjectDigest + { + get { return objectDigest; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + * + *
+		 *  
+		 *    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
+		 *    }
+		 *   
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(digestedObjectType); + + if (otherObjectTypeID != null) + { + v.Add(otherObjectTypeID); + } + + v.Add(digestAlgorithm, objectDigest); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/PolicyInformation.cs b/crypto/src/asn1/x509/PolicyInformation.cs new file mode 100644 index 000000000..29d245084 --- /dev/null +++ b/crypto/src/asn1/x509/PolicyInformation.cs @@ -0,0 +1,80 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class PolicyInformation + : Asn1Encodable + { + private readonly DerObjectIdentifier policyIdentifier; + private readonly Asn1Sequence policyQualifiers; + + private PolicyInformation( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + policyIdentifier = DerObjectIdentifier.GetInstance(seq[0]); + + if (seq.Count > 1) + { + policyQualifiers = Asn1Sequence.GetInstance(seq[1]); + } + } + + public PolicyInformation( + DerObjectIdentifier policyIdentifier) + { + this.policyIdentifier = policyIdentifier; + } + + public PolicyInformation( + DerObjectIdentifier policyIdentifier, + Asn1Sequence policyQualifiers) + { + this.policyIdentifier = policyIdentifier; + this.policyQualifiers = policyQualifiers; + } + + public static PolicyInformation GetInstance( + object obj) + { + if (obj == null || obj is PolicyInformation) + { + return (PolicyInformation) obj; + } + + return new PolicyInformation(Asn1Sequence.GetInstance(obj)); + } + + public DerObjectIdentifier PolicyIdentifier + { + get { return policyIdentifier; } + } + + public Asn1Sequence PolicyQualifiers + { + get { return policyQualifiers; } + } + + /* + * PolicyInformation ::= Sequence { + * policyIdentifier CertPolicyId, + * policyQualifiers Sequence SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(policyIdentifier); + + if (policyQualifiers != null) + { + v.Add(policyQualifiers); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x509/PolicyMappings.cs b/crypto/src/asn1/x509/PolicyMappings.cs new file mode 100644 index 000000000..3ad351107 --- /dev/null +++ b/crypto/src/asn1/x509/PolicyMappings.cs @@ -0,0 +1,70 @@ +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * PolicyMappings V3 extension, described in RFC3280. + *
+	 *    PolicyMappings ::= Sequence SIZE (1..MAX) OF Sequence {
+	 *      issuerDomainPolicy      CertPolicyId,
+	 *      subjectDomainPolicy     CertPolicyId }
+	 * 
+ * + * @see RFC 3280, section 4.2.1.6 + */ + public class PolicyMappings + : Asn1Encodable + { + private readonly Asn1Sequence seq; + + /** + * Creates a new PolicyMappings instance. + * + * @param seq an Asn1Sequence constructed as specified + * in RFC 3280 + */ + public PolicyMappings( + Asn1Sequence seq) + { + this.seq = seq; + } + +#if !SILVERLIGHT + public PolicyMappings( + Hashtable mappings) + : this((IDictionary)mappings) + { + } +#endif + + /** + * Creates a new PolicyMappings instance. + * + * @param mappings a HashMap value that maps + * string oids + * to other string oids. + */ + public PolicyMappings( + IDictionary mappings) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + foreach (string idp in mappings.Keys) + { + string sdp = (string) mappings[idp]; + + v.Add( + new DerSequence( + new DerObjectIdentifier(idp), + new DerObjectIdentifier(sdp))); + } + + seq = new DerSequence(v); + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/x509/PolicyQualifierId.cs b/crypto/src/asn1/x509/PolicyQualifierId.cs new file mode 100644 index 000000000..c858f0864 --- /dev/null +++ b/crypto/src/asn1/x509/PolicyQualifierId.cs @@ -0,0 +1,28 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * PolicyQualifierId, used in the CertificatePolicies + * X509V3 extension. + * + *
+	 *    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 )
+	 * 
+ */ + public sealed class PolicyQualifierID : DerObjectIdentifier + { + private const string IdQt = "1.3.6.1.5.5.7.2"; + + private PolicyQualifierID( + string id) + : base(id) + { + } + + public static readonly PolicyQualifierID IdQtCps = new PolicyQualifierID(IdQt + ".1"); + public static readonly PolicyQualifierID IdQtUnotice = new PolicyQualifierID(IdQt + ".2"); + } +} diff --git a/crypto/src/asn1/x509/PolicyQualifierInfo.cs b/crypto/src/asn1/x509/PolicyQualifierInfo.cs new file mode 100644 index 000000000..f2c617ff6 --- /dev/null +++ b/crypto/src/asn1/x509/PolicyQualifierInfo.cs @@ -0,0 +1,101 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Policy qualifiers, used in the X509V3 CertificatePolicies + * extension. + * + *
+	 *   PolicyQualifierInfo ::= Sequence {
+	 *       policyQualifierId  PolicyQualifierId,
+	 *       qualifier          ANY DEFINED BY policyQualifierId }
+	 * 
+ */ + public class PolicyQualifierInfo + : Asn1Encodable + { + internal readonly DerObjectIdentifier policyQualifierId; + internal readonly Asn1Encodable qualifier; + + /** + * Creates a new PolicyQualifierInfo instance. + * + * @param policyQualifierId a PolicyQualifierId value + * @param qualifier the qualifier, defined by the above field. + */ + public PolicyQualifierInfo( + DerObjectIdentifier policyQualifierId, + Asn1Encodable qualifier) + { + this.policyQualifierId = policyQualifierId; + this.qualifier = qualifier; + } + + /** + * Creates a new PolicyQualifierInfo containing a + * cPSuri qualifier. + * + * @param cps the CPS (certification practice statement) uri as a + * string. + */ + public PolicyQualifierInfo( + string cps) + { + policyQualifierId = PolicyQualifierID.IdQtCps; + qualifier = new DerIA5String(cps); + } + + /** + * Creates a new PolicyQualifierInfo instance. + * + * @param as PolicyQualifierInfo X509 structure + * encoded as an Asn1Sequence. + */ + private PolicyQualifierInfo( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + policyQualifierId = DerObjectIdentifier.GetInstance(seq[0]); + qualifier = seq[1]; + } + + public static PolicyQualifierInfo GetInstance( + object obj) + { + if (obj is PolicyQualifierInfo) + { + return (PolicyQualifierInfo) obj; + } + + if (obj is Asn1Sequence) + { + return new PolicyQualifierInfo((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public virtual DerObjectIdentifier PolicyQualifierId + { + get { return policyQualifierId; } + } + + public virtual Asn1Encodable Qualifier + { + get { return qualifier; } + } + + /** + * Returns a Der-encodable representation of this instance. + * + * @return a Asn1Object value + */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(policyQualifierId, qualifier); + } + } +} diff --git a/crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs b/crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs new file mode 100644 index 000000000..ad2961eb0 --- /dev/null +++ b/crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs @@ -0,0 +1,82 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /// + ///
+	/// PrivateKeyUsagePeriod ::= SEQUENCE
+	/// {
+	/// notBefore       [0]     GeneralizedTime OPTIONAL,
+	/// notAfter        [1]     GeneralizedTime OPTIONAL }
+	/// 
+ ///
+ public class PrivateKeyUsagePeriod + : Asn1Encodable + { + public static PrivateKeyUsagePeriod GetInstance( + object obj) + { + if (obj is PrivateKeyUsagePeriod) + { + return (PrivateKeyUsagePeriod) obj; + } + + if (obj is Asn1Sequence) + { + return new PrivateKeyUsagePeriod((Asn1Sequence) obj); + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + private DerGeneralizedTime _notBefore, _notAfter; + + private PrivateKeyUsagePeriod( + Asn1Sequence seq) + { + foreach (Asn1TaggedObject tObj in seq) + { + if (tObj.TagNo == 0) + { + _notBefore = DerGeneralizedTime.GetInstance(tObj, false); + } + else if (tObj.TagNo == 1) + { + _notAfter = DerGeneralizedTime.GetInstance(tObj, false); + } + } + } + + public DerGeneralizedTime NotBefore + { + get { return _notBefore; } + } + + public DerGeneralizedTime NotAfter + { + get { return _notAfter; } + } + + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/x509/RSAPublicKeyStructure.cs b/crypto/src/asn1/x509/RSAPublicKeyStructure.cs new file mode 100644 index 000000000..bdcba783e --- /dev/null +++ b/crypto/src/asn1/x509/RSAPublicKeyStructure.cs @@ -0,0 +1,92 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class RsaPublicKeyStructure + : Asn1Encodable + { + private BigInteger modulus; + private BigInteger publicExponent; + + public static RsaPublicKeyStructure GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static RsaPublicKeyStructure GetInstance( + object obj) + { + if (obj == null || obj is RsaPublicKeyStructure) + { + return (RsaPublicKeyStructure) obj; + } + + if (obj is Asn1Sequence) + { + return new RsaPublicKeyStructure((Asn1Sequence) obj); + } + + throw new ArgumentException("Invalid RsaPublicKeyStructure: " + obj.GetType().Name); + } + + public RsaPublicKeyStructure( + BigInteger modulus, + BigInteger publicExponent) + { + if (modulus == null) + throw new ArgumentNullException("modulus"); + if (publicExponent == null) + throw new ArgumentNullException("publicExponent"); + if (modulus.SignValue <= 0) + throw new ArgumentException("Not a valid RSA modulus", "modulus"); + if (publicExponent.SignValue <= 0) + throw new ArgumentException("Not a valid RSA public exponent", "publicExponent"); + + this.modulus = modulus; + this.publicExponent = publicExponent; + } + + private RsaPublicKeyStructure( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + // Note: we are accepting technically incorrect (i.e. negative) values here + modulus = DerInteger.GetInstance(seq[0]).PositiveValue; + publicExponent = DerInteger.GetInstance(seq[1]).PositiveValue; + } + + public BigInteger Modulus + { + get { return modulus; } + } + + public BigInteger PublicExponent + { + get { return publicExponent; } + } + + /** + * This outputs the key in Pkcs1v2 format. + *
+         *      RSAPublicKey ::= Sequence {
+         *                          modulus Integer, -- n
+         *                          publicExponent Integer, -- e
+         *                      }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence( + new DerInteger(Modulus), + new DerInteger(PublicExponent)); + } + } +} diff --git a/crypto/src/asn1/x509/ReasonFlags.cs b/crypto/src/asn1/x509/ReasonFlags.cs new file mode 100644 index 000000000..f204c36aa --- /dev/null +++ b/crypto/src/asn1/x509/ReasonFlags.cs @@ -0,0 +1,46 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The ReasonFlags object. + *
+     * ReasonFlags ::= BIT STRING {
+     *    unused(0),
+     *    keyCompromise(1),
+     *    cACompromise(2),
+     *    affiliationChanged(3),
+     *    superseded(4),
+     *    cessationOfOperation(5),
+     *    certficateHold(6)
+     * }
+     * 
+ */ + public class ReasonFlags + : DerBitString + { + public const int Unused = (1 << 7); + public const int KeyCompromise = (1 << 6); + public const int CACompromise = (1 << 5); + public const int AffiliationChanged = (1 << 4); + public const int Superseded = (1 << 3); + public const int CessationOfOperation = (1 << 2); + public const int CertificateHold = (1 << 1); + public const int PrivilegeWithdrawn = (1 << 0); + public const 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) + : base(GetBytes(reasons), GetPadBits(reasons)) + { + } + + public ReasonFlags( + DerBitString reasons) + : base(reasons.GetBytes(), reasons.PadBits) + { + } + } +} diff --git a/crypto/src/asn1/x509/RoleSyntax.cs b/crypto/src/asn1/x509/RoleSyntax.cs new file mode 100644 index 000000000..48c3c6cae --- /dev/null +++ b/crypto/src/asn1/x509/RoleSyntax.cs @@ -0,0 +1,230 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Implementation of the RoleSyntax object as specified by the RFC3281. + * + *
+	* RoleSyntax ::= SEQUENCE {
+	*                 roleAuthority  [0] GeneralNames OPTIONAL,
+	*                 roleName       [1] GeneralName
+	*           }
+	* 
+ */ + public class RoleSyntax + : Asn1Encodable + { + private readonly GeneralNames roleAuthority; + private readonly GeneralName roleName; + + /** + * RoleSyntax factory method. + * @param obj the object used to construct an instance of + * RoleSyntax. It must be an instance of RoleSyntax + * or Asn1Sequence. + * @return the instance of RoleSyntax built from the + * supplied object. + * @throws java.lang.ArgumentException if the object passed + * to the factory is not an instance of RoleSyntax or + * Asn1Sequence. + */ + public static RoleSyntax GetInstance( + object obj) + { + if (obj is RoleSyntax) + return (RoleSyntax)obj; + + 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.TagNo != GeneralName.UniformResourceIdentifier + || ((IAsn1String) roleName.Name).GetString().Equals("")) + { + throw new ArgumentException("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 + * new RoleSyntax(null, roleName). + * @param roleName the role name of this RoleSyntax. + */ + public RoleSyntax( + GeneralName roleName) + : this(null, roleName) + { + } + + /** + * Utility constructor. Takes a string argument representing + * the role name, builds a GeneralName to hold the role name + * and calls the constructor that takes a GeneralName. + * @param roleName + */ + public RoleSyntax( + string roleName) + : this(new GeneralName(GeneralName.UniformResourceIdentifier, + (roleName == null)? "": roleName)) + { + } + + /** + * Constructor that builds an instance of RoleSyntax by + * extracting the encoded elements from the Asn1Sequence + * object supplied. + * @param seq an instance of Asn1Sequence that holds + * the encoded elements used to build this RoleSyntax. + */ + private RoleSyntax( + Asn1Sequence seq) + { + if (seq.Count < 1 || seq.Count > 2) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + for (int i = 0; i != seq.Count; i++) + { + Asn1TaggedObject taggedObject = Asn1TaggedObject.GetInstance(seq[i]); + switch (taggedObject.TagNo) + { + case 0: + roleAuthority = GeneralNames.GetInstance(taggedObject, false); + break; + case 1: + roleName = GeneralName.GetInstance(taggedObject, true); + break; + default: + throw new ArgumentException("Unknown tag in RoleSyntax"); + } + } + } + + /** + * Gets the role authority of this RoleSyntax. + * @return an instance of GeneralNames holding the + * role authority of this RoleSyntax. + */ + public GeneralNames RoleAuthority + { + get { return this.roleAuthority; } + } + + /** + * Gets the role name of this RoleSyntax. + * @return an instance of GeneralName holding the + * role name of this RoleSyntax. + */ + public GeneralName RoleName + { + get { return this.roleName; } + } + + /** + * Gets the role name as a java.lang.string object. + * @return the role name of this RoleSyntax represented as a + * string object. + */ + public string GetRoleNameAsString() + { + return ((IAsn1String) this.roleName.Name).GetString(); + } + + /** + * Gets the role authority as a string[] object. + * @return the role authority of this RoleSyntax represented as a + * string[] 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 asn1Value = names[i].Name; + if (asn1Value is IAsn1String) + { + namesString[i] = ((IAsn1String) asn1Value).GetString(); + } + else + { + namesString[i] = asn1Value.ToString(); + } + } + + return namesString; + } + + /** + * Implementation of the method ToAsn1Object as + * required by the superclass ASN1Encodable. + * + *
+		* RoleSyntax ::= SEQUENCE {
+		*                 roleAuthority  [0] GeneralNames OPTIONAL,
+		*                 roleName       [1] GeneralName
+		*           }
+		* 
+ */ + public override Asn1Object ToAsn1Object() + { + 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 override string ToString() + { + StringBuilder buff = new StringBuilder("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/crypto/src/asn1/x509/SubjectDirectoryAttributes.cs b/crypto/src/asn1/x509/SubjectDirectoryAttributes.cs new file mode 100644 index 000000000..fcb30290d --- /dev/null +++ b/crypto/src/asn1/x509/SubjectDirectoryAttributes.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * This extension may contain further X.500 attributes of the subject. See also + * RFC 3039. + * + *
+	 *     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
+	 * 
+ * + * @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers. + */ + public class SubjectDirectoryAttributes + : Asn1Encodable + { + private readonly IList attributes; + + public static SubjectDirectoryAttributes GetInstance( + object obj) + { + if (obj == null || obj is SubjectDirectoryAttributes) + { + return (SubjectDirectoryAttributes) obj; + } + + if (obj is Asn1Sequence) + { + return new SubjectDirectoryAttributes((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + * + * The sequence is of type SubjectDirectoryAttributes: + * + *
+		 *      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
+		 * 
+ * + * @param seq + * The ASN.1 sequence. + */ + private SubjectDirectoryAttributes( + Asn1Sequence seq) + { + this.attributes = Platform.CreateArrayList(); + foreach (object o in seq) + { + Asn1Sequence s = Asn1Sequence.GetInstance(o); + attributes.Add(AttributeX509.GetInstance(s)); + } + } + +#if !SILVERLIGHT + [Obsolete] + public SubjectDirectoryAttributes( + ArrayList attributes) + : this((IList)attributes) + { + } +#endif + + /** + * Constructor from an ArrayList of attributes. + * + * The ArrayList consists of attributes of type {@link Attribute Attribute} + * + * @param attributes The attributes. + * + */ + public SubjectDirectoryAttributes( + IList attributes) + { + this.attributes = Platform.CreateArrayList(attributes); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + * + * Returns: + * + *
+		 *      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
+		 * 
+ * + * @return a DERObject + */ + public override Asn1Object ToAsn1Object() + { + AttributeX509[] v = new AttributeX509[attributes.Count]; + for (int i = 0; i < attributes.Count; ++i) + { + v[i] = (AttributeX509)attributes[i]; + } + return new DerSequence(v); + } + + /** + * @return Returns the attributes. + */ + public IEnumerable Attributes + { + get { return new EnumerableProxy(attributes); } + } + } +} diff --git a/crypto/src/asn1/x509/SubjectKeyIdentifier.cs b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs new file mode 100644 index 000000000..e640760f3 --- /dev/null +++ b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs @@ -0,0 +1,141 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The SubjectKeyIdentifier object. + *
+     * SubjectKeyIdentifier::= OCTET STRING
+     * 
+ */ + public class SubjectKeyIdentifier + : Asn1Encodable + { + private readonly byte[] keyIdentifier; + + public static SubjectKeyIdentifier GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1OctetString.GetInstance(obj, explicitly)); + } + + public static SubjectKeyIdentifier GetInstance( + object obj) + { + if (obj is SubjectKeyIdentifier) + { + return (SubjectKeyIdentifier) obj; + } + + if (obj is SubjectPublicKeyInfo) + { + return new SubjectKeyIdentifier((SubjectPublicKeyInfo) obj); + } + + if (obj is Asn1OctetString) + { + return new SubjectKeyIdentifier((Asn1OctetString) obj); + } + + if (obj is X509Extension) + { + return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); + } + + throw new ArgumentException("Invalid SubjectKeyIdentifier: " + obj.GetType().Name); + } + + public SubjectKeyIdentifier( + byte[] keyID) + { + if (keyID == null) + throw new ArgumentNullException("keyID"); + + this.keyIdentifier = keyID; + } + + public SubjectKeyIdentifier( + Asn1OctetString keyID) + { + this.keyIdentifier = keyID.GetOctets(); + } + + /** + * Calculates the keyIdentifier using a SHA1 hash over the BIT STRING + * from SubjectPublicKeyInfo as defined in RFC3280. + * + * @param spki the subject public key info. + */ + public SubjectKeyIdentifier( + SubjectPublicKeyInfo spki) + { + this.keyIdentifier = GetDigest(spki); + } + + public byte[] GetKeyIdentifier() + { + return keyIdentifier; + } + + public override Asn1Object ToAsn1Object() + { + return new DerOctetString(keyIdentifier); + } + + /** + * Return a RFC 3280 type 1 key identifier. As in: + *
+		 * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+		 * value of the BIT STRING subjectPublicKey (excluding the tag,
+		 * length, and number of unused bits).
+		 * 
+ * @param keyInfo the key info object containing the subjectPublicKey field. + * @return the key identifier. + */ + public static SubjectKeyIdentifier CreateSha1KeyIdentifier( + SubjectPublicKeyInfo keyInfo) + { + return new SubjectKeyIdentifier(keyInfo); + } + + /** + * Return a RFC 3280 type 2 key identifier. As in: + *
+		 * (2) The keyIdentifier is composed of a four bit type field with
+		 * the value 0100 followed by the least significant 60 bits of the
+		 * SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+		 * 
+ * @param keyInfo the key info object containing the subjectPublicKey field. + * @return the key identifier. + */ + public static SubjectKeyIdentifier CreateTruncatedSha1KeyIdentifier( + SubjectPublicKeyInfo keyInfo) + { + byte[] dig = GetDigest(keyInfo); + byte[] id = new byte[8]; + + Array.Copy(dig, dig.Length - 8, id, 0, id.Length); + + id[0] &= 0x0f; + id[0] |= 0x40; + + return new SubjectKeyIdentifier(id); + } + + private static byte[] GetDigest( + SubjectPublicKeyInfo spki) + { + IDigest digest = new Sha1Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + byte[] bytes = spki.PublicKeyData.GetBytes(); + digest.BlockUpdate(bytes, 0, bytes.Length); + digest.DoFinal(resBuf, 0); + return resBuf; + } + } +} diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs new file mode 100644 index 000000000..8ce4b2762 --- /dev/null +++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The object that contains the public key stored in a certficate. + *

+ * The GetEncoded() method in the public keys in the JCE produces a DER + * encoded one of these.

+ */ + public class SubjectPublicKeyInfo + : Asn1Encodable + { + private readonly AlgorithmIdentifier algID; + private readonly DerBitString keyData; + + public static SubjectPublicKeyInfo GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static SubjectPublicKeyInfo GetInstance( + object obj) + { + if (obj is SubjectPublicKeyInfo) + return (SubjectPublicKeyInfo) obj; + + if (obj != null) + return new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public SubjectPublicKeyInfo( + AlgorithmIdentifier algID, + Asn1Encodable publicKey) + { + this.keyData = new DerBitString(publicKey); + this.algID = algID; + } + + public SubjectPublicKeyInfo( + AlgorithmIdentifier algID, + byte[] publicKey) + { + this.keyData = new DerBitString(publicKey); + this.algID = algID; + } + + private SubjectPublicKeyInfo( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.algID = AlgorithmIdentifier.GetInstance(seq[0]); + this.keyData = DerBitString.GetInstance(seq[1]); + } + + public AlgorithmIdentifier AlgorithmID + { + get { return algID; } + } + + /** + * for when the public key is an encoded object - if the bitstring + * can't be decoded this routine raises an IOException. + * + * @exception IOException - if the bit string doesn't represent a Der + * encoded object. + */ + public Asn1Object GetPublicKey() + { + return Asn1Object.FromByteArray(keyData.GetBytes()); + } + + /** + * for when the public key is raw bits... + */ + public DerBitString PublicKeyData + { + get { return keyData; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * SubjectPublicKeyInfo ::= Sequence {
+         *                          algorithm AlgorithmIdentifier,
+         *                          publicKey BIT STRING }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algID, keyData); + } + } +} diff --git a/crypto/src/asn1/x509/TBSCertList.cs b/crypto/src/asn1/x509/TBSCertList.cs new file mode 100644 index 000000000..b5934a230 --- /dev/null +++ b/crypto/src/asn1/x509/TBSCertList.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class CrlEntry + : Asn1Encodable + { + internal Asn1Sequence seq; + internal DerInteger userCertificate; + internal Time revocationDate; + internal X509Extensions crlEntryExtensions; + + public CrlEntry( + Asn1Sequence seq) + { + if (seq.Count < 2 || seq.Count > 3) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + this.seq = seq; + + userCertificate = DerInteger.GetInstance(seq[0]); + revocationDate = Time.GetInstance(seq[1]); + } + + public DerInteger UserCertificate + { + get { return userCertificate; } + } + + public Time RevocationDate + { + get { return revocationDate; } + } + + public X509Extensions Extensions + { + get + { + if (crlEntryExtensions == null && seq.Count == 3) + { + crlEntryExtensions = X509Extensions.GetInstance(seq[2]); + } + + return crlEntryExtensions; + } + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + } + + /** + * PKIX RFC-2459 - TbsCertList object. + *
+     * 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
+     *                                }
+     * 
+ */ + public class TbsCertificateList + : Asn1Encodable + { + private class RevokedCertificatesEnumeration + : IEnumerable + { + private readonly IEnumerable en; + + internal RevokedCertificatesEnumeration( + IEnumerable en) + { + this.en = en; + } + + public IEnumerator GetEnumerator() + { + return new RevokedCertificatesEnumerator(en.GetEnumerator()); + } + + private class RevokedCertificatesEnumerator + : IEnumerator + { + private readonly IEnumerator e; + + internal RevokedCertificatesEnumerator( + IEnumerator e) + { + this.e = e; + } + + public bool MoveNext() + { + return e.MoveNext(); + } + + public void Reset() + { + e.Reset(); + } + + public object Current + { + get { return new CrlEntry(Asn1Sequence.GetInstance(e.Current)); } + } + } + } + + internal Asn1Sequence seq; + internal DerInteger version; + internal AlgorithmIdentifier signature; + internal X509Name issuer; + internal Time thisUpdate; + internal Time nextUpdate; + internal Asn1Sequence revokedCertificates; + internal X509Extensions crlExtensions; + + public static TbsCertificateList GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static TbsCertificateList GetInstance( + object obj) + { + TbsCertificateList list = obj as TbsCertificateList; + + if (obj == null || list != null) + { + return list; + } + + if (obj is Asn1Sequence) + { + return new TbsCertificateList((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + internal TbsCertificateList( + Asn1Sequence seq) + { + if (seq.Count < 3 || seq.Count > 7) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + int seqPos = 0; + + this.seq = seq; + + if (seq[seqPos] is DerInteger) + { + version = DerInteger.GetInstance(seq[seqPos++]); + } + else + { + version = new DerInteger(0); + } + + signature = AlgorithmIdentifier.GetInstance(seq[seqPos++]); + issuer = X509Name.GetInstance(seq[seqPos++]); + thisUpdate = Time.GetInstance(seq[seqPos++]); + + if (seqPos < seq.Count + && (seq[seqPos] is DerUtcTime + || seq[seqPos] is DerGeneralizedTime + || seq[seqPos] is Time)) + { + nextUpdate = Time.GetInstance(seq[seqPos++]); + } + + if (seqPos < seq.Count + && !(seq[seqPos] is DerTaggedObject)) + { + revokedCertificates = Asn1Sequence.GetInstance(seq[seqPos++]); + } + + if (seqPos < seq.Count + && seq[seqPos] is DerTaggedObject) + { + crlExtensions = X509Extensions.GetInstance(seq[seqPos]); + } + } + + public int Version + { + get { return version.Value.IntValue + 1; } + } + + public DerInteger VersionNumber + { + get { return version; } + } + + public AlgorithmIdentifier Signature + { + get { return signature; } + } + + public X509Name Issuer + { + get { return issuer; } + } + + public Time ThisUpdate + { + get { return thisUpdate; } + } + + public Time NextUpdate + { + get { return nextUpdate; } + } + + public CrlEntry[] GetRevokedCertificates() + { + if (revokedCertificates == null) + { + return new CrlEntry[0]; + } + + CrlEntry[] entries = new CrlEntry[revokedCertificates.Count]; + + for (int i = 0; i < entries.Length; i++) + { + entries[i] = new CrlEntry(Asn1Sequence.GetInstance(revokedCertificates[i])); + } + + return entries; + } + + public IEnumerable GetRevokedCertificateEnumeration() + { + if (revokedCertificates == null) + { + return EmptyEnumerable.Instance; + } + + return new RevokedCertificatesEnumeration(revokedCertificates); + } + + public X509Extensions Extensions + { + get { return crlExtensions; } + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/x509/TBSCertificateStructure.cs b/crypto/src/asn1/x509/TBSCertificateStructure.cs new file mode 100644 index 000000000..fc7c39ba2 --- /dev/null +++ b/crypto/src/asn1/x509/TBSCertificateStructure.cs @@ -0,0 +1,185 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The TbsCertificate object. + *
+     * 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
+     *      }
+     * 
+ *

+ * 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 + : Asn1Encodable + { + internal Asn1Sequence seq; + internal DerInteger version; + internal DerInteger serialNumber; + internal AlgorithmIdentifier signature; + internal X509Name issuer; + internal Time startDate, endDate; + internal X509Name subject; + internal SubjectPublicKeyInfo subjectPublicKeyInfo; + internal DerBitString issuerUniqueID; + internal DerBitString subjectUniqueID; + internal X509Extensions extensions; + + public static TbsCertificateStructure GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static TbsCertificateStructure GetInstance( + object obj) + { + if (obj is TbsCertificateStructure) + return (TbsCertificateStructure) obj; + + if (obj != null) + return new TbsCertificateStructure(Asn1Sequence.GetInstance(obj)); + + return null; + } + + internal TbsCertificateStructure( + Asn1Sequence seq) + { + int seqStart = 0; + + this.seq = seq; + + // + // some certficates don't include a version number - we assume v1 + // + if (seq[0] is DerTaggedObject) + { + version = DerInteger.GetInstance((Asn1TaggedObject)seq[0], true); + } + else + { + seqStart = -1; // field 0 is missing! + version = new DerInteger(0); + } + + serialNumber = DerInteger.GetInstance(seq[seqStart + 1]); + + signature = AlgorithmIdentifier.GetInstance(seq[seqStart + 2]); + issuer = X509Name.GetInstance(seq[seqStart + 3]); + + // + // before and after dates + // + Asn1Sequence dates = (Asn1Sequence)seq[seqStart + 4]; + + startDate = Time.GetInstance(dates[0]); + endDate = Time.GetInstance(dates[1]); + + subject = X509Name.GetInstance(seq[seqStart + 5]); + + // + // public key info. + // + subjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(seq[seqStart + 6]); + + for (int extras = seq.Count - (seqStart + 6) - 1; extras > 0; extras--) + { + DerTaggedObject extra = (DerTaggedObject) seq[seqStart + 6 + extras]; + + switch (extra.TagNo) + { + case 1: + issuerUniqueID = DerBitString.GetInstance(extra, false); + break; + case 2: + subjectUniqueID = DerBitString.GetInstance(extra, false); + break; + case 3: + extensions = X509Extensions.GetInstance(extra); + break; + } + } + } + + public int Version + { + get { return version.Value.IntValue + 1; } + } + + public DerInteger VersionNumber + { + get { return version; } + } + + public DerInteger SerialNumber + { + get { return serialNumber; } + } + + public AlgorithmIdentifier Signature + { + get { return signature; } + } + + public X509Name Issuer + { + get { return issuer; } + } + + public Time StartDate + { + get { return startDate; } + } + + public Time EndDate + { + get { return endDate; } + } + + public X509Name Subject + { + get { return subject; } + } + + public SubjectPublicKeyInfo SubjectPublicKeyInfo + { + get { return subjectPublicKeyInfo; } + } + + public DerBitString IssuerUniqueID + { + get { return issuerUniqueID; } + } + + public DerBitString SubjectUniqueID + { + get { return subjectUniqueID; } + } + + public X509Extensions Extensions + { + get { return extensions; } + } + + public override Asn1Object ToAsn1Object() + { + return seq; + } + } +} diff --git a/crypto/src/asn1/x509/Target.cs b/crypto/src/asn1/x509/Target.cs new file mode 100644 index 000000000..309b28c95 --- /dev/null +++ b/crypto/src/asn1/x509/Target.cs @@ -0,0 +1,139 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Target structure used in target information extension for attribute + * certificates from RFC 3281. + * + *
+	 *     Target  ::= CHOICE {
+	 *       targetName          [0] GeneralName,
+	 *       targetGroup         [1] GeneralName,
+	 *       targetCert          [2] TargetCert
+	 *     }
+	 * 
+ * + *

+ * The targetCert field is currently not supported and must not be used + * according to RFC 3281.

+ */ + public class Target + : Asn1Encodable, IAsn1Choice + { + public enum Choice + { + Name = 0, + Group = 1 + }; + + private readonly GeneralName targetName; + private readonly GeneralName targetGroup; + + /** + * Creates an instance of a Target from the given object. + *

+ * obj can be a Target or a {@link Asn1TaggedObject}

+ * + * @param obj The object. + * @return A Target instance. + * @throws ArgumentException if the given object cannot be + * interpreted as Target. + */ + public static Target GetInstance( + object obj) + { + if (obj is Target) + { + return (Target) obj; + } + + if (obj is Asn1TaggedObject) + { + return new Target((Asn1TaggedObject) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1TaggedObject. + * + * @param tagObj The tagged object. + * @throws ArgumentException if the encoding is wrong. + */ + private Target( + Asn1TaggedObject tagObj) + { + switch ((Choice) tagObj.TagNo) + { + case Choice.Name: // GeneralName is already a choice so explicit + targetName = GeneralName.GetInstance(tagObj, true); + break; + case Choice.Group: + targetGroup = GeneralName.GetInstance(tagObj, true); + break; + default: + throw new ArgumentException("unknown tag: " + tagObj.TagNo); + } + } + + /** + * Constructor from given details. + *

+ * Exactly one of the parameters must be not null.

+ * + * @param type the choice type to apply to the name. + * @param name the general name. + * @throws ArgumentException if type is invalid. + */ + public Target( + Choice type, + GeneralName name) + : this(new DerTaggedObject((int) type, name)) + { + } + + /** + * @return Returns the targetGroup. + */ + public virtual GeneralName TargetGroup + { + get { return targetGroup; } + } + + /** + * @return Returns the targetName. + */ + public virtual GeneralName TargetName + { + get { return targetName; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + * + * Returns: + * + *
+		 *     Target  ::= CHOICE {
+		 *       targetName          [0] GeneralName,
+		 *       targetGroup         [1] GeneralName,
+		 *       targetCert          [2] TargetCert
+		 *     }
+		 * 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + // GeneralName is a choice already so most be explicitly tagged + if (targetName != null) + { + return new DerTaggedObject(true, 0, targetName); + } + + return new DerTaggedObject(true, 1, targetGroup); + } + } +} diff --git a/crypto/src/asn1/x509/TargetInformation.cs b/crypto/src/asn1/x509/TargetInformation.cs new file mode 100644 index 000000000..75b18c0c9 --- /dev/null +++ b/crypto/src/asn1/x509/TargetInformation.cs @@ -0,0 +1,123 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Target information extension for attributes certificates according to RFC + * 3281. + * + *
+	 *           SEQUENCE OF Targets
+	 * 
+ * + */ + public class TargetInformation + : Asn1Encodable + { + private readonly Asn1Sequence targets; + + /** + * Creates an instance of a TargetInformation from the given object. + *

+ * obj can be a TargetInformation or a {@link Asn1Sequence}

+ * + * @param obj The object. + * @return A TargetInformation instance. + * @throws ArgumentException if the given object cannot be interpreted as TargetInformation. + */ + public static TargetInformation GetInstance( + object obj) + { + if (obj is TargetInformation) + { + return (TargetInformation) obj; + } + + if (obj is Asn1Sequence) + { + return new TargetInformation((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from a Asn1Sequence. + * + * @param seq The Asn1Sequence. + * @throws ArgumentException if the sequence does not contain + * correctly encoded Targets elements. + */ + private TargetInformation( + Asn1Sequence targets) + { + this.targets = targets; + } + + /** + * Returns the targets in this target information extension. + *

+ * The ArrayList is cloned before it is returned.

+ * + * @return Returns the targets. + */ + public virtual Targets[] GetTargetsObjects() + { + Targets[] result = new Targets[targets.Count]; + + for (int i = 0; i < targets.Count; ++i) + { + result[i] = Targets.GetInstance(targets[i]); + } + + return result; + } + + /** + * 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: + * + *
+		 *          SEQUENCE OF Targets
+		 * 
+ * + *

+ * 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 an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return targets; + } + } +} diff --git a/crypto/src/asn1/x509/Targets.cs b/crypto/src/asn1/x509/Targets.cs new file mode 100644 index 000000000..3e436d8d8 --- /dev/null +++ b/crypto/src/asn1/x509/Targets.cs @@ -0,0 +1,121 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Targets structure used in target information extension for attribute + * certificates from RFC 3281. + * + *
+	 *            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
+	 *            }
+	 * 
+ * + * @see org.bouncycastle.asn1.x509.Target + * @see org.bouncycastle.asn1.x509.TargetInformation + */ + public class Targets + : Asn1Encodable + { + private readonly Asn1Sequence targets; + + /** + * Creates an instance of a Targets from the given object. + *

+ * obj can be a Targets or a {@link Asn1Sequence}

+ * + * @param obj The object. + * @return A Targets instance. + * @throws ArgumentException if the given object cannot be interpreted as Target. + */ + public static Targets GetInstance( + object obj) + { + if (obj is Targets) + { + return (Targets) obj; + } + + if (obj is Asn1Sequence) + { + return new Targets((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + * + * @param targets The ASN.1 SEQUENCE. + * @throws ArgumentException if the contents of the sequence are + * invalid. + */ + private Targets( + Asn1Sequence targets) + { + this.targets = targets; + } + + /** + * Constructor from given targets. + *

+ * The ArrayList is copied.

+ * + * @param targets An ArrayList of {@link Target}s. + * @see Target + * @throws ArgumentException if the ArrayList contains not only Targets. + */ + public Targets( + Target[] targets) + { + this.targets = new DerSequence(targets); + } + + /** + * Returns the targets in an ArrayList. + *

+ * The ArrayList is cloned before it is returned.

+ * + * @return Returns the targets. + */ + public virtual Target[] GetTargets() + { + Target[] result = new Target[targets.Count]; + + for (int i = 0; i < targets.Count; ++i) + { + result[i] = Target.GetInstance(targets[i]); + } + + return result; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + * + * Returns: + * + *
+		 *            Targets ::= SEQUENCE OF Target
+		 * 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + return targets; + } + } +} diff --git a/crypto/src/asn1/x509/Time.cs b/crypto/src/asn1/x509/Time.cs new file mode 100644 index 000000000..0f2511e6d --- /dev/null +++ b/crypto/src/asn1/x509/Time.cs @@ -0,0 +1,120 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class Time + : Asn1Encodable, IAsn1Choice + { + internal Asn1Object time; + + public static Time GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(obj.GetObject()); + } + + public Time( + Asn1Object time) + { + if (time == null) + throw new ArgumentNullException("time"); + + if (!(time is DerUtcTime) && !(time is DerGeneralizedTime)) + { + throw new ArgumentException("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( + DateTime date) + { + string d = date.ToString("yyyyMMddHHmmss") + "Z"; + + int year = Int32.Parse(d.Substring(0, 4)); + + if (year < 1950 || year > 2049) + { + time = new DerGeneralizedTime(d); + } + else + { + time = new DerUtcTime(d.Substring(2)); + } + } + + public static Time GetInstance( + object obj) + { + if (obj == null || obj is Time) + return (Time) obj; + + if (obj is DerUtcTime) + return new Time((DerUtcTime) obj); + + if (obj is DerGeneralizedTime) + return new Time((DerGeneralizedTime) obj); + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + public string GetTime() + { + if (time is DerUtcTime) + { + return ((DerUtcTime) time).AdjustedTimeString; + } + + return ((DerGeneralizedTime) time).GetTime(); + } + + /// + /// Return our time as DateTime. + /// + /// A date time. + public DateTime ToDateTime() + { + try + { + if (time is DerUtcTime) + { + return ((DerUtcTime)time).ToAdjustedDateTime(); + } + else + { + return ((DerGeneralizedTime)time).ToDateTime(); + } + } + catch (FormatException e) + { + // this should never happen + throw new InvalidOperationException("invalid date string: " + e.Message); + } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Time ::= CHOICE {
+         *             utcTime        UTCTime,
+         *             generalTime    GeneralizedTime }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return time; + } + + public override string ToString() + { + return GetTime(); + } + } +} diff --git a/crypto/src/asn1/x509/UserNotice.cs b/crypto/src/asn1/x509/UserNotice.cs new file mode 100644 index 000000000..2878a180f --- /dev/null +++ b/crypto/src/asn1/x509/UserNotice.cs @@ -0,0 +1,104 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * UserNotice class, used in + * CertificatePolicies X509 extensions (in policy + * qualifiers). + *
+     * UserNotice ::= Sequence {
+     *      noticeRef        NoticeReference OPTIONAL,
+     *      explicitText     DisplayText OPTIONAL}
+     *
+     * 
+ * + * @see PolicyQualifierId + * @see PolicyInformation + */ + public class UserNotice + : Asn1Encodable + { + internal NoticeReference noticeRef; + internal DisplayText explicitText; + + /** + * Creates a new UserNotice instance. + * + * @param noticeRef a NoticeReference value + * @param explicitText a DisplayText value + */ + public UserNotice( + NoticeReference noticeRef, + DisplayText explicitText) + { + this.noticeRef = noticeRef; + this.explicitText = explicitText; + } + + /** + * Creates a new UserNotice instance. + * + * @param noticeRef a NoticeReference value + * @param str the explicitText field as a string. + */ + public UserNotice( + NoticeReference noticeRef, + string str) + { + this.noticeRef = noticeRef; + this.explicitText = new DisplayText(str); + } + + /** + * Creates a new UserNotice instance. + *

Useful from reconstructing a UserNotice instance + * from its encodable/encoded form. + * + * @param as an ASN1Sequence value obtained from either + * calling @{link toASN1Object()} for a UserNotice + * instance or from parsing it from a DER-encoded stream.

+ */ + public UserNotice( + Asn1Sequence seq) + { + if (seq.Count == 2) + { + noticeRef = NoticeReference.GetInstance(seq[0]); + explicitText = DisplayText.GetInstance(seq[1]); + } + else if (seq.Count == 1) + { + if (seq[0].ToAsn1Object() is Asn1Sequence) + { + noticeRef = NoticeReference.GetInstance(seq[0]); + } + else + { + explicitText = DisplayText.GetInstance(seq[0]); + } + } + else + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector av = new Asn1EncodableVector(); + + if (noticeRef != null) + { + av.Add(noticeRef); + } + + if (explicitText != null) + { + av.Add(explicitText); + } + + return new DerSequence(av); + } + } +} diff --git a/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs new file mode 100644 index 000000000..20b525a48 --- /dev/null +++ b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs @@ -0,0 +1,108 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Generator for Version 1 TbsCertificateStructures. + *
+     * TbsCertificate ::= Sequence {
+     *      version          [ 0 ]  Version DEFAULT v1(0),
+     *      serialNumber            CertificateSerialNumber,
+     *      signature               AlgorithmIdentifier,
+     *      issuer                  Name,
+     *      validity                Validity,
+     *      subject                 Name,
+     *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
+     *      }
+     * 
+ * + */ + public class V1TbsCertificateGenerator + { + internal DerTaggedObject version = new DerTaggedObject(0, new DerInteger(0)); + internal DerInteger serialNumber; + internal AlgorithmIdentifier signature; + internal X509Name issuer; + internal Time startDate, endDate; + internal X509Name subject; + internal SubjectPublicKeyInfo subjectPublicKeyInfo; + + public V1TbsCertificateGenerator() + { + } + + public void SetSerialNumber( + DerInteger serialNumber) + { + this.serialNumber = serialNumber; + } + + public void SetSignature( + AlgorithmIdentifier signature) + { + this.signature = signature; + } + + public void SetIssuer( + X509Name issuer) + { + this.issuer = issuer; + } + + public void SetStartDate( + Time startDate) + { + this.startDate = startDate; + } + + public void SetStartDate( + DerUtcTime startDate) + { + this.startDate = new Time(startDate); + } + + public void SetEndDate( + Time endDate) + { + this.endDate = endDate; + } + + public void SetEndDate( + DerUtcTime endDate) + { + this.endDate = new Time(endDate); + } + + public void SetSubject( + X509Name subject) + { + this.subject = subject; + } + + public void SetSubjectPublicKeyInfo( + SubjectPublicKeyInfo pubKeyInfo) + { + this.subjectPublicKeyInfo = pubKeyInfo; + } + + public TbsCertificateStructure GenerateTbsCertificate() + { + if ((serialNumber == null) || (signature == null) + || (issuer == null) || (startDate == null) || (endDate == null) + || (subject == null) || (subjectPublicKeyInfo == null)) + { + throw new InvalidOperationException("not all mandatory fields set in V1 TBScertificate generator"); + } + + return new TbsCertificateStructure( + new DerSequence( + //version, - not required as default value + serialNumber, + signature, + issuer, + new DerSequence(startDate, endDate), // before and after dates + subject, + subjectPublicKeyInfo)); + } + } +} diff --git a/crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs b/crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs new file mode 100644 index 000000000..02580b5b8 --- /dev/null +++ b/crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs @@ -0,0 +1,137 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Generator for Version 2 AttributeCertificateInfo + *
+     * AttributeCertificateInfo ::= Sequence {
+     *       version              AttCertVersion -- version is v2,
+     *       holder               Holder,
+     *       issuer               AttCertIssuer,
+     *       signature            AlgorithmIdentifier,
+     *       serialNumber         CertificateSerialNumber,
+     *       attrCertValidityPeriod   AttCertValidityPeriod,
+     *       attributes           Sequence OF Attr,
+     *       issuerUniqueID       UniqueIdentifier OPTIONAL,
+     *       extensions           Extensions OPTIONAL
+     * }
+     * 
+ * + */ + public class V2AttributeCertificateInfoGenerator + { + internal DerInteger version; + internal Holder holder; + internal AttCertIssuer issuer; + internal AlgorithmIdentifier signature; + internal DerInteger serialNumber; +// internal AttCertValidityPeriod attrCertValidityPeriod; + internal Asn1EncodableVector attributes; + internal DerBitString issuerUniqueID; + internal X509Extensions extensions; + internal DerGeneralizedTime startDate, endDate; + + public V2AttributeCertificateInfoGenerator() + { + this.version = new DerInteger(1); + attributes = new Asn1EncodableVector(); + } + + public void SetHolder( + Holder holder) + { + this.holder = holder; + } + + public void AddAttribute( + string oid, + Asn1Encodable value) + { + attributes.Add(new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value))); + } + + /** + * @param attribute + */ + public void AddAttribute(AttributeX509 attribute) + { + attributes.Add(attribute); + } + + public void SetSerialNumber( + DerInteger serialNumber) + { + this.serialNumber = serialNumber; + } + + public void SetSignature( + AlgorithmIdentifier signature) + { + this.signature = signature; + } + + public void SetIssuer( + AttCertIssuer issuer) + { + this.issuer = issuer; + } + + public void SetStartDate( + DerGeneralizedTime startDate) + { + this.startDate = startDate; + } + + public void SetEndDate( + DerGeneralizedTime endDate) + { + this.endDate = endDate; + } + + public void SetIssuerUniqueID( + DerBitString issuerUniqueID) + { + this.issuerUniqueID = issuerUniqueID; + } + + public void SetExtensions( + X509Extensions extensions) + { + this.extensions = extensions; + } + + public AttributeCertificateInfo GenerateAttributeCertificateInfo() + { + if ((serialNumber == null) || (signature == null) + || (issuer == null) || (startDate == null) || (endDate == null) + || (holder == null) || (attributes == null)) + { + throw new InvalidOperationException("not all mandatory fields set in V2 AttributeCertificateInfo generator"); + } + + Asn1EncodableVector v = new Asn1EncodableVector( + version, holder, issuer, signature, serialNumber); + + // + // before and after dates => AttCertValidityPeriod + // + v.Add(new AttCertValidityPeriod(startDate, endDate)); + + // 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/crypto/src/asn1/x509/V2Form.cs b/crypto/src/asn1/x509/V2Form.cs new file mode 100644 index 000000000..2c6e54a77 --- /dev/null +++ b/crypto/src/asn1/x509/V2Form.cs @@ -0,0 +1,137 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class V2Form + : Asn1Encodable + { + internal GeneralNames issuerName; + internal IssuerSerial baseCertificateID; + internal ObjectDigestInfo objectDigestInfo; + + public static V2Form GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static V2Form GetInstance(object obj) + { + if (obj is V2Form) + return (V2Form)obj; + 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; + } + + private V2Form( + Asn1Sequence seq) + { + if (seq.Count > 3) + { + throw new ArgumentException("Bad sequence size: " + seq.Count); + } + + int index = 0; + + if (!(seq[0] is Asn1TaggedObject)) + { + index++; + this.issuerName = GeneralNames.GetInstance(seq[0]); + } + + for (int i = index; i != seq.Count; i++) + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]); + if (o.TagNo == 0) + { + baseCertificateID = IssuerSerial.GetInstance(o, false); + } + else if (o.TagNo == 1) + { + objectDigestInfo = ObjectDigestInfo.GetInstance(o, false); + } + else + { + throw new ArgumentException("Bad tag number: " + o.TagNo); + } + } + } + + public GeneralNames IssuerName + { + get { return issuerName; } + } + + public IssuerSerial BaseCertificateID + { + get { return baseCertificateID; } + } + + public ObjectDigestInfo ObjectDigestInfo + { + get { return objectDigestInfo; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  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
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + 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/crypto/src/asn1/x509/V2TBSCertListGenerator.cs b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs new file mode 100644 index 000000000..2c929188f --- /dev/null +++ b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Generator for Version 2 TbsCertList structures. + *
+     *  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
+     *                                 }
+     * 
+ * + * Note: This class may be subject to change + */ + public class V2TbsCertListGenerator + { + private DerInteger version = new DerInteger(1); + private AlgorithmIdentifier signature; + private X509Name issuer; + private Time thisUpdate, nextUpdate; + private X509Extensions extensions; + private IList crlEntries; + + public V2TbsCertListGenerator() + { + } + + public void SetSignature( + AlgorithmIdentifier signature) + { + this.signature = signature; + } + + public void SetIssuer( + X509Name issuer) + { + this.issuer = issuer; + } + + public void SetThisUpdate( + DerUtcTime thisUpdate) + { + this.thisUpdate = new Time(thisUpdate); + } + + public void SetNextUpdate( + DerUtcTime nextUpdate) + { + this.nextUpdate = (nextUpdate != null) + ? new Time(nextUpdate) + : null; + } + + public void SetThisUpdate( + Time thisUpdate) + { + this.thisUpdate = thisUpdate; + } + + public void SetNextUpdate( + Time nextUpdate) + { + this.nextUpdate = nextUpdate; + } + + public void AddCrlEntry( + Asn1Sequence crlEntry) + { + if (crlEntries == null) + { + crlEntries = Platform.CreateArrayList(); + } + + crlEntries.Add(crlEntry); + } + + public void AddCrlEntry(DerInteger userCertificate, DerUtcTime revocationDate, int reason) + { + AddCrlEntry(userCertificate, new Time(revocationDate), reason); + } + + public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason) + { + AddCrlEntry(userCertificate, revocationDate, reason, null); + } + + public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason, + DerGeneralizedTime invalidityDate) + { + IList extOids = Platform.CreateArrayList(); + IList extValues = Platform.CreateArrayList(); + + if (reason != 0) + { + CrlReason crlReason = new CrlReason(reason); + + try + { + extOids.Add(X509Extensions.ReasonCode); + extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded()))); + } + catch (IOException e) + { + throw new ArgumentException("error encoding reason: " + e); + } + } + + if (invalidityDate != null) + { + try + { + extOids.Add(X509Extensions.InvalidityDate); + extValues.Add(new X509Extension(false, new DerOctetString(invalidityDate.GetEncoded()))); + } + catch (IOException e) + { + throw new ArgumentException("error encoding invalidityDate: " + e); + } + } + + if (extOids.Count != 0) + { + AddCrlEntry(userCertificate, revocationDate, new X509Extensions(extOids, extValues)); + } + else + { + AddCrlEntry(userCertificate, revocationDate, null); + } + } + + public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, X509Extensions extensions) + { + Asn1EncodableVector v = new Asn1EncodableVector( + userCertificate, revocationDate); + + if (extensions != null) + { + v.Add(extensions); + } + + AddCrlEntry(new DerSequence(v)); + } + + public void SetExtensions( + X509Extensions extensions) + { + this.extensions = extensions; + } + + public TbsCertificateList GenerateTbsCertList() + { + if ((signature == null) || (issuer == null) || (thisUpdate == null)) + { + throw new InvalidOperationException("Not all mandatory fields set in V2 TbsCertList generator."); + } + + Asn1EncodableVector v = new Asn1EncodableVector( + version, signature, issuer, thisUpdate); + + if (nextUpdate != null) + { + v.Add(nextUpdate); + } + + // Add CRLEntries if they exist + if (crlEntries != null) + { + Asn1Sequence[] certs = new Asn1Sequence[crlEntries.Count]; + for (int i = 0; i < crlEntries.Count; ++i) + { + certs[i] = (Asn1Sequence)crlEntries[i]; + } + v.Add(new DerSequence(certs)); + } + + if (extensions != null) + { + v.Add(new DerTaggedObject(0, extensions)); + } + + return new TbsCertificateList(new DerSequence(v)); + } + } +} diff --git a/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs new file mode 100644 index 000000000..beb469a0d --- /dev/null +++ b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs @@ -0,0 +1,168 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * Generator for Version 3 TbsCertificateStructures. + *
+     * 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
+     *      }
+     * 
+ * + */ + public class V3TbsCertificateGenerator + { + internal DerTaggedObject version = new DerTaggedObject(0, new DerInteger(2)); + internal DerInteger serialNumber; + internal AlgorithmIdentifier signature; + internal X509Name issuer; + internal Time startDate, endDate; + internal X509Name subject; + internal SubjectPublicKeyInfo subjectPublicKeyInfo; + internal X509Extensions extensions; + + private bool altNamePresentAndCritical; + private DerBitString issuerUniqueID; + private DerBitString subjectUniqueID; + + public V3TbsCertificateGenerator() + { + } + + public void SetSerialNumber( + DerInteger serialNumber) + { + this.serialNumber = serialNumber; + } + + public void SetSignature( + AlgorithmIdentifier signature) + { + this.signature = signature; + } + + public void SetIssuer( + X509Name issuer) + { + this.issuer = issuer; + } + + public void SetStartDate( + DerUtcTime startDate) + { + this.startDate = new Time(startDate); + } + + public void SetStartDate( + Time startDate) + { + this.startDate = startDate; + } + + public void SetEndDate( + DerUtcTime endDate) + { + this.endDate = new Time(endDate); + } + + public void SetEndDate( + Time endDate) + { + this.endDate = endDate; + } + + public void SetSubject( + X509Name 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; + } + + public void SetExtensions( + X509Extensions extensions) + { + this.extensions = extensions; + + if (extensions != null) + { + X509Extension altName = extensions.GetExtension(X509Extensions.SubjectAlternativeName); + + if (altName != null && altName.IsCritical) + { + altNamePresentAndCritical = true; + } + } + } + + public TbsCertificateStructure GenerateTbsCertificate() + { + if ((serialNumber == null) || (signature == null) + || (issuer == null) || (startDate == null) || (endDate == null) + || (subject == null && !altNamePresentAndCritical) + || (subjectPublicKeyInfo == null)) + { + throw new InvalidOperationException("not all mandatory fields set in V3 TBScertificate generator"); + } + + DerSequence validity = new DerSequence(startDate, endDate); // before and after dates + + Asn1EncodableVector v = new Asn1EncodableVector( + version, serialNumber, signature, issuer, validity); + + if (subject != null) + { + v.Add(subject); + } + else + { + v.Add(DerSequence.Empty); + } + + 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(3, extensions)); + } + + return new TbsCertificateStructure(new DerSequence(v)); + } + } +} diff --git a/crypto/src/asn1/x509/X509Attributes.cs b/crypto/src/asn1/x509/X509Attributes.cs new file mode 100644 index 000000000..291329a62 --- /dev/null +++ b/crypto/src/asn1/x509/X509Attributes.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class X509Attributes + { + public static readonly DerObjectIdentifier RoleSyntax = new DerObjectIdentifier("2.5.4.72"); + } +} diff --git a/crypto/src/asn1/x509/X509CertificateStructure.cs b/crypto/src/asn1/x509/X509CertificateStructure.cs new file mode 100644 index 000000000..e50d3563b --- /dev/null +++ b/crypto/src/asn1/x509/X509CertificateStructure.cs @@ -0,0 +1,129 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * an X509Certificate structure. + *
+     *  Certificate ::= Sequence {
+     *      tbsCertificate          TbsCertificate,
+     *      signatureAlgorithm      AlgorithmIdentifier,
+     *      signature               BIT STRING
+     *  }
+     * 
+ */ + public class X509CertificateStructure + : Asn1Encodable + { + private readonly TbsCertificateStructure tbsCert; + private readonly AlgorithmIdentifier sigAlgID; + private readonly DerBitString sig; + + public static X509CertificateStructure GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static X509CertificateStructure GetInstance( + object obj) + { + if (obj is X509CertificateStructure) + return (X509CertificateStructure)obj; + + if (obj != null) + return new X509CertificateStructure(Asn1Sequence.GetInstance(obj)); + + return null; + } + + public X509CertificateStructure( + TbsCertificateStructure tbsCert, + AlgorithmIdentifier sigAlgID, + DerBitString sig) + { + if (tbsCert == null) + throw new ArgumentNullException("tbsCert"); + if (sigAlgID == null) + throw new ArgumentNullException("sigAlgID"); + if (sig == null) + throw new ArgumentNullException("sig"); + + this.tbsCert = tbsCert; + this.sigAlgID = sigAlgID; + this.sig = sig; + } + + private X509CertificateStructure( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("sequence wrong size for a certificate", "seq"); + + // + // correct x509 certficate + // + tbsCert = TbsCertificateStructure.GetInstance(seq[0]); + sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]); + sig = DerBitString.GetInstance(seq[2]); + } + + public TbsCertificateStructure TbsCertificate + { + get { return tbsCert; } + } + + public int Version + { + get { return tbsCert.Version; } + } + + public DerInteger SerialNumber + { + get { return tbsCert.SerialNumber; } + } + + public X509Name Issuer + { + get { return tbsCert.Issuer; } + } + + public Time StartDate + { + get { return tbsCert.StartDate; } + } + + public Time EndDate + { + get { return tbsCert.EndDate; } + } + + public X509Name Subject + { + get { return tbsCert.Subject; } + } + + public SubjectPublicKeyInfo SubjectPublicKeyInfo + { + get { return tbsCert.SubjectPublicKeyInfo; } + } + + public AlgorithmIdentifier SignatureAlgorithm + { + get { return sigAlgID; } + } + + public DerBitString Signature + { + get { return sig; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(tbsCert, sigAlgID, sig); + } + } +} diff --git a/crypto/src/asn1/x509/X509DefaultEntryConverter.cs b/crypto/src/asn1/x509/X509DefaultEntryConverter.cs new file mode 100644 index 000000000..7282ead26 --- /dev/null +++ b/crypto/src/asn1/x509/X509DefaultEntryConverter.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * The default converter for X509 DN entries when going from their + * string value to ASN.1 strings. + */ + public class X509DefaultEntryConverter + : X509NameEntryConverter + { + /** + * Apply default conversion 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 override Asn1Object GetConvertedValue( + DerObjectIdentifier oid, + string value) + { + if (value.Length != 0 && value[0] == '#') + { + try + { + return ConvertHexEncoded(value, 1); + } + catch (IOException) + { + throw new Exception("can't recode value for oid " + oid.Id); + } + } + + if (value.Length != 0 && value[0] == '\\') + { + value = value.Substring(1); + } + + if (oid.Equals(X509Name.EmailAddress) || oid.Equals(X509Name.DC)) + { + return new DerIA5String(value); + } + + if (oid.Equals(X509Name.DateOfBirth)) // accept time string as well as # (for compatibility) + { + return new DerGeneralizedTime(value); + } + + if (oid.Equals(X509Name.C) + || oid.Equals(X509Name.SerialNumber) + || oid.Equals(X509Name.DnQualifier) + || oid.Equals(X509Name.TelephoneNumber)) + { + return new DerPrintableString(value); + } + + return new DerUtf8String(value); + } + } +} diff --git a/crypto/src/asn1/x509/X509Extension.cs b/crypto/src/asn1/x509/X509Extension.cs new file mode 100644 index 000000000..430ce4447 --- /dev/null +++ b/crypto/src/asn1/x509/X509Extension.cs @@ -0,0 +1,79 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * an object for the elements in the X.509 V3 extension block. + */ + public class X509Extension + { + internal bool critical; + internal Asn1OctetString value; + + public X509Extension( + DerBoolean critical, + Asn1OctetString value) + { + if (critical == null) + { + throw new ArgumentNullException("critical"); + } + + this.critical = critical.IsTrue; + this.value = value; + } + + public X509Extension( + bool critical, + Asn1OctetString value) + { + this.critical = critical; + this.value = value; + } + + public bool IsCritical { get { return critical; } } + + public Asn1OctetString Value { get { return value; } } + + public Asn1Encodable GetParsedValue() + { + return ConvertValueToObject(this); + } + + public override int GetHashCode() + { + int vh = this.Value.GetHashCode(); + + return IsCritical ? vh : ~vh; + } + + public override bool Equals( + object obj) + { + X509Extension other = obj as X509Extension; + if (other == null) + { + return false; + } + + return Value.Equals(other.Value) && IsCritical == other.IsCritical; + } + + /// Convert the value of the passed in extension to an object. + /// The extension to parse. + /// The object the value string contains. + /// If conversion is not possible. + public static Asn1Object ConvertValueToObject( + X509Extension ext) + { + try + { + return Asn1Object.FromByteArray(ext.Value.GetOctets()); + } + catch (Exception e) + { + throw new ArgumentException("can't convert extension", e); + } + } + } +} diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs new file mode 100644 index 000000000..5dce5622d --- /dev/null +++ b/crypto/src/asn1/x509/X509Extensions.cs @@ -0,0 +1,451 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Asn1.X509 +{ + public class X509Extensions + : Asn1Encodable + { + /** + * Subject Directory Attributes + */ + public static readonly DerObjectIdentifier SubjectDirectoryAttributes = new DerObjectIdentifier("2.5.29.9"); + + /** + * Subject Key Identifier + */ + public static readonly DerObjectIdentifier SubjectKeyIdentifier = new DerObjectIdentifier("2.5.29.14"); + + /** + * Key Usage + */ + public static readonly DerObjectIdentifier KeyUsage = new DerObjectIdentifier("2.5.29.15"); + + /** + * Private Key Usage Period + */ + public static readonly DerObjectIdentifier PrivateKeyUsagePeriod = new DerObjectIdentifier("2.5.29.16"); + + /** + * Subject Alternative Name + */ + public static readonly DerObjectIdentifier SubjectAlternativeName = new DerObjectIdentifier("2.5.29.17"); + + /** + * Issuer Alternative Name + */ + public static readonly DerObjectIdentifier IssuerAlternativeName = new DerObjectIdentifier("2.5.29.18"); + + /** + * Basic Constraints + */ + public static readonly DerObjectIdentifier BasicConstraints = new DerObjectIdentifier("2.5.29.19"); + + /** + * CRL Number + */ + public static readonly DerObjectIdentifier CrlNumber = new DerObjectIdentifier("2.5.29.20"); + + /** + * Reason code + */ + public static readonly DerObjectIdentifier ReasonCode = new DerObjectIdentifier("2.5.29.21"); + + /** + * Hold Instruction Code + */ + public static readonly DerObjectIdentifier InstructionCode = new DerObjectIdentifier("2.5.29.23"); + + /** + * Invalidity Date + */ + public static readonly DerObjectIdentifier InvalidityDate = new DerObjectIdentifier("2.5.29.24"); + + /** + * Delta CRL indicator + */ + public static readonly DerObjectIdentifier DeltaCrlIndicator = new DerObjectIdentifier("2.5.29.27"); + + /** + * Issuing Distribution Point + */ + public static readonly DerObjectIdentifier IssuingDistributionPoint = new DerObjectIdentifier("2.5.29.28"); + + /** + * Certificate Issuer + */ + public static readonly DerObjectIdentifier CertificateIssuer = new DerObjectIdentifier("2.5.29.29"); + + /** + * Name Constraints + */ + public static readonly DerObjectIdentifier NameConstraints = new DerObjectIdentifier("2.5.29.30"); + + /** + * CRL Distribution Points + */ + public static readonly DerObjectIdentifier CrlDistributionPoints = new DerObjectIdentifier("2.5.29.31"); + + /** + * Certificate Policies + */ + public static readonly DerObjectIdentifier CertificatePolicies = new DerObjectIdentifier("2.5.29.32"); + + /** + * Policy Mappings + */ + public static readonly DerObjectIdentifier PolicyMappings = new DerObjectIdentifier("2.5.29.33"); + + /** + * Authority Key Identifier + */ + public static readonly DerObjectIdentifier AuthorityKeyIdentifier = new DerObjectIdentifier("2.5.29.35"); + + /** + * Policy Constraints + */ + public static readonly DerObjectIdentifier PolicyConstraints = new DerObjectIdentifier("2.5.29.36"); + + /** + * Extended Key Usage + */ + public static readonly DerObjectIdentifier ExtendedKeyUsage = new DerObjectIdentifier("2.5.29.37"); + + /** + * Freshest CRL + */ + public static readonly DerObjectIdentifier FreshestCrl = new DerObjectIdentifier("2.5.29.46"); + + /** + * Inhibit Any Policy + */ + public static readonly DerObjectIdentifier InhibitAnyPolicy = new DerObjectIdentifier("2.5.29.54"); + + /** + * Authority Info Access + */ + public static readonly DerObjectIdentifier AuthorityInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.1"); + + /** + * Subject Info Access + */ + public static readonly DerObjectIdentifier SubjectInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.11"); + + /** + * Logo Type + */ + public static readonly DerObjectIdentifier LogoType = new DerObjectIdentifier("1.3.6.1.5.5.7.1.12"); + + /** + * BiometricInfo + */ + public static readonly DerObjectIdentifier BiometricInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.1.2"); + + /** + * QCStatements + */ + public static readonly DerObjectIdentifier QCStatements = new DerObjectIdentifier("1.3.6.1.5.5.7.1.3"); + + /** + * Audit identity extension in attribute certificates. + */ + public static readonly DerObjectIdentifier AuditIdentity = new DerObjectIdentifier("1.3.6.1.5.5.7.1.4"); + + /** + * NoRevAvail extension in attribute certificates. + */ + public static readonly DerObjectIdentifier NoRevAvail = new DerObjectIdentifier("2.5.29.56"); + + /** + * TargetInformation extension in attribute certificates. + */ + public static readonly DerObjectIdentifier TargetInformation = new DerObjectIdentifier("2.5.29.55"); + + private readonly IDictionary extensions = Platform.CreateHashtable(); + private readonly IList ordering; + + public static X509Extensions GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static X509Extensions GetInstance( + object obj) + { + if (obj == null || obj is X509Extensions) + { + return (X509Extensions) obj; + } + + if (obj is Asn1Sequence) + { + return new X509Extensions((Asn1Sequence) obj); + } + + if (obj is Asn1TaggedObject) + { + return GetInstance(((Asn1TaggedObject) obj).GetObject()); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + * + * the extensions are a list of constructed sequences, either with (Oid, OctetString) or (Oid, Boolean, OctetString) + */ + private X509Extensions( + Asn1Sequence seq) + { + this.ordering = Platform.CreateArrayList(); + + foreach (Asn1Encodable ae in seq) + { + Asn1Sequence s = Asn1Sequence.GetInstance(ae.ToAsn1Object()); + + if (s.Count < 2 || s.Count > 3) + throw new ArgumentException("Bad sequence size: " + s.Count); + + DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()); + + bool isCritical = s.Count == 3 + && DerBoolean.GetInstance(s[1].ToAsn1Object()).IsTrue; + + Asn1OctetString octets = Asn1OctetString.GetInstance(s[s.Count - 1].ToAsn1Object()); + + extensions.Add(oid, new X509Extension(isCritical, octets)); + ordering.Add(oid); + } + } + + /** + * constructor from a table of extensions. + *

+ * it's is assumed the table contains Oid/string pairs.

+ */ + public X509Extensions( + IDictionary extensions) + : this(null, extensions) + { + } + + /** + * Constructor from a table of extensions with ordering. + *

+ * It's is assumed the table contains Oid/string pairs.

+ */ + public X509Extensions( + IList ordering, + IDictionary extensions) + { + if (ordering == null) + { + this.ordering = Platform.CreateArrayList(extensions.Keys); + } + else + { + this.ordering = Platform.CreateArrayList(ordering); + } + + foreach (DerObjectIdentifier oid in this.ordering) + { + this.extensions.Add(oid, (X509Extension)extensions[oid]); + } + } + + /** + * Constructor from two vectors + * + * @param objectIDs an ArrayList of the object identifiers. + * @param values an ArrayList of the extension values. + */ + public X509Extensions( + IList oids, + IList values) + { + this.ordering = Platform.CreateArrayList(oids); + + int count = 0; + foreach (DerObjectIdentifier oid in this.ordering) + { + this.extensions.Add(oid, (X509Extension)values[count++]); + } + } + +#if !SILVERLIGHT + /** + * constructor from a table of extensions. + *

+ * it's is assumed the table contains Oid/string pairs.

+ */ + [Obsolete] + public X509Extensions( + Hashtable extensions) + : this(null, extensions) + { + } + + /** + * Constructor from a table of extensions with ordering. + *

+ * It's is assumed the table contains Oid/string pairs.

+ */ + [Obsolete] + public X509Extensions( + ArrayList ordering, + Hashtable extensions) + { + if (ordering == null) + { + this.ordering = Platform.CreateArrayList(extensions.Keys); + } + else + { + this.ordering = Platform.CreateArrayList(ordering); + } + + foreach (DerObjectIdentifier oid in this.ordering) + { + this.extensions.Add(oid, (X509Extension) extensions[oid]); + } + } + + /** + * Constructor from two vectors + * + * @param objectIDs an ArrayList of the object identifiers. + * @param values an ArrayList of the extension values. + */ + [Obsolete] + public X509Extensions( + ArrayList oids, + ArrayList values) + { + this.ordering = Platform.CreateArrayList(oids); + + int count = 0; + foreach (DerObjectIdentifier oid in this.ordering) + { + this.extensions.Add(oid, (X509Extension) values[count++]); + } + } +#endif + + [Obsolete("Use ExtensionOids IEnumerable property")] + public IEnumerator Oids() + { + return ExtensionOids.GetEnumerator(); + } + + /** + * return an Enumeration of the extension field's object ids. + */ + public IEnumerable ExtensionOids + { + get { return new EnumerableProxy(ordering); } + } + + /** + * return the extension represented by the object identifier + * passed in. + * + * @return the extension if it's present, null otherwise. + */ + public X509Extension GetExtension( + DerObjectIdentifier oid) + { + return (X509Extension) extensions[oid]; + } + + /** + *
+		 *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
+		 *
+		 *     Extension         ::=   SEQUENCE {
+		 *        extnId            EXTENSION.&id ({ExtensionSet}),
+		 *        critical          BOOLEAN DEFAULT FALSE,
+		 *        extnValue         OCTET STRING }
+		 * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector vec = new Asn1EncodableVector(); + + foreach (DerObjectIdentifier oid in ordering) + { + X509Extension ext = (X509Extension) extensions[oid]; + Asn1EncodableVector v = new Asn1EncodableVector(oid); + + if (ext.IsCritical) + { + v.Add(DerBoolean.True); + } + + v.Add(ext.Value); + + vec.Add(new DerSequence(v)); + } + + return new DerSequence(vec); + } + + public bool Equivalent( + X509Extensions other) + { + if (extensions.Count != other.extensions.Count) + return false; + + foreach (DerObjectIdentifier oid in extensions.Keys) + { + if (!extensions[oid].Equals(other.extensions[oid])) + return false; + } + + return true; + } + + public DerObjectIdentifier[] GetExtensionOids() + { + return ToOidArray(ordering); + } + + public DerObjectIdentifier[] GetNonCriticalExtensionOids() + { + return GetExtensionOids(false); + } + + public DerObjectIdentifier[] GetCriticalExtensionOids() + { + return GetExtensionOids(true); + } + + private DerObjectIdentifier[] GetExtensionOids(bool isCritical) + { + IList oids = Platform.CreateArrayList(); + + foreach (DerObjectIdentifier oid in this.ordering) + { + X509Extension ext = (X509Extension)extensions[oid]; + if (ext.IsCritical == isCritical) + { + oids.Add(oid); + } + } + + return ToOidArray(oids); + } + + private static DerObjectIdentifier[] ToOidArray(IList oids) + { + DerObjectIdentifier[] oidArray = new DerObjectIdentifier[oids.Count]; + oids.CopyTo(oidArray, 0); + return oidArray; + } + } +} diff --git a/crypto/src/asn1/x509/X509ExtensionsGenerator.cs b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs new file mode 100644 index 000000000..d6f567b22 --- /dev/null +++ b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /// Generator for X.509 extensions + public class X509ExtensionsGenerator + { + private IDictionary extensions = Platform.CreateHashtable(); + private IList extOrdering = Platform.CreateArrayList(); + + /// Reset the generator + public void Reset() + { + extensions = Platform.CreateHashtable(); + extOrdering = Platform.CreateArrayList(); + } + + /// + /// Add an extension with the given oid and the passed in value to be included + /// in the OCTET STRING associated with the extension. + /// + /// OID for the extension. + /// True if critical, false otherwise. + /// The ASN.1 object to be included in the extension. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + Asn1Encodable extValue) + { + byte[] encoded; + try + { + encoded = extValue.GetDerEncoded(); + } + catch (Exception e) + { + throw new ArgumentException("error encoding value: " + e); + } + + this.AddExtension(oid, critical, encoded); + } + + /// + /// Add an extension with the given oid and the passed in byte array to be wrapped + /// in the OCTET STRING associated with the extension. + /// + /// OID for the extension. + /// True if critical, false otherwise. + /// The byte array to be wrapped. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + byte[] extValue) + { + if (extensions.Contains(oid)) + { + throw new ArgumentException("extension " + oid + " already added"); + } + + extOrdering.Add(oid); + extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue))); + } + + /// Return true if there are no extension present in this generator. + /// True if empty, false otherwise + public bool IsEmpty + { + get { return extOrdering.Count < 1; } + } + + /// Generate an X509Extensions object based on the current state of the generator. + /// An X509Extensions object + public X509Extensions Generate() + { + return new X509Extensions(extOrdering, extensions); + } + } +} diff --git a/crypto/src/asn1/x509/X509Name.cs b/crypto/src/asn1/x509/X509Name.cs new file mode 100644 index 000000000..a77707354 --- /dev/null +++ b/crypto/src/asn1/x509/X509Name.cs @@ -0,0 +1,1188 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +#if SILVERLIGHT +using System.Collections.Generic; +#endif + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + *
+    *     RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+    *
+    *     RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+    *
+    *     AttributeTypeAndValue ::= SEQUENCE {
+    *                                   type  OBJECT IDENTIFIER,
+    *                                   value ANY }
+    * 
+ */ + public class X509Name + : Asn1Encodable + { + /** + * country code - StringType(SIZE(2)) + */ + public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6"); + + /** + * organization - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10"); + + /** + * organizational unit name - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11"); + + /** + * Title + */ + public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12"); + + /** + * common name - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3"); + + /** + * street - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9"); + + /** + * device serial number name - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5"); + + /** + * locality name - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7"); + + /** + * state, or province name - StringType(SIZE(1..64)) + */ + public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8"); + + /** + * Naming attributes of type X520name + */ + public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4"); + public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42"); + public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43"); + public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44"); + public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45"); + + /** + * businessCategory - DirectoryString(SIZE(1..128) + */ + public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier( + "2.5.4.15"); + + /** + * postalCode - DirectoryString(SIZE(1..40) + */ + public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier( + "2.5.4.17"); + + /** + * dnQualifier - DirectoryString(SIZE(1..64) + */ + public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier( + "2.5.4.46"); + + /** + * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64) + */ + public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier( + "2.5.4.65"); + + /** + * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z + */ + public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier( + "1.3.6.1.5.5.7.9.1"); + + /** + * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128) + */ + public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier( + "1.3.6.1.5.5.7.9.2"); + + /** + * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f" + */ + public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier( + "1.3.6.1.5.5.7.9.3"); + + /** + * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 + * codes only + */ + public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier( + "1.3.6.1.5.5.7.9.4"); + + /** + * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 + * codes only + */ + public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier( + "1.3.6.1.5.5.7.9.5"); + + /** + * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64) + */ + public static readonly DerObjectIdentifier NameAtBirth = new DerObjectIdentifier("1.3.36.8.3.14"); + + /** + * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF + * DirectoryString(SIZE(1..30)) + */ + public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16"); + + /** + * RFC 2256 dmdName + */ + public static readonly DerObjectIdentifier DmdName = new DerObjectIdentifier("2.5.4.54"); + + /** + * id-at-telephoneNumber + */ + public static readonly DerObjectIdentifier TelephoneNumber = X509ObjectIdentifiers.id_at_telephoneNumber; + + /** + * id-at-name + */ + public static readonly DerObjectIdentifier Name = X509ObjectIdentifiers.id_at_name; + + /** + * Email address (RSA PKCS#9 extension) - IA5String. + *

Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.

+ */ + public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress; + + /** + * more from PKCS#9 + */ + public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName; + public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress; + + /** + * email address in Verisign certificates + */ + public static readonly DerObjectIdentifier E = EmailAddress; + + /* + * others... + */ + public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25"); + + /** + * LDAP User id. + */ + public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1"); + + /** + * determines whether or not strings should be processed and printed + * from back to front. + */ +// public static bool DefaultReverse = false; + public static bool DefaultReverse + { + get { return defaultReverse[0]; } + set { defaultReverse[0] = value; } + } + + private static readonly bool[] defaultReverse = { false }; + +#if SILVERLIGHT + /** + * default look up table translating OID values into their common symbols following + * the convention in RFC 2253 with a few extras + */ + public static readonly IDictionary DefaultSymbols = Platform.CreateHashtable(); + + /** + * look up table translating OID values into their common symbols following the convention in RFC 2253 + */ + public static readonly IDictionary RFC2253Symbols = Platform.CreateHashtable(); + + /** + * look up table translating OID values into their common symbols following the convention in RFC 1779 + * + */ + public static readonly IDictionary RFC1779Symbols = Platform.CreateHashtable(); + + /** + * look up table translating common symbols into their OIDS. + */ + public static readonly IDictionary DefaultLookup = Platform.CreateHashtable(); +#else + /** + * default look up table translating OID values into their common symbols following + * the convention in RFC 2253 with a few extras + */ + public static readonly Hashtable DefaultSymbols = new Hashtable(); + + /** + * look up table translating OID values into their common symbols following the convention in RFC 2253 + */ + public static readonly Hashtable RFC2253Symbols = new Hashtable(); + + /** + * look up table translating OID values into their common symbols following the convention in RFC 1779 + * + */ + public static readonly Hashtable RFC1779Symbols = new Hashtable(); + + /** + * look up table translating common symbols into their OIDS. + */ + public static readonly Hashtable DefaultLookup = new Hashtable(); +#endif + + static X509Name() + { + DefaultSymbols.Add(C, "C"); + DefaultSymbols.Add(O, "O"); + DefaultSymbols.Add(T, "T"); + DefaultSymbols.Add(OU, "OU"); + DefaultSymbols.Add(CN, "CN"); + DefaultSymbols.Add(L, "L"); + DefaultSymbols.Add(ST, "ST"); + DefaultSymbols.Add(SerialNumber, "SERIALNUMBER"); + DefaultSymbols.Add(EmailAddress, "E"); + DefaultSymbols.Add(DC, "DC"); + DefaultSymbols.Add(UID, "UID"); + DefaultSymbols.Add(Street, "STREET"); + DefaultSymbols.Add(Surname, "SURNAME"); + DefaultSymbols.Add(GivenName, "GIVENNAME"); + DefaultSymbols.Add(Initials, "INITIALS"); + DefaultSymbols.Add(Generation, "GENERATION"); + DefaultSymbols.Add(UnstructuredAddress, "unstructuredAddress"); + DefaultSymbols.Add(UnstructuredName, "unstructuredName"); + DefaultSymbols.Add(UniqueIdentifier, "UniqueIdentifier"); + DefaultSymbols.Add(DnQualifier, "DN"); + DefaultSymbols.Add(Pseudonym, "Pseudonym"); + DefaultSymbols.Add(PostalAddress, "PostalAddress"); + DefaultSymbols.Add(NameAtBirth, "NameAtBirth"); + DefaultSymbols.Add(CountryOfCitizenship, "CountryOfCitizenship"); + DefaultSymbols.Add(CountryOfResidence, "CountryOfResidence"); + DefaultSymbols.Add(Gender, "Gender"); + DefaultSymbols.Add(PlaceOfBirth, "PlaceOfBirth"); + DefaultSymbols.Add(DateOfBirth, "DateOfBirth"); + DefaultSymbols.Add(PostalCode, "PostalCode"); + DefaultSymbols.Add(BusinessCategory, "BusinessCategory"); + DefaultSymbols.Add(TelephoneNumber, "TelephoneNumber"); + + RFC2253Symbols.Add(C, "C"); + RFC2253Symbols.Add(O, "O"); + RFC2253Symbols.Add(OU, "OU"); + RFC2253Symbols.Add(CN, "CN"); + RFC2253Symbols.Add(L, "L"); + RFC2253Symbols.Add(ST, "ST"); + RFC2253Symbols.Add(Street, "STREET"); + RFC2253Symbols.Add(DC, "DC"); + RFC2253Symbols.Add(UID, "UID"); + + RFC1779Symbols.Add(C, "C"); + RFC1779Symbols.Add(O, "O"); + RFC1779Symbols.Add(OU, "OU"); + RFC1779Symbols.Add(CN, "CN"); + RFC1779Symbols.Add(L, "L"); + RFC1779Symbols.Add(ST, "ST"); + RFC1779Symbols.Add(Street, "STREET"); + + DefaultLookup.Add("c", C); + DefaultLookup.Add("o", O); + DefaultLookup.Add("t", T); + DefaultLookup.Add("ou", OU); + DefaultLookup.Add("cn", CN); + DefaultLookup.Add("l", L); + DefaultLookup.Add("st", ST); + DefaultLookup.Add("serialnumber", SerialNumber); + DefaultLookup.Add("street", Street); + DefaultLookup.Add("emailaddress", E); + DefaultLookup.Add("dc", DC); + DefaultLookup.Add("e", E); + DefaultLookup.Add("uid", UID); + DefaultLookup.Add("surname", Surname); + DefaultLookup.Add("givenname", GivenName); + DefaultLookup.Add("initials", Initials); + DefaultLookup.Add("generation", Generation); + DefaultLookup.Add("unstructuredaddress", UnstructuredAddress); + DefaultLookup.Add("unstructuredname", UnstructuredName); + DefaultLookup.Add("uniqueidentifier", UniqueIdentifier); + DefaultLookup.Add("dn", DnQualifier); + DefaultLookup.Add("pseudonym", Pseudonym); + DefaultLookup.Add("postaladdress", PostalAddress); + DefaultLookup.Add("nameofbirth", NameAtBirth); + DefaultLookup.Add("countryofcitizenship", CountryOfCitizenship); + DefaultLookup.Add("countryofresidence", CountryOfResidence); + DefaultLookup.Add("gender", Gender); + DefaultLookup.Add("placeofbirth", PlaceOfBirth); + DefaultLookup.Add("dateofbirth", DateOfBirth); + DefaultLookup.Add("postalcode", PostalCode); + DefaultLookup.Add("businesscategory", BusinessCategory); + DefaultLookup.Add("telephonenumber", TelephoneNumber); + } + + private readonly IList ordering = Platform.CreateArrayList(); + private readonly X509NameEntryConverter converter; + + private IList values = Platform.CreateArrayList(); + private IList added = Platform.CreateArrayList(); + private Asn1Sequence seq; + + /** + * Return a X509Name based on the passed in tagged object. + * + * @param obj tag object holding name. + * @param explicitly true if explicitly tagged false otherwise. + * @return the X509Name + */ + public static X509Name GetInstance( + Asn1TaggedObject obj, + bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static X509Name GetInstance( + object obj) + { + if (obj == null || obj is X509Name) + return (X509Name)obj; + + if (obj != null) + return new X509Name(Asn1Sequence.GetInstance(obj)); + + throw new ArgumentException("null object in factory", "obj"); + } + + protected X509Name() + { + } + + /** + * Constructor from Asn1Sequence + * + * the principal will be a list of constructed sets, each containing an (OID, string) pair. + */ + protected X509Name( + Asn1Sequence seq) + { + this.seq = seq; + + foreach (Asn1Encodable asn1Obj in seq) + { + Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object()); + + for (int i = 0; i < asn1Set.Count; i++) + { + Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object()); + + if (s.Count != 2) + throw new ArgumentException("badly sized pair"); + + ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object())); + + Asn1Object derValue = s[1].ToAsn1Object(); + if (derValue is IAsn1String && !(derValue is DerUniversalString)) + { + string v = ((IAsn1String)derValue).GetString(); + if (v.StartsWith("#")) + { + v = "\\" + v; + } + + values.Add(v); + } + else + { + values.Add("#" + Hex.ToHexString(derValue.GetEncoded())); + } + + added.Add(i != 0); + } + } + } + +#if !SILVERLIGHT + [Obsolete] + public X509Name( + ArrayList ordering, + Hashtable attributes) + : this(ordering, attributes, new X509DefaultEntryConverter()) + { + } +#endif + + /** + * Constructor from a table of attributes with ordering. + *

+ * 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 ArrayList should contain the OIDs + * in the order they are meant to be encoded or printed in ToString.

+ */ + public X509Name( + IList ordering, + IDictionary attributes) + : this(ordering, attributes, new X509DefaultEntryConverter()) + { + } + +#if !SILVERLIGHT + [Obsolete] + public X509Name( + ArrayList ordering, + Hashtable attributes, + X509NameEntryConverter converter) + : this((IList)ordering, (IDictionary)attributes, converter) + { + } +#endif + + /** + * Constructor from a table of attributes with ordering. + *

+ * 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 ArrayList should contain the OIDs + * in the order they are meant to be encoded or printed in ToString.

+ *

+ * The passed in converter will be used to convert the strings into their + * ASN.1 counterparts.

+ */ + public X509Name( + IList ordering, + IDictionary attributes, + X509NameEntryConverter converter) + { + this.converter = converter; + + foreach (DerObjectIdentifier oid in ordering) + { + object attribute = attributes[oid]; + if (attribute == null) + { + throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name"); + } + + this.ordering.Add(oid); + this.added.Add(false); + this.values.Add(attribute); // copy the hash table + } + } + +#if !SILVERLIGHT + [Obsolete] + public X509Name( + ArrayList oids, + ArrayList values) + : this(oids, values, new X509DefaultEntryConverter()) + { + } +#endif + + /** + * Takes two vectors one of the oids and the other of the values. + */ + public X509Name( + IList oids, + IList values) + : this(oids, values, new X509DefaultEntryConverter()) + { + } + +#if !SILVERLIGHT + [Obsolete] + public X509Name( + ArrayList oids, + ArrayList values, + X509NameEntryConverter converter) + : this((IList)oids, (IList)values, converter) + { + } +#endif + + /** + * Takes two vectors one of the oids and the other of the values. + *

+ * The passed in converter will be used to convert the strings into their + * ASN.1 counterparts.

+ */ + public X509Name( + IList oids, + IList values, + X509NameEntryConverter converter) + { + this.converter = converter; + + if (oids.Count != values.Count) + { + throw new ArgumentException("'oids' must be same length as 'values'."); + } + + for (int i = 0; i < oids.Count; i++) + { + this.ordering.Add(oids[i]); + this.values.Add(values[i]); + this.added.Add(false); + } + } + +// private static bool IsEncoded( +// string s) +// { +// return s.StartsWith("#"); +// } + + /** + * 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. + */ + public X509Name( + string dirName) + : this(DefaultReverse, (IDictionary)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. + */ + 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. + */ + public X509Name( + bool reverse, + string dirName) + : this(reverse, (IDictionary)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. + */ + public X509Name( + bool reverse, + string dirName, + X509NameEntryConverter converter) + : this(reverse, DefaultLookup, dirName, converter) + { + } + +#if !SILVERLIGHT + [Obsolete] + public X509Name( + bool reverse, + Hashtable lookUp, + string dirName) + : this(reverse, lookUp, dirName, new X509DefaultEntryConverter()) + { + } +#endif + + /** + * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or + * some such, converting it into an ordered set of name attributes. lookUp + * should provide a table of lookups, indexed by lowercase only strings and + * yielding a DerObjectIdentifier, other than that OID. and numeric oids + * will be processed automatically. + *
+ * 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. + */ + public X509Name( + bool reverse, + IDictionary lookUp, + string dirName) + : this(reverse, lookUp, dirName, new X509DefaultEntryConverter()) + { + } + + private DerObjectIdentifier DecodeOid( + string name, + IDictionary lookUp) + { + if (Platform.ToUpperInvariant(name).StartsWith("OID.")) + { + return new DerObjectIdentifier(name.Substring(4)); + } + else if (name[0] >= '0' && name[0] <= '9') + { + return new DerObjectIdentifier(name); + } + + DerObjectIdentifier oid = (DerObjectIdentifier)lookUp[Platform.ToLowerInvariant(name)]; + if (oid == null) + { + throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name"); + } + + return oid; + } + + /** + * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or + * some such, converting it into an ordered set of name attributes. lookUp + * should provide a table of lookups, indexed by lowercase only strings and + * yielding a DerObjectIdentifier, other than that OID. and numeric oids + * 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. + *
+ * @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( + bool reverse, + IDictionary lookUp, + string dirName, + X509NameEntryConverter converter) + { + this.converter = converter; + X509NameTokenizer nTok = new X509NameTokenizer(dirName); + + while (nTok.HasMoreTokens()) + { + string token = nTok.NextToken(); + int index = token.IndexOf('='); + + if (index == -1) + { + throw new ArgumentException("badly formated directory string"); + } + + string name = token.Substring(0, index); + string value = token.Substring(index + 1); + DerObjectIdentifier oid = DecodeOid(name, lookUp); + + if (value.IndexOf('+') > 0) + { + X509NameTokenizer vTok = new X509NameTokenizer(value, '+'); + string v = vTok.NextToken(); + + this.ordering.Add(oid); + this.values.Add(v); + this.added.Add(false); + + while (vTok.HasMoreTokens()) + { + string sv = vTok.NextToken(); + int ndx = sv.IndexOf('='); + + string nm = sv.Substring(0, ndx); + string vl = sv.Substring(ndx + 1); + this.ordering.Add(DecodeOid(nm, lookUp)); + this.values.Add(vl); + this.added.Add(true); + } + } + else + { + this.ordering.Add(oid); + this.values.Add(value); + this.added.Add(false); + } + } + + if (reverse) + { +// this.ordering.Reverse(); +// this.values.Reverse(); +// this.added.Reverse(); + IList o = Platform.CreateArrayList(); + IList v = Platform.CreateArrayList(); + IList a = Platform.CreateArrayList(); + int count = 1; + + for (int i = 0; i < this.ordering.Count; i++) + { + if (!((bool) this.added[i])) + { + count = 0; + } + + int index = count++; + + o.Insert(index, this.ordering[i]); + v.Insert(index, this.values[i]); + a.Insert(index, this.added[i]); + } + + this.ordering = o; + this.values = v; + this.added = a; + } + } + +#if !SILVERLIGHT + /** + * return an ArrayList of the oids in the name, in the order they were found. + */ + [Obsolete("Use 'GetOidList' instead")] + public ArrayList GetOids() + { + return new ArrayList(ordering); + } +#endif + + /** + * return an IList of the oids in the name, in the order they were found. + */ + public IList GetOidList() + { + return Platform.CreateArrayList(ordering); + } + +#if !SILVERLIGHT + /** + * return an ArrayList of the values found in the name, in the order they + * were found. + */ + [Obsolete("Use 'GetValueList' instead")] + public ArrayList GetValues() + { + return new ArrayList(values); + } +#endif + + /** + * return an IList of the values found in the name, in the order they + * were found. + */ + public IList GetValueList() + { + return Platform.CreateArrayList(values); + } + +#if !SILVERLIGHT + /** + * return an ArrayList of the values found in the name, in the order they + * were found, with the DN label corresponding to passed in oid. + */ + public ArrayList GetValues( + DerObjectIdentifier oid) + { + ArrayList v = new ArrayList(); + DoGetValueList(oid, v); + return v; + } +#endif + + /** + * return an IList of the values found in the name, in the order they + * were found, with the DN label corresponding to passed in oid. + */ + public IList GetValueList(DerObjectIdentifier oid) + { + IList v = Platform.CreateArrayList(); + DoGetValueList(oid, v); + return v; + } + + private void DoGetValueList(DerObjectIdentifier oid, IList v) + { + for (int i = 0; i != values.Count; i++) + { + if (ordering[i].Equals(oid)) + { + string val = (string)values[i]; + + if (val.StartsWith("\\#")) + { + val = val.Substring(1); + } + + v.Add(val); + } + } + } + + public override Asn1Object ToAsn1Object() + { + if (seq == null) + { + Asn1EncodableVector vec = new Asn1EncodableVector(); + Asn1EncodableVector sVec = new Asn1EncodableVector(); + DerObjectIdentifier lstOid = null; + + for (int i = 0; i != ordering.Count; i++) + { + DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i]; + string str = (string)values[i]; + + if (lstOid == null + || ((bool)this.added[i])) + { + } + else + { + vec.Add(new DerSet(sVec)); + sVec = new Asn1EncodableVector(); + } + + sVec.Add( + new DerSequence( + oid, + converter.GetConvertedValue(oid, str))); + + lstOid = oid; + } + + vec.Add(new DerSet(sVec)); + + seq = new DerSequence(vec); + } + + return seq; + } + + /// The X509Name object to test equivalency against. + /// If true, the order of elements must be the same, + /// as well as the values associated with each element. + public bool Equivalent( + X509Name other, + bool inOrder) + { + if (!inOrder) + return this.Equivalent(other); + + if (other == null) + return false; + + if (other == this) + return true; + + int orderingSize = ordering.Count; + + if (orderingSize != other.ordering.Count) + return false; + + for (int i = 0; i < orderingSize; i++) + { + DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i]; + DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i]; + + if (!oid.Equals(oOid)) + return false; + + string val = (string) values[i]; + string oVal = (string) other.values[i]; + + if (!equivalentStrings(val, oVal)) + return false; + } + + return true; + } + + /** + * test for equivalence - note: case is ignored. + */ + public bool Equivalent( + X509Name other) + { + if (other == null) + return false; + + if (other == this) + return true; + + int orderingSize = ordering.Count; + + if (orderingSize != other.ordering.Count) + { + return false; + } + + bool[] indexes = new bool[orderingSize]; + int start, end, delta; + + if (ordering[0].Equals(other.ordering[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) + { + bool found = false; + DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i]; + string value = (string)values[i]; + + for (int j = 0; j < orderingSize; j++) + { + if (indexes[j]) + { + continue; + } + + DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j]; + + if (oid.Equals(oOid)) + { + string oValue = (string)other.values[j]; + + if (equivalentStrings(value, oValue)) + { + indexes[j] = true; + found = true; + break; + } + } + } + + if (!found) + { + return false; + } + } + + return true; + } + + private static bool equivalentStrings( + string s1, + string s2) + { + string v1 = canonicalize(s1); + string v2 = canonicalize(s2); + + if (!v1.Equals(v2)) + { + v1 = stripInternalSpaces(v1); + v2 = stripInternalSpaces(v2); + + if (!v1.Equals(v2)) + { + return false; + } + } + + return true; + } + + private static string canonicalize( + string s) + { + string v = Platform.ToLowerInvariant(s).Trim(); + + if (v.StartsWith("#")) + { + Asn1Object obj = decodeObject(v); + + if (obj is IAsn1String) + { + v = Platform.ToLowerInvariant(((IAsn1String)obj).GetString()).Trim(); + } + } + + return v; + } + + private static Asn1Object decodeObject( + string v) + { + try + { + return Asn1Object.FromByteArray(Hex.Decode(v.Substring(1))); + } + catch (IOException e) + { + throw new InvalidOperationException("unknown encoding in name: " + e.Message, e); + } + } + + private static string stripInternalSpaces( + string str) + { + StringBuilder res = new StringBuilder(); + + if (str.Length != 0) + { + char c1 = str[0]; + + res.Append(c1); + + for (int k = 1; k < str.Length; k++) + { + char c2 = str[k]; + if (!(c1 == ' ' && c2 == ' ')) + { + res.Append(c2); + } + c1 = c2; + } + } + + return res.ToString(); + } + + private void AppendValue( + StringBuilder buf, + IDictionary oidSymbols, + DerObjectIdentifier oid, + string val) + { + string sym = (string)oidSymbols[oid]; + + if (sym != null) + { + buf.Append(sym); + } + else + { + buf.Append(oid.Id); + } + + buf.Append('='); + + int index = buf.Length; + + buf.Append(val); + + int end = buf.Length; + + if (val.StartsWith("\\#")) + { + index += 2; + } + + while (index != end) + { + if ((buf[index] == ',') + || (buf[index] == '"') + || (buf[index] == '\\') + || (buf[index] == '+') + || (buf[index] == '=') + || (buf[index] == '<') + || (buf[index] == '>') + || (buf[index] == ';')) + { + buf.Insert(index++, "\\"); + end++; + } + + index++; + } + } + +#if !SILVERLIGHT + [Obsolete] + public string ToString( + bool reverse, + Hashtable oidSymbols) + { + return ToString(reverse, (IDictionary)oidSymbols); + } +#endif + + /** + * 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( + bool reverse, + IDictionary oidSymbols) + { +#if SILVERLIGHT + List components = new List(); +#else + ArrayList components = new ArrayList(); +#endif + + StringBuilder ava = null; + + for (int i = 0; i < ordering.Count; i++) + { + if ((bool) added[i]) + { + ava.Append('+'); + AppendValue(ava, oidSymbols, + (DerObjectIdentifier)ordering[i], + (string)values[i]); + } + else + { + ava = new StringBuilder(); + AppendValue(ava, oidSymbols, + (DerObjectIdentifier)ordering[i], + (string)values[i]); + components.Add(ava); + } + } + + if (reverse) + { + components.Reverse(); + } + + StringBuilder buf = new StringBuilder(); + + if (components.Count > 0) + { + buf.Append(components[0].ToString()); + + for (int i = 1; i < components.Count; ++i) + { + buf.Append(','); + buf.Append(components[i].ToString()); + } + } + + return buf.ToString(); + } + + public override string ToString() + { + return ToString(DefaultReverse, (IDictionary)DefaultSymbols); + } + } +} diff --git a/crypto/src/asn1/x509/X509NameEntryConverter.cs b/crypto/src/asn1/x509/X509NameEntryConverter.cs new file mode 100644 index 000000000..5872656a9 --- /dev/null +++ b/crypto/src/asn1/x509/X509NameEntryConverter.cs @@ -0,0 +1,89 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.X509 +{ + /** + * 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). + *

+ * An example of an encoder look like below: + *

+     * public class X509DirEntryConverter
+     *     : X509NameEntryConverter
+     * {
+     *     public Asn1Object GetConvertedValue(
+     *         DerObjectIdentifier  oid,
+     *         string               value)
+     *     {
+     *         if (str.Length() != 0 && 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);
+     *         }
+     *     }
+     * }
+	 * 
+ *

+ */ + 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 Asn1Object ConvertHexEncoded( + string hexString, + int offset) + { + string str = hexString.Substring(offset); + + return Asn1Object.FromByteArray(Hex.Decode(str)); + } + + /** + * return true if the passed in string can be represented without + * loss as a PrintableString, false otherwise. + */ + protected bool 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 Asn1Object GetConvertedValue(DerObjectIdentifier oid, string value); + } +} diff --git a/crypto/src/asn1/x509/X509NameTokenizer.cs b/crypto/src/asn1/x509/X509NameTokenizer.cs new file mode 100644 index 000000000..ab5529535 --- /dev/null +++ b/crypto/src/asn1/x509/X509NameTokenizer.cs @@ -0,0 +1,104 @@ +using System.Text; + +namespace 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. + */ + public class X509NameTokenizer + { + private string value; + private int index; + private char separator; + private StringBuilder buffer = new StringBuilder(); + + public X509NameTokenizer( + string oid) + : this(oid, ',') + { + } + + public X509NameTokenizer( + string oid, + char separator) + { + this.value = oid; + this.index = -1; + this.separator = separator; + } + + public bool HasMoreTokens() + { + return index != value.Length; + } + + public string NextToken() + { + if (index == value.Length) + { + return null; + } + + int end = index + 1; + bool quoted = false; + bool escaped = false; + + buffer.Remove(0, buffer.Length); + + while (end != value.Length) + { + char c = value[end]; + + if (c == '"') + { + if (!escaped) + { + quoted = !quoted; + } + else + { + buffer.Append(c); + escaped = false; + } + } + else + { + if (escaped || quoted) + { + if (c == '#' && buffer[buffer.Length - 1] == '=') + { + buffer.Append('\\'); + } + else if (c == '+' && separator != '+') + { + buffer.Append('\\'); + } + buffer.Append(c); + escaped = false; + } + else if (c == '\\') + { + escaped = true; + } + else if (c == separator) + { + break; + } + else + { + buffer.Append(c); + } + } + + end++; + } + + index = end; + + return buffer.ToString().Trim(); + } + } +} diff --git a/crypto/src/asn1/x509/X509ObjectIdentifiers.cs b/crypto/src/asn1/x509/X509ObjectIdentifiers.cs new file mode 100644 index 000000000..f00e31475 --- /dev/null +++ b/crypto/src/asn1/x509/X509ObjectIdentifiers.cs @@ -0,0 +1,59 @@ +namespace Org.BouncyCastle.Asn1.X509 +{ + public abstract class X509ObjectIdentifiers + { + // + // base id + // + internal const string ID = "2.5.4"; + + public static readonly DerObjectIdentifier CommonName = new DerObjectIdentifier(ID + ".3"); + public static readonly DerObjectIdentifier CountryName = new DerObjectIdentifier(ID + ".6"); + public static readonly DerObjectIdentifier LocalityName = new DerObjectIdentifier(ID + ".7"); + public static readonly DerObjectIdentifier StateOrProvinceName = new DerObjectIdentifier(ID + ".8"); + public static readonly DerObjectIdentifier Organization = new DerObjectIdentifier(ID + ".10"); + public static readonly DerObjectIdentifier OrganizationalUnitName = new DerObjectIdentifier(ID + ".11"); + + public static readonly DerObjectIdentifier id_at_telephoneNumber = new DerObjectIdentifier(ID + ".20"); + public static readonly DerObjectIdentifier id_at_name = new DerObjectIdentifier(ID + ".41"); + + // id-SHA1 OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } // + public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26"); + + // + // ripemd160 OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RipeMD-160(1)} + // + public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier("1.3.36.3.2.1"); + + // + // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::= + // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) } + // + public static readonly DerObjectIdentifier RipeMD160WithRsaEncryption = new DerObjectIdentifier("1.3.36.3.3.1.2"); + + public static readonly DerObjectIdentifier IdEARsa = new DerObjectIdentifier("2.5.8.1.1"); + + // id-pkix + public static readonly DerObjectIdentifier IdPkix = new DerObjectIdentifier("1.3.6.1.5.5.7"); + + // + // private internet extensions + // + public static readonly DerObjectIdentifier IdPE = new DerObjectIdentifier(IdPkix + ".1"); + + // + // authority information access + // + public static readonly DerObjectIdentifier IdAD = new DerObjectIdentifier(IdPkix + ".48"); + public static readonly DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier(IdAD + ".2"); + public static readonly DerObjectIdentifier IdADOcsp = new DerObjectIdentifier(IdAD + ".1"); + + // + // OID for ocsp and crl uri in AuthorityInformationAccess extension + // + public static readonly DerObjectIdentifier OcspAccessMethod = IdADOcsp; + public static readonly DerObjectIdentifier CrlAccessMethod = IdADCAIssuers; + } +} diff --git a/crypto/src/asn1/x509/qualified/BiometricData.cs b/crypto/src/asn1/x509/qualified/BiometricData.cs new file mode 100644 index 000000000..61d7c99cb --- /dev/null +++ b/crypto/src/asn1/x509/qualified/BiometricData.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The BiometricData object. + *
+    * BiometricData  ::=  SEQUENCE {
+    *       typeOfBiometricData  TypeOfBiometricData,
+    *       hashAlgorithm        AlgorithmIdentifier,
+    *       biometricDataHash    OCTET STRING,
+    *       sourceDataUri        IA5String OPTIONAL  }
+    * 
+ */ + public class BiometricData + : Asn1Encodable + { + private readonly TypeOfBiometricData typeOfBiometricData; + private readonly AlgorithmIdentifier hashAlgorithm; + private readonly Asn1OctetString biometricDataHash; + private readonly DerIA5String sourceDataUri; + + public static BiometricData GetInstance( + object obj) + { + if (obj == null || obj is BiometricData) + { + return (BiometricData)obj; + } + + if (obj is Asn1Sequence) + { + return new BiometricData(Asn1Sequence.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + private BiometricData( + Asn1Sequence seq) + { + typeOfBiometricData = TypeOfBiometricData.GetInstance(seq[0]); + hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + biometricDataHash = Asn1OctetString.GetInstance(seq[2]); + + if (seq.Count > 3) + { + sourceDataUri = DerIA5String.GetInstance(seq[3]); + } + } + + 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 TypeOfBiometricData + { + get { return typeOfBiometricData; } + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return hashAlgorithm; } + } + + public Asn1OctetString BiometricDataHash + { + get { return biometricDataHash; } + } + + public DerIA5String SourceDataUri + { + get { return sourceDataUri; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector seq = new Asn1EncodableVector( + typeOfBiometricData, hashAlgorithm, biometricDataHash); + + if (sourceDataUri != null) + { + seq.Add(sourceDataUri); + } + + return new DerSequence(seq); + } + } +} diff --git a/crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs b/crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs new file mode 100644 index 000000000..86a4eee0a --- /dev/null +++ b/crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs @@ -0,0 +1,19 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + public abstract class EtsiQCObjectIdentifiers + { + // + // base id + // + public static readonly DerObjectIdentifier IdEtsiQcs = new DerObjectIdentifier("0.4.0.1862.1"); + + public static readonly DerObjectIdentifier IdEtsiQcsQcCompliance = new DerObjectIdentifier(IdEtsiQcs+".1"); + public static readonly DerObjectIdentifier IdEtsiQcsLimitValue = new DerObjectIdentifier(IdEtsiQcs+".2"); + public static readonly DerObjectIdentifier IdEtsiQcsRetentionPeriod = new DerObjectIdentifier(IdEtsiQcs+".3"); + public static readonly DerObjectIdentifier IdEtsiQcsQcSscd = new DerObjectIdentifier(IdEtsiQcs+".4"); + } +} diff --git a/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs new file mode 100644 index 000000000..3300562c8 --- /dev/null +++ b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs @@ -0,0 +1,84 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The Iso4217CurrencyCode object. + *
+    * 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
+    * 
+ */ + public class Iso4217CurrencyCode + : Asn1Encodable, IAsn1Choice + { + internal const int AlphabeticMaxSize = 3; + internal const int NumericMinSize = 1; + internal const int NumericMaxSize = 999; + + internal Asn1Encodable obj; +// internal int numeric; + + public static Iso4217CurrencyCode GetInstance( + object obj) + { + if (obj == null || obj is Iso4217CurrencyCode) + { + return (Iso4217CurrencyCode) obj; + } + + if (obj is DerInteger) + { + DerInteger numericobj = DerInteger.GetInstance(obj); + int numeric = numericobj.Value.IntValue; + return new Iso4217CurrencyCode(numeric); + } + + if (obj is DerPrintableString) + { + DerPrintableString alphabetic = DerPrintableString.GetInstance(obj); + return new Iso4217CurrencyCode(alphabetic.GetString()); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public Iso4217CurrencyCode( + int numeric) + { + if (numeric > NumericMaxSize || numeric < NumericMinSize) + { + throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")"); + } + + obj = new DerInteger(numeric); + } + + public Iso4217CurrencyCode( + string alphabetic) + { + if (alphabetic.Length > AlphabeticMaxSize) + { + throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize); + } + + obj = new DerPrintableString(alphabetic); + } + + public bool IsAlphabetic { get { return obj is DerPrintableString; } } + + public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } } + + public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } } + + public override Asn1Object ToAsn1Object() + { + return obj.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/x509/qualified/MonetaryValue.cs b/crypto/src/asn1/x509/qualified/MonetaryValue.cs new file mode 100644 index 000000000..45e113671 --- /dev/null +++ b/crypto/src/asn1/x509/qualified/MonetaryValue.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The MonetaryValue object. + *
+    * MonetaryValue  ::=  SEQUENCE {
+    *       currency              Iso4217CurrencyCode,
+    *       amount               INTEGER,
+    *       exponent             INTEGER }
+    * -- value = amount * 10^exponent
+    * 
+ */ + public class MonetaryValue + : Asn1Encodable + { + internal Iso4217CurrencyCode currency; + internal DerInteger amount; + internal DerInteger exponent; + + public static MonetaryValue GetInstance( + object obj) + { + if (obj == null || obj is MonetaryValue) + { + return (MonetaryValue) obj; + } + + if (obj is Asn1Sequence) + { + return new MonetaryValue(Asn1Sequence.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + private MonetaryValue( + Asn1Sequence seq) + { + if (seq.Count != 3) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + currency = Iso4217CurrencyCode.GetInstance(seq[0]); + amount = DerInteger.GetInstance(seq[1]); + exponent = DerInteger.GetInstance(seq[2]); + } + + public MonetaryValue( + Iso4217CurrencyCode currency, + int amount, + int exponent) + { + this.currency = currency; + this.amount = new DerInteger(amount); + this.exponent = new DerInteger(exponent); + } + + public Iso4217CurrencyCode Currency + { + get { return currency; } + } + + public BigInteger Amount + { + get { return amount.Value; } + } + + public BigInteger Exponent + { + get { return exponent.Value; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(currency, amount, exponent); + } + } +} diff --git a/crypto/src/asn1/x509/qualified/QCStatement.cs b/crypto/src/asn1/x509/qualified/QCStatement.cs new file mode 100644 index 000000000..317f03447 --- /dev/null +++ b/crypto/src/asn1/x509/qualified/QCStatement.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The QCStatement object. + *
+    * QCStatement ::= SEQUENCE {
+    *   statementId        OBJECT IDENTIFIER,
+    *   statementInfo      ANY DEFINED BY statementId OPTIONAL}
+    * 
+ */ + public class QCStatement + : Asn1Encodable + { + private readonly DerObjectIdentifier qcStatementId; + private readonly Asn1Encodable qcStatementInfo; + + public static QCStatement GetInstance( + object obj) + { + if (obj == null || obj is QCStatement) + { + return (QCStatement) obj; + } + + if (obj is Asn1Sequence) + { + return new QCStatement(Asn1Sequence.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + private QCStatement( + Asn1Sequence seq) + { + qcStatementId = DerObjectIdentifier.GetInstance(seq[0]); + + if (seq.Count > 1) + { + qcStatementInfo = seq[1]; + } + } + + public QCStatement( + DerObjectIdentifier qcStatementId) + { + this.qcStatementId = qcStatementId; + } + + public QCStatement( + DerObjectIdentifier qcStatementId, + Asn1Encodable qcStatementInfo) + { + this.qcStatementId = qcStatementId; + this.qcStatementInfo = qcStatementInfo; + } + + public DerObjectIdentifier StatementId + { + get { return qcStatementId; } + } + + public Asn1Encodable StatementInfo + { + get { return qcStatementInfo; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector seq = new Asn1EncodableVector(qcStatementId); + + if (qcStatementInfo != null) + { + seq.Add(qcStatementInfo); + } + + return new DerSequence(seq); + } + } +} diff --git a/crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs b/crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs new file mode 100644 index 000000000..8ebd69edb --- /dev/null +++ b/crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs @@ -0,0 +1,21 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + public sealed class Rfc3739QCObjectIdentifiers + { + private Rfc3739QCObjectIdentifiers() + { + } + + // + // base id + // + public static readonly DerObjectIdentifier IdQcs = new DerObjectIdentifier("1.3.6.1.5.5.7.11"); + + public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV1 = new DerObjectIdentifier(IdQcs+".1"); + public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV2 = new DerObjectIdentifier(IdQcs+".2"); + } +} diff --git a/crypto/src/asn1/x509/qualified/SemanticsInformation.cs b/crypto/src/asn1/x509/qualified/SemanticsInformation.cs new file mode 100644 index 000000000..72e7cd0e1 --- /dev/null +++ b/crypto/src/asn1/x509/qualified/SemanticsInformation.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The SemanticsInformation object. + *
+    *       SemanticsInformation ::= SEQUENCE {
+    *         semanticsIdentifier        OBJECT IDENTIFIER   OPTIONAL,
+    *         nameRegistrationAuthorities NameRegistrationAuthorities
+    *                                                         OPTIONAL }
+    *         (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+    *          WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+    *
+    *     NameRegistrationAuthorities ::=  SEQUENCE SIZE (1..MAX) OF
+    *         GeneralName
+    * 
+ */ + public class SemanticsInformation + : Asn1Encodable + { + private readonly DerObjectIdentifier semanticsIdentifier; + private readonly GeneralName[] nameRegistrationAuthorities; + + public static SemanticsInformation GetInstance( + object obj) + { + if (obj == null || obj is SemanticsInformation) + { + return (SemanticsInformation) obj; + } + + if (obj is Asn1Sequence) + { + return new SemanticsInformation(Asn1Sequence.GetInstance(obj)); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public SemanticsInformation( + Asn1Sequence seq) + { + if (seq.Count < 1) + { + throw new ArgumentException("no objects in SemanticsInformation"); + } + + IEnumerator e = seq.GetEnumerator(); + e.MoveNext(); + object obj = e.Current; + if (obj is DerObjectIdentifier) + { + semanticsIdentifier = DerObjectIdentifier.GetInstance(obj); + if (e.MoveNext()) + { + obj = e.Current; + } + else + { + obj = null; + } + } + + if (obj != null) + { + Asn1Sequence generalNameSeq = Asn1Sequence.GetInstance(obj ); + nameRegistrationAuthorities = new GeneralName[generalNameSeq.Count]; + for (int i= 0; i < generalNameSeq.Count; i++) + { + nameRegistrationAuthorities[i] = GeneralName.GetInstance(generalNameSeq[i]); + } + } + } + + public SemanticsInformation( + DerObjectIdentifier semanticsIdentifier, + GeneralName[] generalNames) + { + this.semanticsIdentifier = semanticsIdentifier; + this.nameRegistrationAuthorities = generalNames; + } + + public SemanticsInformation( + DerObjectIdentifier semanticsIdentifier) + { + this.semanticsIdentifier = semanticsIdentifier; + } + + public SemanticsInformation( + GeneralName[] generalNames) + { + this.nameRegistrationAuthorities = generalNames; + } + + public DerObjectIdentifier SemanticsIdentifier { get { return semanticsIdentifier; } } + + public GeneralName[] GetNameRegistrationAuthorities() + { + return nameRegistrationAuthorities; + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector seq = new Asn1EncodableVector(); + + if (this.semanticsIdentifier != null) + { + seq.Add(semanticsIdentifier); + } + + if (this.nameRegistrationAuthorities != null) + { + seq.Add(new DerSequence(nameRegistrationAuthorities)); + } + + return new DerSequence(seq); + } + } +} diff --git a/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs new file mode 100644 index 000000000..a77e54acb --- /dev/null +++ b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs @@ -0,0 +1,91 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X509.Qualified +{ + /** + * The TypeOfBiometricData object. + *
+    * TypeOfBiometricData ::= CHOICE {
+    *   predefinedBiometricType   PredefinedBiometricType,
+    *   biometricDataOid          OBJECT IDENTIFIER }
+    *
+    * PredefinedBiometricType ::= INTEGER {
+    *   picture(0),handwritten-signature(1)}
+    *   (picture|handwritten-signature)
+    * 
+ */ + public class TypeOfBiometricData + : Asn1Encodable, IAsn1Choice + { + public const int Picture = 0; + public const int HandwrittenSignature = 1; + + internal Asn1Encodable obj; + + public static TypeOfBiometricData GetInstance( + object obj) + { + if (obj == null || obj is TypeOfBiometricData) + { + return (TypeOfBiometricData) obj; + } + + if (obj is DerInteger) + { + DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj); + int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue; + + return new TypeOfBiometricData(predefinedBiometricType); + } + + if (obj is DerObjectIdentifier) + { + DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj); + return new TypeOfBiometricData(BiometricDataOid); + } + + throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); + } + + public TypeOfBiometricData( + int predefinedBiometricType) + { + if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature) + { + obj = new DerInteger(predefinedBiometricType); + } + else + { + throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType); + } + } + + public TypeOfBiometricData( + DerObjectIdentifier biometricDataOid) + { + obj = biometricDataOid; + } + + public bool IsPredefined + { + get { return obj is DerInteger; } + } + + public int PredefinedBiometricType + { + get { return ((DerInteger) obj).Value.IntValue; } + } + + public DerObjectIdentifier BiometricDataOid + { + get { return (DerObjectIdentifier) obj; } + } + + public override Asn1Object ToAsn1Object() + { + return obj.ToAsn1Object(); + } + } +} diff --git a/crypto/src/asn1/x509/sigi/NameOrPseudonym.cs b/crypto/src/asn1/x509/sigi/NameOrPseudonym.cs new file mode 100644 index 000000000..222895cf1 --- /dev/null +++ b/crypto/src/asn1/x509/sigi/NameOrPseudonym.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.X509.SigI +{ + /** + * Structure for a name or pseudonym. + * + *
+	*       NameOrPseudonym ::= CHOICE {
+	*     	   surAndGivenName SEQUENCE {
+	*     	     surName DirectoryString,
+	*     	     givenName SEQUENCE OF DirectoryString 
+	*         },
+	*     	   pseudonym DirectoryString 
+	*       }
+	* 
+ * + * @see org.bouncycastle.asn1.x509.sigi.PersonalData + * + */ + public class NameOrPseudonym + : Asn1Encodable, IAsn1Choice + { + private readonly DirectoryString pseudonym; + private readonly DirectoryString surname; + private readonly Asn1Sequence givenName; + + public static NameOrPseudonym GetInstance( + object obj) + { + if (obj == null || obj is NameOrPseudonym) + { + return (NameOrPseudonym)obj; + } + + if (obj is IAsn1String) + { + return new NameOrPseudonym(DirectoryString.GetInstance(obj)); + } + + if (obj is Asn1Sequence) + { + return new NameOrPseudonym((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from DERString. + *

+ * The sequence is of type NameOrPseudonym: + *

+ *

+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* 
+ * @param pseudonym pseudonym value to use. + */ + public NameOrPseudonym( + DirectoryString pseudonym) + { + this.pseudonym = pseudonym; + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type NameOrPseudonym: + *

+ *

+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private NameOrPseudonym( + Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + if (!(seq[0] is IAsn1String)) + throw new ArgumentException("Bad object encountered: " + seq[0].GetType().Name); + + surname = DirectoryString.GetInstance(seq[0]); + givenName = Asn1Sequence.GetInstance(seq[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 Pseudonym + { + get { return pseudonym; } + } + + public DirectoryString Surname + { + get { return surname; } + } + + public DirectoryString[] GetGivenName() + { + DirectoryString[] items = new DirectoryString[givenName.Count]; + int count = 0; + foreach (object o in givenName) + { + items[count++] = DirectoryString.GetInstance(o); + } + return items; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + if (pseudonym != null) + { + return pseudonym.ToAsn1Object(); + } + + return new DerSequence(surname, givenName); + } + } +} diff --git a/crypto/src/asn1/x509/sigi/PersonalData.cs b/crypto/src/asn1/x509/sigi/PersonalData.cs new file mode 100644 index 000000000..6acdc7308 --- /dev/null +++ b/crypto/src/asn1/x509/sigi/PersonalData.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X509.SigI +{ + /** + * Contains personal data for the otherName field in the subjectAltNames + * extension. + *

+ *

+	*     PersonalData ::= SEQUENCE {
+	*       nameOrPseudonym NameOrPseudonym,
+	*       nameDistinguisher [0] INTEGER OPTIONAL,
+	*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+	*       placeOfBirth [2] DirectoryString OPTIONAL,
+	*       gender [3] PrintableString OPTIONAL,
+	*       postalAddress [4] DirectoryString OPTIONAL
+	*       }
+	* 
+ * + * @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym + * @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers + */ + public class PersonalData + : Asn1Encodable + { + private readonly NameOrPseudonym nameOrPseudonym; + private readonly BigInteger nameDistinguisher; + private readonly DerGeneralizedTime dateOfBirth; + private readonly DirectoryString placeOfBirth; + private readonly string gender; + private readonly DirectoryString postalAddress; + + public static PersonalData GetInstance( + object obj) + { + if (obj == null || obj is PersonalData) + { + return (PersonalData) obj; + } + + if (obj is Asn1Sequence) + { + return new PersonalData((Asn1Sequence) obj); + } + + throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj"); + } + + /** + * Constructor from Asn1Sequence. + *

+ * The sequence is of type NameOrPseudonym: + *

+ *

+		*     PersonalData ::= SEQUENCE {
+		*       nameOrPseudonym NameOrPseudonym,
+		*       nameDistinguisher [0] INTEGER OPTIONAL,
+		*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+		*       placeOfBirth [2] DirectoryString OPTIONAL,
+		*       gender [3] PrintableString OPTIONAL,
+		*       postalAddress [4] DirectoryString OPTIONAL
+		*       }
+		* 
+ * + * @param seq The ASN.1 sequence. + */ + private PersonalData( + Asn1Sequence seq) + { + if (seq.Count < 1) + throw new ArgumentException("Bad sequence size: " + seq.Count); + + IEnumerator e = seq.GetEnumerator(); + e.MoveNext(); + + nameOrPseudonym = NameOrPseudonym.GetInstance(e.Current); + + while (e.MoveNext()) + { + Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current); + int tag = o.TagNo; + switch (tag) + { + case 0: + nameDistinguisher = DerInteger.GetInstance(o, false).Value; + break; + case 1: + dateOfBirth = DerGeneralizedTime.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 ArgumentException("Bad tag number: " + o.TagNo); + } + } + } + + /** + * 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, + DerGeneralizedTime 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 NameOrPseudonym + { + get { return nameOrPseudonym; } + } + + public BigInteger NameDistinguisher + { + get { return nameDistinguisher; } + } + + public DerGeneralizedTime DateOfBirth + { + get { return dateOfBirth; } + } + + public DirectoryString PlaceOfBirth + { + get { return placeOfBirth; } + } + + public string Gender + { + get { return gender; } + } + + public DirectoryString PostalAddress + { + get { return postalAddress; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *

+ * Returns: + *

+ *

+		*     PersonalData ::= SEQUENCE {
+		*       nameOrPseudonym NameOrPseudonym,
+		*       nameDistinguisher [0] INTEGER OPTIONAL,
+		*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+		*       placeOfBirth [2] DirectoryString OPTIONAL,
+		*       gender [3] PrintableString OPTIONAL,
+		*       postalAddress [4] DirectoryString OPTIONAL
+		*       }
+		* 
+ * + * @return an Asn1Object + */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector vec = new Asn1EncodableVector(); + vec.Add(nameOrPseudonym); + if (nameDistinguisher != null) + { + vec.Add(new DerTaggedObject(false, 0, new DerInteger(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/crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs b/crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs new file mode 100644 index 000000000..682311adc --- /dev/null +++ b/crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs @@ -0,0 +1,49 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X509.SigI +{ + /** + * Object Identifiers of SigI specifciation (German Signature Law + * Interoperability specification). + */ + public sealed class SigIObjectIdentifiers + { + private SigIObjectIdentifiers() + { + } + + public readonly static DerObjectIdentifier IdSigI = new DerObjectIdentifier("1.3.36.8"); + + /** + * Key purpose IDs for German SigI (Signature Interoperability + * Specification) + */ + public readonly static DerObjectIdentifier IdSigIKP = new DerObjectIdentifier(IdSigI + ".2"); + + /** + * Certificate policy IDs for German SigI (Signature Interoperability + * Specification) + */ + public readonly static DerObjectIdentifier IdSigICP = new DerObjectIdentifier(IdSigI + ".1"); + + /** + * Other Name IDs for German SigI (Signature Interoperability Specification) + */ + public readonly static DerObjectIdentifier IdSigION = new DerObjectIdentifier(IdSigI + ".4"); + + /** + * To be used for for the generation of directory service certificates. + */ + public static readonly DerObjectIdentifier IdSigIKPDirectoryService = new DerObjectIdentifier(IdSigIKP + ".1"); + + /** + * ID for PersonalData + */ + public static readonly DerObjectIdentifier IdSigIONPersonalData = new DerObjectIdentifier(IdSigION + ".1"); + + /** + * Certificate is conform to german signature law. + */ + public static readonly DerObjectIdentifier IdSigICPSigConform = new DerObjectIdentifier(IdSigICP + ".1"); + } +} diff --git a/crypto/src/asn1/x9/DHDomainParameters.cs b/crypto/src/asn1/x9/DHDomainParameters.cs new file mode 100644 index 000000000..8de869694 --- /dev/null +++ b/crypto/src/asn1/x9/DHDomainParameters.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public class DHDomainParameters + : Asn1Encodable + { + private readonly DerInteger p, g, q, j; + private readonly DHValidationParms validationParms; + + public static DHDomainParameters GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public static DHDomainParameters GetInstance(object obj) + { + if (obj == null || obj is DHDomainParameters) + return (DHDomainParameters)obj; + + if (obj is Asn1Sequence) + return new DHDomainParameters((Asn1Sequence)obj); + + throw new ArgumentException("Invalid DHDomainParameters: " + obj.GetType().FullName, "obj"); + } + + public DHDomainParameters(DerInteger p, DerInteger g, DerInteger q, DerInteger j, + DHValidationParms validationParms) + { + if (p == null) + throw new ArgumentNullException("p"); + if (g == null) + throw new ArgumentNullException("g"); + if (q == null) + throw new ArgumentNullException("q"); + + this.p = p; + this.g = g; + this.q = q; + this.j = j; + this.validationParms = validationParms; + } + + private DHDomainParameters(Asn1Sequence seq) + { + if (seq.Count < 3 || seq.Count > 5) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + IEnumerator e = seq.GetEnumerator(); + this.p = DerInteger.GetInstance(GetNext(e)); + this.g = DerInteger.GetInstance(GetNext(e)); + this.q = DerInteger.GetInstance(GetNext(e)); + + Asn1Encodable next = GetNext(e); + + if (next != null && next is DerInteger) + { + this.j = DerInteger.GetInstance(next); + next = GetNext(e); + } + + if (next != null) + { + this.validationParms = DHValidationParms.GetInstance(next.ToAsn1Object()); + } + } + + private static Asn1Encodable GetNext(IEnumerator e) + { + return e.MoveNext() ? (Asn1Encodable)e.Current : null; + } + + public DerInteger P + { + get { return this.p; } + } + + public DerInteger G + { + get { return this.g; } + } + + public DerInteger Q + { + get { return this.q; } + } + + public DerInteger J + { + get { return this.j; } + } + + public DHValidationParms ValidationParms + { + get { return this.validationParms; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(p, g, q); + + if (this.j != null) + { + v.Add(this.j); + } + + if (this.validationParms != null) + { + v.Add(this.validationParms); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x9/DHPublicKey.cs b/crypto/src/asn1/x9/DHPublicKey.cs new file mode 100644 index 000000000..1a20a8a16 --- /dev/null +++ b/crypto/src/asn1/x9/DHPublicKey.cs @@ -0,0 +1,44 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public class DHPublicKey + : Asn1Encodable + { + private readonly DerInteger y; + + public static DHPublicKey GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(DerInteger.GetInstance(obj, isExplicit)); + } + + public static DHPublicKey GetInstance(object obj) + { + if (obj == null || obj is DHPublicKey) + return (DHPublicKey)obj; + + if (obj is DerInteger) + return new DHPublicKey((DerInteger)obj); + + throw new ArgumentException("Invalid DHPublicKey: " + obj.GetType().FullName, "obj"); + } + + public DHPublicKey(DerInteger y) + { + if (y == null) + throw new ArgumentNullException("y"); + + this.y = y; + } + + public DerInteger Y + { + get { return this.y; } + } + + public override Asn1Object ToAsn1Object() + { + return this.y; + } + } +} diff --git a/crypto/src/asn1/x9/DHValidationParms.cs b/crypto/src/asn1/x9/DHValidationParms.cs new file mode 100644 index 000000000..a37964cfb --- /dev/null +++ b/crypto/src/asn1/x9/DHValidationParms.cs @@ -0,0 +1,62 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public class DHValidationParms + : Asn1Encodable + { + private readonly DerBitString seed; + private readonly DerInteger pgenCounter; + + public static DHValidationParms GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + + public static DHValidationParms GetInstance(object obj) + { + if (obj == null || obj is DHDomainParameters) + return (DHValidationParms)obj; + + if (obj is Asn1Sequence) + return new DHValidationParms((Asn1Sequence)obj); + + throw new ArgumentException("Invalid DHValidationParms: " + obj.GetType().FullName, "obj"); + } + + public DHValidationParms(DerBitString seed, DerInteger pgenCounter) + { + if (seed == null) + throw new ArgumentNullException("seed"); + if (pgenCounter == null) + throw new ArgumentNullException("pgenCounter"); + + this.seed = seed; + this.pgenCounter = pgenCounter; + } + + private DHValidationParms(Asn1Sequence seq) + { + if (seq.Count != 2) + throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + + this.seed = DerBitString.GetInstance(seq[0]); + this.pgenCounter = DerInteger.GetInstance(seq[1]); + } + + public DerBitString Seed + { + get { return this.seed; } + } + + public DerInteger PgenCounter + { + get { return this.pgenCounter; } + } + + public override Asn1Object ToAsn1Object() + { + return new DerSequence(seed, pgenCounter); + } + } +} diff --git a/crypto/src/asn1/x9/KeySpecificInfo.cs b/crypto/src/asn1/x9/KeySpecificInfo.cs new file mode 100644 index 000000000..46298646b --- /dev/null +++ b/crypto/src/asn1/x9/KeySpecificInfo.cs @@ -0,0 +1,58 @@ +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See + * RFC 2631, or X9.42, for further details. + */ + public class KeySpecificInfo + : Asn1Encodable + { + private DerObjectIdentifier algorithm; + private Asn1OctetString counter; + + public KeySpecificInfo( + DerObjectIdentifier algorithm, + Asn1OctetString counter) + { + this.algorithm = algorithm; + this.counter = counter; + } + + public KeySpecificInfo( + Asn1Sequence seq) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + algorithm = (DerObjectIdentifier)e.Current; + e.MoveNext(); + counter = (Asn1OctetString)e.Current; + } + + public DerObjectIdentifier Algorithm + { + get { return algorithm; } + } + + public Asn1OctetString Counter + { + get { return counter; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  KeySpecificInfo ::= Sequence {
+         *      algorithm OBJECT IDENTIFIER,
+         *      counter OCTET STRING SIZE (4..4)
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(algorithm, counter); + } + } +} diff --git a/crypto/src/asn1/x9/OtherInfo.cs b/crypto/src/asn1/x9/OtherInfo.cs new file mode 100644 index 000000000..21863bd17 --- /dev/null +++ b/crypto/src/asn1/x9/OtherInfo.cs @@ -0,0 +1,88 @@ +using System.Collections; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See + * RFC 2631, or X9.42, for further details. + */ + public class OtherInfo + : Asn1Encodable + { + 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) + { + IEnumerator e = seq.GetEnumerator(); + + e.MoveNext(); + keyInfo = new KeySpecificInfo((Asn1Sequence) e.Current); + + while (e.MoveNext()) + { + DerTaggedObject o = (DerTaggedObject) e.Current; + + if (o.TagNo == 0) + { + partyAInfo = (Asn1OctetString) o.GetObject(); + } + else if ((int) o.TagNo == 2) + { + suppPubInfo = (Asn1OctetString) o.GetObject(); + } + } + } + + public KeySpecificInfo KeyInfo + { + get { return keyInfo; } + } + + public Asn1OctetString PartyAInfo + { + get { return partyAInfo; } + } + + public Asn1OctetString SuppPubInfo + { + get { return suppPubInfo; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  OtherInfo ::= Sequence {
+         *      keyInfo KeySpecificInfo,
+         *      partyAInfo [0] OCTET STRING OPTIONAL,
+         *      suppPubInfo [2] OCTET STRING
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(keyInfo); + + if (partyAInfo != null) + { + v.Add(new DerTaggedObject(0, partyAInfo)); + } + + v.Add(new DerTaggedObject(2, suppPubInfo)); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x9/X962NamedCurves.cs b/crypto/src/asn1/x9/X962NamedCurves.cs new file mode 100644 index 000000000..221300277 --- /dev/null +++ b/crypto/src/asn1/x9/X962NamedCurves.cs @@ -0,0 +1,732 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * table of the current named curves defined in X.962 EC-DSA. + */ + public sealed class X962NamedCurves + { + private X962NamedCurves() + { + } + + internal class Prime192v1Holder + : X9ECParametersHolder + { + private Prime192v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime192v1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp192v1 = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); + + return new X9ECParameters( + cFp192v1, + cFp192v1.DecodePoint( + Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), + new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16), + BigInteger.One, + Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5")); + } + } + + internal class Prime192v2Holder + : X9ECParametersHolder + { + private Prime192v2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime192v2Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp192v2 = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16)); + + return new X9ECParameters( + cFp192v2, + cFp192v2.DecodePoint( + Hex.Decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")), + new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16), + BigInteger.One, + Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6")); + } + } + + internal class Prime192v3Holder + : X9ECParametersHolder + { + private Prime192v3Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime192v3Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp192v3 = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16)); + + return new X9ECParameters( + cFp192v3, + cFp192v3.DecodePoint( + Hex.Decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")), + new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16), + BigInteger.One, + Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e")); + } + } + + internal class Prime239v1Holder + : X9ECParametersHolder + { + private Prime239v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime239v1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp239v1 = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); + + return new X9ECParameters( + cFp239v1, + cFp239v1.DecodePoint( + Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), + new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16), + BigInteger.One, + Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d")); + } + } + + internal class Prime239v2Holder + : X9ECParametersHolder + { + private Prime239v2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime239v2Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp239v2 = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16)); + + return new X9ECParameters( + cFp239v2, + cFp239v2.DecodePoint( + Hex.Decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")), + new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16), + BigInteger.One, + Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616")); + } + } + + internal class Prime239v3Holder + : X9ECParametersHolder + { + private Prime239v3Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime239v3Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp239v3 = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16)); + + return new X9ECParameters( + cFp239v3, + cFp239v3.DecodePoint( + Hex.Decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")), + new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16), + BigInteger.One, + Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff")); + } + } + + internal class Prime256v1Holder + : X9ECParametersHolder + { + private Prime256v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new Prime256v1Holder(); + + protected override X9ECParameters CreateParameters() + { + ECCurve cFp256v1 = new FpCurve( + new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)); + + return new X9ECParameters( + cFp256v1, + cFp256v1.DecodePoint( + Hex.Decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + BigInteger.One, + Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90")); + } + } + + /* + * F2m Curves + */ + internal class C2pnb163v1Holder + : X9ECParametersHolder + { + private C2pnb163v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb163v1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve c2m163v1 = new F2mCurve( + 163, + 1, 2, 8, + new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16), + new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16), + n, h); + + return new X9ECParameters( + c2m163v1, + c2m163v1.DecodePoint( + Hex.Decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")), + n, h, + Hex.Decode("D2COFB15760860DEF1EEF4D696E6768756151754")); + } + } + + internal class C2pnb163v2Holder + : X9ECParametersHolder + { + private C2pnb163v2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb163v2Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve c2m163v2 = new F2mCurve( + 163, + 1, 2, 8, + new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16), + new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16), + n, h); + + return new X9ECParameters( + c2m163v2, + c2m163v2.DecodePoint( + Hex.Decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")), + n, h, + null); + } + } + + internal class C2pnb163v3Holder + : X9ECParametersHolder + { + private C2pnb163v3Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb163v3Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve c2m163v3 = new F2mCurve( + 163, + 1, 2, 8, + new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16), + new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16), + n, h); + + return new X9ECParameters( + c2m163v3, + c2m163v3.DecodePoint(Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")), + n, h, + null); + } + } + + internal class C2pnb176w1Holder + : X9ECParametersHolder + { + private C2pnb176w1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb176w1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16); + BigInteger h = BigInteger.ValueOf(0xFF6E); + + ECCurve c2m176w1 = new F2mCurve( + 176, + 1, 2, 43, + new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16), + new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16), + n, h); + + return new X9ECParameters( + c2m176w1, + c2m176w1.DecodePoint( + Hex.Decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")), + n, h, + null); + } + } + + internal class C2tnb191v1Holder + : X9ECParametersHolder + { + private C2tnb191v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb191v1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16); + BigInteger h = BigInteger.ValueOf(2); + + ECCurve c2m191v1 = new F2mCurve( + 191, + 9, + new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), + new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16), + n, h); + + return new X9ECParameters( + c2m191v1, + c2m191v1.DecodePoint( + Hex.Decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")), + n, h, + Hex.Decode("4E13CA542744D696E67687561517552F279A8C84")); + } + } + + internal class C2tnb191v2Holder + : X9ECParametersHolder + { + private C2tnb191v2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb191v2Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve c2m191v2 = new F2mCurve( + 191, + 9, + new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16), + new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16), + n, h); + + return new X9ECParameters( + c2m191v2, + c2m191v2.DecodePoint( + Hex.Decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")), + n, h, + null); + } + } + + internal class C2tnb191v3Holder + : X9ECParametersHolder + { + private C2tnb191v3Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb191v3Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16); + BigInteger h = BigInteger.ValueOf(6); + + ECCurve c2m191v3 = new F2mCurve( + 191, + 9, + new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16), + new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16), + n, h); + + return new X9ECParameters( + c2m191v3, + c2m191v3.DecodePoint( + Hex.Decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")), + n, h, + null); + } + } + + internal class C2pnb208w1Holder + : X9ECParametersHolder + { + private C2pnb208w1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb208w1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16); + BigInteger h = BigInteger.ValueOf(0xFE48); + + ECCurve c2m208w1 = new F2mCurve( + 208, + 1, 2, 83, + new BigInteger("0", 16), + new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16), + n, h); + + return new X9ECParameters( + c2m208w1, + c2m208w1.DecodePoint( + Hex.Decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")), + n, h, + null); + } + } + + internal class C2tnb239v1Holder + : X9ECParametersHolder + { + private C2tnb239v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb239v1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16); + BigInteger h = BigInteger.ValueOf(4); + + ECCurve c2m239v1 = new F2mCurve( + 239, + 36, + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), + n, h); + + return new X9ECParameters( + c2m239v1, + c2m239v1.DecodePoint( + Hex.Decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")), + n, h, + null); + } + } + + internal class C2tnb239v2Holder + : X9ECParametersHolder + { + private C2tnb239v2Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb239v2Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16); + BigInteger h = BigInteger.ValueOf(6); + + ECCurve c2m239v2 = new F2mCurve( + 239, + 36, + new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16), + new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16), + n, h); + + return new X9ECParameters( + c2m239v2, + c2m239v2.DecodePoint( + Hex.Decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")), + n, h, + null); + } + } + + internal class C2tnb239v3Holder + : X9ECParametersHolder + { + private C2tnb239v3Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb239v3Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16); + BigInteger h = BigInteger.ValueOf(10); + + ECCurve c2m239v3 = new F2mCurve( + 239, + 36, + new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16), + new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16), + n, h); + + return new X9ECParameters( + c2m239v3, + c2m239v3.DecodePoint( + Hex.Decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")), + n, h, + null); + } + } + + internal class C2pnb272w1Holder + : X9ECParametersHolder + { + private C2pnb272w1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb272w1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16); + BigInteger h = BigInteger.ValueOf(0xFF06); + + ECCurve c2m272w1 = new F2mCurve( + 272, + 1, 3, 56, + new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16), + new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16), + n, h); + + return new X9ECParameters( + c2m272w1, + c2m272w1.DecodePoint( + Hex.Decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")), + n, h, + null); + } + } + + internal class C2pnb304w1Holder + : X9ECParametersHolder + { + private C2pnb304w1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb304w1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16); + BigInteger h = BigInteger.ValueOf(0xFE2E); + + ECCurve c2m304w1 = new F2mCurve( + 304, + 1, 2, 11, + new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16), + new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16), + n, h); + + return new X9ECParameters( + c2m304w1, + c2m304w1.DecodePoint( + Hex.Decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")), + n, h, + null); + } + } + + internal class C2tnb359v1Holder + : X9ECParametersHolder + { + private C2tnb359v1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb359v1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16); + BigInteger h = BigInteger.ValueOf(0x4C); + + ECCurve c2m359v1 = new F2mCurve( + 359, + 68, + new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16), + new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16), + n, h); + + return new X9ECParameters( + c2m359v1, + c2m359v1.DecodePoint( + Hex.Decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")), + n, h, + null); + } + } + + internal class C2pnb368w1Holder + : X9ECParametersHolder + { + private C2pnb368w1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2pnb368w1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16); + BigInteger h = BigInteger.ValueOf(0xFF70); + + ECCurve c2m368w1 = new F2mCurve( + 368, + 1, 2, 85, + new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16), + new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16), + n, h); + + return new X9ECParameters( + c2m368w1, + c2m368w1.DecodePoint( + Hex.Decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")), + n, h, + null); + } + } + + internal class C2tnb431r1Holder + : X9ECParametersHolder + { + private C2tnb431r1Holder() {} + + internal static readonly X9ECParametersHolder Instance = new C2tnb431r1Holder(); + + protected override X9ECParameters CreateParameters() + { + BigInteger n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16); + BigInteger h = BigInteger.ValueOf(0x2760); + + ECCurve c2m431r1 = new F2mCurve( + 431, + 120, + new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16), + new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16), + n, h); + + return new X9ECParameters( + c2m431r1, + c2m431r1.DecodePoint( + Hex.Decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")), + n, h, + null); + } + } + + private static readonly IDictionary objIds = Platform.CreateHashtable(); + private static readonly IDictionary curves = Platform.CreateHashtable(); + private static readonly IDictionary names = Platform.CreateHashtable(); + + private static void DefineCurve( + string name, + DerObjectIdentifier oid, + X9ECParametersHolder holder) + { + objIds.Add(name, oid); + names.Add(oid, name); + curves.Add(oid, holder); + } + + static X962NamedCurves() + { + DefineCurve("prime192v1", X9ObjectIdentifiers.Prime192v1, Prime192v1Holder.Instance); + DefineCurve("prime192v2", X9ObjectIdentifiers.Prime192v2, Prime192v2Holder.Instance); + DefineCurve("prime192v3", X9ObjectIdentifiers.Prime192v3, Prime192v3Holder.Instance); + DefineCurve("prime239v1", X9ObjectIdentifiers.Prime239v1, Prime239v1Holder.Instance); + DefineCurve("prime239v2", X9ObjectIdentifiers.Prime239v2, Prime239v2Holder.Instance); + DefineCurve("prime239v3", X9ObjectIdentifiers.Prime239v3, Prime239v3Holder.Instance); + DefineCurve("prime256v1", X9ObjectIdentifiers.Prime256v1, Prime256v1Holder.Instance); + DefineCurve("c2pnb163v1", X9ObjectIdentifiers.C2Pnb163v1, C2pnb163v1Holder.Instance); + DefineCurve("c2pnb163v2", X9ObjectIdentifiers.C2Pnb163v2, C2pnb163v2Holder.Instance); + DefineCurve("c2pnb163v3", X9ObjectIdentifiers.C2Pnb163v3, C2pnb163v3Holder.Instance); + DefineCurve("c2pnb176w1", X9ObjectIdentifiers.C2Pnb176w1, C2pnb176w1Holder.Instance); + DefineCurve("c2tnb191v1", X9ObjectIdentifiers.C2Tnb191v1, C2tnb191v1Holder.Instance); + DefineCurve("c2tnb191v2", X9ObjectIdentifiers.C2Tnb191v2, C2tnb191v2Holder.Instance); + DefineCurve("c2tnb191v3", X9ObjectIdentifiers.C2Tnb191v3, C2tnb191v3Holder.Instance); + DefineCurve("c2pnb208w1", X9ObjectIdentifiers.C2Pnb208w1, C2pnb208w1Holder.Instance); + DefineCurve("c2tnb239v1", X9ObjectIdentifiers.C2Tnb239v1, C2tnb239v1Holder.Instance); + DefineCurve("c2tnb239v2", X9ObjectIdentifiers.C2Tnb239v2, C2tnb239v2Holder.Instance); + DefineCurve("c2tnb239v3", X9ObjectIdentifiers.C2Tnb239v3, C2tnb239v3Holder.Instance); + DefineCurve("c2pnb272w1", X9ObjectIdentifiers.C2Pnb272w1, C2pnb272w1Holder.Instance); + DefineCurve("c2pnb304w1", X9ObjectIdentifiers.C2Pnb304w1, C2pnb304w1Holder.Instance); + DefineCurve("c2tnb359v1", X9ObjectIdentifiers.C2Tnb359v1, C2tnb359v1Holder.Instance); + DefineCurve("c2pnb368w1", X9ObjectIdentifiers.C2Pnb368w1, C2pnb368w1Holder.Instance); + DefineCurve("c2tnb431r1", X9ObjectIdentifiers.C2Tnb431r1, C2tnb431r1Holder.Instance); + } + + public static X9ECParameters GetByName( + string name) + { + DerObjectIdentifier oid = (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)]; + + return oid == null ? null : GetByOid(oid); + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters GetByOid( + DerObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid]; + + return holder == null ? null : holder.Parameters; + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DerObjectIdentifier GetOid( + string name) + { + return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)]; + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static string GetName( + DerObjectIdentifier oid) + { + return (string) names[oid]; + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static IEnumerable Names + { + get { return new EnumerableProxy(objIds.Keys); } + } + } +} diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs new file mode 100644 index 000000000..5b7eaa1de --- /dev/null +++ b/crypto/src/asn1/x9/X962Parameters.cs @@ -0,0 +1,53 @@ +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public class X962Parameters + : Asn1Encodable, IAsn1Choice + { + private readonly Asn1Object _params; + + public X962Parameters( + X9ECParameters ecParameters) + { + this._params = ecParameters.ToAsn1Object(); + } + + public X962Parameters( + DerObjectIdentifier namedCurve) + { + this._params = namedCurve; + } + + public X962Parameters( + Asn1Object obj) + { + this._params = obj; + } + + public bool IsNamedCurve + { + get { return (_params is DerObjectIdentifier); } + } + + public Asn1Object Parameters + { + get { return _params; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         * Parameters ::= CHOICE {
+         *    ecParameters ECParameters,
+         *    namedCurve   CURVES.&id({CurveNames}),
+         *    implicitlyCA Null
+         * }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return _params; + } + } +} diff --git a/crypto/src/asn1/x9/X9Curve.cs b/crypto/src/asn1/x9/X9Curve.cs new file mode 100644 index 000000000..b92e7b3b5 --- /dev/null +++ b/crypto/src/asn1/x9/X9Curve.cs @@ -0,0 +1,147 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * ASN.1 def for Elliptic-Curve Curve structure. See + * X9.62, for further details. + */ + public class X9Curve + : Asn1Encodable + { + private readonly ECCurve curve; + private readonly byte[] seed; + private readonly DerObjectIdentifier fieldIdentifier; + + public X9Curve( + ECCurve curve) + : this(curve, null) + { + this.curve = curve; + } + + public X9Curve( + ECCurve curve, + byte[] seed) + { + if (curve == null) + throw new ArgumentNullException("curve"); + + this.curve = curve; + this.seed = Arrays.Clone(seed); + + if (curve is FpCurve) + { + this.fieldIdentifier = X9ObjectIdentifiers.PrimeField; + } + else if (curve is F2mCurve) + { + this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField; + } + else + { + throw new ArgumentException("This type of ECCurve is not implemented"); + } + } + + public X9Curve( + X9FieldID fieldID, + Asn1Sequence seq) + { + if (fieldID == null) + throw new ArgumentNullException("fieldID"); + if (seq == null) + throw new ArgumentNullException("seq"); + + this.fieldIdentifier = fieldID.Identifier; + + if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)) + { + BigInteger q = ((DerInteger) fieldID.Parameters).Value; + X9FieldElement x9A = new X9FieldElement(q, (Asn1OctetString) seq[0]); + X9FieldElement x9B = new X9FieldElement(q, (Asn1OctetString) seq[1]); + curve = new FpCurve(q, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger()); + } + else + { + if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField)) + { + // Characteristic two field + DerSequence parameters = (DerSequence)fieldID.Parameters; + int m = ((DerInteger)parameters[0]).Value.IntValue; + DerObjectIdentifier representation + = (DerObjectIdentifier)parameters[1]; + + int k1 = 0; + int k2 = 0; + int k3 = 0; + if (representation.Equals(X9ObjectIdentifiers.TPBasis)) + { + // Trinomial basis representation + k1 = ((DerInteger)parameters[2]).Value.IntValue; + } + else + { + // Pentanomial basis representation + DerSequence pentanomial = (DerSequence) parameters[2]; + k1 = ((DerInteger) pentanomial[0]).Value.IntValue; + k2 = ((DerInteger) pentanomial[1]).Value.IntValue; + k3 = ((DerInteger) pentanomial[2]).Value.IntValue; + } + X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]); + X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]); + // TODO Is it possible to get the order (n) and cofactor(h) too? + curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger()); + } + } + + if (seq.Count == 3) + { + seed = ((DerBitString) seq[2]).GetBytes(); + } + } + + public ECCurve Curve + { + get { return curve; } + } + + public byte[] GetSeed() + { + return Arrays.Clone(seed); + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  Curve ::= Sequence {
+         *      a               FieldElement,
+         *      b               FieldElement,
+         *      seed            BIT STRING      OPTIONAL
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField) + || fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField)) + { + v.Add(new X9FieldElement(curve.A).ToAsn1Object()); + v.Add(new X9FieldElement(curve.B).ToAsn1Object()); + } + + if (seed != null) + { + v.Add(new DerBitString(seed)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x9/X9ECParameters.cs b/crypto/src/asn1/x9/X9ECParameters.cs new file mode 100644 index 000000000..d025b36ce --- /dev/null +++ b/crypto/src/asn1/x9/X9ECParameters.cs @@ -0,0 +1,170 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * ASN.1 def for Elliptic-Curve ECParameters structure. See + * X9.62, for further details. + */ + public class X9ECParameters + : Asn1Encodable + { + private X9FieldID fieldID; + private ECCurve curve; + private ECPoint g; + private BigInteger n; + private BigInteger h; + private byte[] seed; + + public X9ECParameters( + Asn1Sequence seq) + { + if (!(seq[0] is DerInteger) + || !((DerInteger) seq[0]).Value.Equals(BigInteger.One)) + { + throw new ArgumentException("bad version in X9ECParameters"); + } + + X9Curve x9c = null; + if (seq[2] is X9Curve) + { + x9c = (X9Curve) seq[2]; + } + else + { + x9c = new X9Curve( + new X9FieldID( + (Asn1Sequence) seq[1]), + (Asn1Sequence) seq[2]); + } + + this.curve = x9c.Curve; + + if (seq[3] is X9ECPoint) + { + this.g = ((X9ECPoint) seq[3]).Point; + } + else + { + this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point; + } + + this.n = ((DerInteger) seq[4]).Value; + this.seed = x9c.GetSeed(); + + if (seq.Count == 6) + { + this.h = ((DerInteger) seq[5]).Value; + } + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n) + : this(curve, g, n, BigInteger.One, null) + { + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n, + BigInteger h) + : this(curve, g, n, h, null) + { + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n, + BigInteger h, + byte[] seed) + { + this.curve = curve; + this.g = g; + this.n = n; + this.h = h; + this.seed = seed; + + if (curve is FpCurve) + { + this.fieldID = new X9FieldID(((FpCurve) curve).Q); + } + else if (curve is F2mCurve) + { + F2mCurve curveF2m = (F2mCurve) curve; + this.fieldID = new X9FieldID(curveF2m.M, curveF2m.K1, + curveF2m.K2, curveF2m.K3); + } + } + + public ECCurve Curve + { + get { return curve; } + } + + public ECPoint G + { + get { return g; } + } + + public BigInteger N + { + get { return n; } + } + + public BigInteger H + { + get + { + if (h == null) + { + // TODO - this should be calculated, it will cause issues with custom curves. + return BigInteger.One; + } + + return h; + } + } + + public byte[] GetSeed() + { + return seed; + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  ECParameters ::= Sequence {
+         *      version         Integer { ecpVer1(1) } (ecpVer1),
+         *      fieldID         FieldID {{FieldTypes}},
+         *      curve           X9Curve,
+         *      base            X9ECPoint,
+         *      order           Integer,
+         *      cofactor        Integer OPTIONAL
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(1), + fieldID, + new X9Curve(curve, seed), + new X9ECPoint(g), + new DerInteger(n)); + + if (h != null) + { + v.Add(new DerInteger(h)); + } + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/x9/X9ECParametersHolder.cs b/crypto/src/asn1/x9/X9ECParametersHolder.cs new file mode 100644 index 000000000..b3455709c --- /dev/null +++ b/crypto/src/asn1/x9/X9ECParametersHolder.cs @@ -0,0 +1,22 @@ +namespace Org.BouncyCastle.Asn1.X9 +{ + public abstract class X9ECParametersHolder + { + private X9ECParameters parameters; + + public X9ECParameters Parameters + { + get + { + if (parameters == null) + { + parameters = CreateParameters(); + } + + return parameters; + } + } + + protected abstract X9ECParameters CreateParameters(); + } +} diff --git a/crypto/src/asn1/x9/X9ECPoint.cs b/crypto/src/asn1/x9/X9ECPoint.cs new file mode 100644 index 000000000..ba2b2bcbf --- /dev/null +++ b/crypto/src/asn1/x9/X9ECPoint.cs @@ -0,0 +1,44 @@ +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * class for describing an ECPoint as a Der object. + */ + public class X9ECPoint + : Asn1Encodable + { + private readonly ECPoint p; + + public X9ECPoint( + ECPoint p) + { + this.p = p; + } + + public X9ECPoint( + ECCurve c, + Asn1OctetString s) + { + this.p = c.DecodePoint(s.GetOctets()); + } + + public ECPoint Point + { + get { return p; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+         *  ECPoint ::= OCTET STRING
+         * 
+ *

+ * Octet string produced using ECPoint.GetEncoded().

+ */ + public override Asn1Object ToAsn1Object() + { + return new DerOctetString(p.GetEncoded()); + } + } +} diff --git a/crypto/src/asn1/x9/X9FieldElement.cs b/crypto/src/asn1/x9/X9FieldElement.cs new file mode 100644 index 000000000..06fa0e3dc --- /dev/null +++ b/crypto/src/asn1/x9/X9FieldElement.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * Class for processing an ECFieldElement as a DER object. + */ + public class X9FieldElement + : Asn1Encodable + { + private ECFieldElement f; + + public X9FieldElement( + ECFieldElement f) + { + this.f = f; + } + + public X9FieldElement( + BigInteger p, + Asn1OctetString s) + : this(new FpFieldElement(p, new BigInteger(1, s.GetOctets()))) + { + } + + public X9FieldElement( + int m, + int k1, + int k2, + int k3, + Asn1OctetString s) + : this(new F2mFieldElement(m, k1, k2, k3, new BigInteger(1, s.GetOctets()))) + { + } + + public ECFieldElement Value + { + get { return f; } + } + + /** + * Produce an object suitable for an Asn1OutputStream. + *
+		 *  FieldElement ::= OCTET STRING
+		 * 
+ *

+ *

    + *
  1. if q 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.
  2. + *
  3. if q is 2m 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. + *
  4. + *
+ *

+ */ + public override Asn1Object ToAsn1Object() + { + int byteCount = X9IntegerConverter.GetByteLength(f); + byte[] paddedBigInteger = X9IntegerConverter.IntegerToBytes(f.ToBigInteger(), byteCount); + + return new DerOctetString(paddedBigInteger); + } + } +} diff --git a/crypto/src/asn1/x9/X9FieldID.cs b/crypto/src/asn1/x9/X9FieldID.cs new file mode 100644 index 000000000..c51cc4df2 --- /dev/null +++ b/crypto/src/asn1/x9/X9FieldID.cs @@ -0,0 +1,102 @@ +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.X9 +{ + /** + * ASN.1 def for Elliptic-Curve Field ID structure. See + * X9.62, for further details. + */ + public class X9FieldID + : Asn1Encodable + { + private readonly DerObjectIdentifier id; + private readonly Asn1Object parameters; + + /** + * Constructor for elliptic curves over prime fields + * F2. + * @param primeP The prime p defining the prime field. + */ + public X9FieldID( + BigInteger primeP) + { + this.id = X9ObjectIdentifiers.PrimeField; + this.parameters = new DerInteger(primeP); + } + + /** + * Constructor for elliptic curves over binary fields + * F2m. + * @param m The exponent m of + * F2m. + * @param k1 The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k2 The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k3 The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).. + */ + public X9FieldID( + int m, + int k1, + int k2, + int k3) + { + this.id = X9ObjectIdentifiers.CharacteristicTwoField; + + Asn1EncodableVector fieldIdParams = new Asn1EncodableVector(new DerInteger(m)); + + if (k2 == 0) + { + fieldIdParams.Add( + X9ObjectIdentifiers.TPBasis, + new DerInteger(k1)); + } + else + { + fieldIdParams.Add( + X9ObjectIdentifiers.PPBasis, + new DerSequence( + new DerInteger(k1), + new DerInteger(k2), + new DerInteger(k3))); + } + + this.parameters = new DerSequence(fieldIdParams); + } + + internal X9FieldID( + Asn1Sequence seq) + { + this.id = (DerObjectIdentifier) seq[0]; + this.parameters = (Asn1Object) seq[1]; + } + + public DerObjectIdentifier Identifier + { + get { return id; } + } + + public Asn1Object Parameters + { + get { return parameters; } + } + + /** + * Produce a Der encoding of the following structure. + *
+         *  FieldID ::= Sequence {
+         *      fieldType       FIELD-ID.&id({IOSet}),
+         *      parameters      FIELD-ID.&Type({IOSet}{@fieldType})
+         *  }
+         * 
+ */ + public override Asn1Object ToAsn1Object() + { + return new DerSequence(id, parameters); + } + } +} diff --git a/crypto/src/asn1/x9/X9IntegerConverter.cs b/crypto/src/asn1/x9/X9IntegerConverter.cs new file mode 100644 index 000000000..2bce20488 --- /dev/null +++ b/crypto/src/asn1/x9/X9IntegerConverter.cs @@ -0,0 +1,48 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public sealed class X9IntegerConverter + { + private X9IntegerConverter() + { + } + + public static int GetByteLength( + ECFieldElement fe) + { + return (fe.FieldSize + 7) / 8; + } + + public static int GetByteLength( + ECCurve c) + { + return (c.FieldSize + 7) / 8; + } + + public static byte[] IntegerToBytes( + BigInteger s, + int qLength) + { + byte[] bytes = s.ToByteArrayUnsigned(); + + if (qLength < bytes.Length) + { + byte[] tmp = new byte[qLength]; + Array.Copy(bytes, bytes.Length - tmp.Length, tmp, 0, tmp.Length); + return tmp; + } + else if (qLength > bytes.Length) + { + byte[] tmp = new byte[qLength]; + Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length); + return tmp; + } + + return bytes; + } + } +} diff --git a/crypto/src/asn1/x9/X9ObjectIdentifiers.cs b/crypto/src/asn1/x9/X9ObjectIdentifiers.cs new file mode 100644 index 000000000..9d7ecae6e --- /dev/null +++ b/crypto/src/asn1/x9/X9ObjectIdentifiers.cs @@ -0,0 +1,137 @@ +using System; + +namespace Org.BouncyCastle.Asn1.X9 +{ + public abstract class X9ObjectIdentifiers + { + // + // X9.62 + // + // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) ansi-x962(10045) } + // + + internal const string AnsiX962 = "1.2.840.10045"; + + public static readonly DerObjectIdentifier ansi_X9_62 = new DerObjectIdentifier(AnsiX962); + + public static readonly DerObjectIdentifier IdFieldType = ansi_X9_62.Branch("1"); + + public static readonly DerObjectIdentifier PrimeField = IdFieldType.Branch("1"); + public static readonly DerObjectIdentifier CharacteristicTwoField = IdFieldType.Branch("2"); + + public static readonly DerObjectIdentifier GNBasis = CharacteristicTwoField.Branch("3.1"); + public static readonly DerObjectIdentifier TPBasis = CharacteristicTwoField.Branch("3.2"); + public static readonly DerObjectIdentifier PPBasis = CharacteristicTwoField.Branch("3.3"); + + [Obsolete("Use 'id_ecSigType' instead")] + public const string IdECSigType = AnsiX962 + ".4"; + public static readonly DerObjectIdentifier id_ecSigType = ansi_X9_62.Branch("4"); + + public static readonly DerObjectIdentifier ECDsaWithSha1 = id_ecSigType.Branch("1"); + + [Obsolete("Use 'id_publicKeyType' instead")] + public const string IdPublicKeyType = AnsiX962 + ".2"; + public static readonly DerObjectIdentifier id_publicKeyType = ansi_X9_62.Branch("2"); + + public static readonly DerObjectIdentifier IdECPublicKey = id_publicKeyType.Branch("1"); + + public static readonly DerObjectIdentifier ECDsaWithSha2 = id_ecSigType.Branch("3"); + + public static readonly DerObjectIdentifier ECDsaWithSha224 = ECDsaWithSha2.Branch("1"); + public static readonly DerObjectIdentifier ECDsaWithSha256 = ECDsaWithSha2.Branch("2"); + public static readonly DerObjectIdentifier ECDsaWithSha384 = ECDsaWithSha2.Branch("3"); + public static readonly DerObjectIdentifier ECDsaWithSha512 = ECDsaWithSha2.Branch("4"); + + + // + // named curves + // + public static readonly DerObjectIdentifier EllipticCurve = ansi_X9_62.Branch("3"); + + // + // Two Curves + // + public static readonly DerObjectIdentifier CTwoCurve = EllipticCurve.Branch("0"); + + public static readonly DerObjectIdentifier C2Pnb163v1 = CTwoCurve.Branch("1"); + public static readonly DerObjectIdentifier C2Pnb163v2 = CTwoCurve.Branch("2"); + public static readonly DerObjectIdentifier C2Pnb163v3 = CTwoCurve.Branch("3"); + public static readonly DerObjectIdentifier C2Pnb176w1 = CTwoCurve.Branch("4"); + public static readonly DerObjectIdentifier C2Tnb191v1 = CTwoCurve.Branch("5"); + public static readonly DerObjectIdentifier C2Tnb191v2 = CTwoCurve.Branch("6"); + public static readonly DerObjectIdentifier C2Tnb191v3 = CTwoCurve.Branch("7"); + public static readonly DerObjectIdentifier C2Onb191v4 = CTwoCurve.Branch("8"); + public static readonly DerObjectIdentifier C2Onb191v5 = CTwoCurve.Branch("9"); + public static readonly DerObjectIdentifier C2Pnb208w1 = CTwoCurve.Branch("10"); + public static readonly DerObjectIdentifier C2Tnb239v1 = CTwoCurve.Branch("11"); + public static readonly DerObjectIdentifier C2Tnb239v2 = CTwoCurve.Branch("12"); + public static readonly DerObjectIdentifier C2Tnb239v3 = CTwoCurve.Branch("13"); + public static readonly DerObjectIdentifier C2Onb239v4 = CTwoCurve.Branch("14"); + public static readonly DerObjectIdentifier C2Onb239v5 = CTwoCurve.Branch("15"); + public static readonly DerObjectIdentifier C2Pnb272w1 = CTwoCurve.Branch("16"); + public static readonly DerObjectIdentifier C2Pnb304w1 = CTwoCurve.Branch("17"); + public static readonly DerObjectIdentifier C2Tnb359v1 = CTwoCurve.Branch("18"); + public static readonly DerObjectIdentifier C2Pnb368w1 = CTwoCurve.Branch("19"); + public static readonly DerObjectIdentifier C2Tnb431r1 = CTwoCurve.Branch("20"); + + // + // Prime + // + public static readonly DerObjectIdentifier PrimeCurve = EllipticCurve.Branch("1"); + + public static readonly DerObjectIdentifier Prime192v1 = PrimeCurve.Branch("1"); + public static readonly DerObjectIdentifier Prime192v2 = PrimeCurve.Branch("2"); + public static readonly DerObjectIdentifier Prime192v3 = PrimeCurve.Branch("3"); + public static readonly DerObjectIdentifier Prime239v1 = PrimeCurve.Branch("4"); + public static readonly DerObjectIdentifier Prime239v2 = PrimeCurve.Branch("5"); + public static readonly DerObjectIdentifier Prime239v3 = PrimeCurve.Branch("6"); + public static readonly DerObjectIdentifier Prime256v1 = PrimeCurve.Branch("7"); + + // + // DSA + // + // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) ansi-x957(10040) number-type(4) 1 } + public static readonly DerObjectIdentifier IdDsa = new DerObjectIdentifier("1.2.840.10040.4.1"); + + /** + * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + * us(840) x9-57 (10040) x9cm(4) 3 } + */ + public static readonly DerObjectIdentifier IdDsaWithSha1 = new DerObjectIdentifier("1.2.840.10040.4.3"); + + /** + * X9.63 + */ + public static readonly DerObjectIdentifier X9x63Scheme = new DerObjectIdentifier("1.3.133.16.840.63.0"); + public static readonly DerObjectIdentifier DHSinglePassStdDHSha1KdfScheme = X9x63Scheme.Branch("2"); + public static readonly DerObjectIdentifier DHSinglePassCofactorDHSha1KdfScheme = X9x63Scheme.Branch("3"); + public static readonly DerObjectIdentifier MqvSinglePassSha1KdfScheme = X9x63Scheme.Branch("16"); + + /** + * X9.42 + */ + + public static readonly DerObjectIdentifier ansi_x9_42 = new DerObjectIdentifier("1.2.840.10046"); + + // + // Diffie-Hellman + // + // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) ansi-x942(10046) number-type(2) 1 } + // + public static readonly DerObjectIdentifier DHPublicNumber = ansi_x9_42.Branch("2.1"); + + public static readonly DerObjectIdentifier X9x42Schemes = ansi_x9_42.Branch("2.3"); + + public static readonly DerObjectIdentifier DHStatic = X9x42Schemes.Branch("1"); + public static readonly DerObjectIdentifier DHEphem = X9x42Schemes.Branch("2"); + public static readonly DerObjectIdentifier DHOneFlow = X9x42Schemes.Branch("3"); + public static readonly DerObjectIdentifier DHHybrid1 = X9x42Schemes.Branch("4"); + public static readonly DerObjectIdentifier DHHybrid2 = X9x42Schemes.Branch("5"); + public static readonly DerObjectIdentifier DHHybridOneFlow = X9x42Schemes.Branch("6"); + public static readonly DerObjectIdentifier Mqv2 = X9x42Schemes.Branch("7"); + public static readonly DerObjectIdentifier Mqv1 = X9x42Schemes.Branch("8"); + } +} diff --git a/crypto/src/bcpg/ArmoredInputStream.cs b/crypto/src/bcpg/ArmoredInputStream.cs new file mode 100644 index 000000000..3109dd4fd --- /dev/null +++ b/crypto/src/bcpg/ArmoredInputStream.cs @@ -0,0 +1,513 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * reader for Base64 armored objects - read the headers and then start returning + * bytes when the data is reached. An IOException is thrown if the CRC check + * fails. + */ + public class ArmoredInputStream + : BaseInputStream + { + /* + * set up the decoding table. + */ + private readonly static byte[] decodingTable; + static ArmoredInputStream() + { + decodingTable = new byte[128]; + for (int i = 'A'; i <= 'Z'; i++) + { + decodingTable[i] = (byte)(i - 'A'); + } + for (int i = 'a'; i <= 'z'; i++) + { + decodingTable[i] = (byte)(i - 'a' + 26); + } + for (int i = '0'; i <= '9'; i++) + { + decodingTable[i] = (byte)(i - '0' + 52); + } + decodingTable['+'] = 62; + decodingTable['/'] = 63; + } + + /** + * decode the base 64 encoded input data. + * + * @return the offset the data starts in out. + */ + private int Decode( + int in0, + int in1, + int in2, + int in3, + int[] result) + { + if (in3 < 0) + { + throw new EndOfStreamException("unexpected end of file in armored stream."); + } + + int b1, b2, b3, b4; + if (in2 == '=') + { + b1 = decodingTable[in0] &0xff; + b2 = decodingTable[in1] & 0xff; + result[2] = ((b1 << 2) | (b2 >> 4)) & 0xff; + return 2; + } + else if (in3 == '=') + { + b1 = decodingTable[in0]; + b2 = decodingTable[in1]; + b3 = decodingTable[in2]; + result[1] = ((b1 << 2) | (b2 >> 4)) & 0xff; + result[2] = ((b2 << 4) | (b3 >> 2)) & 0xff; + return 1; + } + else + { + b1 = decodingTable[in0]; + b2 = decodingTable[in1]; + b3 = decodingTable[in2]; + b4 = decodingTable[in3]; + result[0] = ((b1 << 2) | (b2 >> 4)) & 0xff; + result[1] = ((b2 << 4) | (b3 >> 2)) & 0xff; + result[2] = ((b3 << 6) | b4) & 0xff; + return 0; + } + } + + Stream input; + bool start = true; + int[] outBuf = new int[3]; + int bufPtr = 3; + Crc24 crc = new Crc24(); + bool crcFound = false; + bool hasHeaders = true; + string header = null; + bool newLineFound = false; + bool clearText = false; + bool restart = false; + IList headerList= Platform.CreateArrayList(); + int lastC = 0; + bool isEndOfStream; + + /** + * Create a stream for reading a PGP armoured message, parsing up to a header + * and then reading the data that follows. + * + * @param input + */ + public ArmoredInputStream( + Stream input) + : this(input, true) + { + } + + /** + * Create an armoured input stream which will assume the data starts + * straight away, or parse for headers first depending on the value of + * hasHeaders. + * + * @param input + * @param hasHeaders true if headers are to be looked for, false otherwise. + */ + public ArmoredInputStream( + Stream input, + bool hasHeaders) + { + this.input = input; + this.hasHeaders = hasHeaders; + + if (hasHeaders) + { + ParseHeaders(); + } + + start = false; + } + + private bool ParseHeaders() + { + header = null; + + int c; + int last = 0; + bool headerFound = false; + + headerList = Platform.CreateArrayList(); + + // + // if restart we already have a header + // + if (restart) + { + headerFound = true; + } + else + { + while ((c = input.ReadByte()) >= 0) + { + if (c == '-' && (last == 0 || last == '\n' || last == '\r')) + { + headerFound = true; + break; + } + + last = c; + } + } + + if (headerFound) + { + StringBuilder Buffer = new StringBuilder("-"); + bool eolReached = false; + bool crLf = false; + + if (restart) // we've had to look ahead two '-' + { + Buffer.Append('-'); + } + + while ((c = input.ReadByte()) >= 0) + { + if (last == '\r' && c == '\n') + { + crLf = true; + } + if (eolReached && (last != '\r' && c == '\n')) + { + break; + } + if (eolReached && c == '\r') + { + break; + } + if (c == '\r' || (last != '\r' && c == '\n')) + { + string line = Buffer.ToString(); + if (line.Trim().Length < 1) + break; + headerList.Add(line); + Buffer.Length = 0; + } + + if (c != '\n' && c != '\r') + { + Buffer.Append((char)c); + eolReached = false; + } + else + { + if (c == '\r' || (last != '\r' && c == '\n')) + { + eolReached = true; + } + } + + last = c; + } + + if (crLf) + { + input.ReadByte(); // skip last \n + } + } + + if (headerList.Count > 0) + { + header = (string) headerList[0]; + } + + clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header); + newLineFound = true; + + return headerFound; + } + + /** + * @return true if we are inside the clear text section of a PGP + * signed message. + */ + public bool IsClearText() + { + return clearText; + } + + /** + * @return true if the stream is actually at end of file. + */ + public bool IsEndOfStream() + { + return isEndOfStream; + } + + /** + * Return the armor header line (if there is one) + * @return the armor header line, null if none present. + */ + public string GetArmorHeaderLine() + { + return header; + } + + /** + * Return the armor headers (the lines after the armor header line), + * @return an array of armor headers, null if there aren't any. + */ + public string[] GetArmorHeaders() + { + if (headerList.Count <= 1) + { + return null; + } + + string[] hdrs = new string[headerList.Count - 1]; + for (int i = 0; i != hdrs.Length; i++) + { + hdrs[i] = (string) headerList[i + 1]; + } + + return hdrs; + } + + private int ReadIgnoreSpace() + { + int c; + do + { + c = input.ReadByte(); + } + while (c == ' ' || c == '\t'); + + return c; + } + + private int ReadIgnoreWhitespace() + { + int c; + do + { + c = input.ReadByte(); + } + while (c == ' ' || c == '\t' || c == '\r' || c == '\n'); + + return c; + } + + private int ReadByteClearText() + { + int c = input.ReadByte(); + + if (c == '\r' || (c == '\n' && lastC != '\r')) + { + newLineFound = true; + } + else if (newLineFound && c == '-') + { + c = input.ReadByte(); + if (c == '-') // a header, not dash escaped + { + clearText = false; + start = true; + restart = true; + } + else // a space - must be a dash escape + { + c = input.ReadByte(); + } + newLineFound = false; + } + else + { + if (c != '\n' && lastC != '\r') + { + newLineFound = false; + } + } + + lastC = c; + + if (c < 0) + { + isEndOfStream = true; + } + + return c; + } + + private int ReadClearText(byte[] buffer, int offset, int count) + { + int pos = offset; + try + { + int end = offset + count; + while (pos < end) + { + int c = ReadByteClearText(); + if (c == -1) + { + break; + } + buffer[pos++] = (byte) c; + } + } + catch (IOException ioe) + { + if (pos == offset) throw ioe; + } + + return pos - offset; + } + + private int DoReadByte() + { + if (bufPtr > 2 || crcFound) + { + int c = ReadIgnoreSpace(); + if (c == '\n' || c == '\r') + { + c = ReadIgnoreWhitespace(); + if (c == '=') // crc reached + { + bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf); + + if (bufPtr != 0) + { + throw new IOException("no crc found in armored message."); + } + + crcFound = true; + + int i = ((outBuf[0] & 0xff) << 16) + | ((outBuf[1] & 0xff) << 8) + | (outBuf[2] & 0xff); + + if (i != crc.Value) + { + throw new IOException("crc check failed in armored message."); + } + + return ReadByte(); + } + + if (c == '-') // end of record reached + { + while ((c = input.ReadByte()) >= 0) + { + if (c == '\n' || c == '\r') + { + break; + } + } + + if (!crcFound) + { + throw new IOException("crc check not found."); + } + + crcFound = false; + start = true; + bufPtr = 3; + + if (c < 0) + { + isEndOfStream = true; + } + + return -1; + } + } + + if (c < 0) + { + isEndOfStream = true; + return -1; + } + + bufPtr = Decode(c, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf); + } + + return outBuf[bufPtr++]; + } + + public override int ReadByte() + { + if (start) + { + if (hasHeaders) + { + ParseHeaders(); + } + + crc.Reset(); + start = false; + } + + if (clearText) + { + return ReadByteClearText(); + } + + int c = DoReadByte(); + + crc.Update(c); + + return c; + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (start && count > 0) + { + if (hasHeaders) + { + ParseHeaders(); + } + start = false; + } + + if (clearText) + { + return ReadClearText(buffer, offset, count); + } + + int pos = offset; + try + { + int end = offset + count; + while (pos < end) + { + int c = DoReadByte(); + crc.Update(c); + if (c == -1) + { + break; + } + buffer[pos++] = (byte) c; + } + } + catch (IOException ioe) + { + if (pos == offset) throw ioe; + } + + return pos - offset; + } + + public override void Close() + { + input.Close(); + base.Close(); + } + } +} diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs new file mode 100644 index 000000000..b3a32c6f5 --- /dev/null +++ b/crypto/src/bcpg/ArmoredOutputStream.cs @@ -0,0 +1,330 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic output stream. + */ + public class ArmoredOutputStream + : BaseOutputStream + { + private static readonly 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)'/' + }; + + /** + * encode the input data producing a base 64 encoded byte array. + */ + private static void Encode( + Stream outStream, + int[] data, + int len) + { + Debug.Assert(len > 0); + Debug.Assert(len < 4); + + byte[] bs = new byte[4]; + int d1 = data[0]; + bs[0] = encodingTable[(d1 >> 2) & 0x3f]; + + switch (len) + { + case 1: + { + bs[1] = encodingTable[(d1 << 4) & 0x3f]; + bs[2] = (byte)'='; + bs[3] = (byte)'='; + break; + } + case 2: + { + int d2 = data[1]; + bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f]; + bs[2] = encodingTable[(d2 << 2) & 0x3f]; + bs[3] = (byte)'='; + break; + } + case 3: + { + int d2 = data[1]; + int d3 = data[2]; + bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f]; + bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f]; + bs[3] = encodingTable[d3 & 0x3f]; + break; + } + } + + outStream.Write(bs, 0, bs.Length); + } + + private readonly Stream outStream; + private int[] buf = new int[3]; + private int bufPtr = 0; + private Crc24 crc = new Crc24(); + private int chunkCount = 0; + private int lastb; + + private bool start = true; + private bool clearText = false; + private bool newLine = false; + + private string type; + + private static readonly string nl = Platform.NewLine; + private static readonly string headerStart = "-----BEGIN PGP "; + private static readonly string headerTail = "-----"; + private static readonly string footerStart = "-----END PGP "; + private static readonly string footerTail = "-----"; + + private static readonly string version = "BCPG C# v" + + Assembly.GetExecutingAssembly().GetName().Version; + + private readonly IDictionary headers; + + public ArmoredOutputStream(Stream outStream) + { + this.outStream = outStream; + this.headers = Platform.CreateHashtable(); + this.headers["Version"] = version; + } + + public ArmoredOutputStream(Stream outStream, IDictionary headers) + { + this.outStream = outStream; + this.headers = Platform.CreateHashtable(headers); + this.headers["Version"] = version; + } + + /** + * Set an additional header entry. + * + * @param name the name of the header entry. + * @param v the value of the header entry. + */ + public void SetHeader( + string name, + string v) + { + headers[name] = v; + } + + /** + * Reset the headers to only contain a Version string. + */ + public void ResetHeaders() + { + headers.Clear(); + headers["Version"] = version; + } + + /** + * Start a clear text signed message. + * @param hashAlgorithm + */ + public void BeginClearText( + HashAlgorithmTag hashAlgorithm) + { + string hash; + + switch (hashAlgorithm) + { + case HashAlgorithmTag.Sha1: + hash = "SHA1"; + break; + case HashAlgorithmTag.Sha256: + hash = "SHA256"; + break; + case HashAlgorithmTag.Sha384: + hash = "SHA384"; + break; + case HashAlgorithmTag.Sha512: + hash = "SHA512"; + break; + case HashAlgorithmTag.MD2: + hash = "MD2"; + break; + case HashAlgorithmTag.MD5: + hash = "MD5"; + break; + case HashAlgorithmTag.RipeMD160: + hash = "RIPEMD160"; + break; + default: + throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm); + } + + DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl); + DoWrite("Hash: " + hash + nl + nl); + + clearText = true; + newLine = true; + lastb = 0; + } + + public void EndClearText() + { + clearText = false; + } + + public override void WriteByte( + byte b) + { + if (clearText) + { + outStream.WriteByte(b); + + if (newLine) + { + if (!(b == '\n' && lastb == '\r')) + { + newLine = false; + } + if (b == '-') + { + outStream.WriteByte((byte)' '); + outStream.WriteByte((byte)'-'); // dash escape + } + } + if (b == '\r' || (b == '\n' && lastb != '\r')) + { + newLine = true; + } + lastb = b; + return; + } + + if (start) + { + bool newPacket = (b & 0x40) != 0; + + int tag; + if (newPacket) + { + tag = b & 0x3f; + } + else + { + tag = (b & 0x3f) >> 2; + } + + switch ((PacketTag)tag) + { + case PacketTag.PublicKey: + type = "PUBLIC KEY BLOCK"; + break; + case PacketTag.SecretKey: + type = "PRIVATE KEY BLOCK"; + break; + case PacketTag.Signature: + type = "SIGNATURE"; + break; + default: + type = "MESSAGE"; + break; + } + + DoWrite(headerStart + type + headerTail + nl); + WriteHeaderEntry("Version", (string) headers["Version"]); + + foreach (DictionaryEntry de in headers) + { + string k = (string) de.Key; + if (k != "Version") + { + string v = (string) de.Value; + WriteHeaderEntry(k, v); + } + } + + DoWrite(nl); + + start = false; + } + + if (bufPtr == 3) + { + Encode(outStream, buf, bufPtr); + bufPtr = 0; + if ((++chunkCount & 0xf) == 0) + { + DoWrite(nl); + } + } + + crc.Update(b); + buf[bufPtr++] = b & 0xff; + } + + /** + * Note: close does nor close the underlying stream. So it is possible to write + * multiple objects using armoring to a single stream. + */ + public override void Close() + { + if (type != null) + { + if (bufPtr > 0) + { + Encode(outStream, buf, bufPtr); + } + + DoWrite(nl + '='); + + int crcV = crc.Value; + + buf[0] = ((crcV >> 16) & 0xff); + buf[1] = ((crcV >> 8) & 0xff); + buf[2] = (crcV & 0xff); + + Encode(outStream, buf, 3); + + DoWrite(nl); + DoWrite(footerStart); + DoWrite(type); + DoWrite(footerTail); + DoWrite(nl); + + outStream.Flush(); + + type = null; + start = true; + base.Close(); + } + } + + private void WriteHeaderEntry( + string name, + string v) + { + DoWrite(name + ": " + v + nl); + } + + private void DoWrite( + string s) + { + byte[] bs = Strings.ToAsciiByteArray(s); + outStream.Write(bs, 0, bs.Length); + } + } +} diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs new file mode 100644 index 000000000..3c69fbdf5 --- /dev/null +++ b/crypto/src/bcpg/BcpgInputStream.cs @@ -0,0 +1,355 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Reader for PGP objects. + public class BcpgInputStream + : BaseInputStream + { + private Stream m_in; + private bool next = false; + private int nextB; + + internal static BcpgInputStream Wrap( + Stream inStr) + { + if (inStr is BcpgInputStream) + { + return (BcpgInputStream) inStr; + } + + return new BcpgInputStream(inStr); + } + + private BcpgInputStream( + Stream inputStream) + { + this.m_in = inputStream; + } + + public override int ReadByte() + { + if (next) + { + next = false; + return nextB; + } + + return m_in.ReadByte(); + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + // Strangely, when count == 0, we should still attempt to read a byte +// if (count == 0) +// return 0; + + if (!next) + return m_in.Read(buffer, offset, count); + + // We have next byte waiting, so return it + + if (nextB < 0) + return 0; // EndOfStream + + if (buffer == null) + throw new ArgumentNullException("buffer"); + + buffer[offset] = (byte) nextB; + next = false; + + return 1; + } + + public byte[] ReadAll() + { + return Streams.ReadAll(this); + } + + public void ReadFully( + byte[] buffer, + int off, + int len) + { + if (Streams.ReadFully(this, buffer, off, len) < len) + throw new EndOfStreamException(); + } + + public void ReadFully( + byte[] buffer) + { + ReadFully(buffer, 0, buffer.Length); + } + + /// Returns the next packet tag in the stream. + public PacketTag NextPacketTag() + { + if (!next) + { + try + { + nextB = m_in.ReadByte(); + } + catch (EndOfStreamException) + { + nextB = -1; + } + + next = true; + } + + if (nextB >= 0) + { + if ((nextB & 0x40) != 0) // new + { + return (PacketTag)(nextB & 0x3f); + } + else // old + { + return (PacketTag)((nextB & 0x3f) >> 2); + } + } + + return (PacketTag) nextB; + } + + public Packet ReadPacket() + { + int hdr = this.ReadByte(); + + if (hdr < 0) + { + return null; + } + + if ((hdr & 0x80) == 0) + { + throw new IOException("invalid header encountered"); + } + + bool newPacket = (hdr & 0x40) != 0; + PacketTag tag = 0; + int bodyLen = 0; + bool partial = false; + + if (newPacket) + { + tag = (PacketTag)(hdr & 0x3f); + + int l = this.ReadByte(); + + if (l < 192) + { + bodyLen = l; + } + else if (l <= 223) + { + int b = m_in.ReadByte(); + bodyLen = ((l - 192) << 8) + (b) + 192; + } + else if (l == 255) + { + bodyLen = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) + | (m_in.ReadByte() << 8) | m_in.ReadByte(); + } + else + { + partial = true; + bodyLen = 1 << (l & 0x1f); + } + } + else + { + int lengthType = hdr & 0x3; + + tag = (PacketTag)((hdr & 0x3f) >> 2); + + switch (lengthType) + { + case 0: + bodyLen = this.ReadByte(); + break; + case 1: + bodyLen = (this.ReadByte() << 8) | this.ReadByte(); + break; + case 2: + bodyLen = (this.ReadByte() << 24) | (this.ReadByte() << 16) + | (this.ReadByte() << 8) | this.ReadByte(); + break; + case 3: + partial = true; + break; + default: + throw new IOException("unknown length type encountered"); + } + } + + BcpgInputStream objStream; + if (bodyLen == 0 && partial) + { + objStream = this; + } + else + { + PartialInputStream pis = new PartialInputStream(this, partial, bodyLen); + objStream = new BcpgInputStream(pis); + } + + switch (tag) + { + case PacketTag.Reserved: + return new InputStreamPacket(objStream); + case PacketTag.PublicKeyEncryptedSession: + return new PublicKeyEncSessionPacket(objStream); + case PacketTag.Signature: + return new SignaturePacket(objStream); + case PacketTag.SymmetricKeyEncryptedSessionKey: + return new SymmetricKeyEncSessionPacket(objStream); + case PacketTag.OnePassSignature: + return new OnePassSignaturePacket(objStream); + case PacketTag.SecretKey: + return new SecretKeyPacket(objStream); + case PacketTag.PublicKey: + return new PublicKeyPacket(objStream); + case PacketTag.SecretSubkey: + return new SecretSubkeyPacket(objStream); + case PacketTag.CompressedData: + return new CompressedDataPacket(objStream); + case PacketTag.SymmetricKeyEncrypted: + return new SymmetricEncDataPacket(objStream); + case PacketTag.Marker: + return new MarkerPacket(objStream); + case PacketTag.LiteralData: + return new LiteralDataPacket(objStream); + case PacketTag.Trust: + return new TrustPacket(objStream); + case PacketTag.UserId: + return new UserIdPacket(objStream); + case PacketTag.UserAttribute: + return new UserAttributePacket(objStream); + case PacketTag.PublicSubkey: + return new PublicSubkeyPacket(objStream); + case PacketTag.SymmetricEncryptedIntegrityProtected: + return new SymmetricEncIntegrityPacket(objStream); + case PacketTag.ModificationDetectionCode: + return new ModDetectionCodePacket(objStream); + case PacketTag.Experimental1: + case PacketTag.Experimental2: + case PacketTag.Experimental3: + case PacketTag.Experimental4: + return new ExperimentalPacket(tag, objStream); + default: + throw new IOException("unknown packet type encountered: " + tag); + } + } + + public override void Close() + { + m_in.Close(); + base.Close(); + } + + /// + /// A stream that overlays our input stream, allowing the user to only read a segment of it. + /// NB: dataLength will be negative if the segment length is in the upper range above 2**31. + /// + private class PartialInputStream + : BaseInputStream + { + private BcpgInputStream m_in; + private bool partial; + private int dataLength; + + internal PartialInputStream( + BcpgInputStream bcpgIn, + bool partial, + int dataLength) + { + this.m_in = bcpgIn; + this.partial = partial; + this.dataLength = dataLength; + } + + public override int ReadByte() + { + do + { + if (dataLength != 0) + { + int ch = m_in.ReadByte(); + if (ch < 0) + { + throw new EndOfStreamException("Premature end of stream in PartialInputStream"); + } + dataLength--; + return ch; + } + } + while (partial && ReadPartialDataLength() >= 0); + + return -1; + } + + public override int Read(byte[] buffer, int offset, int count) + { + do + { + if (dataLength != 0) + { + int readLen = (dataLength > count || dataLength < 0) ? count : dataLength; + int len = m_in.Read(buffer, offset, readLen); + if (len < 1) + { + throw new EndOfStreamException("Premature end of stream in PartialInputStream"); + } + dataLength -= len; + return len; + } + } + while (partial && ReadPartialDataLength() >= 0); + + return 0; + } + + private int ReadPartialDataLength() + { + int l = m_in.ReadByte(); + + if (l < 0) + { + return -1; + } + + partial = false; + + if (l < 192) + { + dataLength = l; + } + else if (l <= 223) + { + dataLength = ((l - 192) << 8) + (m_in.ReadByte()) + 192; + } + else if (l == 255) + { + dataLength = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) + | (m_in.ReadByte() << 8) | m_in.ReadByte(); + } + else + { + partial = true; + dataLength = 1 << (l & 0x1f); + } + + return 0; + } + } + } +} diff --git a/crypto/src/bcpg/BcpgObject.cs b/crypto/src/bcpg/BcpgObject.cs new file mode 100644 index 000000000..92811c3d3 --- /dev/null +++ b/crypto/src/bcpg/BcpgObject.cs @@ -0,0 +1,22 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for a PGP object. + public abstract class BcpgObject + { + public virtual byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WriteObject(this); + + return bOut.ToArray(); + } + + public abstract void Encode(BcpgOutputStream bcpgOut); + } +} + diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs new file mode 100644 index 000000000..204f65b50 --- /dev/null +++ b/crypto/src/bcpg/BcpgOutputStream.cs @@ -0,0 +1,390 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic output stream. + public class BcpgOutputStream + : BaseOutputStream + { + internal static BcpgOutputStream Wrap( + Stream outStr) + { + if (outStr is BcpgOutputStream) + { + return (BcpgOutputStream) outStr; + } + + return new BcpgOutputStream(outStr); + } + + private Stream outStr; + private byte[] partialBuffer; + private int partialBufferLength; + private int partialPower; + private int partialOffset; + private const int BufferSizePower = 16; // 2^16 size buffer on long files + + /// Create a stream representing a general packet. + /// Output stream to write to. + public BcpgOutputStream( + Stream outStr) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.outStr = outStr; + } + + /// Create a stream representing an old style partial object. + /// Output stream to write to. + /// The packet tag for the object. + public BcpgOutputStream( + Stream outStr, + PacketTag tag) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.outStr = outStr; + this.WriteHeader(tag, true, true, 0); + } + + /// Create a stream representing a general packet. + /// Output stream to write to. + /// Packet tag. + /// Size of chunks making up the packet. + /// If true, the header is written out in old format. + public BcpgOutputStream( + Stream outStr, + PacketTag tag, + long length, + bool oldFormat) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.outStr = outStr; + + if (length > 0xFFFFFFFFL) + { + this.WriteHeader(tag, false, true, 0); + this.partialBufferLength = 1 << BufferSizePower; + this.partialBuffer = new byte[partialBufferLength]; + this.partialPower = BufferSizePower; + this.partialOffset = 0; + } + else + { + this.WriteHeader(tag, oldFormat, false, length); + } + } + + /// Create a new style partial input stream buffered into chunks. + /// Output stream to write to. + /// Packet tag. + /// Size of chunks making up the packet. + public BcpgOutputStream( + Stream outStr, + PacketTag tag, + long length) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.outStr = outStr; + this.WriteHeader(tag, false, false, length); + } + + /// Create a new style partial input stream buffered into chunks. + /// Output stream to write to. + /// Packet tag. + /// Buffer to use for collecting chunks. + public BcpgOutputStream( + Stream outStr, + PacketTag tag, + byte[] buffer) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.outStr = outStr; + this.WriteHeader(tag, false, true, 0); + + this.partialBuffer = buffer; + + uint length = (uint) partialBuffer.Length; + for (partialPower = 0; length != 1; partialPower++) + { + length >>= 1; + } + + if (partialPower > 30) + { + throw new IOException("Buffer cannot be greater than 2^30 in length."); + } + this.partialBufferLength = 1 << partialPower; + this.partialOffset = 0; + } + + private void WriteNewPacketLength( + long bodyLen) + { + if (bodyLen < 192) + { + outStr.WriteByte((byte)bodyLen); + } + else if (bodyLen <= 8383) + { + bodyLen -= 192; + + outStr.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192)); + outStr.WriteByte((byte)bodyLen); + } + else + { + outStr.WriteByte(0xff); + outStr.WriteByte((byte)(bodyLen >> 24)); + outStr.WriteByte((byte)(bodyLen >> 16)); + outStr.WriteByte((byte)(bodyLen >> 8)); + outStr.WriteByte((byte)bodyLen); + } + } + + private void WriteHeader( + PacketTag tag, + bool oldPackets, + bool partial, + long bodyLen) + { + int hdr = 0x80; + + if (partialBuffer != null) + { + PartialFlush(true); + partialBuffer = null; + } + + if (oldPackets) + { + hdr |= ((int) tag) << 2; + + if (partial) + { + this.WriteByte((byte)(hdr | 0x03)); + } + else + { + if (bodyLen <= 0xff) + { + this.WriteByte((byte) hdr); + this.WriteByte((byte)bodyLen); + } + else if (bodyLen <= 0xffff) + { + this.WriteByte((byte)(hdr | 0x01)); + this.WriteByte((byte)(bodyLen >> 8)); + this.WriteByte((byte)(bodyLen)); + } + else + { + this.WriteByte((byte)(hdr | 0x02)); + this.WriteByte((byte)(bodyLen >> 24)); + this.WriteByte((byte)(bodyLen >> 16)); + this.WriteByte((byte)(bodyLen >> 8)); + this.WriteByte((byte)bodyLen); + } + } + } + else + { + hdr |= 0x40 | (int) tag; + this.WriteByte((byte) hdr); + + if (partial) + { + partialOffset = 0; + } + else + { + this.WriteNewPacketLength(bodyLen); + } + } + } + + private void PartialFlush( + bool isLast) + { + if (isLast) + { + WriteNewPacketLength(partialOffset); + outStr.Write(partialBuffer, 0, partialOffset); + } + else + { + outStr.WriteByte((byte)(0xE0 | partialPower)); + outStr.Write(partialBuffer, 0, partialBufferLength); + } + + partialOffset = 0; + } + + private void WritePartial( + byte b) + { + if (partialOffset == partialBufferLength) + { + PartialFlush(false); + } + + partialBuffer[partialOffset++] = b; + } + + private void WritePartial( + byte[] buffer, + int off, + int len) + { + if (partialOffset == partialBufferLength) + { + PartialFlush(false); + } + + if (len <= (partialBufferLength - partialOffset)) + { + Array.Copy(buffer, off, partialBuffer, partialOffset, len); + partialOffset += len; + } + else + { + int diff = partialBufferLength - partialOffset; + Array.Copy(buffer, off, partialBuffer, partialOffset, diff); + off += diff; + len -= diff; + PartialFlush(false); + while (len > partialBufferLength) + { + Array.Copy(buffer, off, partialBuffer, 0, partialBufferLength); + off += partialBufferLength; + len -= partialBufferLength; + PartialFlush(false); + } + Array.Copy(buffer, off, partialBuffer, 0, len); + partialOffset += len; + } + } + public override void WriteByte( + byte value) + { + if (partialBuffer != null) + { + WritePartial(value); + } + else + { + outStr.WriteByte(value); + } + } + public override void Write( + byte[] buffer, + int offset, + int count) + { + if (partialBuffer != null) + { + WritePartial(buffer, offset, count); + } + else + { + outStr.Write(buffer, offset, count); + } + } + + // Additional helper methods to write primitive types + internal virtual void WriteShort( + short n) + { + this.Write( + (byte)(n >> 8), + (byte)n); + } + internal virtual void WriteInt( + int n) + { + this.Write( + (byte)(n >> 24), + (byte)(n >> 16), + (byte)(n >> 8), + (byte)n); + } + internal virtual void WriteLong( + long n) + { + this.Write( + (byte)(n >> 56), + (byte)(n >> 48), + (byte)(n >> 40), + (byte)(n >> 32), + (byte)(n >> 24), + (byte)(n >> 16), + (byte)(n >> 8), + (byte)n); + } + + public void WritePacket( + ContainedPacket p) + { + p.Encode(this); + } + + internal void WritePacket( + PacketTag tag, + byte[] body, + bool oldFormat) + { + this.WriteHeader(tag, oldFormat, false, body.Length); + this.Write(body); + } + + public void WriteObject( + BcpgObject bcpgObject) + { + bcpgObject.Encode(this); + } + + public void WriteObjects( + params BcpgObject[] v) + { + foreach (BcpgObject o in v) + { + o.Encode(this); + } + } + + /// Flush the underlying stream. + public override void Flush() + { + outStr.Flush(); + } + + /// Finish writing out the current packet without closing the underlying stream. + public void Finish() + { + if (partialBuffer != null) + { + PartialFlush(true); + partialBuffer = null; + } + } + + public override void Close() + { + this.Finish(); + outStr.Flush(); + outStr.Close(); + base.Close(); + } + } +} diff --git a/crypto/src/bcpg/CompressedDataPacket.cs b/crypto/src/bcpg/CompressedDataPacket.cs new file mode 100644 index 000000000..2432825eb --- /dev/null +++ b/crypto/src/bcpg/CompressedDataPacket.cs @@ -0,0 +1,24 @@ +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Generic compressed data object. + public class CompressedDataPacket + : InputStreamPacket + { + private readonly CompressionAlgorithmTag algorithm; + + internal CompressedDataPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + this.algorithm = (CompressionAlgorithmTag) bcpgIn.ReadByte(); + } + + /// The algorithm tag value. + public CompressionAlgorithmTag Algorithm + { + get { return algorithm; } + } + } +} diff --git a/crypto/src/bcpg/CompressionAlgorithmTags.cs b/crypto/src/bcpg/CompressionAlgorithmTags.cs new file mode 100644 index 000000000..0e452298e --- /dev/null +++ b/crypto/src/bcpg/CompressionAlgorithmTags.cs @@ -0,0 +1,11 @@ +namespace Org.BouncyCastle.Bcpg +{ + /// Basic tags for compression algorithms. + public enum CompressionAlgorithmTag + { + Uncompressed = 0, // Uncompressed + Zip = 1, // ZIP (RFC 1951) + ZLib = 2, // ZLIB (RFC 1950) + BZip2 = 3, // BZ2 + } +} diff --git a/crypto/src/bcpg/ContainedPacket.cs b/crypto/src/bcpg/ContainedPacket.cs new file mode 100644 index 000000000..e8f387ca4 --- /dev/null +++ b/crypto/src/bcpg/ContainedPacket.cs @@ -0,0 +1,22 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic type for a PGP packet. + public abstract class ContainedPacket + : Packet + { + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WritePacket(this); + + return bOut.ToArray(); + } + + public abstract void Encode(BcpgOutputStream bcpgOut); + } +} diff --git a/crypto/src/bcpg/Crc24.cs b/crypto/src/bcpg/Crc24.cs new file mode 100644 index 000000000..97846f4fb --- /dev/null +++ b/crypto/src/bcpg/Crc24.cs @@ -0,0 +1,46 @@ +using System; + +namespace Org.BouncyCastle.Bcpg +{ + public class Crc24 + { + private const int Crc24Init = 0x0b704ce; + private const int Crc24Poly = 0x1864cfb; + + private int crc = Crc24Init; + + public Crc24() + { + } + + public void Update( + int b) + { + crc ^= b << 16; + for (int i = 0; i < 8; i++) + { + crc <<= 1; + if ((crc & 0x1000000) != 0) + { + crc ^= Crc24Poly; + } + } + } + + [Obsolete("Use 'Value' property instead")] + public int GetValue() + { + return crc; + } + + public int Value + { + get { return crc; } + } + + public void Reset() + { + crc = Crc24Init; + } + } +} diff --git a/crypto/src/bcpg/DsaPublicBcpgKey.cs b/crypto/src/bcpg/DsaPublicBcpgKey.cs new file mode 100644 index 000000000..61159567c --- /dev/null +++ b/crypto/src/bcpg/DsaPublicBcpgKey.cs @@ -0,0 +1,80 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for a DSA public key. + public class DsaPublicBcpgKey + : BcpgObject, IBcpgKey + { + private readonly MPInteger p, q, g, y; + + /// The stream to read the packet from. + public DsaPublicBcpgKey( + BcpgInputStream bcpgIn) + { + this.p = new MPInteger(bcpgIn); + this.q = new MPInteger(bcpgIn); + this.g = new MPInteger(bcpgIn); + this.y = new MPInteger(bcpgIn); + } + + public DsaPublicBcpgKey( + BigInteger p, + BigInteger q, + BigInteger g, + BigInteger y) + { + this.p = new MPInteger(p); + this.q = new MPInteger(q); + this.g = new MPInteger(g); + this.y = new MPInteger(y); + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObjects(p, q, g, y); + } + + public BigInteger G + { + get { return g.Value; } + } + + public BigInteger P + { + get { return p.Value; } + } + + public BigInteger Q + { + get { return q.Value; } + } + + public BigInteger Y + { + get { return y.Value; } + } + } +} diff --git a/crypto/src/bcpg/DsaSecretBcpgKey.cs b/crypto/src/bcpg/DsaSecretBcpgKey.cs new file mode 100644 index 000000000..41835d419 --- /dev/null +++ b/crypto/src/bcpg/DsaSecretBcpgKey.cs @@ -0,0 +1,61 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for a DSA secret key. + public class DsaSecretBcpgKey + : BcpgObject, IBcpgKey + { + internal MPInteger x; + + /** + * @param in + */ + public DsaSecretBcpgKey( + BcpgInputStream bcpgIn) + { + this.x = new MPInteger(bcpgIn); + } + + public DsaSecretBcpgKey( + BigInteger x) + { + this.x = new MPInteger(x); + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObject(x); + } + + /** + * @return x + */ + public BigInteger X + { + get { return x.Value; } + } + } +} diff --git a/crypto/src/bcpg/ElGamalPublicBcpgKey.cs b/crypto/src/bcpg/ElGamalPublicBcpgKey.cs new file mode 100644 index 000000000..808e427b2 --- /dev/null +++ b/crypto/src/bcpg/ElGamalPublicBcpgKey.cs @@ -0,0 +1,71 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for an ElGamal public key. + public class ElGamalPublicBcpgKey + : BcpgObject, IBcpgKey + { + internal MPInteger p, g, y; + + public ElGamalPublicBcpgKey( + BcpgInputStream bcpgIn) + { + this.p = new MPInteger(bcpgIn); + this.g = new MPInteger(bcpgIn); + this.y = new MPInteger(bcpgIn); + } + + public ElGamalPublicBcpgKey( + BigInteger p, + BigInteger g, + BigInteger y) + { + this.p = new MPInteger(p); + this.g = new MPInteger(g); + this.y = new MPInteger(y); + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public BigInteger P + { + get { return p.Value; } + } + + public BigInteger G + { + get { return g.Value; } + } + + public BigInteger Y + { + get { return y.Value; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObjects(p, g, y); + } + } +} diff --git a/crypto/src/bcpg/ElGamalSecretBcpgKey.cs b/crypto/src/bcpg/ElGamalSecretBcpgKey.cs new file mode 100644 index 000000000..2d95b29b1 --- /dev/null +++ b/crypto/src/bcpg/ElGamalSecretBcpgKey.cs @@ -0,0 +1,61 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for an ElGamal secret key. + public class ElGamalSecretBcpgKey + : BcpgObject, IBcpgKey + { + internal MPInteger x; + + /** + * @param in + */ + public ElGamalSecretBcpgKey( + BcpgInputStream bcpgIn) + { + this.x = new MPInteger(bcpgIn); + } + + /** + * @param x + */ + public ElGamalSecretBcpgKey( + BigInteger x) + { + this.x = new MPInteger(x); + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + public BigInteger X + { + get { return x.Value; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObject(x); + } + } +} diff --git a/crypto/src/bcpg/ExperimentalPacket.cs b/crypto/src/bcpg/ExperimentalPacket.cs new file mode 100644 index 000000000..36a254be1 --- /dev/null +++ b/crypto/src/bcpg/ExperimentalPacket.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for an experimental packet. + public class ExperimentalPacket + : ContainedPacket //, PublicKeyAlgorithmTag + { + private readonly PacketTag tag; + private readonly byte[] contents; + + internal ExperimentalPacket( + PacketTag tag, + BcpgInputStream bcpgIn) + { + this.tag = tag; + + this.contents = bcpgIn.ReadAll(); + } + + public PacketTag Tag + { + get { return tag; } + } + + public byte[] GetContents() + { + return (byte[]) contents.Clone(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(tag, contents, true); + } + } +} diff --git a/crypto/src/bcpg/HashAlgorithmTags.cs b/crypto/src/bcpg/HashAlgorithmTags.cs new file mode 100644 index 000000000..96c009153 --- /dev/null +++ b/crypto/src/bcpg/HashAlgorithmTags.cs @@ -0,0 +1,19 @@ +namespace Org.BouncyCastle.Bcpg +{ + /// Basic tags for hash algorithms. + public enum HashAlgorithmTag + { + MD5 = 1, // MD5 + Sha1 = 2, // SHA-1 + RipeMD160 = 3, // RIPE-MD/160 + DoubleSha = 4, // Reserved for double-width SHA (experimental) + MD2 = 5, // MD2 + Tiger192 = 6, // Reserved for TIGER/192 + Haval5pass160 = 7, // Reserved for HAVAL (5 pass, 160-bit) + + Sha256 = 8, // SHA-256 + Sha384 = 9, // SHA-384 + Sha512 = 10, // SHA-512 + Sha224 = 11, // SHA-224 + } +} diff --git a/crypto/src/bcpg/IBcpgKey.cs b/crypto/src/bcpg/IBcpgKey.cs new file mode 100644 index 000000000..275461772 --- /dev/null +++ b/crypto/src/bcpg/IBcpgKey.cs @@ -0,0 +1,16 @@ +using System; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base interface for a PGP key. + public interface IBcpgKey + { + /// + /// The base format for this key - in the case of the symmetric keys it will generally + /// be raw indicating that the key is just a straight byte representation, for an asymmetric + /// key the format will be PGP, indicating the key is a string of MPIs encoded in PGP format. + /// + /// "RAW" or "PGP". + string Format { get; } + } +} diff --git a/crypto/src/bcpg/InputStreamPacket.cs b/crypto/src/bcpg/InputStreamPacket.cs new file mode 100644 index 000000000..c45efab7b --- /dev/null +++ b/crypto/src/bcpg/InputStreamPacket.cs @@ -0,0 +1,20 @@ +namespace Org.BouncyCastle.Bcpg +{ + public class InputStreamPacket + : Packet + { + private readonly BcpgInputStream bcpgIn; + + public InputStreamPacket( + BcpgInputStream bcpgIn) + { + this.bcpgIn = bcpgIn; + } + + /// Note: you can only read from this once... + public BcpgInputStream GetInputStream() + { + return bcpgIn; + } + } +} diff --git a/crypto/src/bcpg/LiteralDataPacket.cs b/crypto/src/bcpg/LiteralDataPacket.cs new file mode 100644 index 000000000..63a2c6d44 --- /dev/null +++ b/crypto/src/bcpg/LiteralDataPacket.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg +{ + /// Generic literal data packet. + public class LiteralDataPacket + : InputStreamPacket + { + private int format; + private byte[] fileName; + private long modDate; + + internal LiteralDataPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + format = bcpgIn.ReadByte(); + int len = bcpgIn.ReadByte(); + + fileName = new byte[len]; + for (int i = 0; i != len; ++i) + { + fileName[i] = (byte)bcpgIn.ReadByte(); + } + + modDate = (((uint)bcpgIn.ReadByte() << 24) + | ((uint)bcpgIn.ReadByte() << 16) + | ((uint)bcpgIn.ReadByte() << 8) + | (uint)bcpgIn.ReadByte()) * 1000L; + } + + /// The format tag value. + public int Format + { + get { return format; } + } + + /// The modification time of the file in milli-seconds (since Jan 1, 1970 UTC) + public long ModificationTime + { + get { return modDate; } + } + + public string FileName + { + get { return Strings.FromUtf8ByteArray(fileName); } + } + + public byte[] GetRawFileName() + { + return Arrays.Clone(fileName); + } + } +} diff --git a/crypto/src/bcpg/MPInteger.cs b/crypto/src/bcpg/MPInteger.cs new file mode 100644 index 000000000..441407244 --- /dev/null +++ b/crypto/src/bcpg/MPInteger.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// A multiple precision integer + public class MPInteger + : BcpgObject + { + private readonly BigInteger val; + + public MPInteger( + BcpgInputStream bcpgIn) + { + if (bcpgIn == null) + throw new ArgumentNullException("bcpgIn"); + + int length = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte(); + byte[] bytes = new byte[(length + 7) / 8]; + + bcpgIn.ReadFully(bytes); + + this.val = new BigInteger(1, bytes); + } + + public MPInteger( + BigInteger val) + { + if (val == null) + throw new ArgumentNullException("val"); + if (val.SignValue < 0) + throw new ArgumentException("Values must be positive", "val"); + + this.val = val; + } + + public BigInteger Value + { + get { return val; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteShort((short) val.BitLength); + bcpgOut.Write(val.ToByteArrayUnsigned()); + } + + internal static void Encode( + BcpgOutputStream bcpgOut, + BigInteger val) + { + bcpgOut.WriteShort((short) val.BitLength); + bcpgOut.Write(val.ToByteArrayUnsigned()); + } + } +} diff --git a/crypto/src/bcpg/MarkerPacket.cs b/crypto/src/bcpg/MarkerPacket.cs new file mode 100644 index 000000000..4dc4b5a83 --- /dev/null +++ b/crypto/src/bcpg/MarkerPacket.cs @@ -0,0 +1,24 @@ +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic type for a marker packet. + public class MarkerPacket + : ContainedPacket + { + // "PGP" + byte[] marker = { (byte)0x50, (byte)0x47, (byte)0x50 }; + + public MarkerPacket( + BcpgInputStream bcpgIn) + { + bcpgIn.ReadFully(marker); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.Marker, marker, true); + } + } +} diff --git a/crypto/src/bcpg/ModDetectionCodePacket.cs b/crypto/src/bcpg/ModDetectionCodePacket.cs new file mode 100644 index 000000000..6bb23645a --- /dev/null +++ b/crypto/src/bcpg/ModDetectionCodePacket.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a modification detection code packet. + public class ModDetectionCodePacket + : ContainedPacket + { + private readonly byte[] digest; + + internal ModDetectionCodePacket( + BcpgInputStream bcpgIn) + { + if (bcpgIn == null) + throw new ArgumentNullException("bcpgIn"); + + this.digest = new byte[20]; + bcpgIn.ReadFully(this.digest); + } + + public ModDetectionCodePacket( + byte[] digest) + { + if (digest == null) + throw new ArgumentNullException("digest"); + + this.digest = (byte[]) digest.Clone(); + } + + public byte[] GetDigest() + { + return (byte[]) digest.Clone(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.ModificationDetectionCode, digest, false); + } + } +} diff --git a/crypto/src/bcpg/OnePassSignaturePacket.cs b/crypto/src/bcpg/OnePassSignaturePacket.cs new file mode 100644 index 000000000..b67df0a52 --- /dev/null +++ b/crypto/src/bcpg/OnePassSignaturePacket.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Generic signature object + public class OnePassSignaturePacket + : ContainedPacket + { + private int version; + private int sigType; + private HashAlgorithmTag hashAlgorithm; + private PublicKeyAlgorithmTag keyAlgorithm; + private long keyId; + private int nested; + + internal OnePassSignaturePacket( + BcpgInputStream bcpgIn) + { + version = bcpgIn.ReadByte(); + sigType = bcpgIn.ReadByte(); + hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte(); + keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte(); + + keyId |= (long)bcpgIn.ReadByte() << 56; + keyId |= (long)bcpgIn.ReadByte() << 48; + keyId |= (long)bcpgIn.ReadByte() << 40; + keyId |= (long)bcpgIn.ReadByte() << 32; + keyId |= (long)bcpgIn.ReadByte() << 24; + keyId |= (long)bcpgIn.ReadByte() << 16; + keyId |= (long)bcpgIn.ReadByte() << 8; + keyId |= (uint)bcpgIn.ReadByte(); + + nested = bcpgIn.ReadByte(); + } + + public OnePassSignaturePacket( + int sigType, + HashAlgorithmTag hashAlgorithm, + PublicKeyAlgorithmTag keyAlgorithm, + long keyId, + bool isNested) + { + this.version = 3; + this.sigType = sigType; + this.hashAlgorithm = hashAlgorithm; + this.keyAlgorithm = keyAlgorithm; + this.keyId = keyId; + this.nested = (isNested) ? 0 : 1; + } + + public int SignatureType + { + get { return sigType; } + } + + /// The encryption algorithm tag. + public PublicKeyAlgorithmTag KeyAlgorithm + { + get { return keyAlgorithm; } + } + + /// The hash algorithm tag. + public HashAlgorithmTag HashAlgorithm + { + get { return hashAlgorithm; } + } + + public long KeyId + { + get { return keyId; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.Write( + (byte) version, + (byte) sigType, + (byte) hashAlgorithm, + (byte) keyAlgorithm); + + pOut.WriteLong(keyId); + + pOut.WriteByte((byte) nested); + + bcpgOut.WritePacket(PacketTag.OnePassSignature, bOut.ToArray(), true); + } + } +} diff --git a/crypto/src/bcpg/OutputStreamPacket.cs b/crypto/src/bcpg/OutputStreamPacket.cs new file mode 100644 index 000000000..aa8316dcb --- /dev/null +++ b/crypto/src/bcpg/OutputStreamPacket.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + public abstract class OutputStreamPacket + { + private readonly BcpgOutputStream bcpgOut; + + internal OutputStreamPacket( + BcpgOutputStream bcpgOut) + { + if (bcpgOut == null) + throw new ArgumentNullException("bcpgOut"); + + this.bcpgOut = bcpgOut; + } + + public abstract BcpgOutputStream Open(); + + public abstract void Close(); + } +} + diff --git a/crypto/src/bcpg/Packet.cs b/crypto/src/bcpg/Packet.cs new file mode 100644 index 000000000..83f6d1f74 --- /dev/null +++ b/crypto/src/bcpg/Packet.cs @@ -0,0 +1,7 @@ +namespace Org.BouncyCastle.Bcpg +{ + public class Packet + //: PacketTag + { + } +} diff --git a/crypto/src/bcpg/PacketTags.cs b/crypto/src/bcpg/PacketTags.cs new file mode 100644 index 000000000..5a53d4e95 --- /dev/null +++ b/crypto/src/bcpg/PacketTags.cs @@ -0,0 +1,30 @@ +namespace Org.BouncyCastle.Bcpg +{ + /// Basic PGP packet tag types. + public enum PacketTag + { + Reserved = 0, // Reserved - a packet tag must not have this value + PublicKeyEncryptedSession = 1, // Public-Key Encrypted Session Key Packet + Signature = 2, // Signature Packet + SymmetricKeyEncryptedSessionKey = 3, // Symmetric-Key Encrypted Session Key Packet + OnePassSignature = 4, // One-Pass Signature Packet + SecretKey = 5, // Secret Key Packet + PublicKey = 6, // Public Key Packet + SecretSubkey = 7, // Secret Subkey Packet + CompressedData = 8, // Compressed Data Packet + SymmetricKeyEncrypted = 9, // Symmetrically Encrypted Data Packet + Marker = 10, // Marker Packet + LiteralData = 11, // Literal Data Packet + Trust = 12, // Trust Packet + UserId = 13, // User ID Packet + PublicSubkey = 14, // Public Subkey Packet + UserAttribute = 17, // User attribute + SymmetricEncryptedIntegrityProtected = 18, // Symmetric encrypted, integrity protected + ModificationDetectionCode = 19, // Modification detection code + + Experimental1 = 60, // Private or Experimental Values + Experimental2 = 61, + Experimental3 = 62, + Experimental4 = 63 + } +} diff --git a/crypto/src/bcpg/PublicKeyAlgorithmTags.cs b/crypto/src/bcpg/PublicKeyAlgorithmTags.cs new file mode 100644 index 000000000..85ae548eb --- /dev/null +++ b/crypto/src/bcpg/PublicKeyAlgorithmTags.cs @@ -0,0 +1,28 @@ +namespace Org.BouncyCastle.Bcpg +{ + /// Public Key Algorithm tag numbers. + public enum PublicKeyAlgorithmTag + { + RsaGeneral = 1, // RSA (Encrypt or Sign) + RsaEncrypt = 2, // RSA Encrypt-Only + RsaSign = 3, // RSA Sign-Only + ElGamalEncrypt = 16, // Elgamal (Encrypt-Only), see [ELGAMAL] + Dsa = 17, // DSA (Digital Signature Standard) + EC = 18, // Reserved for Elliptic Curve + ECDsa = 19, // Reserved for ECDSA + ElGamalGeneral = 20, // Elgamal (Encrypt or Sign) + DiffieHellman = 21, // Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME) + + Experimental_1 = 100, + Experimental_2 = 101, + Experimental_3 = 102, + Experimental_4 = 103, + Experimental_5 = 104, + Experimental_6 = 105, + Experimental_7 = 106, + Experimental_8 = 107, + Experimental_9 = 108, + Experimental_10 = 109, + Experimental_11 = 110, + } +} diff --git a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs new file mode 100644 index 000000000..d10605f1d --- /dev/null +++ b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a PGP public key. + public class PublicKeyEncSessionPacket + : ContainedPacket //, PublicKeyAlgorithmTag + { + private int version; + private long keyId; + private PublicKeyAlgorithmTag algorithm; + private BigInteger[] data; + + internal PublicKeyEncSessionPacket( + BcpgInputStream bcpgIn) + { + version = bcpgIn.ReadByte(); + + keyId |= (long)bcpgIn.ReadByte() << 56; + keyId |= (long)bcpgIn.ReadByte() << 48; + keyId |= (long)bcpgIn.ReadByte() << 40; + keyId |= (long)bcpgIn.ReadByte() << 32; + keyId |= (long)bcpgIn.ReadByte() << 24; + keyId |= (long)bcpgIn.ReadByte() << 16; + keyId |= (long)bcpgIn.ReadByte() << 8; + keyId |= (uint)bcpgIn.ReadByte(); + + algorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte(); + + switch ((PublicKeyAlgorithmTag) algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + data = new BigInteger[]{ new MPInteger(bcpgIn).Value }; + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + data = new BigInteger[] + { + new MPInteger(bcpgIn).Value, + new MPInteger(bcpgIn).Value + }; + break; + default: + throw new IOException("unknown PGP public key algorithm encountered"); + } + } + + public PublicKeyEncSessionPacket( + long keyId, + PublicKeyAlgorithmTag algorithm, + BigInteger[] data) + { + this.version = 3; + this.keyId = keyId; + this.algorithm = algorithm; + this.data = (BigInteger[]) data.Clone(); + } + + public int Version + { + get { return version; } + } + + public long KeyId + { + get { return keyId; } + } + + public PublicKeyAlgorithmTag Algorithm + { + get { return algorithm; } + } + + public BigInteger[] GetEncSessionKey() + { + return (BigInteger[]) data.Clone(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WriteByte((byte) version); + + pOut.WriteLong(keyId); + + pOut.WriteByte((byte)algorithm); + + for (int i = 0; i != data.Length; i++) + { + MPInteger.Encode(pOut, data[i]); + } + + bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession , bOut.ToArray(), true); + } + } +} diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs new file mode 100644 index 000000000..32d43149b --- /dev/null +++ b/crypto/src/bcpg/PublicKeyPacket.cs @@ -0,0 +1,115 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a PGP public key. + public class PublicKeyPacket + : ContainedPacket //, PublicKeyAlgorithmTag + { + private int version; + private long time; + private int validDays; + private PublicKeyAlgorithmTag algorithm; + private IBcpgKey key; + + internal PublicKeyPacket( + BcpgInputStream bcpgIn) + { + version = bcpgIn.ReadByte(); + + time = ((uint)bcpgIn.ReadByte() << 24) | ((uint)bcpgIn.ReadByte() << 16) + | ((uint)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte(); + + if (version <= 3) + { + validDays = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte(); + } + + algorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte(); + + switch ((PublicKeyAlgorithmTag) algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + key = new RsaPublicBcpgKey(bcpgIn); + break; + case PublicKeyAlgorithmTag.Dsa: + key = new DsaPublicBcpgKey(bcpgIn); + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + key = new ElGamalPublicBcpgKey(bcpgIn); + break; + default: + throw new IOException("unknown PGP public key algorithm encountered"); + } + } + + /// Construct a version 4 public key packet. + public PublicKeyPacket( + PublicKeyAlgorithmTag algorithm, + DateTime time, + IBcpgKey key) + { + this.version = 4; + this.time = DateTimeUtilities.DateTimeToUnixMs(time) / 1000L; + this.algorithm = algorithm; + this.key = key; + } + + public int Version + { + get { return version; } + } + + public PublicKeyAlgorithmTag Algorithm + { + get { return algorithm; } + } + + public int ValidDays + { + get { return validDays; } + } + + public DateTime GetTime() + { + return DateTimeUtilities.UnixMsToDateTime(time * 1000L); + } + + public IBcpgKey Key + { + get { return key; } + } + + public byte[] GetEncodedContents() + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WriteByte((byte) version); + pOut.WriteInt((int) time); + + if (version <= 3) + { + pOut.WriteShort((short) validDays); + } + + pOut.WriteByte((byte) algorithm); + + pOut.WriteObject((BcpgObject)key); + + return bOut.ToArray(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), true); + } + } +} diff --git a/crypto/src/bcpg/PublicSubkeyPacket.cs b/crypto/src/bcpg/PublicSubkeyPacket.cs new file mode 100644 index 000000000..6e1aeda98 --- /dev/null +++ b/crypto/src/bcpg/PublicSubkeyPacket.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a PGP public subkey + public class PublicSubkeyPacket + : PublicKeyPacket + { + internal PublicSubkeyPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + } + + /// Construct a version 4 public subkey packet. + public PublicSubkeyPacket( + PublicKeyAlgorithmTag algorithm, + DateTime time, + IBcpgKey key) + : base(algorithm, time, key) + { + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.PublicSubkey, GetEncodedContents(), true); + } + } +} diff --git a/crypto/src/bcpg/RsaPublicBcpgKey.cs b/crypto/src/bcpg/RsaPublicBcpgKey.cs new file mode 100644 index 000000000..fd2313c89 --- /dev/null +++ b/crypto/src/bcpg/RsaPublicBcpgKey.cs @@ -0,0 +1,66 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for an RSA public key. + public class RsaPublicBcpgKey + : BcpgObject, IBcpgKey + { + private readonly MPInteger n, e; + + /// Construct an RSA public key from the passed in stream. + public RsaPublicBcpgKey( + BcpgInputStream bcpgIn) + { + this.n = new MPInteger(bcpgIn); + this.e = new MPInteger(bcpgIn); + } + + /// The modulus. + /// The public exponent. + public RsaPublicBcpgKey( + BigInteger n, + BigInteger e) + { + this.n = new MPInteger(n); + this.e = new MPInteger(e); + } + + public BigInteger PublicExponent + { + get { return e.Value; } + } + + public BigInteger Modulus + { + get { return n.Value; } + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObjects(n, e); + } + } +} diff --git a/crypto/src/bcpg/RsaSecretBcpgKey.cs b/crypto/src/bcpg/RsaSecretBcpgKey.cs new file mode 100644 index 000000000..5c04d9f85 --- /dev/null +++ b/crypto/src/bcpg/RsaSecretBcpgKey.cs @@ -0,0 +1,114 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg +{ + /// Base class for an RSA secret (or priate) key. + public class RsaSecretBcpgKey + : BcpgObject, IBcpgKey + { + private readonly MPInteger d, p, q, u; + private readonly BigInteger expP, expQ, crt; + + public RsaSecretBcpgKey( + BcpgInputStream bcpgIn) + { + this.d = new MPInteger(bcpgIn); + this.p = new MPInteger(bcpgIn); + this.q = new MPInteger(bcpgIn); + this.u = new MPInteger(bcpgIn); + + this.expP = d.Value.Remainder(p.Value.Subtract(BigInteger.One)); + this.expQ = d.Value.Remainder(q.Value.Subtract(BigInteger.One)); + this.crt = q.Value.ModInverse(p.Value); + } + + public RsaSecretBcpgKey( + BigInteger d, + BigInteger p, + BigInteger q) + { + // PGP requires (p < q) + int cmp = p.CompareTo(q); + if (cmp >= 0) + { + if (cmp == 0) + throw new ArgumentException("p and q cannot be equal"); + + BigInteger tmp = p; + p = q; + q = tmp; + } + + this.d = new MPInteger(d); + this.p = new MPInteger(p); + this.q = new MPInteger(q); + this.u = new MPInteger(p.ModInverse(q)); + + this.expP = d.Remainder(p.Subtract(BigInteger.One)); + this.expQ = d.Remainder(q.Subtract(BigInteger.One)); + this.crt = q.ModInverse(p); + } + + public BigInteger Modulus + { + get { return p.Value.Multiply(q.Value); } + } + + public BigInteger PrivateExponent + { + get { return d.Value; } + } + + public BigInteger PrimeP + { + get { return p.Value; } + } + + public BigInteger PrimeQ + { + get { return q.Value; } + } + + public BigInteger PrimeExponentP + { + get { return expP; } + } + + public BigInteger PrimeExponentQ + { + get { return expQ; } + } + + public BigInteger CrtCoefficient + { + get { return crt; } + } + + /// The format, as a string, always "PGP". + public string Format + { + get { return "PGP"; } + } + + /// Return the standard PGP encoding of the key. + public override byte[] GetEncoded() + { + try + { + return base.GetEncoded(); + } + catch (Exception) + { + return null; + } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteObjects(d, p, q, u); + } + } +} diff --git a/crypto/src/bcpg/S2k.cs b/crypto/src/bcpg/S2k.cs new file mode 100644 index 000000000..de08c016c --- /dev/null +++ b/crypto/src/bcpg/S2k.cs @@ -0,0 +1,147 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// The string to key specifier class. + public class S2k + : BcpgObject + { + private const int ExpBias = 6; + + public const int Simple = 0; + public const int Salted = 1; + public const int SaltedAndIterated = 3; + public const int GnuDummyS2K = 101; + + internal int type; + internal HashAlgorithmTag algorithm; + internal byte[] iv; + internal int itCount = -1; + internal int protectionMode = -1; + + internal S2k( + Stream inStr) + { + type = inStr.ReadByte(); + algorithm = (HashAlgorithmTag) inStr.ReadByte(); + + // + // if this happens we have a dummy-S2k packet. + // + if (type != GnuDummyS2K) + { + if (type != 0) + { + iv = new byte[8]; + if (Streams.ReadFully(inStr, iv, 0, iv.Length) < iv.Length) + throw new EndOfStreamException(); + + if (type == 3) + { + itCount = inStr.ReadByte(); + } + } + } + else + { + inStr.ReadByte(); // G + inStr.ReadByte(); // N + inStr.ReadByte(); // U + protectionMode = inStr.ReadByte(); // protection mode + } + } + + public S2k( + HashAlgorithmTag algorithm) + { + this.type = 0; + this.algorithm = algorithm; + } + + public S2k( + HashAlgorithmTag algorithm, + byte[] iv) + { + this.type = 1; + this.algorithm = algorithm; + this.iv = iv; + } + + public S2k( + HashAlgorithmTag algorithm, + byte[] iv, + int itCount) + { + this.type = 3; + this.algorithm = algorithm; + this.iv = iv; + this.itCount = itCount; + } + + public int Type + { + get { return type; } + } + + /// The hash algorithm. + public HashAlgorithmTag HashAlgorithm + { + get { return algorithm; } + } + + /// The IV for the key generation algorithm. + public byte[] GetIV() + { + return Arrays.Clone(iv); + } + + [Obsolete("Use 'IterationCount' property instead")] + public long GetIterationCount() + { + return IterationCount; + } + + /// The iteration count + public long IterationCount + { + get { return (16 + (itCount & 15)) << ((itCount >> 4) + ExpBias); } + } + + /// The protection mode - only if GnuDummyS2K + public int ProtectionMode + { + get { return protectionMode; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WriteByte((byte) type); + bcpgOut.WriteByte((byte) algorithm); + + if (type != GnuDummyS2K) + { + if (type != 0) + { + bcpgOut.Write(iv); + } + + if (type == 3) + { + bcpgOut.WriteByte((byte) itCount); + } + } + else + { + bcpgOut.WriteByte((byte) 'G'); + bcpgOut.WriteByte((byte) 'N'); + bcpgOut.WriteByte((byte) 'U'); + bcpgOut.WriteByte((byte) protectionMode); + } + } + } +} diff --git a/crypto/src/bcpg/SecretKeyPacket.cs b/crypto/src/bcpg/SecretKeyPacket.cs new file mode 100644 index 000000000..d9ceab4f1 --- /dev/null +++ b/crypto/src/bcpg/SecretKeyPacket.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a PGP secret key. + public class SecretKeyPacket + : ContainedPacket //, PublicKeyAlgorithmTag + { + public const int UsageNone = 0x00; + public const int UsageChecksum = 0xff; + public const int UsageSha1 = 0xfe; + + private PublicKeyPacket pubKeyPacket; + private readonly byte[] secKeyData; + private int s2kUsage; + private SymmetricKeyAlgorithmTag encAlgorithm; + private S2k s2k; + private byte[] iv; + + internal SecretKeyPacket( + BcpgInputStream bcpgIn) + { + if (this is SecretSubkeyPacket) + { + pubKeyPacket = new PublicSubkeyPacket(bcpgIn); + } + else + { + pubKeyPacket = new PublicKeyPacket(bcpgIn); + } + + s2kUsage = bcpgIn.ReadByte(); + + if (s2kUsage == UsageChecksum || s2kUsage == UsageSha1) + { + encAlgorithm = (SymmetricKeyAlgorithmTag) bcpgIn.ReadByte(); + s2k = new S2k(bcpgIn); + } + else + { + encAlgorithm = (SymmetricKeyAlgorithmTag) s2kUsage; + } + + if (!(s2k != null && s2k.Type == S2k.GnuDummyS2K && s2k.ProtectionMode == 0x01)) + { + if (s2kUsage != 0) + { + if (((int) encAlgorithm) < 7) + { + iv = new byte[8]; + } + else + { + iv = new byte[16]; + } + bcpgIn.ReadFully(iv); + } + } + + secKeyData = bcpgIn.ReadAll(); + } + + public SecretKeyPacket( + PublicKeyPacket pubKeyPacket, + SymmetricKeyAlgorithmTag encAlgorithm, + S2k s2k, + byte[] iv, + byte[] secKeyData) + { + this.pubKeyPacket = pubKeyPacket; + this.encAlgorithm = encAlgorithm; + + if (encAlgorithm != SymmetricKeyAlgorithmTag.Null) + { + this.s2kUsage = UsageChecksum; + } + else + { + this.s2kUsage = UsageNone; + } + + this.s2k = s2k; + this.iv = Arrays.Clone(iv); + this.secKeyData = secKeyData; + } + + public SecretKeyPacket( + PublicKeyPacket pubKeyPacket, + SymmetricKeyAlgorithmTag encAlgorithm, + int s2kUsage, + S2k s2k, + byte[] iv, + byte[] secKeyData) + { + this.pubKeyPacket = pubKeyPacket; + this.encAlgorithm = encAlgorithm; + this.s2kUsage = s2kUsage; + this.s2k = s2k; + this.iv = Arrays.Clone(iv); + this.secKeyData = secKeyData; + } + + public SymmetricKeyAlgorithmTag EncAlgorithm + { + get { return encAlgorithm; } + } + + public int S2kUsage + { + get { return s2kUsage; } + } + + public byte[] GetIV() + { + return Arrays.Clone(iv); + } + + public S2k S2k + { + get { return s2k; } + } + + public PublicKeyPacket PublicKeyPacket + { + get { return pubKeyPacket; } + } + + public byte[] GetSecretKeyData() + { + return secKeyData; + } + + public byte[] GetEncodedContents() + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.Write(pubKeyPacket.GetEncodedContents()); + + pOut.WriteByte((byte) s2kUsage); + + if (s2kUsage == UsageChecksum || s2kUsage == UsageSha1) + { + pOut.WriteByte((byte) encAlgorithm); + pOut.WriteObject(s2k); + } + + if (iv != null) + { + pOut.Write(iv); + } + + if (secKeyData != null && secKeyData.Length > 0) + { + pOut.Write(secKeyData); + } + + return bOut.ToArray(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.SecretKey, GetEncodedContents(), true); + } + } +} diff --git a/crypto/src/bcpg/SecretSubkeyPacket.cs b/crypto/src/bcpg/SecretSubkeyPacket.cs new file mode 100644 index 000000000..8f1746942 --- /dev/null +++ b/crypto/src/bcpg/SecretSubkeyPacket.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic packet for a PGP secret key. + public class SecretSubkeyPacket + : SecretKeyPacket + { + internal SecretSubkeyPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + } + + public SecretSubkeyPacket( + PublicKeyPacket pubKeyPacket, + SymmetricKeyAlgorithmTag encAlgorithm, + S2k s2k, + byte[] iv, + byte[] secKeyData) + : base(pubKeyPacket, encAlgorithm, s2k, iv, secKeyData) + { + } + + public SecretSubkeyPacket( + PublicKeyPacket pubKeyPacket, + SymmetricKeyAlgorithmTag encAlgorithm, + int s2kUsage, + S2k s2k, + byte[] iv, + byte[] secKeyData) + : base(pubKeyPacket, encAlgorithm, s2kUsage, s2k, iv, secKeyData) + { + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.SecretSubkey, GetEncodedContents(), true); + } + } +} diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs new file mode 100644 index 000000000..605ce84c4 --- /dev/null +++ b/crypto/src/bcpg/SignaturePacket.cs @@ -0,0 +1,472 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg +{ + /// Generic signature packet. + public class SignaturePacket + : ContainedPacket //, PublicKeyAlgorithmTag + { + private int version; + private int signatureType; + private long creationTime; + private long keyId; + private PublicKeyAlgorithmTag keyAlgorithm; + private HashAlgorithmTag hashAlgorithm; + private MPInteger[] signature; + private byte[] fingerprint; + private SignatureSubpacket[] hashedData; + private SignatureSubpacket[] unhashedData; + private byte[] signatureEncoding; + + internal SignaturePacket( + BcpgInputStream bcpgIn) + { + version = bcpgIn.ReadByte(); + + if (version == 3 || version == 2) + { +// int l = + bcpgIn.ReadByte(); + + signatureType = bcpgIn.ReadByte(); + creationTime = (((long)bcpgIn.ReadByte() << 24) | ((long)bcpgIn.ReadByte() << 16) + | ((long)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte()) * 1000L; + + keyId |= (long)bcpgIn.ReadByte() << 56; + keyId |= (long)bcpgIn.ReadByte() << 48; + keyId |= (long)bcpgIn.ReadByte() << 40; + keyId |= (long)bcpgIn.ReadByte() << 32; + keyId |= (long)bcpgIn.ReadByte() << 24; + keyId |= (long)bcpgIn.ReadByte() << 16; + keyId |= (long)bcpgIn.ReadByte() << 8; + keyId |= (uint)bcpgIn.ReadByte(); + + keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte(); + hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte(); + } + else if (version == 4) + { + signatureType = bcpgIn.ReadByte(); + keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte(); + hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte(); + + int hashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte(); + byte[] hashed = new byte[hashedLength]; + + bcpgIn.ReadFully(hashed); + + // + // read the signature sub packet data. + // + SignatureSubpacketsParser sIn = new SignatureSubpacketsParser( + new MemoryStream(hashed, false)); + + IList v = Platform.CreateArrayList(); + SignatureSubpacket sub; + while ((sub = sIn.ReadPacket()) != null) + { + v.Add(sub); + } + + hashedData = new SignatureSubpacket[v.Count]; + + for (int i = 0; i != hashedData.Length; i++) + { + SignatureSubpacket p = (SignatureSubpacket)v[i]; + if (p is IssuerKeyId) + { + keyId = ((IssuerKeyId)p).KeyId; + } + else if (p is SignatureCreationTime) + { + creationTime = DateTimeUtilities.DateTimeToUnixMs( + ((SignatureCreationTime)p).GetTime()); + } + + hashedData[i] = p; + } + + int unhashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte(); + byte[] unhashed = new byte[unhashedLength]; + + bcpgIn.ReadFully(unhashed); + + sIn = new SignatureSubpacketsParser(new MemoryStream(unhashed, false)); + + v.Clear(); + + while ((sub = sIn.ReadPacket()) != null) + { + v.Add(sub); + } + + unhashedData = new SignatureSubpacket[v.Count]; + + for (int i = 0; i != unhashedData.Length; i++) + { + SignatureSubpacket p = (SignatureSubpacket)v[i]; + if (p is IssuerKeyId) + { + keyId = ((IssuerKeyId)p).KeyId; + } + + unhashedData[i] = p; + } + } + else + { + throw new Exception("unsupported version: " + version); + } + + fingerprint = new byte[2]; + bcpgIn.ReadFully(fingerprint); + + switch (keyAlgorithm) + { + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + MPInteger v = new MPInteger(bcpgIn); + signature = new MPInteger[]{ v }; + break; + case PublicKeyAlgorithmTag.Dsa: + MPInteger r = new MPInteger(bcpgIn); + MPInteger s = new MPInteger(bcpgIn); + signature = new MPInteger[]{ r, s }; + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: // yep, this really does happen sometimes. + case PublicKeyAlgorithmTag.ElGamalGeneral: + MPInteger p = new MPInteger(bcpgIn); + MPInteger g = new MPInteger(bcpgIn); + MPInteger y = new MPInteger(bcpgIn); + signature = new MPInteger[]{ p, g, y }; + break; + default: + if (keyAlgorithm >= PublicKeyAlgorithmTag.Experimental_1 && keyAlgorithm <= PublicKeyAlgorithmTag.Experimental_11) + { + signature = null; + MemoryStream bOut = new MemoryStream(); + int ch; + while ((ch = bcpgIn.ReadByte()) >= 0) + { + bOut.WriteByte((byte) ch); + } + signatureEncoding = bOut.ToArray(); + } + else + { + throw new IOException("unknown signature key algorithm: " + keyAlgorithm); + } + break; + } + } + + /** + * Generate a version 4 signature packet. + * + * @param signatureType + * @param keyAlgorithm + * @param hashAlgorithm + * @param hashedData + * @param unhashedData + * @param fingerprint + * @param signature + */ + public SignaturePacket( + int signatureType, + long keyId, + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm, + SignatureSubpacket[] hashedData, + SignatureSubpacket[] unhashedData, + byte[] fingerprint, + MPInteger[] signature) + : this(4, signatureType, keyId, keyAlgorithm, hashAlgorithm, hashedData, unhashedData, fingerprint, signature) + { + } + + /** + * Generate a version 2/3 signature packet. + * + * @param signatureType + * @param keyAlgorithm + * @param hashAlgorithm + * @param fingerprint + * @param signature + */ + public SignaturePacket( + int version, + int signatureType, + long keyId, + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm, + long creationTime, + byte[] fingerprint, + MPInteger[] signature) + : this(version, signatureType, keyId, keyAlgorithm, hashAlgorithm, null, null, fingerprint, signature) + { + this.creationTime = creationTime; + } + + public SignaturePacket( + int version, + int signatureType, + long keyId, + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm, + SignatureSubpacket[] hashedData, + SignatureSubpacket[] unhashedData, + byte[] fingerprint, + MPInteger[] signature) + { + this.version = version; + this.signatureType = signatureType; + this.keyId = keyId; + this.keyAlgorithm = keyAlgorithm; + this.hashAlgorithm = hashAlgorithm; + this.hashedData = hashedData; + this.unhashedData = unhashedData; + this.fingerprint = fingerprint; + this.signature = signature; + + if (hashedData != null) + { + setCreationTime(); + } + } + + public int Version + { + get { return version; } + } + + public int SignatureType + { + get { return signatureType; } + } + + /** + * return the keyId + * @return the keyId that created the signature. + */ + public long KeyId + { + get { return keyId; } + } + + /** + * return the signature trailer that must be included with the data + * to reconstruct the signature + * + * @return byte[] + */ + public byte[] GetSignatureTrailer() + { + byte[] trailer = null; + + if (version == 3) + { + trailer = new byte[5]; + + long time = creationTime / 1000L; + + trailer[0] = (byte)signatureType; + trailer[1] = (byte)(time >> 24); + trailer[2] = (byte)(time >> 16); + trailer[3] = (byte)(time >> 8); + trailer[4] = (byte)(time); + } + else + { + MemoryStream sOut = new MemoryStream(); + + sOut.WriteByte((byte)this.Version); + sOut.WriteByte((byte)this.SignatureType); + sOut.WriteByte((byte)this.KeyAlgorithm); + sOut.WriteByte((byte)this.HashAlgorithm); + + MemoryStream hOut = new MemoryStream(); + SignatureSubpacket[] hashed = this.GetHashedSubPackets(); + + for (int i = 0; i != hashed.Length; i++) + { + hashed[i].Encode(hOut); + } + + byte[] data = hOut.ToArray(); + + sOut.WriteByte((byte)(data.Length >> 8)); + sOut.WriteByte((byte)data.Length); + sOut.Write(data, 0, data.Length); + + byte[] hData = sOut.ToArray(); + + sOut.WriteByte((byte)this.Version); + sOut.WriteByte((byte)0xff); + sOut.WriteByte((byte)(hData.Length>> 24)); + sOut.WriteByte((byte)(hData.Length >> 16)); + sOut.WriteByte((byte)(hData.Length >> 8)); + sOut.WriteByte((byte)(hData.Length)); + + trailer = sOut.ToArray(); + } + + return trailer; + } + + public PublicKeyAlgorithmTag KeyAlgorithm + { + get { return keyAlgorithm; } + } + + public HashAlgorithmTag HashAlgorithm + { + get { return hashAlgorithm; } + } + + /** + * return the signature as a set of integers - note this is normalised to be the + * ASN.1 encoding of what appears in the signature packet. + */ + public MPInteger[] GetSignature() + { + return signature; + } + + /** + * Return the byte encoding of the signature section. + * @return uninterpreted signature bytes. + */ + public byte[] GetSignatureBytes() + { + if (signatureEncoding != null) + { + return (byte[]) signatureEncoding.Clone(); + } + + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream bcOut = new BcpgOutputStream(bOut); + + foreach (MPInteger sigObj in signature) + { + try + { + bcOut.WriteObject(sigObj); + } + catch (IOException e) + { + throw new Exception("internal error: " + e); + } + } + + return bOut.ToArray(); + } + + public SignatureSubpacket[] GetHashedSubPackets() + { + return hashedData; + } + + public SignatureSubpacket[] GetUnhashedSubPackets() + { + return unhashedData; + } + + /// Return the creation time in milliseconds since 1 Jan., 1970 UTC. + public long CreationTime + { + get { return creationTime; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WriteByte((byte) version); + + if (version == 3 || version == 2) + { + pOut.Write( + 5, // the length of the next block + (byte) signatureType); + + pOut.WriteInt((int)(creationTime / 1000L)); + + pOut.WriteLong(keyId); + + pOut.Write( + (byte) keyAlgorithm, + (byte) hashAlgorithm); + } + else if (version == 4) + { + pOut.Write( + (byte) signatureType, + (byte) keyAlgorithm, + (byte) hashAlgorithm); + + EncodeLengthAndData(pOut, GetEncodedSubpackets(hashedData)); + + EncodeLengthAndData(pOut, GetEncodedSubpackets(unhashedData)); + } + else + { + throw new IOException("unknown version: " + version); + } + + pOut.Write(fingerprint); + + if (signature != null) + { + pOut.WriteObjects(signature); + } + else + { + pOut.Write(signatureEncoding); + } + + bcpgOut.WritePacket(PacketTag.Signature, bOut.ToArray(), true); + } + + private static void EncodeLengthAndData( + BcpgOutputStream pOut, + byte[] data) + { + pOut.WriteShort((short) data.Length); + pOut.Write(data); + } + + private static byte[] GetEncodedSubpackets( + SignatureSubpacket[] ps) + { + MemoryStream sOut = new MemoryStream(); + + foreach (SignatureSubpacket p in ps) + { + p.Encode(sOut); + } + + return sOut.ToArray(); + } + + private void setCreationTime() + { + foreach (SignatureSubpacket p in hashedData) + { + if (p is SignatureCreationTime) + { + creationTime = DateTimeUtilities.DateTimeToUnixMs( + ((SignatureCreationTime)p).GetTime()); + break; + } + } + } + } +} diff --git a/crypto/src/bcpg/SignatureSubpacket.cs b/crypto/src/bcpg/SignatureSubpacket.cs new file mode 100644 index 000000000..ac26f8a3c --- /dev/null +++ b/crypto/src/bcpg/SignatureSubpacket.cs @@ -0,0 +1,76 @@ +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic type for a PGP Signature sub-packet. + public class SignatureSubpacket + { + private readonly SignatureSubpacketTag type; + private readonly bool critical; + + internal readonly byte[] data; + + protected internal SignatureSubpacket( + SignatureSubpacketTag type, + bool critical, + byte[] data) + { + this.type = type; + this.critical = critical; + this.data = data; + } + + public SignatureSubpacketTag SubpacketType + { + get { return type; } + } + + public bool IsCritical() + { + return critical; + } + + /// Return the generic data making up the packet. + public byte[] GetData() + { + return (byte[]) data.Clone(); + } + + public void Encode( + Stream os) + { + int bodyLen = data.Length + 1; + + if (bodyLen < 192) + { + os.WriteByte((byte)bodyLen); + } + else if (bodyLen <= 8383) + { + bodyLen -= 192; + + os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192)); + os.WriteByte((byte)bodyLen); + } + else + { + os.WriteByte(0xff); + os.WriteByte((byte)(bodyLen >> 24)); + os.WriteByte((byte)(bodyLen >> 16)); + os.WriteByte((byte)(bodyLen >> 8)); + os.WriteByte((byte)bodyLen); + } + + if (critical) + { + os.WriteByte((byte)(0x80 | (int) type)); + } + else + { + os.WriteByte((byte) type); + } + + os.Write(data, 0, data.Length); + } + } +} diff --git a/crypto/src/bcpg/SignatureSubpacketTags.cs b/crypto/src/bcpg/SignatureSubpacketTags.cs new file mode 100644 index 000000000..1a8e254c0 --- /dev/null +++ b/crypto/src/bcpg/SignatureSubpacketTags.cs @@ -0,0 +1,33 @@ +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic PGP signature sub-packet tag types. + */ + public enum SignatureSubpacketTag + { + CreationTime = 2, // signature creation time + ExpireTime = 3, // signature expiration time + Exportable = 4, // exportable certification + TrustSig = 5, // trust signature + RegExp = 6, // regular expression + Revocable = 7, // revocable + KeyExpireTime = 9, // key expiration time + Placeholder = 10, // placeholder for backward compatibility + PreferredSymmetricAlgorithms = 11, // preferred symmetric algorithms + RevocationKey = 12, // revocation key + IssuerKeyId = 16, // issuer key ID + NotationData = 20, // notation data + PreferredHashAlgorithms = 21, // preferred hash algorithms + PreferredCompressionAlgorithms = 22, // preferred compression algorithms + KeyServerPreferences = 23, // key server preferences + PreferredKeyServer = 24, // preferred key server + PrimaryUserId = 25, // primary user id + PolicyUrl = 26, // policy URL + KeyFlags = 27, // key flags + SignerUserId = 28, // signer's user id + RevocationReason = 29, // reason for revocation + Features = 30, // features + SignatureTarget = 31, // signature target + EmbeddedSignature = 32 // embedded signature + } +} diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs new file mode 100644 index 000000000..8dd1af332 --- /dev/null +++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * reader for signature sub-packets + */ + public class SignatureSubpacketsParser + { + private readonly Stream input; + + public SignatureSubpacketsParser( + Stream input) + { + this.input = input; + } + + public SignatureSubpacket ReadPacket() + { + int l = input.ReadByte(); + if (l < 0) + return null; + + int bodyLen = 0; + if (l < 192) + { + bodyLen = l; + } + else if (l <= 223) + { + bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192; + } + else if (l == 255) + { + bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16) + | (input.ReadByte() << 8) | input.ReadByte(); + } + else + { + // TODO Error? + } + + int tag = input.ReadByte(); + if (tag < 0) + throw new EndOfStreamException("unexpected EOF reading signature sub packet"); + + byte[] data = new byte[bodyLen - 1]; + if (Streams.ReadFully(input, data) < data.Length) + throw new EndOfStreamException(); + + bool isCritical = ((tag & 0x80) != 0); + SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f); + switch (type) + { + case SignatureSubpacketTag.CreationTime: + return new SignatureCreationTime(isCritical, data); + case SignatureSubpacketTag.KeyExpireTime: + return new KeyExpirationTime(isCritical, data); + case SignatureSubpacketTag.ExpireTime: + return new SignatureExpirationTime(isCritical, data); + case SignatureSubpacketTag.Revocable: + return new Revocable(isCritical, data); + case SignatureSubpacketTag.Exportable: + return new Exportable(isCritical, data); + case SignatureSubpacketTag.IssuerKeyId: + return new IssuerKeyId(isCritical, data); + case SignatureSubpacketTag.TrustSig: + return new TrustSignature(isCritical, data); + case SignatureSubpacketTag.PreferredCompressionAlgorithms: + case SignatureSubpacketTag.PreferredHashAlgorithms: + case SignatureSubpacketTag.PreferredSymmetricAlgorithms: + return new PreferredAlgorithms(type, isCritical, data); + case SignatureSubpacketTag.KeyFlags: + return new KeyFlags(isCritical, data); + case SignatureSubpacketTag.PrimaryUserId: + return new PrimaryUserId(isCritical, data); + case SignatureSubpacketTag.SignerUserId: + return new SignerUserId(isCritical, data); + case SignatureSubpacketTag.NotationData: + return new NotationData(isCritical, data); + } + return new SignatureSubpacket(type, isCritical, data); + } + } +} diff --git a/crypto/src/bcpg/SymmetricEncDataPacket.cs b/crypto/src/bcpg/SymmetricEncDataPacket.cs new file mode 100644 index 000000000..17ee55bb7 --- /dev/null +++ b/crypto/src/bcpg/SymmetricEncDataPacket.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic type for a symmetric key encrypted packet. + public class SymmetricEncDataPacket + : InputStreamPacket + { + public SymmetricEncDataPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + } + } +} diff --git a/crypto/src/bcpg/SymmetricEncIntegrityPacket.cs b/crypto/src/bcpg/SymmetricEncIntegrityPacket.cs new file mode 100644 index 000000000..a9b6d0678 --- /dev/null +++ b/crypto/src/bcpg/SymmetricEncIntegrityPacket.cs @@ -0,0 +1,18 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + public class SymmetricEncIntegrityPacket + : InputStreamPacket + { + internal readonly int version; + + internal SymmetricEncIntegrityPacket( + BcpgInputStream bcpgIn) + : base(bcpgIn) + { + version = bcpgIn.ReadByte(); + } + } +} diff --git a/crypto/src/bcpg/SymmetricKeyAlgorithmTags.cs b/crypto/src/bcpg/SymmetricKeyAlgorithmTags.cs new file mode 100644 index 000000000..7633b1dba --- /dev/null +++ b/crypto/src/bcpg/SymmetricKeyAlgorithmTags.cs @@ -0,0 +1,20 @@ +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic tags for symmetric key algorithms + */ + public enum SymmetricKeyAlgorithmTag + { + Null = 0, // Plaintext or unencrypted data + Idea = 1, // IDEA [IDEA] + TripleDes = 2, // Triple-DES (DES-EDE, as per spec -168 bit key derived from 192) + Cast5 = 3, // Cast5 (128 bit key, as per RFC 2144) + Blowfish = 4, // Blowfish (128 bit key, 16 rounds) [Blowfish] + Safer = 5, // Safer-SK128 (13 rounds) [Safer] + Des = 6, // Reserved for DES/SK + Aes128 = 7, // Reserved for AES with 128-bit key + Aes192 = 8, // Reserved for AES with 192-bit key + Aes256 = 9, // Reserved for AES with 256-bit key + Twofish = 10 // Reserved for Twofish + } +} diff --git a/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs b/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs new file mode 100644 index 000000000..0381fa386 --- /dev/null +++ b/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic type for a symmetric encrypted session key packet + */ + public class SymmetricKeyEncSessionPacket + : ContainedPacket + { + private int version; + private SymmetricKeyAlgorithmTag encAlgorithm; + private S2k s2k; + private readonly byte[] secKeyData; + + public SymmetricKeyEncSessionPacket( + BcpgInputStream bcpgIn) + { + version = bcpgIn.ReadByte(); + encAlgorithm = (SymmetricKeyAlgorithmTag) bcpgIn.ReadByte(); + + s2k = new S2k(bcpgIn); + + secKeyData = bcpgIn.ReadAll(); + } + + public SymmetricKeyEncSessionPacket( + SymmetricKeyAlgorithmTag encAlgorithm, + S2k s2k, + byte[] secKeyData) + { + this.version = 4; + this.encAlgorithm = encAlgorithm; + this.s2k = s2k; + this.secKeyData = secKeyData; + } + + /** + * @return int + */ + public SymmetricKeyAlgorithmTag EncAlgorithm + { + get { return encAlgorithm; } + } + + /** + * @return S2k + */ + public S2k S2k + { + get { return s2k; } + } + + /** + * @return byte[] + */ + public byte[] GetSecKeyData() + { + return secKeyData; + } + + /** + * @return int + */ + public int Version + { + get { return version; } + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.Write( + (byte) version, + (byte) encAlgorithm); + + pOut.WriteObject(s2k); + + if (secKeyData != null && secKeyData.Length > 0) + { + pOut.Write(secKeyData); + } + + bcpgOut.WritePacket(PacketTag.SymmetricKeyEncryptedSessionKey, bOut.ToArray(), true); + } + } +} diff --git a/crypto/src/bcpg/TrustPacket.cs b/crypto/src/bcpg/TrustPacket.cs new file mode 100644 index 000000000..6f1969c2a --- /dev/null +++ b/crypto/src/bcpg/TrustPacket.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /// Basic type for a trust packet. + public class TrustPacket + : ContainedPacket + { + private readonly byte[] levelAndTrustAmount; + + public TrustPacket( + BcpgInputStream bcpgIn) + { + MemoryStream bOut = new MemoryStream(); + + int ch; + while ((ch = bcpgIn.ReadByte()) >= 0) + { + bOut.WriteByte((byte) ch); + } + + levelAndTrustAmount = bOut.ToArray(); + } + + public TrustPacket( + int trustCode) + { + this.levelAndTrustAmount = new byte[]{ (byte) trustCode }; + } + + public byte[] GetLevelAndTrustAmount() + { + return (byte[]) levelAndTrustAmount.Clone(); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.Trust, levelAndTrustAmount, true); + } + } +} diff --git a/crypto/src/bcpg/UserAttributePacket.cs b/crypto/src/bcpg/UserAttributePacket.cs new file mode 100644 index 000000000..20e3598ab --- /dev/null +++ b/crypto/src/bcpg/UserAttributePacket.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic type for a user attribute packet. + */ + public class UserAttributePacket + : ContainedPacket + { + private readonly UserAttributeSubpacket[] subpackets; + + public UserAttributePacket( + BcpgInputStream bcpgIn) + { + UserAttributeSubpacketsParser sIn = new UserAttributeSubpacketsParser(bcpgIn); + UserAttributeSubpacket sub; + + IList v = Platform.CreateArrayList(); + while ((sub = sIn.ReadPacket()) != null) + { + v.Add(sub); + } + + subpackets = new UserAttributeSubpacket[v.Count]; + + for (int i = 0; i != subpackets.Length; i++) + { + subpackets[i] = (UserAttributeSubpacket)v[i]; + } + } + + public UserAttributePacket( + UserAttributeSubpacket[] subpackets) + { + this.subpackets = subpackets; + } + + public UserAttributeSubpacket[] GetSubpackets() + { + return subpackets; + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + MemoryStream bOut = new MemoryStream(); + + for (int i = 0; i != subpackets.Length; i++) + { + subpackets[i].Encode(bOut); + } + + bcpgOut.WritePacket(PacketTag.UserAttribute, bOut.ToArray(), false); + } + } +} diff --git a/crypto/src/bcpg/UserAttributeSubpacket.cs b/crypto/src/bcpg/UserAttributeSubpacket.cs new file mode 100644 index 000000000..bd49d2150 --- /dev/null +++ b/crypto/src/bcpg/UserAttributeSubpacket.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic type for a user attribute sub-packet. + */ + public class UserAttributeSubpacket + { + private readonly UserAttributeSubpacketTag type; + private readonly byte[] data; + + internal UserAttributeSubpacket( + UserAttributeSubpacketTag type, + byte[] data) + { + this.type = type; + this.data = data; + } + + public UserAttributeSubpacketTag SubpacketType + { + get { return type; } + } + + /** + * return the generic data making up the packet. + */ + public byte[] GetData() + { + return data; + } + + public void Encode( + Stream os) + { + int bodyLen = data.Length + 1; + + if (bodyLen < 192) + { + os.WriteByte((byte)bodyLen); + } + else if (bodyLen <= 8383) + { + bodyLen -= 192; + + os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192)); + os.WriteByte((byte)bodyLen); + } + else + { + os.WriteByte(0xff); + os.WriteByte((byte)(bodyLen >> 24)); + os.WriteByte((byte)(bodyLen >> 16)); + os.WriteByte((byte)(bodyLen >> 8)); + os.WriteByte((byte)bodyLen); + } + + os.WriteByte((byte) type); + os.Write(data, 0, data.Length); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + UserAttributeSubpacket other = obj as UserAttributeSubpacket; + + if (other == null) + return false; + + return type == other.type + && Arrays.AreEqual(data, other.data); + } + + public override int GetHashCode() + { + return type.GetHashCode() ^ Arrays.GetHashCode(data); + } + } +} diff --git a/crypto/src/bcpg/UserAttributeSubpacketTags.cs b/crypto/src/bcpg/UserAttributeSubpacketTags.cs new file mode 100644 index 000000000..7a9cd1d5d --- /dev/null +++ b/crypto/src/bcpg/UserAttributeSubpacketTags.cs @@ -0,0 +1,10 @@ +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic PGP user attribute sub-packet tag types. + */ + public enum UserAttributeSubpacketTag + { + ImageAttribute = 1 + } +} diff --git a/crypto/src/bcpg/UserAttributeSubpacketsReader.cs b/crypto/src/bcpg/UserAttributeSubpacketsReader.cs new file mode 100644 index 000000000..2e5ea0f3e --- /dev/null +++ b/crypto/src/bcpg/UserAttributeSubpacketsReader.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using Org.BouncyCastle.Bcpg.Attr; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * reader for user attribute sub-packets + */ + public class UserAttributeSubpacketsParser + { + private readonly Stream input; + + public UserAttributeSubpacketsParser( + Stream input) + { + this.input = input; + } + + public UserAttributeSubpacket ReadPacket() + { + int l = input.ReadByte(); + if (l < 0) + return null; + + int bodyLen = 0; + if (l < 192) + { + bodyLen = l; + } + else if (l <= 223) + { + bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192; + } + else if (l == 255) + { + bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16) + | (input.ReadByte() << 8) | input.ReadByte(); + } + else + { + // TODO Error? + } + + int tag = input.ReadByte(); + if (tag < 0) + throw new EndOfStreamException("unexpected EOF reading user attribute sub packet"); + + byte[] data = new byte[bodyLen - 1]; + if (Streams.ReadFully(input, data) < data.Length) + throw new EndOfStreamException(); + + UserAttributeSubpacketTag type = (UserAttributeSubpacketTag) tag; + switch (type) + { + case UserAttributeSubpacketTag.ImageAttribute: + return new ImageAttrib(data); + } + return new UserAttributeSubpacket(type, data); + } + } +} diff --git a/crypto/src/bcpg/UserIdPacket.cs b/crypto/src/bcpg/UserIdPacket.cs new file mode 100644 index 000000000..a175e74a6 --- /dev/null +++ b/crypto/src/bcpg/UserIdPacket.cs @@ -0,0 +1,37 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Bcpg +{ + /** + * Basic type for a user ID packet. + */ + public class UserIdPacket + : ContainedPacket + { + private readonly byte[] idData; + + public UserIdPacket( + BcpgInputStream bcpgIn) + { + this.idData = bcpgIn.ReadAll(); + } + + public UserIdPacket( + string id) + { + this.idData = Encoding.UTF8.GetBytes(id); + } + + public string GetId() + { + return Encoding.UTF8.GetString(idData, 0, idData.Length); + } + + public override void Encode( + BcpgOutputStream bcpgOut) + { + bcpgOut.WritePacket(PacketTag.UserId, idData, true); + } + } +} diff --git a/crypto/src/bcpg/attr/ImageAttrib.cs b/crypto/src/bcpg/attr/ImageAttrib.cs new file mode 100644 index 000000000..73490791c --- /dev/null +++ b/crypto/src/bcpg/attr/ImageAttrib.cs @@ -0,0 +1,68 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg.Attr +{ + /// Basic type for a image attribute packet. + public class ImageAttrib + : UserAttributeSubpacket + { + public enum Format : byte + { + Jpeg = 1 + } + + private static readonly byte[] Zeroes = new byte[12]; + + private int hdrLength; + private int _version; + private int _encoding; + private byte[] imageData; + + public ImageAttrib( + byte[] data) + : base(UserAttributeSubpacketTag.ImageAttribute, data) + { + hdrLength = ((data[1] & 0xff) << 8) | (data[0] & 0xff); + _version = data[2] & 0xff; + _encoding = data[3] & 0xff; + + imageData = new byte[data.Length - hdrLength]; + Array.Copy(data, hdrLength, imageData, 0, imageData.Length); + } + + public ImageAttrib( + Format imageType, + byte[] imageData) + : this(ToByteArray(imageType, imageData)) + { + } + + private static byte[] ToByteArray( + Format imageType, + byte[] imageData) + { + MemoryStream bOut = new MemoryStream(); + bOut.WriteByte(0x10); bOut.WriteByte(0x00); bOut.WriteByte(0x01); + bOut.WriteByte((byte) imageType); + bOut.Write(Zeroes, 0, Zeroes.Length); + bOut.Write(imageData, 0, imageData.Length); + return bOut.ToArray(); + } + + public int Version + { + get { return _version; } + } + + public int Encoding + { + get { return _encoding; } + } + + public byte[] GetImageData() + { + return imageData; + } + } +} diff --git a/crypto/src/bcpg/sig/EmbeddedSignature.cs b/crypto/src/bcpg/sig/EmbeddedSignature.cs new file mode 100644 index 000000000..e47604ac8 --- /dev/null +++ b/crypto/src/bcpg/sig/EmbeddedSignature.cs @@ -0,0 +1,18 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * Packet embedded signature + */ + public class EmbeddedSignature + : SignatureSubpacket + { + public EmbeddedSignature( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.EmbeddedSignature, critical, data) + { + } + } +} diff --git a/crypto/src/bcpg/sig/Exportable.cs b/crypto/src/bcpg/sig/Exportable.cs new file mode 100644 index 000000000..4455c3814 --- /dev/null +++ b/crypto/src/bcpg/sig/Exportable.cs @@ -0,0 +1,47 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving signature creation time. + */ + public class Exportable + : SignatureSubpacket + { + private static byte[] BooleanToByteArray(bool val) + { + byte[] data = new byte[1]; + + if (val) + { + data[0] = 1; + return data; + } + else + { + return data; + } + } + + public Exportable( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.Exportable, critical, data) + { + } + + public Exportable( + bool critical, + bool isExportable) + : base(SignatureSubpacketTag.Exportable, critical, BooleanToByteArray(isExportable)) + { + } + + public bool IsExportable() + { + return data[0] != 0; + } + } +} diff --git a/crypto/src/bcpg/sig/IssuerKeyId.cs b/crypto/src/bcpg/sig/IssuerKeyId.cs new file mode 100644 index 000000000..91490d33b --- /dev/null +++ b/crypto/src/bcpg/sig/IssuerKeyId.cs @@ -0,0 +1,61 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving signature creation time. + */ + public class IssuerKeyId + : SignatureSubpacket + { + protected static byte[] KeyIdToBytes( + long keyId) + { + byte[] data = new byte[8]; + + data[0] = (byte)(keyId >> 56); + data[1] = (byte)(keyId >> 48); + data[2] = (byte)(keyId >> 40); + data[3] = (byte)(keyId >> 32); + data[4] = (byte)(keyId >> 24); + data[5] = (byte)(keyId >> 16); + data[6] = (byte)(keyId >> 8); + data[7] = (byte)keyId; + + return data; + } + + public IssuerKeyId( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.IssuerKeyId, critical, data) + { + } + + public IssuerKeyId( + bool critical, + long keyId) + : base(SignatureSubpacketTag.IssuerKeyId, critical, KeyIdToBytes(keyId)) + { + } + + public long KeyId + { + get + { + long keyId = ((long)(data[0] & 0xff) << 56) + | ((long)(data[1] & 0xff) << 48) + | ((long)(data[2] & 0xff) << 40) + | ((long)(data[3] & 0xff) << 32) + | ((long)(data[4] & 0xff) << 24) + | ((long)(data[5] & 0xff) << 16) + | ((long)(data[6] & 0xff) << 8) + | ((long)data[7] & 0xff); + + return keyId; + } + } + } +} diff --git a/crypto/src/bcpg/sig/KeyExpirationTime.cs b/crypto/src/bcpg/sig/KeyExpirationTime.cs new file mode 100644 index 000000000..23b4cac29 --- /dev/null +++ b/crypto/src/bcpg/sig/KeyExpirationTime.cs @@ -0,0 +1,56 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving time after creation at which the key expires. + */ + public class KeyExpirationTime + : SignatureSubpacket + { + protected static byte[] TimeToBytes( + long t) + { + byte[] data = new byte[4]; + + data[0] = (byte)(t >> 24); + data[1] = (byte)(t >> 16); + data[2] = (byte)(t >> 8); + data[3] = (byte)t; + + return data; + } + + public KeyExpirationTime( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.KeyExpireTime, critical, data) + { + } + + public KeyExpirationTime( + bool critical, + long seconds) + : base(SignatureSubpacketTag.KeyExpireTime, critical, TimeToBytes(seconds)) + { + } + + /** + * Return the number of seconds after creation time a key is valid for. + * + * @return second count for key validity. + */ + public long Time + { + get + { + long time = ((long)(data[0] & 0xff) << 24) | ((long)(data[1] & 0xff) << 16) + | ((long)(data[2] & 0xff) << 8) | ((long)data[3] & 0xff); + + return time; + } + } + } +} diff --git a/crypto/src/bcpg/sig/KeyFlags.cs b/crypto/src/bcpg/sig/KeyFlags.cs new file mode 100644 index 000000000..0592301b3 --- /dev/null +++ b/crypto/src/bcpg/sig/KeyFlags.cs @@ -0,0 +1,74 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * Packet holding the key flag values. + */ + public class KeyFlags + : SignatureSubpacket + { + public const int CertifyOther = 0x01; + public const int SignData = 0x02; + public const int EncryptComms = 0x04; + public const int EncryptStorage = 0x08; + public const int Split = 0x10; + public const int Authentication = 0x20; + public const int Shared = 0x80; + + private static byte[] IntToByteArray( + int v) + { + byte[] tmp = new byte[4]; + int size = 0; + + for (int i = 0; i != 4; i++) + { + tmp[i] = (byte)(v >> (i * 8)); + if (tmp[i] != 0) + { + size = i; + } + } + + byte[] data = new byte[size + 1]; + Array.Copy(tmp, 0, data, 0, data.Length); + return data; + } + + public KeyFlags( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.KeyFlags, critical, data) + { + } + + public KeyFlags( + bool critical, + int flags) + : base(SignatureSubpacketTag.KeyFlags, critical, IntToByteArray(flags)) + { + } + + /// + /// Return the flag values contained in the first 4 octets (note: at the moment + /// the standard only uses the first one). + /// + public int Flags + { + get + { + int flags = 0; + + for (int i = 0; i != data.Length; i++) + { + flags |= (data[i] & 0xff) << (i * 8); + } + + return flags; + } + } + } +} diff --git a/crypto/src/bcpg/sig/NotationData.cs b/crypto/src/bcpg/sig/NotationData.cs new file mode 100644 index 000000000..ccc9aa745 --- /dev/null +++ b/crypto/src/bcpg/sig/NotationData.cs @@ -0,0 +1,112 @@ +using System; +using System.IO; +using System.Text; + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * Class provided a NotationData object according to + * RFC2440, Chapter 5.2.3.15. Notation Data + */ + public class NotationData + : SignatureSubpacket + { + public const int HeaderFlagLength = 4; + public const int HeaderNameLength = 2; + public const int HeaderValueLength = 2; + + public NotationData( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.NotationData, critical, data) + { + } + + public NotationData( + bool critical, + bool humanReadable, + string notationName, + string notationValue) + : base(SignatureSubpacketTag.NotationData, critical, + createData(humanReadable, notationName, notationValue)) + { + } + + private static byte[] createData( + bool humanReadable, + string notationName, + string notationValue) + { + MemoryStream os = new MemoryStream(); + + // (4 octets of flags, 2 octets of name length (M), + // 2 octets of value length (N), + // M octets of name data, + // N octets of value data) + + // flags + os.WriteByte(humanReadable ? (byte)0x80 : (byte)0x00); + os.WriteByte(0x0); + os.WriteByte(0x0); + os.WriteByte(0x0); + + byte[] nameData, valueData = null; + int nameLength, valueLength; + + nameData = Encoding.UTF8.GetBytes(notationName); + nameLength = System.Math.Min(nameData.Length, 0xFF); + + valueData = Encoding.UTF8.GetBytes(notationValue); + valueLength = System.Math.Min(valueData.Length, 0xFF); + + // name length + os.WriteByte((byte)(nameLength >> 8)); + os.WriteByte((byte)(nameLength >> 0)); + + // value length + os.WriteByte((byte)(valueLength >> 8)); + os.WriteByte((byte)(valueLength >> 0)); + + // name + os.Write(nameData, 0, nameLength); + + // value + os.Write(valueData, 0, valueLength); + + return os.ToArray(); + } + + public bool IsHumanReadable + { + get { return data[0] == (byte)0x80; } + } + + public string GetNotationName() + { + int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0)); + int namePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength; + + return Encoding.UTF8.GetString(data, namePos, nameLength); + } + + public string GetNotationValue() + { + int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0)); + int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0)); + int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength; + + return Encoding.UTF8.GetString(data, valuePos, valueLength); + } + + public byte[] GetNotationValueBytes() + { + int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0)); + int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0)); + int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength; + + byte[] bytes = new byte[valueLength]; + Array.Copy(data, valuePos, bytes, 0, valueLength); + return bytes; + } + } +} diff --git a/crypto/src/bcpg/sig/PreferredAlgorithms.cs b/crypto/src/bcpg/sig/PreferredAlgorithms.cs new file mode 100644 index 000000000..0f282a38c --- /dev/null +++ b/crypto/src/bcpg/sig/PreferredAlgorithms.cs @@ -0,0 +1,54 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving signature creation time. + */ + public class PreferredAlgorithms + : SignatureSubpacket + { + private static byte[] IntToByteArray( + int[] v) + { + byte[] data = new byte[v.Length]; + + for (int i = 0; i != v.Length; i++) + { + data[i] = (byte)v[i]; + } + + return data; + } + + public PreferredAlgorithms( + SignatureSubpacketTag type, + bool critical, + byte[] data) + : base(type, critical, data) + { + } + + public PreferredAlgorithms( + SignatureSubpacketTag type, + bool critical, + int[] preferences) + : base(type, critical, IntToByteArray(preferences)) + { + } + + public int[] GetPreferences() + { + int[] v = new int[data.Length]; + + for (int i = 0; i != v.Length; i++) + { + v[i] = data[i] & 0xff; + } + + return v; + } + } +} diff --git a/crypto/src/bcpg/sig/PrimaryUserId.cs b/crypto/src/bcpg/sig/PrimaryUserId.cs new file mode 100644 index 000000000..fc0353afd --- /dev/null +++ b/crypto/src/bcpg/sig/PrimaryUserId.cs @@ -0,0 +1,48 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving whether or not the signature is signed using the primary user ID for the key. + */ + public class PrimaryUserId + : SignatureSubpacket + { + private static byte[] BooleanToByteArray( + bool val) + { + byte[] data = new byte[1]; + + if (val) + { + data[0] = 1; + return data; + } + else + { + return data; + } + } + + public PrimaryUserId( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.PrimaryUserId, critical, data) + { + } + + public PrimaryUserId( + bool critical, + bool isPrimaryUserId) + : base(SignatureSubpacketTag.PrimaryUserId, critical, BooleanToByteArray(isPrimaryUserId)) + { + } + + public bool IsPrimaryUserId() + { + return data[0] != 0; + } + } +} diff --git a/crypto/src/bcpg/sig/Revocable.cs b/crypto/src/bcpg/sig/Revocable.cs new file mode 100644 index 000000000..b5e94feec --- /dev/null +++ b/crypto/src/bcpg/sig/Revocable.cs @@ -0,0 +1,48 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving whether or not is revocable. + */ + public class Revocable + : SignatureSubpacket + { + private static byte[] BooleanToByteArray( + bool value) + { + byte[] data = new byte[1]; + + if (value) + { + data[0] = 1; + return data; + } + else + { + return data; + } + } + + public Revocable( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.Revocable, critical, data) + { + } + + public Revocable( + bool critical, + bool isRevocable) + : base(SignatureSubpacketTag.Revocable, critical, BooleanToByteArray(isRevocable)) + { + } + + public bool IsRevocable() + { + return data[0] != 0; + } + } +} diff --git a/crypto/src/bcpg/sig/RevocationKey.cs b/crypto/src/bcpg/sig/RevocationKey.cs new file mode 100644 index 000000000..66982cb5a --- /dev/null +++ b/crypto/src/bcpg/sig/RevocationKey.cs @@ -0,0 +1,62 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Bcpg +{ + /// + /// Represents revocation key OpenPGP signature sub packet. + /// + public class RevocationKey + : SignatureSubpacket + { + // 1 octet of class, + // 1 octet of public-key algorithm ID, + // 20 octets of fingerprint + public RevocationKey( + bool isCritical, + byte[] data) + : base(SignatureSubpacketTag.RevocationKey, isCritical, data) + { + } + + public RevocationKey( + bool isCritical, + RevocationKeyTag signatureClass, + PublicKeyAlgorithmTag keyAlgorithm, + byte[] fingerprint) + : base(SignatureSubpacketTag.RevocationKey, isCritical, + CreateData(signatureClass, keyAlgorithm, fingerprint)) + { + } + + private static byte[] CreateData( + RevocationKeyTag signatureClass, + PublicKeyAlgorithmTag keyAlgorithm, + byte[] fingerprint) + { + byte[] data = new byte[2 + fingerprint.Length]; + data[0] = (byte)signatureClass; + data[1] = (byte)keyAlgorithm; + Array.Copy(fingerprint, 0, data, 2, fingerprint.Length); + return data; + } + + public virtual RevocationKeyTag SignatureClass + { + get { return (RevocationKeyTag)this.GetData()[0]; } + } + + public virtual PublicKeyAlgorithmTag Algorithm + { + get { return (PublicKeyAlgorithmTag)this.GetData()[1]; } + } + + public virtual byte[] GetFingerprint() + { + byte[] data = this.GetData(); + byte[] fingerprint = new byte[data.Length - 2]; + Array.Copy(data, 2, fingerprint, 0, fingerprint.Length); + return fingerprint; + } + } +} diff --git a/crypto/src/bcpg/sig/RevocationKeyTags.cs b/crypto/src/bcpg/sig/RevocationKeyTags.cs new file mode 100644 index 000000000..d76d1dcf4 --- /dev/null +++ b/crypto/src/bcpg/sig/RevocationKeyTags.cs @@ -0,0 +1,9 @@ +namespace Org.BouncyCastle.Bcpg +{ + public enum RevocationKeyTag + : byte + { + ClassDefault = 0x80, + ClassSensitive = 0x40 + } +} diff --git a/crypto/src/bcpg/sig/RevocationReason.cs b/crypto/src/bcpg/sig/RevocationReason.cs new file mode 100644 index 000000000..98e9b0a3d --- /dev/null +++ b/crypto/src/bcpg/sig/RevocationReason.cs @@ -0,0 +1,59 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg +{ + /// + /// Represents revocation reason OpenPGP signature sub packet. + /// + public class RevocationReason + : SignatureSubpacket + { + public RevocationReason(bool isCritical, byte[] data) + : base(SignatureSubpacketTag.RevocationReason, isCritical, data) + { + } + + public RevocationReason( + bool isCritical, + RevocationReasonTag reason, + string description) + : base(SignatureSubpacketTag.RevocationReason, isCritical, CreateData(reason, description)) + { + } + + private static byte[] CreateData( + RevocationReasonTag reason, + string description) + { + byte[] descriptionBytes = Strings.ToUtf8ByteArray(description); + byte[] data = new byte[1 + descriptionBytes.Length]; + + data[0] = (byte)reason; + Array.Copy(descriptionBytes, 0, data, 1, descriptionBytes.Length); + + return data; + } + + public virtual RevocationReasonTag GetRevocationReason() + { + return (RevocationReasonTag)GetData()[0]; + } + + public virtual string GetRevocationDescription() + { + byte[] data = GetData(); + if (data.Length == 1) + { + return string.Empty; + } + + byte[] description = new byte[data.Length - 1]; + Array.Copy(data, 1, description, 0, description.Length); + + return Strings.FromUtf8ByteArray(description); + } + } +} diff --git a/crypto/src/bcpg/sig/RevocationReasonTags.cs b/crypto/src/bcpg/sig/RevocationReasonTags.cs new file mode 100644 index 000000000..524a58c49 --- /dev/null +++ b/crypto/src/bcpg/sig/RevocationReasonTags.cs @@ -0,0 +1,14 @@ +namespace Org.BouncyCastle.Bcpg +{ + public enum RevocationReasonTag + : byte + { + NoReason = 0, // No reason specified (key revocations or cert revocations) + KeySuperseded = 1, // Key is superseded (key revocations) + KeyCompromised = 2, // Key material has been compromised (key revocations) + KeyRetired = 3, // Key is retired and no longer used (key revocations) + UserNoLongerValid = 32, // User ID information is no longer valid (cert revocations) + + // 100-110 - Private Use + } +} diff --git a/crypto/src/bcpg/sig/SignatureCreationTime.cs b/crypto/src/bcpg/sig/SignatureCreationTime.cs new file mode 100644 index 000000000..e6f241f11 --- /dev/null +++ b/crypto/src/bcpg/sig/SignatureCreationTime.cs @@ -0,0 +1,47 @@ +using System; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving signature creation time. + */ + public class SignatureCreationTime + : SignatureSubpacket + { + protected static byte[] TimeToBytes( + DateTime time) + { + long t = DateTimeUtilities.DateTimeToUnixMs(time) / 1000L; + byte[] data = new byte[4]; + data[0] = (byte)(t >> 24); + data[1] = (byte)(t >> 16); + data[2] = (byte)(t >> 8); + data[3] = (byte)t; + return data; + } + public SignatureCreationTime( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.CreationTime, critical, data) + { + } + public SignatureCreationTime( + bool critical, + DateTime date) + : base(SignatureSubpacketTag.CreationTime, critical, TimeToBytes(date)) + { + } + public DateTime GetTime() + { + long time = (long)( + ((uint)data[0] << 24) + | ((uint)data[1] << 16) + | ((uint)data[2] << 8) + | ((uint)data[3]) + ); + return DateTimeUtilities.UnixMsToDateTime(time * 1000L); + } + } +} diff --git a/crypto/src/bcpg/sig/SignatureExpirationTime.cs b/crypto/src/bcpg/sig/SignatureExpirationTime.cs new file mode 100644 index 000000000..7fddf5743 --- /dev/null +++ b/crypto/src/bcpg/sig/SignatureExpirationTime.cs @@ -0,0 +1,54 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving signature expiration time. + */ + public class SignatureExpirationTime + : SignatureSubpacket + { + protected static byte[] TimeToBytes( + long t) + { + byte[] data = new byte[4]; + + data[0] = (byte)(t >> 24); + data[1] = (byte)(t >> 16); + data[2] = (byte)(t >> 8); + data[3] = (byte)t; + + return data; + } + + public SignatureExpirationTime( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.ExpireTime, critical, data) + { + } + + public SignatureExpirationTime( + bool critical, + long seconds) + : base(SignatureSubpacketTag.ExpireTime, critical, TimeToBytes(seconds)) + { + } + + /** + * return time in seconds before signature expires after creation time. + */ + public long Time + { + get + { + long time = ((long)(data[0] & 0xff) << 24) | ((long)(data[1] & 0xff) << 16) + | ((long)(data[2] & 0xff) << 8) | ((long)data[3] & 0xff); + + return time; + } + } + } +} diff --git a/crypto/src/bcpg/sig/SignerUserId.cs b/crypto/src/bcpg/sig/SignerUserId.cs new file mode 100644 index 000000000..98cc808e7 --- /dev/null +++ b/crypto/src/bcpg/sig/SignerUserId.cs @@ -0,0 +1,52 @@ +using System; + + + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving the User ID of the signer. + */ + public class SignerUserId + : SignatureSubpacket + { + private static byte[] UserIdToBytes( + string id) + { + byte[] idData = new byte[id.Length]; + + for (int i = 0; i != id.Length; i++) + { + idData[i] = (byte)id[i]; + } + + return idData; + } + + public SignerUserId( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.SignerUserId, critical, data) + { + } + + public SignerUserId( + bool critical, + string userId) + : base(SignatureSubpacketTag.SignerUserId, critical, UserIdToBytes(userId)) + { + } + + public string GetId() + { + char[] chars = new char[data.Length]; + + for (int i = 0; i != chars.Length; i++) + { + chars[i] = (char)(data[i] & 0xff); + } + + return new string(chars); + } + } +} diff --git a/crypto/src/bcpg/sig/TrustSignature.cs b/crypto/src/bcpg/sig/TrustSignature.cs new file mode 100644 index 000000000..bbadd3067 --- /dev/null +++ b/crypto/src/bcpg/sig/TrustSignature.cs @@ -0,0 +1,43 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.Sig +{ + /** + * packet giving trust. + */ + public class TrustSignature + : SignatureSubpacket + { + private static byte[] IntToByteArray( + int v1, + int v2) + { + return new byte[]{ (byte)v1, (byte)v2 }; + } + + public TrustSignature( + bool critical, + byte[] data) + : base(SignatureSubpacketTag.TrustSig, critical, data) + { + } + + public TrustSignature( + bool critical, + int depth, + int trustAmount) + : base(SignatureSubpacketTag.TrustSig, critical, IntToByteArray(depth, trustAmount)) + { + } + + public int Depth + { + get { return data[0] & 0xff; } + } + + public int TrustAmount + { + get { return data[1] & 0xff; } + } + } +} diff --git a/crypto/src/cms/BaseDigestCalculator.cs b/crypto/src/cms/BaseDigestCalculator.cs new file mode 100644 index 000000000..3dcbca753 --- /dev/null +++ b/crypto/src/cms/BaseDigestCalculator.cs @@ -0,0 +1,23 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + internal class BaseDigestCalculator + : IDigestCalculator + { + private readonly byte[] digest; + + internal BaseDigestCalculator( + byte[] digest) + { + this.digest = digest; + } + + public byte[] GetDigest() + { + return Arrays.Clone(digest); + } + } +} diff --git a/crypto/src/cms/CMSAttributeTableGenerationException.cs b/crypto/src/cms/CMSAttributeTableGenerationException.cs new file mode 100644 index 000000000..31b06d6dd --- /dev/null +++ b/crypto/src/cms/CMSAttributeTableGenerationException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Cms +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CmsAttributeTableGenerationException + : CmsException + { + public CmsAttributeTableGenerationException() + { + } + + public CmsAttributeTableGenerationException( + string name) + : base(name) + { + } + + public CmsAttributeTableGenerationException( + string name, + Exception e) + : base(name, e) + { + } + } +} diff --git a/crypto/src/cms/CMSAttributeTableGenerator.cs b/crypto/src/cms/CMSAttributeTableGenerator.cs new file mode 100644 index 000000000..92c9a29d9 --- /dev/null +++ b/crypto/src/cms/CMSAttributeTableGenerator.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Cms +{ + /// + /// The 'Signature' parameter is only available when generating unsigned attributes. + /// + public enum CmsAttributeTableParameter + { +// const string ContentType = "contentType"; +// const string Digest = "digest"; +// const string Signature = "encryptedDigest"; +// const string DigestAlgorithmIdentifier = "digestAlgID"; + + ContentType, Digest, Signature, DigestAlgorithmIdentifier + } + + public interface CmsAttributeTableGenerator + { + AttributeTable GetAttributes(IDictionary parameters); + } +} diff --git a/crypto/src/cms/CMSAuthEnvelopedData.cs b/crypto/src/cms/CMSAuthEnvelopedData.cs new file mode 100644 index 000000000..d35e946ae --- /dev/null +++ b/crypto/src/cms/CMSAuthEnvelopedData.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Cms +{ + /** + * containing class for an CMS AuthEnveloped Data object + */ + internal class CmsAuthEnvelopedData + { + internal RecipientInformationStore recipientInfoStore; + internal ContentInfo contentInfo; + + private OriginatorInfo originator; + private AlgorithmIdentifier authEncAlg; + private Asn1Set authAttrs; + private byte[] mac; + private Asn1Set unauthAttrs; + + public CmsAuthEnvelopedData( + byte[] authEnvData) + : this(CmsUtilities.ReadContentInfo(authEnvData)) + { + } + + public CmsAuthEnvelopedData( + Stream authEnvData) + : this(CmsUtilities.ReadContentInfo(authEnvData)) + { + } + + public CmsAuthEnvelopedData( + ContentInfo contentInfo) + { + this.contentInfo = contentInfo; + + AuthEnvelopedData authEnvData = AuthEnvelopedData.GetInstance(contentInfo.Content); + + this.originator = authEnvData.OriginatorInfo; + + // + // read the recipients + // + Asn1Set recipientInfos = authEnvData.RecipientInfos; + + // + // read the auth-encrypted content info + // + EncryptedContentInfo authEncInfo = authEnvData.AuthEncryptedContentInfo; + this.authEncAlg = authEncInfo.ContentEncryptionAlgorithm; + CmsSecureReadable secureReadable = new AuthEnvelopedSecureReadable(this); + + // + // build the RecipientInformationStore + // + this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore( + recipientInfos, secureReadable); + + // FIXME These need to be passed to the AEAD cipher as AAD (Additional Authenticated Data) + this.authAttrs = authEnvData.AuthAttrs; + this.mac = authEnvData.Mac.GetOctets(); + this.unauthAttrs = authEnvData.UnauthAttrs; + } + + private class AuthEnvelopedSecureReadable : CmsSecureReadable + { + private readonly CmsAuthEnvelopedData parent; + + internal AuthEnvelopedSecureReadable(CmsAuthEnvelopedData parent) + { + this.parent = parent; + } + + public AlgorithmIdentifier Algorithm + { + get { return parent.authEncAlg; } + } + + public object CryptoObject + { + get { return null; } + } + + public CmsReadable GetReadable(KeyParameter key) + { + // TODO Create AEAD cipher instance to decrypt and calculate tag ( MAC) + throw new CmsException("AuthEnveloped data decryption not yet implemented"); + +// RFC 5084 ASN.1 Module +// -- Parameters for AlgorithmIdentifier +// +// CCMParameters ::= SEQUENCE { +// aes-nonce OCTET STRING (SIZE(7..13)), +// aes-ICVlen AES-CCM-ICVlen DEFAULT 12 } +// +// AES-CCM-ICVlen ::= INTEGER (4 | 6 | 8 | 10 | 12 | 14 | 16) +// +// GCMParameters ::= SEQUENCE { +// aes-nonce OCTET STRING, -- recommended size is 12 octets +// aes-ICVlen AES-GCM-ICVlen DEFAULT 12 } +// +// AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16) + } + } + } +} diff --git a/crypto/src/cms/CMSAuthEnvelopedGenerator.cs b/crypto/src/cms/CMSAuthEnvelopedGenerator.cs new file mode 100644 index 000000000..4273cff29 --- /dev/null +++ b/crypto/src/cms/CMSAuthEnvelopedGenerator.cs @@ -0,0 +1,16 @@ +using System; + +using Org.BouncyCastle.Asn1.Nist; + +namespace Org.BouncyCastle.Cms +{ + internal class CmsAuthEnvelopedGenerator + { + public static readonly string Aes128Ccm = NistObjectIdentifiers.IdAes128Ccm.Id; + public static readonly string Aes192Ccm = NistObjectIdentifiers.IdAes192Ccm.Id; + public static readonly string Aes256Ccm = NistObjectIdentifiers.IdAes256Ccm.Id; + public static readonly string Aes128Gcm = NistObjectIdentifiers.IdAes128Gcm.Id; + public static readonly string Aes192Gcm = NistObjectIdentifiers.IdAes192Gcm.Id; + public static readonly string Aes256Gcm = NistObjectIdentifiers.IdAes256Gcm.Id; + } +} diff --git a/crypto/src/cms/CMSAuthenticatedData.cs b/crypto/src/cms/CMSAuthenticatedData.cs new file mode 100644 index 000000000..5e234da2b --- /dev/null +++ b/crypto/src/cms/CMSAuthenticatedData.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + /** + * containing class for an CMS Authenticated Data object + */ + public class CmsAuthenticatedData + { + internal RecipientInformationStore recipientInfoStore; + internal ContentInfo contentInfo; + + private AlgorithmIdentifier macAlg; + private Asn1Set authAttrs; + private Asn1Set unauthAttrs; + private byte[] mac; + + public CmsAuthenticatedData( + byte[] authData) + : this(CmsUtilities.ReadContentInfo(authData)) + { + } + + public CmsAuthenticatedData( + Stream authData) + : this(CmsUtilities.ReadContentInfo(authData)) + { + } + + public CmsAuthenticatedData( + ContentInfo contentInfo) + { + this.contentInfo = contentInfo; + + AuthenticatedData authData = AuthenticatedData.GetInstance(contentInfo.Content); + + // + // read the recipients + // + Asn1Set recipientInfos = authData.RecipientInfos; + + this.macAlg = authData.MacAlgorithm; + + // + // read the authenticated content info + // + ContentInfo encInfo = authData.EncapsulatedContentInfo; + CmsReadable readable = new CmsProcessableByteArray( + Asn1OctetString.GetInstance(encInfo.Content).GetOctets()); + CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable( + this.macAlg, readable); + + // + // build the RecipientInformationStore + // + this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore( + recipientInfos, secureReadable); + + this.authAttrs = authData.AuthAttrs; + this.mac = authData.Mac.GetOctets(); + this.unauthAttrs = authData.UnauthAttrs; + } + + public byte[] GetMac() + { + return Arrays.Clone(mac); + } + + public AlgorithmIdentifier MacAlgorithmID + { + get { return macAlg; } + } + + /** + * return the object identifier for the content MAC algorithm. + */ + public string MacAlgOid + { + get { return macAlg.ObjectID.Id; } + } + + /** + * return a store of the intended recipients for this message + */ + public RecipientInformationStore GetRecipientInfos() + { + return recipientInfoStore; + } + + /** + * return the ContentInfo + */ + public ContentInfo ContentInfo + { + get { return contentInfo; } + } + + /** + * return a table of the digested attributes indexed by + * the OID of the attribute. + */ + public Asn1.Cms.AttributeTable GetAuthAttrs() + { + if (authAttrs == null) + return null; + + return new Asn1.Cms.AttributeTable(authAttrs); + } + + /** + * return a table of the undigested attributes indexed by + * the OID of the attribute. + */ + public Asn1.Cms.AttributeTable GetUnauthAttrs() + { + if (unauthAttrs == null) + return null; + + return new Asn1.Cms.AttributeTable(unauthAttrs); + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return contentInfo.GetEncoded(); + } + } +} diff --git a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs new file mode 100644 index 000000000..846c19a24 --- /dev/null +++ b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs @@ -0,0 +1,156 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a CMS authenticated-data message. + * + * A simple example of usage. + * + *
+	 *      CMSAuthenticatedDataGenerator  fact = new CMSAuthenticatedDataGenerator();
+	 *
+	 *      fact.addKeyTransRecipient(cert);
+	 *
+	 *      CMSAuthenticatedData         data = fact.generate(content, algorithm, "BC");
+	 * 
+ */ + public class CmsAuthenticatedDataGenerator + : CmsAuthenticatedGenerator + { + /** + * base constructor + */ + public CmsAuthenticatedDataGenerator() + { + } + + /** + * constructor allowing specific source of randomness + * @param rand instance of SecureRandom to use + */ + public CmsAuthenticatedDataGenerator( + SecureRandom rand) + : base(rand) + { + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data + * object using the given provider and the passed in key generator. + */ + private CmsAuthenticatedData Generate( + CmsProcessable content, + string macOid, + CipherKeyGenerator keyGen) + { + AlgorithmIdentifier macAlgId; + KeyParameter encKey; + Asn1OctetString encContent; + Asn1OctetString macResult; + + try + { + // FIXME Will this work for macs? + byte[] encKeyBytes = keyGen.GenerateKey(); + encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes); + + Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes); + + ICipherParameters cipherParameters; + macAlgId = GetAlgorithmIdentifier( + macOid, encKey, asn1Params, out cipherParameters); + + IMac mac = MacUtilities.GetMac(macOid); + // TODO Confirm no ParametersWithRandom needed + // FIXME Only passing key at the moment +// mac.Init(cipherParameters); + mac.Init(encKey); + + MemoryStream bOut = new MemoryStream(); + Stream mOut = new TeeOutputStream(bOut, new MacOutputStream(mac)); + + content.Write(mOut); + + mOut.Close(); + bOut.Close(); + + encContent = new BerOctetString(bOut.ToArray()); + + byte[] macOctets = MacUtilities.DoFinal(mac); + macResult = new DerOctetString(macOctets); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("exception decoding algorithm parameters.", e); + } + + Asn1EncodableVector recipientInfos = new Asn1EncodableVector(); + + foreach (RecipientInfoGenerator rig in recipientInfoGenerators) + { + try + { + recipientInfos.Add(rig.Generate(encKey, rand)); + } + catch (InvalidKeyException e) + { + throw new CmsException("key inappropriate for algorithm.", e); + } + catch (GeneralSecurityException e) + { + throw new CmsException("error making encrypted content.", e); + } + } + + ContentInfo eci = new ContentInfo(CmsObjectIdentifiers.Data, encContent); + + ContentInfo contentInfo = new ContentInfo( + CmsObjectIdentifiers.AuthenticatedData, + new AuthenticatedData(null, new DerSet(recipientInfos), macAlgId, null, eci, null, macResult, null)); + + return new CmsAuthenticatedData(contentInfo); + } + + /** + * generate an authenticated object that contains an CMS Authenticated Data object + */ + public CmsAuthenticatedData Generate( + CmsProcessable content, + string encryptionOid) + { + try + { + // FIXME Will this work for macs? + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength)); + + return Generate(content, encryptionOid, keyGen); + } + catch (SecurityUtilityException e) + { + throw new CmsException("can't find key generation algorithm.", e); + } + } + } +} diff --git a/crypto/src/cms/CMSAuthenticatedDataParser.cs b/crypto/src/cms/CMSAuthenticatedDataParser.cs new file mode 100644 index 000000000..c99aac61c --- /dev/null +++ b/crypto/src/cms/CMSAuthenticatedDataParser.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + /** + * Parsing class for an CMS Authenticated Data object from an input stream. + *

+ * Note: that because we are in a streaming mode only one recipient can be tried and it is important + * that the methods on the parser are called in the appropriate order. + *

+ *

+ * Example of use - assuming the first recipient matches the private key we have. + *

+	*      CMSAuthenticatedDataParser     ad = new CMSAuthenticatedDataParser(inputStream);
+	*
+	*      RecipientInformationStore  recipients = ad.getRecipientInfos();
+	*
+	*      Collection  c = recipients.getRecipients();
+	*      Iterator    it = c.iterator();
+	*
+	*      if (it.hasNext())
+	*      {
+	*          RecipientInformation   recipient = (RecipientInformation)it.next();
+	*
+	*          CMSTypedStream recData = recipient.getContentStream(privateKey, "BC");
+	*
+	*          processDataStream(recData.getContentStream());
+	*
+	*          if (!Arrays.equals(ad.getMac(), recipient.getMac())
+	*          {
+	*              System.err.println("Data corrupted!!!!");
+	*          }
+	*      }
+	*  
+ * Note: this class does not introduce buffering - if you are processing large files you should create + * the parser with: + *
+	*          CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
+	*  
+ * where bufSize is a suitably large buffer size. + *

+ */ + public class CmsAuthenticatedDataParser + : CmsContentInfoParser + { + internal RecipientInformationStore _recipientInfoStore; + internal AuthenticatedDataParser authData; + + private AlgorithmIdentifier macAlg; + private byte[] mac; + private Asn1.Cms.AttributeTable authAttrs; + private Asn1.Cms.AttributeTable unauthAttrs; + + private bool authAttrNotRead; + private bool unauthAttrNotRead; + + public CmsAuthenticatedDataParser( + byte[] envelopedData) + : this(new MemoryStream(envelopedData, false)) + { + } + + public CmsAuthenticatedDataParser( + Stream envelopedData) + : base(envelopedData) + { + this.authAttrNotRead = true; + this.authData = new AuthenticatedDataParser( + (Asn1SequenceParser)contentInfo.GetContent(Asn1Tags.Sequence)); + + // TODO Validate version? + //DerInteger version = this.authData.getVersion(); + + // + // read the recipients + // + Asn1Set recipientInfos = Asn1Set.GetInstance(authData.GetRecipientInfos().ToAsn1Object()); + + this.macAlg = authData.GetMacAlgorithm(); + + // + // read the authenticated content info + // + ContentInfoParser data = authData.GetEnapsulatedContentInfo(); + CmsReadable readable = new CmsProcessableInputStream( + ((Asn1OctetStringParser)data.GetContent(Asn1Tags.OctetString)).GetOctetStream()); + CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable( + this.macAlg, readable); + + // + // build the RecipientInformationStore + // + this._recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore( + recipientInfos, secureReadable); + } + + public AlgorithmIdentifier MacAlgorithmID + { + get { return macAlg; } + } + + /** + * return the object identifier for the mac algorithm. + */ + public string MacAlgOid + { + get { return macAlg.ObjectID.Id; } + } + + + /** + * return the ASN.1 encoded encryption algorithm parameters, or null if + * there aren't any. + */ + public Asn1Object MacAlgParams + { + get + { + Asn1Encodable ae = macAlg.Parameters; + + return ae == null ? null : ae.ToAsn1Object(); + } + } + + /** + * return a store of the intended recipients for this message + */ + public RecipientInformationStore GetRecipientInfos() + { + return _recipientInfoStore; + } + + public byte[] GetMac() + { + if (mac == null) + { + GetAuthAttrs(); + mac = authData.GetMac().GetOctets(); + } + return Arrays.Clone(mac); + } + + /** + * return a table of the unauthenticated attributes indexed by + * the OID of the attribute. + * @exception java.io.IOException + */ + public Asn1.Cms.AttributeTable GetAuthAttrs() + { + if (authAttrs == null && authAttrNotRead) + { + Asn1SetParser s = authData.GetAuthAttrs(); + + authAttrNotRead = false; + + if (s != null) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + IAsn1Convertible o; + while ((o = s.ReadObject()) != null) + { + Asn1SequenceParser seq = (Asn1SequenceParser)o; + + v.Add(seq.ToAsn1Object()); + } + + authAttrs = new Asn1.Cms.AttributeTable(new DerSet(v)); + } + } + + return authAttrs; + } + + /** + * return a table of the unauthenticated attributes indexed by + * the OID of the attribute. + * @exception java.io.IOException + */ + public Asn1.Cms.AttributeTable GetUnauthAttrs() + { + if (unauthAttrs == null && unauthAttrNotRead) + { + Asn1SetParser s = authData.GetUnauthAttrs(); + + unauthAttrNotRead = false; + + if (s != null) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + IAsn1Convertible o; + while ((o = s.ReadObject()) != null) + { + Asn1SequenceParser seq = (Asn1SequenceParser)o; + + v.Add(seq.ToAsn1Object()); + } + + unauthAttrs = new Asn1.Cms.AttributeTable(new DerSet(v)); + } + } + + return unauthAttrs; + } + } +} diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs new file mode 100644 index 000000000..2603cb380 --- /dev/null +++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs @@ -0,0 +1,272 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a CMS authenticated-data message stream. + *

+ * A simple example of usage. + *

+	*      CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
+	*
+	*      edGen.addKeyTransRecipient(cert);
+	*
+	*      ByteArrayOutputStream  bOut = new ByteArrayOutputStream();
+	*
+	*      OutputStream out = edGen.open(
+	*                              bOut, CMSAuthenticatedDataGenerator.AES128_CBC, "BC");*
+	*      out.write(data);
+	*
+	*      out.close();
+	* 
+ *

+ */ + public class CmsAuthenticatedDataStreamGenerator + : CmsAuthenticatedGenerator + { + // TODO Add support +// private object _originatorInfo = null; +// private object _unprotectedAttributes = null; + private int _bufferSize; + private bool _berEncodeRecipientSet; + + /** + * base constructor + */ + public CmsAuthenticatedDataStreamGenerator() + { + } + + /** + * constructor allowing specific source of randomness + * @param rand instance of SecureRandom to use + */ + public CmsAuthenticatedDataStreamGenerator( + SecureRandom rand) + : base(rand) + { + } + + /** + * Set the underlying string size for encapsulated data + * + * @param bufferSize length of octet strings to buffer the data. + */ + public void SetBufferSize( + int bufferSize) + { + _bufferSize = bufferSize; + } + + /** + * Use a BER Set to store the recipient information + */ + public void SetBerEncodeRecipients( + bool berEncodeRecipientSet) + { + _berEncodeRecipientSet = berEncodeRecipientSet; + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data + * object using the given provider and the passed in key generator. + * @throws java.io.IOException + */ + private Stream Open( + Stream outStr, + string macOid, + CipherKeyGenerator keyGen) + { + // FIXME Will this work for macs? + byte[] encKeyBytes = keyGen.GenerateKey(); + KeyParameter encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes); + + Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes); + + ICipherParameters cipherParameters; + AlgorithmIdentifier macAlgId = GetAlgorithmIdentifier( + macOid, encKey, asn1Params, out cipherParameters); + + Asn1EncodableVector recipientInfos = new Asn1EncodableVector(); + + foreach (RecipientInfoGenerator rig in recipientInfoGenerators) + { + try + { + recipientInfos.Add(rig.Generate(encKey, rand)); + } + catch (InvalidKeyException e) + { + throw new CmsException("key inappropriate for algorithm.", e); + } + catch (GeneralSecurityException e) + { + throw new CmsException("error making encrypted content.", e); + } + } + + // FIXME Only passing key at the moment +// return Open(outStr, macAlgId, cipherParameters, recipientInfos); + return Open(outStr, macAlgId, encKey, recipientInfos); + } + + protected Stream Open( + Stream outStr, + AlgorithmIdentifier macAlgId, + ICipherParameters cipherParameters, + Asn1EncodableVector recipientInfos) + { + try + { + // + // ContentInfo + // + BerSequenceGenerator cGen = new BerSequenceGenerator(outStr); + + cGen.AddObject(CmsObjectIdentifiers.AuthenticatedData); + + // + // Authenticated Data + // + BerSequenceGenerator authGen = new BerSequenceGenerator( + cGen.GetRawOutputStream(), 0, true); + + authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null))); + + Stream authRaw = authGen.GetRawOutputStream(); + Asn1Generator recipGen = _berEncodeRecipientSet + ? (Asn1Generator) new BerSetGenerator(authRaw) + : new DerSetGenerator(authRaw); + + foreach (Asn1Encodable ae in recipientInfos) + { + recipGen.AddObject(ae); + } + + recipGen.Close(); + + authGen.AddObject(macAlgId); + + BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw); + eiGen.AddObject(CmsObjectIdentifiers.Data); + + Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream( + eiGen.GetRawOutputStream(), 0, false, _bufferSize); + + IMac mac = MacUtilities.GetMac(macAlgId.ObjectID); + // TODO Confirm no ParametersWithRandom needed + mac.Init(cipherParameters); + Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac)); + + return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("exception decoding algorithm parameters.", e); + } + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data object + */ + public Stream Open( + Stream outStr, + string encryptionOid) + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength)); + + return Open(outStr, encryptionOid, keyGen); + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data object + */ + public Stream Open( + Stream outStr, + string encryptionOid, + int keySize) + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keySize)); + + return Open(outStr, encryptionOid, keyGen); + } + + private class CmsAuthenticatedDataOutputStream + : BaseOutputStream + { + private readonly Stream macStream; + private readonly IMac mac; + private readonly BerSequenceGenerator cGen; + private readonly BerSequenceGenerator authGen; + private readonly BerSequenceGenerator eiGen; + + public CmsAuthenticatedDataOutputStream( + Stream macStream, + IMac mac, + BerSequenceGenerator cGen, + BerSequenceGenerator authGen, + BerSequenceGenerator eiGen) + { + this.macStream = macStream; + this.mac = mac; + this.cGen = cGen; + this.authGen = authGen; + this.eiGen = eiGen; + } + + public override void WriteByte( + byte b) + { + macStream.WriteByte(b); + } + + public override void Write( + byte[] bytes, + int off, + int len) + { + macStream.Write(bytes, off, len); + } + + public override void Close() + { + macStream.Close(); + + // TODO Parent context(s) should really be be closed explicitly + + eiGen.Close(); + + // [TODO] auth attributes go here + byte[] macOctets = MacUtilities.DoFinal(mac); + authGen.AddObject(new DerOctetString(macOctets)); + // [TODO] unauth attributes go here + + authGen.Close(); + cGen.Close(); + } + } + } +} diff --git a/crypto/src/cms/CMSAuthenticatedGenerator.cs b/crypto/src/cms/CMSAuthenticatedGenerator.cs new file mode 100644 index 000000000..8824d1913 --- /dev/null +++ b/crypto/src/cms/CMSAuthenticatedGenerator.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + public class CmsAuthenticatedGenerator + : CmsEnvelopedGenerator + { + /** + * base constructor + */ + public CmsAuthenticatedGenerator() + { + } + + /** + * constructor allowing specific source of randomness + * + * @param rand instance of SecureRandom to use + */ + public CmsAuthenticatedGenerator( + SecureRandom rand) + : base(rand) + { + } + } +} diff --git a/crypto/src/cms/CMSCompressedData.cs b/crypto/src/cms/CMSCompressedData.cs new file mode 100644 index 000000000..2d0107e88 --- /dev/null +++ b/crypto/src/cms/CMSCompressedData.cs @@ -0,0 +1,107 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Cms +{ + /** + * containing class for an CMS Compressed Data object + */ + public class CmsCompressedData + { + internal ContentInfo contentInfo; + + public CmsCompressedData( + byte[] compressedData) + : this(CmsUtilities.ReadContentInfo(compressedData)) + { + } + + public CmsCompressedData( + Stream compressedDataStream) + : this(CmsUtilities.ReadContentInfo(compressedDataStream)) + { + } + + public CmsCompressedData( + ContentInfo contentInfo) + { + this.contentInfo = contentInfo; + } + + /** + * Return the uncompressed content. + * + * @return the uncompressed content + * @throws CmsException if there is an exception uncompressing the data. + */ + public byte[] GetContent() + { + CompressedData comData = CompressedData.GetInstance(contentInfo.Content); + ContentInfo content = comData.EncapContentInfo; + + Asn1OctetString bytes = (Asn1OctetString) content.Content; + ZInputStream zIn = new ZInputStream(bytes.GetOctetStream()); + + try + { + return CmsUtilities.StreamToByteArray(zIn); + } + catch (IOException e) + { + throw new CmsException("exception reading compressed stream.", e); + } + finally + { + zIn.Close(); + } + } + + /** + * Return the uncompressed content, throwing an exception if the data size + * is greater than the passed in limit. If the content is exceeded getCause() + * on the CMSException will contain a StreamOverflowException + * + * @param limit maximum number of bytes to read + * @return the content read + * @throws CMSException if there is an exception uncompressing the data. + */ + public byte[] GetContent(int limit) + { + CompressedData comData = CompressedData.GetInstance(contentInfo.Content); + ContentInfo content = comData.EncapContentInfo; + + Asn1OctetString bytes = (Asn1OctetString)content.Content; + + ZInputStream zIn = new ZInputStream(new MemoryStream(bytes.GetOctets(), false)); + + try + { + return CmsUtilities.StreamToByteArray(zIn, limit); + } + catch (IOException e) + { + throw new CmsException("exception reading compressed stream.", e); + } + } + + /** + * return the ContentInfo + */ + public ContentInfo ContentInfo + { + get { return contentInfo; } + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return contentInfo.GetEncoded(); + } + } +} diff --git a/crypto/src/cms/CMSCompressedDataGenerator.cs b/crypto/src/cms/CMSCompressedDataGenerator.cs new file mode 100644 index 000000000..00e2a3df4 --- /dev/null +++ b/crypto/src/cms/CMSCompressedDataGenerator.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a compressed CMS message. + *

+ * A simple example of usage.

+ *

+ *

+    *      CMSCompressedDataGenerator fact = new CMSCompressedDataGenerator();
+    *      CMSCompressedData data = fact.Generate(content, algorithm);
+    * 
+ *

+ */ + public class CmsCompressedDataGenerator + { + public const string ZLib = "1.2.840.113549.1.9.16.3.8"; + + public CmsCompressedDataGenerator() + { + } + + /** + * Generate an object that contains an CMS Compressed Data + */ + public CmsCompressedData Generate( + CmsProcessable content, + string compressionOid) + { + AlgorithmIdentifier comAlgId; + Asn1OctetString comOcts; + + try + { + MemoryStream bOut = new MemoryStream(); + ZOutputStream zOut = new ZOutputStream(bOut, JZlib.Z_DEFAULT_COMPRESSION); + + content.Write(zOut); + + zOut.Close(); + + comAlgId = new AlgorithmIdentifier(new DerObjectIdentifier(compressionOid)); + comOcts = new BerOctetString(bOut.ToArray()); + } + catch (IOException e) + { + throw new CmsException("exception encoding data.", e); + } + + ContentInfo comContent = new ContentInfo(CmsObjectIdentifiers.Data, comOcts); + ContentInfo contentInfo = new ContentInfo( + CmsObjectIdentifiers.CompressedData, + new CompressedData(comAlgId, comContent)); + + return new CmsCompressedData(contentInfo); + } + } +} diff --git a/crypto/src/cms/CMSCompressedDataParser.cs b/crypto/src/cms/CMSCompressedDataParser.cs new file mode 100644 index 000000000..93dfa1286 --- /dev/null +++ b/crypto/src/cms/CMSCompressedDataParser.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Cms +{ + /** + * Class for reading a CMS Compressed Data stream. + *
+    *     CMSCompressedDataParser cp = new CMSCompressedDataParser(inputStream);
+    *
+    *     process(cp.GetContent().GetContentStream());
+    * 
+ * Note: this class does not introduce buffering - if you are processing large files you should create + * the parser with: + *
+    *      CMSCompressedDataParser     ep = new CMSCompressedDataParser(new BufferedInputStream(inputStream, bufSize));
+    *  
+ * where bufSize is a suitably large buffer size. + */ + public class CmsCompressedDataParser + : CmsContentInfoParser + { + public CmsCompressedDataParser( + byte[] compressedData) + : this(new MemoryStream(compressedData, false)) + { + } + + public CmsCompressedDataParser( + Stream compressedData) + : base(compressedData) + { + } + + public CmsTypedStream GetContent() + { + try + { + CompressedDataParser comData = new CompressedDataParser((Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence)); + ContentInfoParser content = comData.GetEncapContentInfo(); + + Asn1OctetStringParser bytes = (Asn1OctetStringParser)content.GetContent(Asn1Tags.OctetString); + + return new CmsTypedStream(content.ContentType.ToString(), new ZInputStream(bytes.GetOctetStream())); + } + catch (IOException e) + { + throw new CmsException("IOException reading compressed content.", e); + } + } + } +} diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs new file mode 100644 index 000000000..db0d19845 --- /dev/null +++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a compressed CMS message stream. + *

+ * A simple example of usage. + *

+ *
+	*      CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
+	*
+	*      Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
+	*
+	*      cOut.Write(data);
+	*
+	*      cOut.Close();
+	* 
+ */ + public class CmsCompressedDataStreamGenerator + { + public const string ZLib = "1.2.840.113549.1.9.16.3.8"; + + private int _bufferSize; + + /** + * base constructor + */ + public CmsCompressedDataStreamGenerator() + { + } + + /** + * Set the underlying string size for encapsulated data + * + * @param bufferSize length of octet strings to buffer the data. + */ + public void SetBufferSize( + int bufferSize) + { + _bufferSize = bufferSize; + } + + public Stream Open( + Stream outStream, + string compressionOID) + { + return Open(outStream, CmsObjectIdentifiers.Data.Id, compressionOID); + } + + public Stream Open( + Stream outStream, + string contentOID, + string compressionOID) + { + BerSequenceGenerator sGen = new BerSequenceGenerator(outStream); + + sGen.AddObject(CmsObjectIdentifiers.CompressedData); + + // + // Compressed Data + // + BerSequenceGenerator cGen = new BerSequenceGenerator( + sGen.GetRawOutputStream(), 0, true); + + // CMSVersion + cGen.AddObject(new DerInteger(0)); + + // CompressionAlgorithmIdentifier + cGen.AddObject(new AlgorithmIdentifier(new DerObjectIdentifier(ZLib))); + + // + // Encapsulated ContentInfo + // + BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream()); + + eiGen.AddObject(new DerObjectIdentifier(contentOID)); + + Stream octetStream = CmsUtilities.CreateBerOctetOutputStream( + eiGen.GetRawOutputStream(), 0, true, _bufferSize); + + return new CmsCompressedOutputStream( + new ZOutputStream(octetStream, JZlib.Z_DEFAULT_COMPRESSION), sGen, cGen, eiGen); + } + + private class CmsCompressedOutputStream + : BaseOutputStream + { + private ZOutputStream _out; + private BerSequenceGenerator _sGen; + private BerSequenceGenerator _cGen; + private BerSequenceGenerator _eiGen; + + internal CmsCompressedOutputStream( + ZOutputStream outStream, + BerSequenceGenerator sGen, + BerSequenceGenerator cGen, + BerSequenceGenerator eiGen) + { + _out = outStream; + _sGen = sGen; + _cGen = cGen; + _eiGen = eiGen; + } + + public override void WriteByte( + byte b) + { + _out.WriteByte(b); + } + + public override void Write( + byte[] bytes, + int off, + int len) + { + _out.Write(bytes, off, len); + } + + public override void Close() + { + _out.Close(); + + // TODO Parent context(s) should really be be closed explicitly + + _eiGen.Close(); + _cGen.Close(); + _sGen.Close(); + base.Close(); + } + } + } +} diff --git a/crypto/src/cms/CMSContentInfoParser.cs b/crypto/src/cms/CMSContentInfoParser.cs new file mode 100644 index 000000000..fde06cf4c --- /dev/null +++ b/crypto/src/cms/CMSContentInfoParser.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Cms +{ + public class CmsContentInfoParser + { + protected ContentInfoParser contentInfo; + protected Stream data; + + protected CmsContentInfoParser( + Stream data) + { + if (data == null) + throw new ArgumentNullException("data"); + + this.data = data; + + try + { + Asn1StreamParser inStream = new Asn1StreamParser(data); + + this.contentInfo = new ContentInfoParser((Asn1SequenceParser)inStream.ReadObject()); + } + catch (IOException e) + { + throw new CmsException("IOException reading content.", e); + } + catch (InvalidCastException e) + { + throw new CmsException("Unexpected object reading content.", e); + } + } + + /** + * Close the underlying data stream. + * @throws IOException if the close fails. + */ + public void Close() + { + this.data.Close(); + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedData.cs b/crypto/src/cms/CMSEnvelopedData.cs new file mode 100644 index 000000000..0731c307e --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedData.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + /** + * containing class for an CMS Enveloped Data object + */ + public class CmsEnvelopedData + { + internal RecipientInformationStore recipientInfoStore; + internal ContentInfo contentInfo; + + private AlgorithmIdentifier encAlg; + private Asn1Set unprotectedAttributes; + + public CmsEnvelopedData( + byte[] envelopedData) + : this(CmsUtilities.ReadContentInfo(envelopedData)) + { + } + + public CmsEnvelopedData( + Stream envelopedData) + : this(CmsUtilities.ReadContentInfo(envelopedData)) + { + } + + public CmsEnvelopedData( + ContentInfo contentInfo) + { + this.contentInfo = contentInfo; + + EnvelopedData envData = EnvelopedData.GetInstance(contentInfo.Content); + + // + // read the recipients + // + Asn1Set recipientInfos = envData.RecipientInfos; + + // + // read the encrypted content info + // + EncryptedContentInfo encInfo = envData.EncryptedContentInfo; + this.encAlg = encInfo.ContentEncryptionAlgorithm; + CmsReadable readable = new CmsProcessableByteArray(encInfo.EncryptedContent.GetOctets()); + CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable( + this.encAlg, readable); + + // + // build the RecipientInformationStore + // + this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore( + recipientInfos, secureReadable); + + this.unprotectedAttributes = envData.UnprotectedAttrs; + } + + public AlgorithmIdentifier EncryptionAlgorithmID + { + get { return encAlg; } + } + + /** + * return the object identifier for the content encryption algorithm. + */ + public string EncryptionAlgOid + { + get { return encAlg.ObjectID.Id; } + } + + /** + * return a store of the intended recipients for this message + */ + public RecipientInformationStore GetRecipientInfos() + { + return recipientInfoStore; + } + + /** + * return the ContentInfo + */ + public ContentInfo ContentInfo + { + get { return contentInfo; } + } + + /** + * return a table of the unprotected attributes indexed by + * the OID of the attribute. + */ + public Asn1.Cms.AttributeTable GetUnprotectedAttributes() + { + if (unprotectedAttributes == null) + return null; + + return new Asn1.Cms.AttributeTable(unprotectedAttributes); + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return contentInfo.GetEncoded(); + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedDataGenerator.cs b/crypto/src/cms/CMSEnvelopedDataGenerator.cs new file mode 100644 index 000000000..3b861cde5 --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedDataGenerator.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /// + /// General class for generating a CMS enveloped-data message. + /// + /// A simple example of usage. + /// + ///
+    ///      CmsEnvelopedDataGenerator  fact = new CmsEnvelopedDataGenerator();
+    ///
+    ///      fact.AddKeyTransRecipient(cert);
+    ///
+    ///      CmsEnvelopedData         data = fact.Generate(content, algorithm);
+    /// 
+ ///
+ public class CmsEnvelopedDataGenerator + : CmsEnvelopedGenerator + { + public CmsEnvelopedDataGenerator() + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + public CmsEnvelopedDataGenerator( + SecureRandom rand) + : base(rand) + { + } + + /// + /// Generate an enveloped object that contains a CMS Enveloped Data + /// object using the passed in key generator. + /// + private CmsEnvelopedData Generate( + CmsProcessable content, + string encryptionOid, + CipherKeyGenerator keyGen) + { + AlgorithmIdentifier encAlgId = null; + KeyParameter encKey; + Asn1OctetString encContent; + + try + { + byte[] encKeyBytes = keyGen.GenerateKey(); + encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes); + + Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes); + + ICipherParameters cipherParameters; + encAlgId = GetAlgorithmIdentifier( + encryptionOid, encKey, asn1Params, out cipherParameters); + + IBufferedCipher cipher = CipherUtilities.GetCipher(encryptionOid); + cipher.Init(true, new ParametersWithRandom(cipherParameters, rand)); + + MemoryStream bOut = new MemoryStream(); + CipherStream cOut = new CipherStream(bOut, null, cipher); + + content.Write(cOut); + + cOut.Close(); + + encContent = new BerOctetString(bOut.ToArray()); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("exception decoding algorithm parameters.", e); + } + + + Asn1EncodableVector recipientInfos = new Asn1EncodableVector(); + + foreach (RecipientInfoGenerator rig in recipientInfoGenerators) + { + try + { + recipientInfos.Add(rig.Generate(encKey, rand)); + } + catch (InvalidKeyException e) + { + throw new CmsException("key inappropriate for algorithm.", e); + } + catch (GeneralSecurityException e) + { + throw new CmsException("error making encrypted content.", e); + } + } + + EncryptedContentInfo eci = new EncryptedContentInfo( + CmsObjectIdentifiers.Data, + encAlgId, + encContent); + + Asn1Set unprotectedAttrSet = null; + if (unprotectedAttributeGenerator != null) + { + Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable()); + + unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector()); + } + + ContentInfo contentInfo = new ContentInfo( + CmsObjectIdentifiers.EnvelopedData, + new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet)); + + return new CmsEnvelopedData(contentInfo); + } + + /// Generate an enveloped object that contains an CMS Enveloped Data object. + public CmsEnvelopedData Generate( + CmsProcessable content, + string encryptionOid) + { + try + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength)); + + return Generate(content, encryptionOid, keyGen); + } + catch (SecurityUtilityException e) + { + throw new CmsException("can't find key generation algorithm.", e); + } + } + + /// Generate an enveloped object that contains an CMS Enveloped Data object. + public CmsEnvelopedData Generate( + CmsProcessable content, + string encryptionOid, + int keySize) + { + try + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keySize)); + + return Generate(content, encryptionOid, keyGen); + } + catch (SecurityUtilityException e) + { + throw new CmsException("can't find key generation algorithm.", e); + } + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedDataParser.cs b/crypto/src/cms/CMSEnvelopedDataParser.cs new file mode 100644 index 000000000..01a949d47 --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedDataParser.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Cms +{ + /** + * Parsing class for an CMS Enveloped Data object from an input stream. + *

+ * Note: that because we are in a streaming mode only one recipient can be tried and it is important + * that the methods on the parser are called in the appropriate order. + *

+ *

+ * Example of use - assuming the first recipient matches the private key we have. + *

+	*      CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(inputStream);
+	*
+	*      RecipientInformationStore  recipients = ep.GetRecipientInfos();
+	*
+	*      Collection  c = recipients.getRecipients();
+	*      Iterator    it = c.iterator();
+	*
+	*      if (it.hasNext())
+	*      {
+	*          RecipientInformation   recipient = (RecipientInformation)it.next();
+	*
+	*          CMSTypedStream recData = recipient.getContentStream(privateKey);
+	*
+	*          processDataStream(recData.getContentStream());
+	*      }
+	*  
+ * Note: this class does not introduce buffering - if you are processing large files you should create + * the parser with: + *
+	*          CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(new BufferedInputStream(inputStream, bufSize));
+	*  
+ * where bufSize is a suitably large buffer size. + *

+ */ + public class CmsEnvelopedDataParser + : CmsContentInfoParser + { + internal RecipientInformationStore recipientInfoStore; + internal EnvelopedDataParser envelopedData; + + private AlgorithmIdentifier _encAlg; + private Asn1.Cms.AttributeTable _unprotectedAttributes; + private bool _attrNotRead; + + public CmsEnvelopedDataParser( + byte[] envelopedData) + : this(new MemoryStream(envelopedData, false)) + { + } + + public CmsEnvelopedDataParser( + Stream envelopedData) + : base(envelopedData) + { + this._attrNotRead = true; + this.envelopedData = new EnvelopedDataParser( + (Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence)); + + // TODO Validate version? + //DerInteger version = this.envelopedData.Version; + + // + // read the recipients + // + Asn1Set recipientInfos = Asn1Set.GetInstance(this.envelopedData.GetRecipientInfos().ToAsn1Object()); + + // + // read the encrypted content info + // + EncryptedContentInfoParser encInfo = this.envelopedData.GetEncryptedContentInfo(); + this._encAlg = encInfo.ContentEncryptionAlgorithm; + CmsReadable readable = new CmsProcessableInputStream( + ((Asn1OctetStringParser)encInfo.GetEncryptedContent(Asn1Tags.OctetString)).GetOctetStream()); + CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable( + this._encAlg, readable); + + // + // build the RecipientInformationStore + // + this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore( + recipientInfos, secureReadable); + } + + public AlgorithmIdentifier EncryptionAlgorithmID + { + get { return _encAlg; } + } + + /** + * return the object identifier for the content encryption algorithm. + */ + public string EncryptionAlgOid + { + get { return _encAlg.ObjectID.Id; } + } + + /** + * return the ASN.1 encoded encryption algorithm parameters, or null if + * there aren't any. + */ + public Asn1Object EncryptionAlgParams + { + get + { + Asn1Encodable ae = _encAlg.Parameters; + + return ae == null ? null : ae.ToAsn1Object(); + } + } + + /** + * return a store of the intended recipients for this message + */ + public RecipientInformationStore GetRecipientInfos() + { + return this.recipientInfoStore; + } + + /** + * return a table of the unprotected attributes indexed by + * the OID of the attribute. + * @throws IOException + */ + public Asn1.Cms.AttributeTable GetUnprotectedAttributes() + { + if (_unprotectedAttributes == null && _attrNotRead) + { + Asn1SetParser asn1Set = this.envelopedData.GetUnprotectedAttrs(); + + _attrNotRead = false; + + if (asn1Set != null) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + IAsn1Convertible o; + + while ((o = asn1Set.ReadObject()) != null) + { + Asn1SequenceParser seq = (Asn1SequenceParser)o; + + v.Add(seq.ToAsn1Object()); + } + + _unprotectedAttributes = new Asn1.Cms.AttributeTable(new DerSet(v)); + } + } + + return _unprotectedAttributes; + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs new file mode 100644 index 000000000..a63ea7b7f --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a CMS enveloped-data message stream. + *

+ * A simple example of usage. + *

+	*      CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+	*
+	*      edGen.AddKeyTransRecipient(cert);
+	*
+	*      MemoryStream  bOut = new MemoryStream();
+	*
+	*      Stream out = edGen.Open(
+	*                              bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
+	*      out.Write(data);
+	*
+	*      out.Close();
+	* 
+ *

+ */ + public class CmsEnvelopedDataStreamGenerator + : CmsEnvelopedGenerator + { + private object _originatorInfo = null; + private object _unprotectedAttributes = null; + private int _bufferSize; + private bool _berEncodeRecipientSet; + + public CmsEnvelopedDataStreamGenerator() + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + public CmsEnvelopedDataStreamGenerator( + SecureRandom rand) + : base(rand) + { + } + + /// Set the underlying string size for encapsulated data. + /// Length of octet strings to buffer the data. + public void SetBufferSize( + int bufferSize) + { + _bufferSize = bufferSize; + } + + /// Use a BER Set to store the recipient information. + public void SetBerEncodeRecipients( + bool berEncodeRecipientSet) + { + _berEncodeRecipientSet = berEncodeRecipientSet; + } + + private DerInteger Version + { + get + { + int version = (_originatorInfo != null || _unprotectedAttributes != null) + ? 2 + : 0; + + return new DerInteger(version); + } + } + + /// + /// Generate an enveloped object that contains an CMS Enveloped Data + /// object using the passed in key generator. + /// + private Stream Open( + Stream outStream, + string encryptionOid, + CipherKeyGenerator keyGen) + { + byte[] encKeyBytes = keyGen.GenerateKey(); + KeyParameter encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes); + + Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes); + + ICipherParameters cipherParameters; + AlgorithmIdentifier encAlgID = GetAlgorithmIdentifier( + encryptionOid, encKey, asn1Params, out cipherParameters); + + Asn1EncodableVector recipientInfos = new Asn1EncodableVector(); + + foreach (RecipientInfoGenerator rig in recipientInfoGenerators) + { + try + { + recipientInfos.Add(rig.Generate(encKey, rand)); + } + catch (InvalidKeyException e) + { + throw new CmsException("key inappropriate for algorithm.", e); + } + catch (GeneralSecurityException e) + { + throw new CmsException("error making encrypted content.", e); + } + } + + return Open(outStream, encAlgID, cipherParameters, recipientInfos); + } + + private Stream Open( + Stream outStream, + AlgorithmIdentifier encAlgID, + ICipherParameters cipherParameters, + Asn1EncodableVector recipientInfos) + { + try + { + // + // ContentInfo + // + BerSequenceGenerator cGen = new BerSequenceGenerator(outStream); + + cGen.AddObject(CmsObjectIdentifiers.EnvelopedData); + + // + // Encrypted Data + // + BerSequenceGenerator envGen = new BerSequenceGenerator( + cGen.GetRawOutputStream(), 0, true); + + envGen.AddObject(this.Version); + + Stream envRaw = envGen.GetRawOutputStream(); + Asn1Generator recipGen = _berEncodeRecipientSet + ? (Asn1Generator) new BerSetGenerator(envRaw) + : new DerSetGenerator(envRaw); + + foreach (Asn1Encodable ae in recipientInfos) + { + recipGen.AddObject(ae); + } + + recipGen.Close(); + + BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw); + eiGen.AddObject(CmsObjectIdentifiers.Data); + eiGen.AddObject(encAlgID); + + Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream( + eiGen.GetRawOutputStream(), 0, false, _bufferSize); + + IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.ObjectID); + cipher.Init(true, new ParametersWithRandom(cipherParameters, rand)); + CipherStream cOut = new CipherStream(octetOutputStream, null, cipher); + + return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("exception decoding algorithm parameters.", e); + } + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data object + * @throws IOException + */ + public Stream Open( + Stream outStream, + string encryptionOid) + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength)); + + return Open(outStream, encryptionOid, keyGen); + } + + /** + * generate an enveloped object that contains an CMS Enveloped Data object + * @throws IOException + */ + public Stream Open( + Stream outStream, + string encryptionOid, + int keySize) + { + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid); + + keyGen.Init(new KeyGenerationParameters(rand, keySize)); + + return Open(outStream, encryptionOid, keyGen); + } + + private class CmsEnvelopedDataOutputStream + : BaseOutputStream + { + private readonly CmsEnvelopedGenerator _outer; + + private readonly CipherStream _out; + private readonly BerSequenceGenerator _cGen; + private readonly BerSequenceGenerator _envGen; + private readonly BerSequenceGenerator _eiGen; + + public CmsEnvelopedDataOutputStream( + CmsEnvelopedGenerator outer, + CipherStream outStream, + BerSequenceGenerator cGen, + BerSequenceGenerator envGen, + BerSequenceGenerator eiGen) + { + _outer = outer; + _out = outStream; + _cGen = cGen; + _envGen = envGen; + _eiGen = eiGen; + } + + public override void WriteByte( + byte b) + { + _out.WriteByte(b); + } + + public override void Write( + byte[] bytes, + int off, + int len) + { + _out.Write(bytes, off, len); + } + + public override void Close() + { + _out.Close(); + + // TODO Parent context(s) should really be be closed explicitly + + _eiGen.Close(); + + if (_outer.unprotectedAttributeGenerator != null) + { + Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable()); + + Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector()); + + _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs)); + } + + _envGen.Close(); + _cGen.Close(); + base.Close(); + } + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs new file mode 100644 index 000000000..f92ae3824 --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedGenerator.cs @@ -0,0 +1,331 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a CMS enveloped-data message. + * + * A simple example of usage. + * + *
+	*      CMSEnvelopedDataGenerator  fact = new CMSEnvelopedDataGenerator();
+	*
+	*      fact.addKeyTransRecipient(cert);
+	*
+	*      CMSEnvelopedData         data = fact.generate(content, algorithm, "BC");
+	* 
+ */ + public class CmsEnvelopedGenerator + { + // Note: These tables are complementary: If rc2Table[i]==j, then rc2Ekb[j]==i + internal static readonly short[] rc2Table = + { + 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, + 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, + 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, + 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, + 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, + 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, + 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, + 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, + 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, + 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, + 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, + 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, + 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, + 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, + 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, + 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab + }; + +// internal static readonly short[] rc2Ekb = +// { +// 0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5, +// 0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5, +// 0xb9, 0x1e, 0x96, 0x43, 0x41, 0xd8, 0xd4, 0x2c, 0xdb, 0xf8, 0x07, 0x77, 0x2a, 0xca, 0xeb, 0xef, +// 0x10, 0x1c, 0x16, 0x0d, 0x38, 0x72, 0x2f, 0x89, 0xc1, 0xf9, 0x80, 0xc4, 0x6d, 0xae, 0x30, 0x3d, +// 0xce, 0x20, 0x63, 0xfe, 0xe6, 0x1a, 0xc7, 0xb8, 0x50, 0xe8, 0x24, 0x17, 0xfc, 0x25, 0x6f, 0xbb, +// 0x6a, 0xa3, 0x44, 0x53, 0xd9, 0xa2, 0x01, 0xab, 0xbc, 0xb6, 0x1f, 0x98, 0xee, 0x9a, 0xa7, 0x2d, +// 0x4f, 0x9e, 0x8e, 0xac, 0xe0, 0xc6, 0x49, 0x46, 0x29, 0xf4, 0x94, 0x8a, 0xaf, 0xe1, 0x5b, 0xc3, +// 0xb3, 0x7b, 0x57, 0xd1, 0x7c, 0x9c, 0xed, 0x87, 0x40, 0x8c, 0xe2, 0xcb, 0x93, 0x14, 0xc9, 0x61, +// 0x2e, 0xe5, 0xcc, 0xf6, 0x5e, 0xa8, 0x5c, 0xd6, 0x75, 0x8d, 0x62, 0x95, 0x58, 0x69, 0x76, 0xa1, +// 0x4a, 0xb5, 0x55, 0x09, 0x78, 0x33, 0x82, 0xd7, 0xdd, 0x79, 0xf5, 0x1b, 0x0b, 0xde, 0x26, 0x21, +// 0x28, 0x74, 0x04, 0x97, 0x56, 0xdf, 0x3c, 0xf0, 0x37, 0x39, 0xdc, 0xff, 0x06, 0xa4, 0xea, 0x42, +// 0x08, 0xda, 0xb4, 0x71, 0xb0, 0xcf, 0x12, 0x7a, 0x4e, 0xfa, 0x6c, 0x1d, 0x84, 0x00, 0xc8, 0x7f, +// 0x91, 0x45, 0xaa, 0x2b, 0xc2, 0xb1, 0x8f, 0xd5, 0xba, 0xf2, 0xad, 0x19, 0xb2, 0x67, 0x36, 0xf7, +// 0x0f, 0x0a, 0x92, 0x7d, 0xe3, 0x9d, 0xe9, 0x90, 0x3e, 0x23, 0x27, 0x66, 0x13, 0xec, 0x81, 0x15, +// 0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7, +// 0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd +// }; + + + // TODO Create named constants for all of these + public static readonly string DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc.Id; + public static readonly string RC2Cbc = PkcsObjectIdentifiers.RC2Cbc.Id; + public const string IdeaCbc = "1.3.6.1.4.1.188.7.1.1.2"; + public const string Cast5Cbc = "1.2.840.113533.7.66.10"; + public static readonly string Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc.Id; + public static readonly string Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc.Id; + public static readonly string Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc.Id; + public static readonly string Camellia128Cbc = NttObjectIdentifiers.IdCamellia128Cbc.Id; + public static readonly string Camellia192Cbc = NttObjectIdentifiers.IdCamellia192Cbc.Id; + public static readonly string Camellia256Cbc = NttObjectIdentifiers.IdCamellia256Cbc.Id; + public static readonly string SeedCbc = KisaObjectIdentifiers.IdSeedCbc.Id; + + public static readonly string DesEde3Wrap = PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id; + public static readonly string Aes128Wrap = NistObjectIdentifiers.IdAes128Wrap.Id; + public static readonly string Aes192Wrap = NistObjectIdentifiers.IdAes192Wrap.Id; + public static readonly string Aes256Wrap = NistObjectIdentifiers.IdAes256Wrap.Id; + public static readonly string Camellia128Wrap = NttObjectIdentifiers.IdCamellia128Wrap.Id; + public static readonly string Camellia192Wrap = NttObjectIdentifiers.IdCamellia192Wrap.Id; + public static readonly string Camellia256Wrap = NttObjectIdentifiers.IdCamellia256Wrap.Id; + public static readonly string SeedWrap = KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id; + + public static readonly string ECDHSha1Kdf = X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id; + public static readonly string ECMqvSha1Kdf = X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id; + + internal readonly IList recipientInfoGenerators = Platform.CreateArrayList(); + internal readonly SecureRandom rand; + + internal CmsAttributeTableGenerator unprotectedAttributeGenerator = null; + + public CmsEnvelopedGenerator() + : this(new SecureRandom()) + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + public CmsEnvelopedGenerator( + SecureRandom rand) + { + this.rand = rand; + } + + public CmsAttributeTableGenerator UnprotectedAttributeGenerator + { + get { return this.unprotectedAttributeGenerator; } + set { this.unprotectedAttributeGenerator = value; } + } + + /** + * add a recipient. + * + * @param cert recipient's public key certificate + * @exception ArgumentException if there is a problem with the certificate + */ + public void AddKeyTransRecipient( + X509Certificate cert) + { + KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator(); + ktrig.RecipientCert = cert; + + recipientInfoGenerators.Add(ktrig); + } + + /** + * add a recipient + * + * @param key the public key used by the recipient + * @param subKeyId the identifier for the recipient's public key + * @exception ArgumentException if there is a problem with the key + */ + public void AddKeyTransRecipient( + AsymmetricKeyParameter pubKey, + byte[] subKeyId) + { + KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator(); + ktrig.RecipientPublicKey = pubKey; + ktrig.SubjectKeyIdentifier = new DerOctetString(subKeyId); + + recipientInfoGenerators.Add(ktrig); + } + + /** + * add a KEK recipient. + * @param key the secret key to use for wrapping + * @param keyIdentifier the byte string that identifies the key + */ + public void AddKekRecipient( + string keyAlgorithm, // TODO Remove need for this parameter + KeyParameter key, + byte[] keyIdentifier) + { + AddKekRecipient(keyAlgorithm, key, new KekIdentifier(keyIdentifier, null, null)); + } + + /** + * add a KEK recipient. + * @param key the secret key to use for wrapping + * @param keyIdentifier the byte string that identifies the key + */ + public void AddKekRecipient( + string keyAlgorithm, // TODO Remove need for this parameter + KeyParameter key, + KekIdentifier kekIdentifier) + { + KekRecipientInfoGenerator kekrig = new KekRecipientInfoGenerator(); + kekrig.KekIdentifier = kekIdentifier; + kekrig.KeyEncryptionKeyOID = keyAlgorithm; + kekrig.KeyEncryptionKey = key; + + recipientInfoGenerators.Add(kekrig); + } + + public void AddPasswordRecipient( + CmsPbeKey pbeKey, + string kekAlgorithmOid) + { + Pbkdf2Params p = new Pbkdf2Params(pbeKey.Salt, pbeKey.IterationCount); + + PasswordRecipientInfoGenerator prig = new PasswordRecipientInfoGenerator(); + prig.KeyDerivationAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbkdf2, p); + prig.KeyEncryptionKeyOID = kekAlgorithmOid; + prig.KeyEncryptionKey = pbeKey.GetEncoded(kekAlgorithmOid); + + recipientInfoGenerators.Add(prig); + } + + /** + * Add a key agreement based recipient. + * + * @param agreementAlgorithm key agreement algorithm to use. + * @param senderPrivateKey private key to initialise sender side of agreement with. + * @param senderPublicKey sender public key to include with message. + * @param recipientCert recipient's public key certificate. + * @param cekWrapAlgorithm OID for key wrapping algorithm to use. + * @exception SecurityUtilityException if the algorithm requested cannot be found + * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified + */ + public void AddKeyAgreementRecipient( + string agreementAlgorithm, + AsymmetricKeyParameter senderPrivateKey, + AsymmetricKeyParameter senderPublicKey, + X509Certificate recipientCert, + string cekWrapAlgorithm) + { + IList recipientCerts = Platform.CreateArrayList(1); + recipientCerts.Add(recipientCert); + + AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey, + recipientCerts, cekWrapAlgorithm); + } + + /** + * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure). + * + * @param agreementAlgorithm key agreement algorithm to use. + * @param senderPrivateKey private key to initialise sender side of agreement with. + * @param senderPublicKey sender public key to include with message. + * @param recipientCerts recipients' public key certificates. + * @param cekWrapAlgorithm OID for key wrapping algorithm to use. + * @exception SecurityUtilityException if the algorithm requested cannot be found + * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified + */ + public void AddKeyAgreementRecipients( + string agreementAlgorithm, + AsymmetricKeyParameter senderPrivateKey, + AsymmetricKeyParameter senderPublicKey, + ICollection recipientCerts, + string cekWrapAlgorithm) + { + if (!senderPrivateKey.IsPrivate) + throw new ArgumentException("Expected private key", "senderPrivateKey"); + if (senderPublicKey.IsPrivate) + throw new ArgumentException("Expected public key", "senderPublicKey"); + + /* TODO + * "a recipient X.509 version 3 certificate that contains a key usage extension MUST + * assert the keyAgreement bit." + */ + + KeyAgreeRecipientInfoGenerator karig = new KeyAgreeRecipientInfoGenerator(); + karig.KeyAgreementOID = new DerObjectIdentifier(agreementAlgorithm); + karig.KeyEncryptionOID = new DerObjectIdentifier(cekWrapAlgorithm); + karig.RecipientCerts = recipientCerts; + karig.SenderKeyPair = new AsymmetricCipherKeyPair(senderPublicKey, senderPrivateKey); + + recipientInfoGenerators.Add(karig); + } + + protected internal virtual AlgorithmIdentifier GetAlgorithmIdentifier( + string encryptionOid, + KeyParameter encKey, + Asn1Encodable asn1Params, + out ICipherParameters cipherParameters) + { + Asn1Object asn1Object; + if (asn1Params != null) + { + asn1Object = asn1Params.ToAsn1Object(); + cipherParameters = ParameterUtilities.GetCipherParameters( + encryptionOid, encKey, asn1Object); + } + else + { + asn1Object = DerNull.Instance; + cipherParameters = encKey; + } + + return new AlgorithmIdentifier( + new DerObjectIdentifier(encryptionOid), + asn1Object); + } + + protected internal virtual Asn1Encodable GenerateAsn1Parameters( + string encryptionOid, + byte[] encKeyBytes) + { + Asn1Encodable asn1Params = null; + + try + { + if (encryptionOid.Equals(RC2Cbc)) + { + byte[] iv = new byte[8]; + rand.NextBytes(iv); + + // TODO Is this detailed repeat of Java version really necessary? + int effKeyBits = encKeyBytes.Length * 8; + int parameterVersion; + + if (effKeyBits < 256) + { + parameterVersion = rc2Table[effKeyBits]; + } + else + { + parameterVersion = effKeyBits; + } + + asn1Params = new RC2CbcParameter(parameterVersion, iv); + } + else + { + asn1Params = ParameterUtilities.GenerateParameters(encryptionOid, rand); + } + } + catch (SecurityUtilityException) + { + // No problem... no parameters generated + } + + return asn1Params; + } + } +} diff --git a/crypto/src/cms/CMSEnvelopedHelper.cs b/crypto/src/cms/CMSEnvelopedHelper.cs new file mode 100644 index 000000000..fe2b14cd9 --- /dev/null +++ b/crypto/src/cms/CMSEnvelopedHelper.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + class CmsEnvelopedHelper + { + internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper(); + + private static readonly IDictionary KeySizes = Platform.CreateHashtable(); + private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable(); + + static CmsEnvelopedHelper() + { + KeySizes.Add(CmsEnvelopedGenerator.DesEde3Cbc, 192); + KeySizes.Add(CmsEnvelopedGenerator.Aes128Cbc, 128); + KeySizes.Add(CmsEnvelopedGenerator.Aes192Cbc, 192); + KeySizes.Add(CmsEnvelopedGenerator.Aes256Cbc, 256); + + BaseCipherNames.Add(CmsEnvelopedGenerator.DesEde3Cbc, "DESEDE"); + BaseCipherNames.Add(CmsEnvelopedGenerator.Aes128Cbc, "AES"); + BaseCipherNames.Add(CmsEnvelopedGenerator.Aes192Cbc, "AES"); + BaseCipherNames.Add(CmsEnvelopedGenerator.Aes256Cbc, "AES"); + } + + private string GetAsymmetricEncryptionAlgName( + string encryptionAlgOid) + { + if (Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid)) + { + return "RSA/ECB/PKCS1Padding"; + } + + return encryptionAlgOid; + } + + internal IBufferedCipher CreateAsymmetricCipher( + string encryptionOid) + { + string asymName = GetAsymmetricEncryptionAlgName(encryptionOid); + if (!asymName.Equals(encryptionOid)) + { + try + { + return CipherUtilities.GetCipher(asymName); + } + catch (SecurityUtilityException) + { + // Ignore + } + } + return CipherUtilities.GetCipher(encryptionOid); + } + + internal IWrapper CreateWrapper( + string encryptionOid) + { + try + { + return WrapperUtilities.GetWrapper(encryptionOid); + } + catch (SecurityUtilityException) + { + return WrapperUtilities.GetWrapper(GetAsymmetricEncryptionAlgName(encryptionOid)); + } + } + + internal string GetRfc3211WrapperName( + string oid) + { + if (oid == null) + throw new ArgumentNullException("oid"); + + string alg = (string) BaseCipherNames[oid]; + + if (alg == null) + throw new ArgumentException("no name for " + oid, "oid"); + + return alg + "RFC3211Wrap"; + } + + internal int GetKeySize( + string oid) + { + if (!KeySizes.Contains(oid)) + { + throw new ArgumentException("no keysize for " + oid, "oid"); + } + + return (int) KeySizes[oid]; + } + + internal static RecipientInformationStore BuildRecipientInformationStore( + Asn1Set recipientInfos, CmsSecureReadable secureReadable) + { + IList infos = Platform.CreateArrayList(); + for (int i = 0; i != recipientInfos.Count; i++) + { + RecipientInfo info = RecipientInfo.GetInstance(recipientInfos[i]); + + ReadRecipientInfo(infos, info, secureReadable); + } + return new RecipientInformationStore(infos); + } + + private static void ReadRecipientInfo( + IList infos, RecipientInfo info, CmsSecureReadable secureReadable) + { + Asn1Encodable recipInfo = info.Info; + if (recipInfo is KeyTransRecipientInfo) + { + infos.Add(new KeyTransRecipientInformation((KeyTransRecipientInfo)recipInfo, secureReadable)); + } + else if (recipInfo is KekRecipientInfo) + { + infos.Add(new KekRecipientInformation((KekRecipientInfo)recipInfo, secureReadable)); + } + else if (recipInfo is KeyAgreeRecipientInfo) + { + KeyAgreeRecipientInformation.ReadRecipientInfo(infos, (KeyAgreeRecipientInfo)recipInfo, secureReadable); + } + else if (recipInfo is PasswordRecipientInfo) + { + infos.Add(new PasswordRecipientInformation((PasswordRecipientInfo)recipInfo, secureReadable)); + } + } + + internal class CmsAuthenticatedSecureReadable : CmsSecureReadable + { + private AlgorithmIdentifier algorithm; + private IMac mac; + private CmsReadable readable; + + internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable) + { + this.algorithm = algorithm; + this.readable = readable; + } + + public AlgorithmIdentifier Algorithm + { + get { return this.algorithm; } + } + + public object CryptoObject + { + get { return this.mac; } + } + + public CmsReadable GetReadable(KeyParameter sKey) + { + string macAlg = this.algorithm.ObjectID.Id; +// Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object(); + + try + { + this.mac = MacUtilities.GetMac(macAlg); + + // FIXME Support for MAC algorithm parameters similar to cipher parameters +// ASN1Object sParams = (ASN1Object)macAlg.getParameters(); +// +// if (sParams != null && !(sParams instanceof ASN1Null)) +// { +// AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE.createAlgorithmParameters(macAlg.getObjectId().getId(), provider); +// +// params.init(sParams.getEncoded(), "ASN.1"); +// +// mac.init(sKey, params.getParameterSpec(IvParameterSpec.class)); +// } +// else + { + mac.Init(sKey); + } + +// Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object(); +// +// ICipherParameters cipherParameters = sKey; +// +// if (asn1Params != null && !(asn1Params is Asn1Null)) +// { +// cipherParameters = ParameterUtilities.GetCipherParameters( +// macAlg.ObjectID, cipherParameters, asn1Params); +// } +// else +// { +// string alg = macAlg.ObjectID.Id; +// if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc) +// || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc) +// || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc)) +// { +// cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]); +// } +// } +// +// mac.Init(cipherParameters); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("error decoding algorithm parameters.", e); + } + + try + { + return new CmsProcessableInputStream( + new TeeInputStream( + readable.GetInputStream(), + new MacOutputStream(this.mac))); + } + catch (IOException e) + { + throw new CmsException("error reading content.", e); + } + } + } + + internal class CmsEnvelopedSecureReadable : CmsSecureReadable + { + private AlgorithmIdentifier algorithm; + private IBufferedCipher cipher; + private CmsReadable readable; + + internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable) + { + this.algorithm = algorithm; + this.readable = readable; + } + + public AlgorithmIdentifier Algorithm + { + get { return this.algorithm; } + } + + public object CryptoObject + { + get { return this.cipher; } + } + + public CmsReadable GetReadable(KeyParameter sKey) + { + try + { + this.cipher = CipherUtilities.GetCipher(this.algorithm.ObjectID); + + Asn1Encodable asn1Enc = this.algorithm.Parameters; + Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object(); + + ICipherParameters cipherParameters = sKey; + + if (asn1Params != null && !(asn1Params is Asn1Null)) + { + cipherParameters = ParameterUtilities.GetCipherParameters( + this.algorithm.ObjectID, cipherParameters, asn1Params); + } + else + { + string alg = this.algorithm.ObjectID.Id; + if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc) + || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc) + || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc)) + { + cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]); + } + } + + cipher.Init(false, cipherParameters); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (IOException e) + { + throw new CmsException("error decoding algorithm parameters.", e); + } + + try + { + return new CmsProcessableInputStream( + new CipherStream(readable.GetInputStream(), cipher, null)); + } + catch (IOException e) + { + throw new CmsException("error reading content.", e); + } + } + } + } +} \ No newline at end of file diff --git a/crypto/src/cms/CMSException.cs b/crypto/src/cms/CMSException.cs new file mode 100644 index 000000000..5a6e33502 --- /dev/null +++ b/crypto/src/cms/CMSException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Cms +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CmsException + : Exception + { + public CmsException() + { + } + + public CmsException( + string msg) + : base(msg) + { + } + + public CmsException( + string msg, + Exception e) + : base(msg, e) + { + } + } +} diff --git a/crypto/src/cms/CMSPBEKey.cs b/crypto/src/cms/CMSPBEKey.cs new file mode 100644 index 000000000..cb1e54c36 --- /dev/null +++ b/crypto/src/cms/CMSPBEKey.cs @@ -0,0 +1,109 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +//import javax.crypto.interfaces.PBEKey; + +namespace Org.BouncyCastle.Cms +{ + public abstract class CmsPbeKey + // TODO Create an equivalent interface somewhere? + // : PBEKey + : ICipherParameters + { + internal readonly char[] password; + internal readonly byte[] salt; + internal readonly int iterationCount; + + [Obsolete("Use version taking 'char[]' instead")] + public CmsPbeKey( + string password, + byte[] salt, + int iterationCount) + : this(password.ToCharArray(), salt, iterationCount) + { + } + + [Obsolete("Use version taking 'char[]' instead")] + public CmsPbeKey( + string password, + AlgorithmIdentifier keyDerivationAlgorithm) + : this(password.ToCharArray(), keyDerivationAlgorithm) + { + } + + public CmsPbeKey( + char[] password, + byte[] salt, + int iterationCount) + { + this.password = (char[])password.Clone(); + this.salt = Arrays.Clone(salt); + this.iterationCount = iterationCount; + } + + public CmsPbeKey( + char[] password, + AlgorithmIdentifier keyDerivationAlgorithm) + { + if (!keyDerivationAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdPbkdf2)) + throw new ArgumentException("Unsupported key derivation algorithm: " + + keyDerivationAlgorithm.ObjectID); + + Pbkdf2Params kdfParams = Pbkdf2Params.GetInstance( + keyDerivationAlgorithm.Parameters.ToAsn1Object()); + + this.password = (char[])password.Clone(); + this.salt = kdfParams.GetSalt(); + this.iterationCount = kdfParams.IterationCount.IntValue; + } + + ~CmsPbeKey() + { + Array.Clear(this.password, 0, this.password.Length); + } + + [Obsolete("Will be removed")] + public string Password + { + get { return new string(password); } + } + + public byte[] Salt + { + get { return Arrays.Clone(salt); } + } + + [Obsolete("Use 'Salt' property instead")] + public byte[] GetSalt() + { + return Salt; + } + + public int IterationCount + { + get { return iterationCount; } + } + + public string Algorithm + { + get { return "PKCS5S2"; } + } + + public string Format + { + get { return "RAW"; } + } + + public byte[] GetEncoded() + { + return null; + } + + internal abstract KeyParameter GetEncoded(string algorithmOid); + } +} diff --git a/crypto/src/cms/CMSProcessable.cs b/crypto/src/cms/CMSProcessable.cs new file mode 100644 index 000000000..41018d12b --- /dev/null +++ b/crypto/src/cms/CMSProcessable.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Cms +{ + public interface CmsProcessable + { + /// + /// Generic routine to copy out the data we want processed. + /// + /// + /// This routine may be called multiple times. + /// + void Write(Stream outStream); + + [Obsolete] + object GetContent(); + } +} diff --git a/crypto/src/cms/CMSProcessableByteArray.cs b/crypto/src/cms/CMSProcessableByteArray.cs new file mode 100644 index 000000000..4bee4f8bd --- /dev/null +++ b/crypto/src/cms/CMSProcessableByteArray.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Cms +{ + /** + * a holding class for a byte array of data to be processed. + */ + public class CmsProcessableByteArray + : CmsProcessable, CmsReadable + { + private readonly byte[] bytes; + + public CmsProcessableByteArray( + byte[] bytes) + { + this.bytes = bytes; + } + + public Stream GetInputStream() + { + return new MemoryStream(bytes, false); + } + + public virtual void Write(Stream zOut) + { + zOut.Write(bytes, 0, bytes.Length); + } + + /// A clone of the byte array + public virtual object GetContent() + { + return bytes.Clone(); + } + } +} diff --git a/crypto/src/cms/CMSProcessableFile.cs b/crypto/src/cms/CMSProcessableFile.cs new file mode 100644 index 000000000..cbc74f44b --- /dev/null +++ b/crypto/src/cms/CMSProcessableFile.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + /** + * a holding class for a file of data to be processed. + */ + public class CmsProcessableFile + : CmsProcessable, CmsReadable + { + private const int DefaultBufSize = 32 * 1024; + + private readonly FileInfo _file; + private readonly int _bufSize; + + public CmsProcessableFile( + FileInfo file) + : this(file, DefaultBufSize) + { + } + + public CmsProcessableFile( + FileInfo file, + int bufSize) + { + _file = file; + _bufSize = bufSize; + } + + public virtual Stream GetInputStream() + { + return new FileStream( + _file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, _bufSize); + } + + public virtual void Write( + Stream zOut) + { + Stream inStr = GetInputStream(); + Streams.PipeAll(inStr, zOut); + inStr.Close(); + } + + /// The file handle + [Obsolete] + public virtual object GetContent() + { + return _file; + } + } +} diff --git a/crypto/src/cms/CMSProcessableInputStream.cs b/crypto/src/cms/CMSProcessableInputStream.cs new file mode 100644 index 000000000..7fdd1dfef --- /dev/null +++ b/crypto/src/cms/CMSProcessableInputStream.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + public class CmsProcessableInputStream + : CmsProcessable, CmsReadable + { + private Stream input; + private bool used = false; + + public CmsProcessableInputStream( + Stream input) + { + this.input = input; + } + + public Stream GetInputStream() + { + CheckSingleUsage(); + + return input; + } + + public void Write(Stream output) + { + CheckSingleUsage(); + + Streams.PipeAll(input, output); + input.Close(); + } + + [Obsolete] + public object GetContent() + { + return GetInputStream(); + } + + private void CheckSingleUsage() + { + lock (this) + { + if (used) + throw new InvalidOperationException("CmsProcessableInputStream can only be used once"); + + used = true; + } + } + } +} diff --git a/crypto/src/cms/CMSReadable.cs b/crypto/src/cms/CMSReadable.cs new file mode 100644 index 000000000..9507b920c --- /dev/null +++ b/crypto/src/cms/CMSReadable.cs @@ -0,0 +1,10 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Cms +{ + internal interface CmsReadable + { + Stream GetInputStream(); + } +} diff --git a/crypto/src/cms/CMSSecureReadable.cs b/crypto/src/cms/CMSSecureReadable.cs new file mode 100644 index 000000000..5ceac24fd --- /dev/null +++ b/crypto/src/cms/CMSSecureReadable.cs @@ -0,0 +1,14 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Cms +{ + internal interface CmsSecureReadable + { + AlgorithmIdentifier Algorithm { get; } + object CryptoObject { get; } + CmsReadable GetReadable(KeyParameter key); + } +} diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs new file mode 100644 index 000000000..81c87a426 --- /dev/null +++ b/crypto/src/cms/CMSSignedData.cs @@ -0,0 +1,425 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + /** + * general class for handling a pkcs7-signature message. + * + * A simple example of usage - note, in the example below the validity of + * the certificate isn't verified, just the fact that one of the certs + * matches the given signer... + * + *
+	*  IX509Store              certs = s.GetCertificates();
+	*  SignerInformationStore  signers = s.GetSignerInfos();
+	*
+	*  foreach (SignerInformation signer in signers.GetSigners())
+	*  {
+	*      ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+	*      X509Certificate cert = (X509Certificate) certList[0];
+	*
+	*      if (signer.Verify(cert.GetPublicKey()))
+	*      {
+	*          verified++;
+	*      }
+	*  }
+	* 
+ */ + public class CmsSignedData + { + private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance; + + private readonly CmsProcessable signedContent; + private SignedData signedData; + private ContentInfo contentInfo; + private SignerInformationStore signerInfoStore; + private IX509Store attrCertStore; + private IX509Store certificateStore; + private IX509Store crlStore; + private IDictionary hashes; + + private CmsSignedData( + CmsSignedData c) + { + this.signedData = c.signedData; + this.contentInfo = c.contentInfo; + this.signedContent = c.signedContent; + this.signerInfoStore = c.signerInfoStore; + } + + public CmsSignedData( + byte[] sigBlock) + : this(CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false))) + { + } + + public CmsSignedData( + CmsProcessable signedContent, + byte[] sigBlock) + : this(signedContent, CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false))) + { + } + + /** + * Content with detached signature, digests precomputed + * + * @param hashes a map of precomputed digests for content indexed by name of hash. + * @param sigBlock the signature object. + */ + public CmsSignedData( + IDictionary hashes, + byte[] sigBlock) + : this(hashes, CmsUtilities.ReadContentInfo(sigBlock)) + { + } + + /** + * base constructor - content with detached signature. + * + * @param signedContent the content that was signed. + * @param sigData the signature object. + */ + public CmsSignedData( + CmsProcessable signedContent, + Stream sigData) + : this(signedContent, CmsUtilities.ReadContentInfo(sigData)) + { + } + + /** + * base constructor - with encapsulated content + */ + public CmsSignedData( + Stream sigData) + : this(CmsUtilities.ReadContentInfo(sigData)) + { + } + + public CmsSignedData( + CmsProcessable signedContent, + ContentInfo sigData) + { + this.signedContent = signedContent; + this.contentInfo = sigData; + this.signedData = SignedData.GetInstance(contentInfo.Content); + } + + public CmsSignedData( + IDictionary hashes, + ContentInfo sigData) + { + this.hashes = hashes; + this.contentInfo = sigData; + this.signedData = SignedData.GetInstance(contentInfo.Content); + } + + public CmsSignedData( + ContentInfo sigData) + { + this.contentInfo = sigData; + this.signedData = SignedData.GetInstance(contentInfo.Content); + + // + // this can happen if the signed message is sent simply to send a + // certificate chain. + // + if (signedData.EncapContentInfo.Content != null) + { + this.signedContent = new CmsProcessableByteArray( + ((Asn1OctetString)(signedData.EncapContentInfo.Content)).GetOctets()); + } +// else +// { +// this.signedContent = null; +// } + } + + /// Return the version number for this object. + public int Version + { + get { return signedData.Version.Value.IntValue; } + } + + /** + * return the collection of signers that are associated with the + * signatures for the message. + */ + public SignerInformationStore GetSignerInfos() + { + if (signerInfoStore == null) + { + IList signerInfos = Platform.CreateArrayList(); + Asn1Set s = signedData.SignerInfos; + + foreach (object obj in s) + { + SignerInfo info = SignerInfo.GetInstance(obj); + DerObjectIdentifier contentType = signedData.EncapContentInfo.ContentType; + + if (hashes == null) + { + signerInfos.Add(new SignerInformation(info, contentType, signedContent, null)); + } + else + { + byte[] hash = (byte[]) hashes[info.DigestAlgorithm.ObjectID.Id]; + + signerInfos.Add(new SignerInformation(info, contentType, null, new BaseDigestCalculator(hash))); + } + } + + signerInfoStore = new SignerInformationStore(signerInfos); + } + + return signerInfoStore; + } + + /** + * return a X509Store containing the attribute certificates, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of attribute certificates + * @exception NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetAttributeCertificates( + string type) + { + if (attrCertStore == null) + { + attrCertStore = Helper.CreateAttributeStore(type, signedData.Certificates); + } + + return attrCertStore; + } + + /** + * return a X509Store containing the public key certificates, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of public key certificates + * @exception NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetCertificates( + string type) + { + if (certificateStore == null) + { + certificateStore = Helper.CreateCertificateStore(type, signedData.Certificates); + } + + return certificateStore; + } + + /** + * return a X509Store containing CRLs, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of CRLs + * @exception NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetCrls( + string type) + { + if (crlStore == null) + { + crlStore = Helper.CreateCrlStore(type, signedData.CRLs); + } + + return crlStore; + } + + [Obsolete("Use 'SignedContentType' property instead.")] + public string SignedContentTypeOid + { + get { return signedData.EncapContentInfo.ContentType.Id; } + } + + /// + /// Return the DerObjectIdentifier associated with the encapsulated + /// content info structure carried in the signed data. + /// + public DerObjectIdentifier SignedContentType + { + get { return signedData.EncapContentInfo.ContentType; } + } + + public CmsProcessable SignedContent + { + get { return signedContent; } + } + + /** + * return the ContentInfo + */ + public ContentInfo ContentInfo + { + get { return contentInfo; } + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return contentInfo.GetEncoded(); + } + + /** + * Replace the signerinformation store associated with this + * CmsSignedData object with the new one passed in. You would + * probably only want to do this if you wanted to change the unsigned + * attributes associated with a signer, or perhaps delete one. + * + * @param signedData the signed data object to be used as a base. + * @param signerInformationStore the new signer information store to use. + * @return a new signed data object. + */ + public static CmsSignedData ReplaceSigners( + CmsSignedData signedData, + SignerInformationStore signerInformationStore) + { + // + // copy + // + CmsSignedData cms = new CmsSignedData(signedData); + + // + // replace the store + // + cms.signerInfoStore = signerInformationStore; + + // + // replace the signers in the SignedData object + // + Asn1EncodableVector digestAlgs = new Asn1EncodableVector(); + Asn1EncodableVector vec = new Asn1EncodableVector(); + + foreach (SignerInformation signer in signerInformationStore.GetSigners()) + { + digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID)); + vec.Add(signer.ToSignerInfo()); + } + + Asn1Set digests = new DerSet(digestAlgs); + Asn1Set signers = new DerSet(vec); + Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object(); + + // + // signers are the last item in the sequence. + // + vec = new Asn1EncodableVector( + sD[0], // version + digests); + + for (int i = 2; i != sD.Count - 1; i++) + { + vec.Add(sD[i]); + } + + vec.Add(signers); + + cms.signedData = SignedData.GetInstance(new BerSequence(vec)); + + // + // replace the contentInfo with the new one + // + cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData); + + return cms; + } + + /** + * Replace the certificate and CRL information associated with this + * CmsSignedData object with the new one passed in. + * + * @param signedData the signed data object to be used as a base. + * @param x509Certs the new certificates to be used. + * @param x509Crls the new CRLs to be used. + * @return a new signed data object. + * @exception CmsException if there is an error processing the stores + */ + public static CmsSignedData ReplaceCertificatesAndCrls( + CmsSignedData signedData, + IX509Store x509Certs, + IX509Store x509Crls, + IX509Store x509AttrCerts) + { + if (x509AttrCerts != null) + throw Platform.CreateNotImplementedException("Currently can't replace attribute certificates"); + + // + // copy + // + CmsSignedData cms = new CmsSignedData(signedData); + + // + // replace the certs and crls in the SignedData object + // + Asn1Set certs = null; + try + { + Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList( + CmsUtilities.GetCertificatesFromStore(x509Certs)); + + if (asn1Set.Count != 0) + { + certs = asn1Set; + } + } + catch (X509StoreException e) + { + throw new CmsException("error getting certificates from store", e); + } + + Asn1Set crls = null; + try + { + Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList( + CmsUtilities.GetCrlsFromStore(x509Crls)); + + if (asn1Set.Count != 0) + { + crls = asn1Set; + } + } + catch (X509StoreException e) + { + throw new CmsException("error getting CRLs from store", e); + } + + // + // replace the CMS structure. + // + SignedData old = signedData.signedData; + cms.signedData = new SignedData( + old.DigestAlgorithms, + old.EncapContentInfo, + certs, + crls, + old.SignerInfos); + + // + // replace the contentInfo with the new one + // + cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData); + + return cms; + } + } +} diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs new file mode 100644 index 000000000..f31105c41 --- /dev/null +++ b/crypto/src/cms/CMSSignedDataGenerator.cs @@ -0,0 +1,551 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * general class for generating a pkcs7-signature message. + *

+ * A simple example of usage. + * + *

+     *      IX509Store certs...
+     *      IX509Store crls...
+     *      CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+     *
+     *      gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
+     *      gen.AddCertificates(certs);
+     *      gen.AddCrls(crls);
+     *
+     *      CmsSignedData data = gen.Generate(content);
+     * 
+ *

+ */ + public class CmsSignedDataGenerator + : CmsSignedGenerator + { + private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance; + + private readonly IList signerInfs = Platform.CreateArrayList(); + + private class SignerInf + { + private readonly CmsSignedGenerator outer; + + private readonly AsymmetricKeyParameter key; + private readonly SignerIdentifier signerIdentifier; + private readonly string digestOID; + private readonly string encOID; + private readonly CmsAttributeTableGenerator sAttr; + private readonly CmsAttributeTableGenerator unsAttr; + private readonly Asn1.Cms.AttributeTable baseSignedTable; + + internal SignerInf( + CmsSignedGenerator outer, + AsymmetricKeyParameter key, + SignerIdentifier signerIdentifier, + string digestOID, + string encOID, + CmsAttributeTableGenerator sAttr, + CmsAttributeTableGenerator unsAttr, + Asn1.Cms.AttributeTable baseSignedTable) + { + this.outer = outer; + this.key = key; + this.signerIdentifier = signerIdentifier; + this.digestOID = digestOID; + this.encOID = encOID; + this.sAttr = sAttr; + this.unsAttr = unsAttr; + this.baseSignedTable = baseSignedTable; + } + + internal AlgorithmIdentifier DigestAlgorithmID + { + get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); } + } + + internal CmsAttributeTableGenerator SignedAttributes + { + get { return sAttr; } + } + + internal CmsAttributeTableGenerator UnsignedAttributes + { + get { return unsAttr; } + } + + internal SignerInfo ToSignerInfo( + DerObjectIdentifier contentType, + CmsProcessable content, + SecureRandom random) + { + AlgorithmIdentifier digAlgId = DigestAlgorithmID; + string digestName = Helper.GetDigestAlgName(digestOID); + IDigest dig = Helper.GetDigestInstance(digestName); + + string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID); + ISigner sig = Helper.GetSignatureInstance(signatureName); + + // TODO Optimise the case where more than one signer with same digest + if (content != null) + { + content.Write(new DigOutputStream(dig)); + } + + byte[] hash = DigestUtilities.DoFinal(dig); + outer._digests.Add(digestOID, hash.Clone()); + + sig.Init(true, new ParametersWithRandom(key, random)); +#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT + Stream sigStr = new SigOutputStream(sig); +#else + Stream sigStr = new BufferedStream(new SigOutputStream(sig)); +#endif + + Asn1Set signedAttr = null; + if (sAttr != null) + { + IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash); + +// Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters)); + Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters); + + if (contentType == null) //counter signature + { + if (signed != null && signed[CmsAttributes.ContentType] != null) + { + IDictionary tmpSigned = signed.ToDictionary(); + tmpSigned.Remove(CmsAttributes.ContentType); + signed = new Asn1.Cms.AttributeTable(tmpSigned); + } + } + + // TODO Validate proposed signed attributes + + signedAttr = outer.GetAttributeSet(signed); + + // sig must be composed from the DER encoding. + new DerOutputStream(sigStr).WriteObject(signedAttr); + } + else if (content != null) + { + // TODO Use raw signature of the hash value instead + content.Write(sigStr); + } + + sigStr.Close(); + byte[] sigBytes = sig.GenerateSignature(); + + Asn1Set unsignedAttr = null; + if (unsAttr != null) + { + IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash); + baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone(); + +// Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters)); + Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters); + + // TODO Validate proposed unsigned attributes + + unsignedAttr = outer.GetAttributeSet(unsigned); + } + + // TODO[RSAPSS] Need the ability to specify non-default parameters + Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName); + AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier( + new DerObjectIdentifier(encOID), sigX509Parameters); + + return new SignerInfo(signerIdentifier, digAlgId, + signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr); + } + } + + public CmsSignedDataGenerator() + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + public CmsSignedDataGenerator( + SecureRandom rand) + : base(rand) + { + } + + /** + * add a signer - no attributes other than the default ones will be + * provided here. + * + * @param key signing key to use + * @param cert certificate containing corresponding public key + * @param digestOID digest algorithm OID + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOID) + { + AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID); + } + + /** + * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be + * provided here. + * + * @param key signing key to use + * @param cert certificate containing corresponding public key + * @param encryptionOID digest encryption algorithm OID + * @param digestOID digest algorithm OID + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOID, + string digestOID) + { + doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID, + new DefaultSignedAttributeTableGenerator(), null, null); + } + + /** + * add a signer - no attributes other than the default ones will be + * provided here. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOID) + { + AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID); + } + + /** + * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be + * provided here. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string encryptionOID, + string digestOID) + { + doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID, + new DefaultSignedAttributeTableGenerator(), null, null); + } + + /** + * add a signer with extra signed/unsigned attributes. + * + * @param key signing key to use + * @param cert certificate containing corresponding public key + * @param digestOID digest algorithm OID + * @param signedAttr table of attributes to be included in signature + * @param unsignedAttr table of attributes to be included as unsigned + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOID, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID, + signedAttr, unsignedAttr); + } + + /** + * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes. + * + * @param key signing key to use + * @param cert certificate containing corresponding public key + * @param encryptionOID digest encryption algorithm OID + * @param digestOID digest algorithm OID + * @param signedAttr table of attributes to be included in signature + * @param unsignedAttr table of attributes to be included as unsigned + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOID, + string digestOID, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID, + new DefaultSignedAttributeTableGenerator(signedAttr), + new SimpleAttributeTableGenerator(unsignedAttr), + signedAttr); + } + + /** + * add a signer with extra signed/unsigned attributes. + * + * @param key signing key to use + * @param subjectKeyID subjectKeyID of corresponding public key + * @param digestOID digest algorithm OID + * @param signedAttr table of attributes to be included in signature + * @param unsignedAttr table of attributes to be included as unsigned + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOID, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID, + signedAttr, unsignedAttr); + } + + /** + * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes. + * + * @param key signing key to use + * @param subjectKeyID subjectKeyID of corresponding public key + * @param encryptionOID digest encryption algorithm OID + * @param digestOID digest algorithm OID + * @param signedAttr table of attributes to be included in signature + * @param unsignedAttr table of attributes to be included as unsigned + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string encryptionOID, + string digestOID, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID, + new DefaultSignedAttributeTableGenerator(signedAttr), + new SimpleAttributeTableGenerator(unsignedAttr), + signedAttr); + } + + /** + * add a signer with extra signed/unsigned attributes based on generators. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOID, + CmsAttributeTableGenerator signedAttrGen, + CmsAttributeTableGenerator unsignedAttrGen) + { + AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID, + signedAttrGen, unsignedAttrGen); + } + + /** + * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOID, + string digestOID, + CmsAttributeTableGenerator signedAttrGen, + CmsAttributeTableGenerator unsignedAttrGen) + { + doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID, signedAttrGen, + unsignedAttrGen, null); + } + + /** + * add a signer with extra signed/unsigned attributes based on generators. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOID, + CmsAttributeTableGenerator signedAttrGen, + CmsAttributeTableGenerator unsignedAttrGen) + { + AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID, + signedAttrGen, unsignedAttrGen); + } + + /** + * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators. + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string encryptionOID, + string digestOID, + CmsAttributeTableGenerator signedAttrGen, + CmsAttributeTableGenerator unsignedAttrGen) + { + doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID, + signedAttrGen, unsignedAttrGen, null); + } + + private void doAddSigner( + AsymmetricKeyParameter privateKey, + SignerIdentifier signerIdentifier, + string encryptionOID, + string digestOID, + CmsAttributeTableGenerator signedAttrGen, + CmsAttributeTableGenerator unsignedAttrGen, + Asn1.Cms.AttributeTable baseSignedTable) + { + signerInfs.Add(new SignerInf(this, privateKey, signerIdentifier, digestOID, encryptionOID, + signedAttrGen, unsignedAttrGen, baseSignedTable)); + } + + /** + * generate a signed object that for a CMS Signed Data object + */ + public CmsSignedData Generate( + CmsProcessable content) + { + return Generate(content, false); + } + + /** + * generate a signed object that for a CMS Signed Data + * object - if encapsulate is true a copy + * of the message will be included in the signature. The content type + * is set according to the OID represented by the string signedContentType. + */ + public CmsSignedData Generate( + string signedContentType, + // FIXME Avoid accessing more than once to support CmsProcessableInputStream + CmsProcessable content, + bool encapsulate) + { + Asn1EncodableVector digestAlgs = new Asn1EncodableVector(); + Asn1EncodableVector signerInfos = new Asn1EncodableVector(); + + _digests.Clear(); // clear the current preserved digest state + + // + // add the precalculated SignerInfo objects. + // + foreach (SignerInformation signer in _signers) + { + digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID)); + + // TODO Verify the content type and calculated digest match the precalculated SignerInfo + signerInfos.Add(signer.ToSignerInfo()); + } + + // + // add the SignerInfo objects + // + bool isCounterSignature = (signedContentType == null); + + DerObjectIdentifier contentTypeOid = isCounterSignature + ? null + : new DerObjectIdentifier(signedContentType); + + foreach (SignerInf signer in signerInfs) + { + try + { + digestAlgs.Add(signer.DigestAlgorithmID); + signerInfos.Add(signer.ToSignerInfo(contentTypeOid, content, rand)); + } + catch (IOException e) + { + throw new CmsException("encoding error.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key inappropriate for signature.", e); + } + catch (SignatureException e) + { + throw new CmsException("error creating signature.", e); + } + catch (CertificateEncodingException e) + { + throw new CmsException("error creating sid.", e); + } + } + + Asn1Set certificates = null; + + if (_certs.Count != 0) + { + certificates = CmsUtilities.CreateBerSetFromList(_certs); + } + + Asn1Set certrevlist = null; + + if (_crls.Count != 0) + { + certrevlist = CmsUtilities.CreateBerSetFromList(_crls); + } + + Asn1OctetString octs = null; + if (encapsulate) + { + MemoryStream bOut = new MemoryStream(); + if (content != null) + { + try + { + content.Write(bOut); + } + catch (IOException e) + { + throw new CmsException("encapsulation error.", e); + } + } + octs = new BerOctetString(bOut.ToArray()); + } + + ContentInfo encInfo = new ContentInfo(contentTypeOid, octs); + + SignedData sd = new SignedData( + new DerSet(digestAlgs), + encInfo, + certificates, + certrevlist, + new DerSet(signerInfos)); + + ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd); + + return new CmsSignedData(content, contentInfo); + } + + /** + * generate a signed object that for a CMS Signed Data + * object - if encapsulate is true a copy + * of the message will be included in the signature with the + * default content type "data". + */ + public CmsSignedData Generate( + CmsProcessable content, + bool encapsulate) + { + return this.Generate(Data, content, encapsulate); + } + + /** + * generate a set of one or more SignerInformation objects representing counter signatures on + * the passed in SignerInformation object. + * + * @param signer the signer to be countersigned + * @param sigProvider the provider to be used for counter signing. + * @return a store containing the signers. + */ + public SignerInformationStore GenerateCounterSigners( + SignerInformation signer) + { + return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos(); + } + } +} diff --git a/crypto/src/cms/CMSSignedDataParser.cs b/crypto/src/cms/CMSSignedDataParser.cs new file mode 100644 index 000000000..35a125196 --- /dev/null +++ b/crypto/src/cms/CMSSignedDataParser.cs @@ -0,0 +1,455 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + /** + * Parsing class for an CMS Signed Data object from an input stream. + *

+ * Note: that because we are in a streaming mode only one signer can be tried and it is important + * that the methods on the parser are called in the appropriate order. + *

+ *

+ * A simple example of usage for an encapsulated signature. + *

+ *

+ * Two notes: first, in the example below the validity of + * the certificate isn't verified, just the fact that one of the certs + * matches the given signer, and, second, because we are in a streaming + * mode the order of the operations is important. + *

+ *
+	*      CmsSignedDataParser     sp = new CmsSignedDataParser(encapSigData);
+	*
+	*      sp.GetSignedContent().Drain();
+	*
+	*      IX509Store              certs = sp.GetCertificates();
+	*      SignerInformationStore  signers = sp.GetSignerInfos();
+	*
+	*      foreach (SignerInformation signer in signers.GetSigners())
+	*      {
+	*          ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+	*          X509Certificate cert = (X509Certificate) certList[0];
+	*
+	*          Console.WriteLine("verify returns: " + signer.Verify(cert));
+	*      }
+	* 
+ * Note also: this class does not introduce buffering - if you are processing large files you should create + * the parser with: + *
+	*          CmsSignedDataParser     ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+	*  
+ * where bufSize is a suitably large buffer size. + */ + public class CmsSignedDataParser + : CmsContentInfoParser + { + private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance; + + private SignedDataParser _signedData; + private DerObjectIdentifier _signedContentType; + private CmsTypedStream _signedContent; + private IDictionary _digests; + private ISet _digestOids; + + private SignerInformationStore _signerInfoStore; + private Asn1Set _certSet, _crlSet; + private bool _isCertCrlParsed; + private IX509Store _attributeStore; + private IX509Store _certificateStore; + private IX509Store _crlStore; + + public CmsSignedDataParser( + byte[] sigBlock) + : this(new MemoryStream(sigBlock, false)) + { + } + + public CmsSignedDataParser( + CmsTypedStream signedContent, + byte[] sigBlock) + : this(signedContent, new MemoryStream(sigBlock, false)) + { + } + + /** + * base constructor - with encapsulated content + */ + public CmsSignedDataParser( + Stream sigData) + : this(null, sigData) + { + } + + /** + * base constructor + * + * @param signedContent the content that was signed. + * @param sigData the signature object. + */ + public CmsSignedDataParser( + CmsTypedStream signedContent, + Stream sigData) + : base(sigData) + { + try + { + this._signedContent = signedContent; + this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence)); + this._digests = Platform.CreateHashtable(); + this._digestOids = new HashSet(); + + Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms(); + IAsn1Convertible o; + + while ((o = digAlgs.ReadObject()) != null) + { + AlgorithmIdentifier id = AlgorithmIdentifier.GetInstance(o.ToAsn1Object()); + + try + { + string digestOid = id.ObjectID.Id; + string digestName = Helper.GetDigestAlgName(digestOid); + + if (!this._digests.Contains(digestName)) + { + this._digests[digestName] = Helper.GetDigestInstance(digestName); + this._digestOids.Add(digestOid); + } + } + catch (SecurityUtilityException) + { + // TODO Should do something other than ignore it + } + } + + // + // If the message is simply a certificate chain message GetContent() may return null. + // + ContentInfoParser cont = _signedData.GetEncapContentInfo(); + Asn1OctetStringParser octs = (Asn1OctetStringParser) + cont.GetContent(Asn1Tags.OctetString); + + if (octs != null) + { + CmsTypedStream ctStr = new CmsTypedStream( + cont.ContentType.Id, octs.GetOctetStream()); + + if (_signedContent == null) + { + this._signedContent = ctStr; + } + else + { + // + // content passed in, need to read past empty encapsulated content info object if present + // + ctStr.Drain(); + } + } + + _signedContentType = _signedContent == null + ? cont.ContentType + : new DerObjectIdentifier(_signedContent.ContentType); + } + catch (IOException e) + { + throw new CmsException("io exception: " + e.Message, e); + } + + if (_digests.Count < 1) + { + throw new CmsException("no digests could be created for message."); + } + } + + /** + * Return the version number for the SignedData object + * + * @return the version number + */ + public int Version + { + get { return _signedData.Version.Value.IntValue; } + } + + public ISet DigestOids + { + get { return new HashSet(_digestOids); } + } + + /** + * return the collection of signers that are associated with the + * signatures for the message. + * @throws CmsException + */ + public SignerInformationStore GetSignerInfos() + { + if (_signerInfoStore == null) + { + PopulateCertCrlSets(); + + IList signerInfos = Platform.CreateArrayList(); + IDictionary hashes = Platform.CreateHashtable(); + + foreach (object digestKey in _digests.Keys) + { + hashes[digestKey] = DigestUtilities.DoFinal( + (IDigest)_digests[digestKey]); + } + + try + { + Asn1SetParser s = _signedData.GetSignerInfos(); + IAsn1Convertible o; + + while ((o = s.ReadObject()) != null) + { + SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object()); + string digestName = Helper.GetDigestAlgName( + info.DigestAlgorithm.ObjectID.Id); + + byte[] hash = (byte[]) hashes[digestName]; + + signerInfos.Add(new SignerInformation(info, _signedContentType, null, new BaseDigestCalculator(hash))); + } + } + catch (IOException e) + { + throw new CmsException("io exception: " + e.Message, e); + } + + _signerInfoStore = new SignerInformationStore(signerInfos); + } + + return _signerInfoStore; + } + + /** + * return a X509Store containing the attribute certificates, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of attribute certificates + * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetAttributeCertificates( + string type) + { + if (_attributeStore == null) + { + PopulateCertCrlSets(); + + _attributeStore = Helper.CreateAttributeStore(type, _certSet); + } + + return _attributeStore; + } + + /** + * return a X509Store containing the public key certificates, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of public key certificates + * @exception NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetCertificates( + string type) + { + if (_certificateStore == null) + { + PopulateCertCrlSets(); + + _certificateStore = Helper.CreateCertificateStore(type, _certSet); + } + + return _certificateStore; + } + + /** + * return a X509Store containing CRLs, if any, contained + * in this message. + * + * @param type type of store to create + * @return a store of CRLs + * @exception NoSuchStoreException if the store type isn't available. + * @exception CmsException if a general exception prevents creation of the X509Store + */ + public IX509Store GetCrls( + string type) + { + if (_crlStore == null) + { + PopulateCertCrlSets(); + + _crlStore = Helper.CreateCrlStore(type, _crlSet); + } + + return _crlStore; + } + + private void PopulateCertCrlSets() + { + if (_isCertCrlParsed) + return; + + _isCertCrlParsed = true; + + try + { + // care! Streaming - Must process the GetCertificates() result before calling GetCrls() + _certSet = GetAsn1Set(_signedData.GetCertificates()); + _crlSet = GetAsn1Set(_signedData.GetCrls()); + } + catch (IOException e) + { + throw new CmsException("problem parsing cert/crl sets", e); + } + } + + /// + /// Return the DerObjectIdentifier associated with the encapsulated + /// content info structure carried in the signed data. + /// + public DerObjectIdentifier SignedContentType + { + get { return _signedContentType; } + } + + public CmsTypedStream GetSignedContent() + { + if (_signedContent == null) + { + return null; + } + + Stream digStream = _signedContent.ContentStream; + + foreach (IDigest digest in _digests.Values) + { + digStream = new DigestStream(digStream, digest, null); + } + + return new CmsTypedStream(_signedContent.ContentType, digStream); + } + + /** + * Replace the signerinformation store associated with the passed + * in message contained in the stream original with the new one passed in. + * You would probably only want to do this if you wanted to change the unsigned + * attributes associated with a signer, or perhaps delete one. + *

+ * The output stream is returned unclosed. + *

+ * @param original the signed data stream to be used as a base. + * @param signerInformationStore the new signer information store to use. + * @param out the stream to Write the new signed data object to. + * @return out. + */ + public static Stream ReplaceSigners( + Stream original, + SignerInformationStore signerInformationStore, + Stream outStr) + { + // NB: SecureRandom would be ignored since using existing signatures only + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + CmsSignedDataParser parser = new CmsSignedDataParser(original); + +// gen.AddDigests(parser.DigestOids); + gen.AddSigners(signerInformationStore); + + CmsTypedStream signedContent = parser.GetSignedContent(); + bool encapsulate = (signedContent != null); + Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate); + if (encapsulate) + { + Streams.PipeAll(signedContent.ContentStream, contentOut); + } + + gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection")); + gen.AddCertificates(parser.GetCertificates("Collection")); + gen.AddCrls(parser.GetCrls("Collection")); + +// gen.AddSigners(parser.GetSignerInfos()); + + contentOut.Close(); + + return outStr; + } + + /** + * Replace the certificate and CRL information associated with this + * CMSSignedData object with the new one passed in. + *

+ * The output stream is returned unclosed. + *

+ * @param original the signed data stream to be used as a base. + * @param certsAndCrls the new certificates and CRLs to be used. + * @param out the stream to Write the new signed data object to. + * @return out. + * @exception CmsException if there is an error processing the CertStore + */ + public static Stream ReplaceCertificatesAndCrls( + Stream original, + IX509Store x509Certs, + IX509Store x509Crls, + IX509Store x509AttrCerts, + Stream outStr) + { + // NB: SecureRandom would be ignored since using existing signatures only + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + CmsSignedDataParser parser = new CmsSignedDataParser(original); + + gen.AddDigests(parser.DigestOids); + + CmsTypedStream signedContent = parser.GetSignedContent(); + bool encapsulate = (signedContent != null); + Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate); + if (encapsulate) + { + Streams.PipeAll(signedContent.ContentStream, contentOut); + } + +// gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection")); +// gen.AddCertificates(parser.GetCertificates("Collection")); +// gen.AddCrls(parser.GetCrls("Collection")); + if (x509AttrCerts != null) + gen.AddAttributeCertificates(x509AttrCerts); + if (x509Certs != null) + gen.AddCertificates(x509Certs); + if (x509Crls != null) + gen.AddCrls(x509Crls); + + gen.AddSigners(parser.GetSignerInfos()); + + contentOut.Close(); + + return outStr; + } + + private static Asn1Set GetAsn1Set( + Asn1SetParser asn1SetParser) + { + return asn1SetParser == null + ? null + : Asn1Set.GetInstance(asn1SetParser.ToAsn1Object()); + } + } +} diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs new file mode 100644 index 000000000..743e9c6c1 --- /dev/null +++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs @@ -0,0 +1,913 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * General class for generating a pkcs7-signature message stream. + *

+ * A simple example of usage. + *

+ *
+    *      IX509Store                   certs...
+    *      CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+    *
+    *      gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
+    *
+    *      gen.AddCertificates(certs);
+    *
+    *      Stream sigOut = gen.Open(bOut);
+    *
+    *      sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
+    *
+    *      sigOut.Close();
+    * 
+ */ + public class CmsSignedDataStreamGenerator + : CmsSignedGenerator + { + private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance; + + private readonly IList _signerInfs = Platform.CreateArrayList(); + private readonly ISet _messageDigestOids = new HashSet(); + private readonly IDictionary _messageDigests = Platform.CreateHashtable(); + private readonly IDictionary _messageHashes = Platform.CreateHashtable(); + private bool _messageDigestsLocked; + private int _bufferSize; + + private class DigestAndSignerInfoGeneratorHolder + { + internal readonly SignerInfoGenerator signerInf; + internal readonly string digestOID; + + internal DigestAndSignerInfoGeneratorHolder(SignerInfoGenerator signerInf, String digestOID) + { + this.signerInf = signerInf; + this.digestOID = digestOID; + } + + internal AlgorithmIdentifier DigestAlgorithm + { + get { return new AlgorithmIdentifier(new DerObjectIdentifier(this.digestOID), DerNull.Instance); } + } + } + + private class SignerInfoGeneratorImpl : SignerInfoGenerator + { + private readonly CmsSignedDataStreamGenerator outer; + + private readonly SignerIdentifier _signerIdentifier; + private readonly string _digestOID; + private readonly string _encOID; + private readonly CmsAttributeTableGenerator _sAttr; + private readonly CmsAttributeTableGenerator _unsAttr; + private readonly string _encName; + private readonly ISigner _sig; + + internal SignerInfoGeneratorImpl( + CmsSignedDataStreamGenerator outer, + AsymmetricKeyParameter key, + SignerIdentifier signerIdentifier, + string digestOID, + string encOID, + CmsAttributeTableGenerator sAttr, + CmsAttributeTableGenerator unsAttr) + { + this.outer = outer; + + _signerIdentifier = signerIdentifier; + _digestOID = digestOID; + _encOID = encOID; + _sAttr = sAttr; + _unsAttr = unsAttr; + _encName = Helper.GetEncryptionAlgName(_encOID); + + string digestName = Helper.GetDigestAlgName(_digestOID); + string signatureName = digestName + "with" + _encName; + + if (_sAttr != null) + { + _sig = Helper.GetSignatureInstance(signatureName); + } + else + { + // Note: Need to use raw signatures here since we have already calculated the digest + if (_encName.Equals("RSA")) + { + _sig = Helper.GetSignatureInstance("RSA"); + } + else if (_encName.Equals("DSA")) + { + _sig = Helper.GetSignatureInstance("NONEwithDSA"); + } + // TODO Add support for raw PSS +// else if (_encName.equals("RSAandMGF1")) +// { +// _sig = CMSSignedHelper.INSTANCE.getSignatureInstance("NONEWITHRSAPSS", _sigProvider); +// try +// { +// // Init the params this way to avoid having a 'raw' version of each PSS algorithm +// Signature sig2 = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, _sigProvider); +// PSSParameterSpec spec = (PSSParameterSpec)sig2.getParameters().getParameterSpec(PSSParameterSpec.class); +// _sig.setParameter(spec); +// } +// catch (Exception e) +// { +// throw new SignatureException("algorithm: " + _encName + " could not be configured."); +// } +// } + else + { + throw new SignatureException("algorithm: " + _encName + " not supported in base signatures."); + } + } + + _sig.Init(true, new ParametersWithRandom(key, outer.rand)); + } + + public SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm, + byte[] calculatedDigest) + { + try + { + string digestName = Helper.GetDigestAlgName(_digestOID); + string signatureName = digestName + "with" + _encName; + +// AlgorithmIdentifier digAlgId = DigestAlgorithmID; +// +// byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)]; +// outer._digests[_digestOID] = hash.Clone(); + + byte[] bytesToSign = calculatedDigest; + + /* RFC 3852 5.4 + * The result of the message digest calculation process depends on + * whether the signedAttrs field is present. When the field is absent, + * the result is just the message digest of the content as described + * + * above. When the field is present, however, the result is the message + * digest of the complete DER encoding of the SignedAttrs value + * contained in the signedAttrs field. + */ + Asn1Set signedAttr = null; + if (_sAttr != null) + { + IDictionary parameters = outer.GetBaseParameters(contentType, digestAlgorithm, calculatedDigest); + +// Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(Collections.unmodifiableMap(parameters)); + Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(parameters); + + if (contentType == null) //counter signature + { + if (signed != null && signed[CmsAttributes.ContentType] != null) + { + IDictionary tmpSigned = signed.ToDictionary(); + tmpSigned.Remove(CmsAttributes.ContentType); + signed = new Asn1.Cms.AttributeTable(tmpSigned); + } + } + + signedAttr = outer.GetAttributeSet(signed); + + // sig must be composed from the DER encoding. + bytesToSign = signedAttr.GetEncoded(Asn1Encodable.Der); + } + else + { + // Note: Need to use raw signatures here since we have already calculated the digest + if (_encName.Equals("RSA")) + { + DigestInfo dInfo = new DigestInfo(digestAlgorithm, calculatedDigest); + bytesToSign = dInfo.GetEncoded(Asn1Encodable.Der); + } + } + + _sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length); + byte[] sigBytes = _sig.GenerateSignature(); + + Asn1Set unsignedAttr = null; + if (_unsAttr != null) + { + IDictionary parameters = outer.GetBaseParameters( + contentType, digestAlgorithm, calculatedDigest); + parameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone(); + +// Asn1.Cms.AttributeTable unsigned = _unsAttr.getAttributes(Collections.unmodifiableMap(parameters)); + Asn1.Cms.AttributeTable unsigned = _unsAttr.GetAttributes(parameters); + + unsignedAttr = outer.GetAttributeSet(unsigned); + } + + // TODO[RSAPSS] Need the ability to specify non-default parameters + Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName); + AlgorithmIdentifier digestEncryptionAlgorithm = CmsSignedGenerator.GetEncAlgorithmIdentifier( + new DerObjectIdentifier(_encOID), sigX509Parameters); + + return new SignerInfo(_signerIdentifier, digestAlgorithm, + signedAttr, digestEncryptionAlgorithm, new DerOctetString(sigBytes), unsignedAttr); + } + catch (IOException e) + { + throw new CmsStreamException("encoding error.", e); + } + catch (SignatureException e) + { + throw new CmsStreamException("error creating signature.", e); + } + } + } + + public CmsSignedDataStreamGenerator() + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + public CmsSignedDataStreamGenerator( + SecureRandom rand) + : base(rand) + { + } + + /** + * Set the underlying string size for encapsulated data + * + * @param bufferSize length of octet strings to buffer the data. + */ + public void SetBufferSize( + int bufferSize) + { + _bufferSize = bufferSize; + } + + public void AddDigests( + params string[] digestOids) + { + AddDigests((IEnumerable) digestOids); + } + + public void AddDigests( + IEnumerable digestOids) + { + foreach (string digestOid in digestOids) + { + ConfigureDigest(digestOid); + } + } + + /** + * add a signer - no attributes other than the default ones will be + * provided here. + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOid) + { + AddSigner(privateKey, cert, digestOid, + new DefaultSignedAttributeTableGenerator(), null); + } + + /** + * add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be + * provided here. + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOid, + string digestOid) + { + AddSigner(privateKey, cert, encryptionOid, digestOid, + new DefaultSignedAttributeTableGenerator(), + (CmsAttributeTableGenerator)null); + } + + /** + * add a signer with extra signed/unsigned attributes. + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOid, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + AddSigner(privateKey, cert, digestOid, + new DefaultSignedAttributeTableGenerator(signedAttr), + new SimpleAttributeTableGenerator(unsignedAttr)); + } + + /** + * add a signer with extra signed/unsigned attributes - specifying digest + * encryption algorithm. + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOid, + string digestOid, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + AddSigner(privateKey, cert, encryptionOid, digestOid, + new DefaultSignedAttributeTableGenerator(signedAttr), + new SimpleAttributeTableGenerator(unsignedAttr)); + } + + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string digestOid, + CmsAttributeTableGenerator signedAttrGenerator, + CmsAttributeTableGenerator unsignedAttrGenerator) + { + AddSigner(privateKey, cert, GetEncOid(privateKey, digestOid), digestOid, + signedAttrGenerator, unsignedAttrGenerator); + } + + public void AddSigner( + AsymmetricKeyParameter privateKey, + X509Certificate cert, + string encryptionOid, + string digestOid, + CmsAttributeTableGenerator signedAttrGenerator, + CmsAttributeTableGenerator unsignedAttrGenerator) + { + DoAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOid, digestOid, + signedAttrGenerator, unsignedAttrGenerator); + } + + /** + * add a signer - no attributes other than the default ones will be + * provided here. + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOid) + { + AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(), + (CmsAttributeTableGenerator)null); + } + + /** + * add a signer - no attributes other than the default ones will be + * provided here. + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string encryptionOid, + string digestOid) + { + AddSigner(privateKey, subjectKeyID, encryptionOid, digestOid, + new DefaultSignedAttributeTableGenerator(), + (CmsAttributeTableGenerator)null); + } + + /** + * add a signer with extra signed/unsigned attributes. + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOid, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + AddSigner(privateKey, subjectKeyID, digestOid, + new DefaultSignedAttributeTableGenerator(signedAttr), + new SimpleAttributeTableGenerator(unsignedAttr)); + } + + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string digestOid, + CmsAttributeTableGenerator signedAttrGenerator, + CmsAttributeTableGenerator unsignedAttrGenerator) + { + AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOid), + digestOid, signedAttrGenerator, unsignedAttrGenerator); + } + + public void AddSigner( + AsymmetricKeyParameter privateKey, + byte[] subjectKeyID, + string encryptionOid, + string digestOid, + CmsAttributeTableGenerator signedAttrGenerator, + CmsAttributeTableGenerator unsignedAttrGenerator) + { + DoAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOid, digestOid, + signedAttrGenerator, unsignedAttrGenerator); + } + + private void DoAddSigner( + AsymmetricKeyParameter privateKey, + SignerIdentifier signerIdentifier, + string encryptionOid, + string digestOid, + CmsAttributeTableGenerator signedAttrGenerator, + CmsAttributeTableGenerator unsignedAttrGenerator) + { + ConfigureDigest(digestOid); + + SignerInfoGeneratorImpl signerInf = new SignerInfoGeneratorImpl(this, privateKey, + signerIdentifier, digestOid, encryptionOid, signedAttrGenerator, unsignedAttrGenerator); + + _signerInfs.Add(new DigestAndSignerInfoGeneratorHolder(signerInf, digestOid)); + } + + internal override void AddSignerCallback( + SignerInformation si) + { + // FIXME If there were parameters in si.DigestAlgorithmID.Parameters, they are lost + // NB: Would need to call FixAlgID on the DigestAlgorithmID + + // For precalculated signers, just need to register the algorithm, not configure a digest + RegisterDigestOid(si.DigestAlgorithmID.ObjectID.Id); + } + + /** + * generate a signed object that for a CMS Signed Data object + */ + public Stream Open( + Stream outStream) + { + return Open(outStream, false); + } + + /** + * generate a signed object that for a CMS Signed Data + * object - if encapsulate is true a copy + * of the message will be included in the signature with the + * default content type "data". + */ + public Stream Open( + Stream outStream, + bool encapsulate) + { + return Open(outStream, Data, encapsulate); + } + + /** + * generate a signed object that for a CMS Signed Data + * object using the given provider - if encapsulate is true a copy + * of the message will be included in the signature with the + * default content type "data". If dataOutputStream is non null the data + * being signed will be written to the stream as it is processed. + * @param out stream the CMS object is to be written to. + * @param encapsulate true if data should be encapsulated. + * @param dataOutputStream output stream to copy the data being signed to. + */ + public Stream Open( + Stream outStream, + bool encapsulate, + Stream dataOutputStream) + { + return Open(outStream, Data, encapsulate, dataOutputStream); + } + + /** + * generate a signed object that for a CMS Signed Data + * object - if encapsulate is true a copy + * of the message will be included in the signature. The content type + * is set according to the OID represented by the string signedContentType. + */ + public Stream Open( + Stream outStream, + string signedContentType, + bool encapsulate) + { + return Open(outStream, signedContentType, encapsulate, null); + } + + /** + * generate a signed object that for a CMS Signed Data + * object using the given provider - if encapsulate is true a copy + * of the message will be included in the signature. The content type + * is set according to the OID represented by the string signedContentType. + * @param out stream the CMS object is to be written to. + * @param signedContentType OID for data to be signed. + * @param encapsulate true if data should be encapsulated. + * @param dataOutputStream output stream to copy the data being signed to. + */ + public Stream Open( + Stream outStream, + string signedContentType, + bool encapsulate, + Stream dataOutputStream) + { + if (outStream == null) + throw new ArgumentNullException("outStream"); + if (!outStream.CanWrite) + throw new ArgumentException("Expected writeable stream", "outStream"); + if (dataOutputStream != null && !dataOutputStream.CanWrite) + throw new ArgumentException("Expected writeable stream", "dataOutputStream"); + + _messageDigestsLocked = true; + + // + // ContentInfo + // + BerSequenceGenerator sGen = new BerSequenceGenerator(outStream); + + sGen.AddObject(CmsObjectIdentifiers.SignedData); + + // + // Signed Data + // + BerSequenceGenerator sigGen = new BerSequenceGenerator( + sGen.GetRawOutputStream(), 0, true); + + bool isCounterSignature = (signedContentType == null); + + DerObjectIdentifier contentTypeOid = isCounterSignature + ? null + : new DerObjectIdentifier(signedContentType); + + sigGen.AddObject(CalculateVersion(contentTypeOid)); + + Asn1EncodableVector digestAlgs = new Asn1EncodableVector(); + + foreach (string digestOid in _messageDigestOids) + { + digestAlgs.Add( + new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance)); + } + + { + byte[] tmp = new DerSet(digestAlgs).GetEncoded(); + sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length); + } + + BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream()); + eiGen.AddObject(contentTypeOid); + + // If encapsulating, add the data as an octet string in the sequence + Stream encapStream = encapsulate + ? CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize) + : null; + + // Also send the data to 'dataOutputStream' if necessary + Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream); + + // Let all the digests see the data as it is written + Stream digStream = AttachDigestsToOutputStream(_messageDigests.Values, teeStream); + + return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen); + } + + private void RegisterDigestOid( + string digestOid) + { + if (_messageDigestsLocked) + { + if (!_messageDigestOids.Contains(digestOid)) + throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened"); + } + else + { + _messageDigestOids.Add(digestOid); + } + } + + private void ConfigureDigest( + string digestOid) + { + RegisterDigestOid(digestOid); + + string digestName = Helper.GetDigestAlgName(digestOid); + IDigest dig = (IDigest)_messageDigests[digestName]; + if (dig == null) + { + if (_messageDigestsLocked) + throw new InvalidOperationException("Cannot configure new digests after the data stream is opened"); + + dig = Helper.GetDigestInstance(digestName); + _messageDigests[digestName] = dig; + } + } + + // TODO Make public? + internal void Generate( + Stream outStream, + string eContentType, + bool encapsulate, + Stream dataOutputStream, + CmsProcessable content) + { + Stream signedOut = Open(outStream, eContentType, encapsulate, dataOutputStream); + if (content != null) + { + content.Write(signedOut); + } + signedOut.Close(); + } + + // RFC3852, section 5.1: + // IF ((certificates is present) AND + // (any certificates with a type of other are present)) OR + // ((crls is present) AND + // (any crls with a type of other are present)) + // THEN version MUST be 5 + // ELSE + // IF (certificates is present) AND + // (any version 2 attribute certificates are present) + // THEN version MUST be 4 + // ELSE + // IF ((certificates is present) AND + // (any version 1 attribute certificates are present)) OR + // (any SignerInfo structures are version 3) OR + // (encapContentInfo eContentType is other than id-data) + // THEN version MUST be 3 + // ELSE version MUST be 1 + // + private DerInteger CalculateVersion( + DerObjectIdentifier contentOid) + { + bool otherCert = false; + bool otherCrl = false; + bool attrCertV1Found = false; + bool attrCertV2Found = false; + + if (_certs != null) + { + foreach (object obj in _certs) + { + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tagged = (Asn1TaggedObject) obj; + + if (tagged.TagNo == 1) + { + attrCertV1Found = true; + } + else if (tagged.TagNo == 2) + { + attrCertV2Found = true; + } + else if (tagged.TagNo == 3) + { + otherCert = true; + break; + } + } + } + } + + if (otherCert) + { + return new DerInteger(5); + } + + if (_crls != null) + { + foreach (object obj in _crls) + { + if (obj is Asn1TaggedObject) + { + otherCrl = true; + break; + } + } + } + + if (otherCrl) + { + return new DerInteger(5); + } + + if (attrCertV2Found) + { + return new DerInteger(4); + } + + if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(_signers)) + { + return new DerInteger(3); + } + + return new DerInteger(1); + } + + private bool CheckForVersion3( + IList signerInfos) + { + foreach (SignerInformation si in signerInfos) + { + SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo()); + + if (s.Version.Value.IntValue == 3) + { + return true; + } + } + + return false; + } + + private static Stream AttachDigestsToOutputStream(ICollection digests, Stream s) + { + Stream result = s; + foreach (IDigest digest in digests) + { + result = GetSafeTeeOutputStream(result, new DigOutputStream(digest)); + } + return result; + } + + private static Stream GetSafeOutputStream(Stream s) + { + if (s == null) + return new NullOutputStream(); + return s; + } + + private static Stream GetSafeTeeOutputStream(Stream s1, Stream s2) + { + if (s1 == null) + return GetSafeOutputStream(s2); + if (s2 == null) + return GetSafeOutputStream(s1); + return new TeeOutputStream(s1, s2); + } + + private class CmsSignedDataOutputStream + : BaseOutputStream + { + private readonly CmsSignedDataStreamGenerator outer; + + private Stream _out; + private DerObjectIdentifier _contentOID; + private BerSequenceGenerator _sGen; + private BerSequenceGenerator _sigGen; + private BerSequenceGenerator _eiGen; + + public CmsSignedDataOutputStream( + CmsSignedDataStreamGenerator outer, + Stream outStream, + string contentOID, + BerSequenceGenerator sGen, + BerSequenceGenerator sigGen, + BerSequenceGenerator eiGen) + { + this.outer = outer; + + _out = outStream; + _contentOID = new DerObjectIdentifier(contentOID); + _sGen = sGen; + _sigGen = sigGen; + _eiGen = eiGen; + } + + public override void WriteByte( + byte b) + { + _out.WriteByte(b); + } + + public override void Write( + byte[] bytes, + int off, + int len) + { + _out.Write(bytes, off, len); + } + + public override void Close() + { + _out.Close(); + + // TODO Parent context(s) should really be be closed explicitly + + _eiGen.Close(); + + outer._digests.Clear(); // clear the current preserved digest state + + if (outer._certs.Count > 0) + { + Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs); + + WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs)); + } + + if (outer._crls.Count > 0) + { + Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls); + + WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls)); + } + + // + // Calculate the digest hashes + // + foreach (DictionaryEntry de in outer._messageDigests) + { + outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value)); + } + + // TODO If the digest OIDs for precalculated signers weren't mixed in with + // the others, we could fill in outer._digests here, instead of SignerInfoGenerator.Generate + + // + // collect all the SignerInfo objects + // + Asn1EncodableVector signerInfos = new Asn1EncodableVector(); + + // + // add the generated SignerInfo objects + // + { + foreach (DigestAndSignerInfoGeneratorHolder holder in outer._signerInfs) + { + AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm; + + byte[] calculatedDigest = (byte[])outer._messageHashes[ + Helper.GetDigestAlgName(holder.digestOID)]; + outer._digests[holder.digestOID] = calculatedDigest.Clone(); + + signerInfos.Add(holder.signerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest)); + } + } + + // + // add the precalculated SignerInfo objects. + // + { + foreach (SignerInformation signer in outer._signers) + { + // TODO Verify the content type and calculated digest match the precalculated SignerInfo +// if (!signer.ContentType.Equals(_contentOID)) +// { +// // TODO The precalculated content type did not match - error? +// } +// +// byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid]; +// if (calculatedDigest == null) +// { +// // TODO We can't confirm this digest because we didn't calculate it - error? +// } +// else +// { +// if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest)) +// { +// // TODO The precalculated digest did not match - error? +// } +// } + + signerInfos.Add(signer.ToSignerInfo()); + } + } + + WriteToGenerator(_sigGen, new DerSet(signerInfos)); + + _sigGen.Close(); + _sGen.Close(); + base.Close(); + } + + private static void WriteToGenerator( + Asn1Generator ag, + Asn1Encodable ae) + { + byte[] encoded = ae.GetEncoded(); + ag.GetRawOutputStream().Write(encoded, 0, encoded.Length); + } + } + } +} diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs new file mode 100644 index 000000000..f272c830e --- /dev/null +++ b/crypto/src/cms/CMSSignedGenerator.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + public class CmsSignedGenerator + { + /** + * Default type for the signed data. + */ + public static readonly string Data = CmsObjectIdentifiers.Data.Id; + + public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.Id; + public static readonly string DigestSha224 = NistObjectIdentifiers.IdSha224.Id; + public static readonly string DigestSha256 = NistObjectIdentifiers.IdSha256.Id; + public static readonly string DigestSha384 = NistObjectIdentifiers.IdSha384.Id; + public static readonly string DigestSha512 = NistObjectIdentifiers.IdSha512.Id; + public static readonly string DigestMD5 = PkcsObjectIdentifiers.MD5.Id; + public static readonly string DigestGost3411 = CryptoProObjectIdentifiers.GostR3411.Id; + public static readonly string DigestRipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id; + public static readonly string DigestRipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id; + public static readonly string DigestRipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id; + + public static readonly string EncryptionRsa = PkcsObjectIdentifiers.RsaEncryption.Id; + public static readonly string EncryptionDsa = X9ObjectIdentifiers.IdDsaWithSha1.Id; + public static readonly string EncryptionECDsa = X9ObjectIdentifiers.ECDsaWithSha1.Id; + public static readonly string EncryptionRsaPss = PkcsObjectIdentifiers.IdRsassaPss.Id; + public static readonly string EncryptionGost3410 = CryptoProObjectIdentifiers.GostR3410x94.Id; + public static readonly string EncryptionECGost3410 = CryptoProObjectIdentifiers.GostR3410x2001.Id; + + private static readonly string EncryptionECDsaWithSha1 = X9ObjectIdentifiers.ECDsaWithSha1.Id; + private static readonly string EncryptionECDsaWithSha224 = X9ObjectIdentifiers.ECDsaWithSha224.Id; + private static readonly string EncryptionECDsaWithSha256 = X9ObjectIdentifiers.ECDsaWithSha256.Id; + private static readonly string EncryptionECDsaWithSha384 = X9ObjectIdentifiers.ECDsaWithSha384.Id; + private static readonly string EncryptionECDsaWithSha512 = X9ObjectIdentifiers.ECDsaWithSha512.Id; + + private static readonly ISet noParams = new HashSet(); + private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable(); + + static CmsSignedGenerator() + { + noParams.Add(EncryptionDsa); +// noParams.Add(EncryptionECDsa); + noParams.Add(EncryptionECDsaWithSha1); + noParams.Add(EncryptionECDsaWithSha224); + noParams.Add(EncryptionECDsaWithSha256); + noParams.Add(EncryptionECDsaWithSha384); + noParams.Add(EncryptionECDsaWithSha512); + + ecAlgorithms.Add(DigestSha1, EncryptionECDsaWithSha1); + ecAlgorithms.Add(DigestSha224, EncryptionECDsaWithSha224); + ecAlgorithms.Add(DigestSha256, EncryptionECDsaWithSha256); + ecAlgorithms.Add(DigestSha384, EncryptionECDsaWithSha384); + ecAlgorithms.Add(DigestSha512, EncryptionECDsaWithSha512); + } + + internal IList _certs = Platform.CreateArrayList(); + internal IList _crls = Platform.CreateArrayList(); + internal IList _signers = Platform.CreateArrayList(); + internal IDictionary _digests = Platform.CreateHashtable(); + + protected readonly SecureRandom rand; + + protected CmsSignedGenerator() + : this(new SecureRandom()) + { + } + + /// Constructor allowing specific source of randomness + /// Instance of SecureRandom to use. + protected CmsSignedGenerator( + SecureRandom rand) + { + this.rand = rand; + } + + protected string GetEncOid( + AsymmetricKeyParameter key, + string digestOID) + { + string encOID = null; + + if (key is RsaKeyParameters) + { + if (!((RsaKeyParameters) key).IsPrivate) + throw new ArgumentException("Expected RSA private key"); + + encOID = EncryptionRsa; + } + else if (key is DsaPrivateKeyParameters) + { + if (!digestOID.Equals(DigestSha1)) + throw new ArgumentException("can't mix DSA with anything but SHA1"); + + encOID = EncryptionDsa; + } + else if (key is ECPrivateKeyParameters) + { + ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) key; + string algName = ecPrivKey.AlgorithmName; + + if (algName == "ECGOST3410") + { + encOID = EncryptionECGost3410; + } + else + { + // TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does? + encOID = (string) ecAlgorithms[digestOID]; + + if (encOID == null) + throw new ArgumentException("can't mix ECDSA with anything but SHA family digests"); + } + } + else if (key is Gost3410PrivateKeyParameters) + { + encOID = EncryptionGost3410; + } + else + { + throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid"); + } + + return encOID; + } + + internal static AlgorithmIdentifier GetEncAlgorithmIdentifier( + DerObjectIdentifier encOid, + Asn1Encodable sigX509Parameters) + { + if (noParams.Contains(encOid.Id)) + { + return new AlgorithmIdentifier(encOid); + } + + return new AlgorithmIdentifier(encOid, sigX509Parameters); + } + + internal protected virtual IDictionary GetBaseParameters( + DerObjectIdentifier contentType, + AlgorithmIdentifier digAlgId, + byte[] hash) + { + IDictionary param = Platform.CreateHashtable(); + + if (contentType != null) + { + param[CmsAttributeTableParameter.ContentType] = contentType; + } + + param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId; + param[CmsAttributeTableParameter.Digest] = hash.Clone(); + + return param; + } + + internal protected virtual Asn1Set GetAttributeSet( + Asn1.Cms.AttributeTable attr) + { + return attr == null + ? null + : new DerSet(attr.ToAsn1EncodableVector()); + } + + public void AddCertificates( + IX509Store certStore) + { + CollectionUtilities.AddRange(_certs, CmsUtilities.GetCertificatesFromStore(certStore)); + } + + public void AddCrls( + IX509Store crlStore) + { + CollectionUtilities.AddRange(_crls, CmsUtilities.GetCrlsFromStore(crlStore)); + } + + /** + * Add the attribute certificates contained in the passed in store to the + * generator. + * + * @param store a store of Version 2 attribute certificates + * @throws CmsException if an error occurse processing the store. + */ + public void AddAttributeCertificates( + IX509Store store) + { + try + { + foreach (IX509AttributeCertificate attrCert in store.GetMatches(null)) + { + _certs.Add(new DerTaggedObject(false, 2, + AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded())))); + } + } + catch (Exception e) + { + throw new CmsException("error processing attribute certs", e); + } + } + + /** + * Add a store of precalculated signers to the generator. + * + * @param signerStore store of signers + */ + public void AddSigners( + SignerInformationStore signerStore) + { + foreach (SignerInformation o in signerStore.GetSigners()) + { + _signers.Add(o); + AddSignerCallback(o); + } + } + + /** + * Return a map of oids and byte arrays representing the digests calculated on the content during + * the last generate. + * + * @return a map of oids (as String objects) and byte[] representing digests. + */ + public IDictionary GetGeneratedDigests() + { + return Platform.CreateHashtable(_digests); + } + + internal virtual void AddSignerCallback( + SignerInformation si) + { + } + + internal static SignerIdentifier GetSignerIdentifier(X509Certificate cert) + { + return new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert)); + } + + internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier) + { + return new SignerIdentifier(new DerOctetString(subjectKeyIdentifier)); + } + } +} diff --git a/crypto/src/cms/CMSSignedHelper.cs b/crypto/src/cms/CMSSignedHelper.cs new file mode 100644 index 000000000..b3406fc06 --- /dev/null +++ b/crypto/src/cms/CMSSignedHelper.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Eac; +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Misc; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + internal class CmsSignedHelper + { + internal static readonly CmsSignedHelper Instance = new CmsSignedHelper(); + + private static readonly IDictionary encryptionAlgs = Platform.CreateHashtable(); + private static readonly IDictionary digestAlgs = Platform.CreateHashtable(); + private static readonly IDictionary digestAliases = Platform.CreateHashtable(); + + private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption) + { + string alias = oid.Id; + digestAlgs.Add(alias, digest); + encryptionAlgs.Add(alias, encryption); + } + + static CmsSignedHelper() + { + AddEntries(NistObjectIdentifiers.DsaWithSha224, "SHA224", "DSA"); + AddEntries(NistObjectIdentifiers.DsaWithSha256, "SHA256", "DSA"); + AddEntries(NistObjectIdentifiers.DsaWithSha384, "SHA384", "DSA"); + AddEntries(NistObjectIdentifiers.DsaWithSha512, "SHA512", "DSA"); + AddEntries(OiwObjectIdentifiers.DsaWithSha1, "SHA1", "DSA"); + AddEntries(OiwObjectIdentifiers.MD4WithRsa, "MD4", "RSA"); + AddEntries(OiwObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA"); + AddEntries(OiwObjectIdentifiers.MD5WithRsa, "MD5", "RSA"); + AddEntries(OiwObjectIdentifiers.Sha1WithRsa, "SHA1", "RSA"); + AddEntries(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2", "RSA"); + AddEntries(PkcsObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA"); + AddEntries(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5", "RSA"); + AddEntries(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1", "RSA"); + AddEntries(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224", "RSA"); + AddEntries(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256", "RSA"); + AddEntries(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384", "RSA"); + AddEntries(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512", "RSA"); + AddEntries(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1", "ECDSA"); + AddEntries(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224", "ECDSA"); + AddEntries(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256", "ECDSA"); + AddEntries(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384", "ECDSA"); + AddEntries(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512", "ECDSA"); + AddEntries(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1", "DSA"); + AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1", "ECDSA"); + AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224", "ECDSA"); + AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256", "ECDSA"); + AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384", "ECDSA"); + AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512", "ECDSA"); + AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_1, "SHA1", "RSA"); + AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA"); + AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1"); + AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1"); + + encryptionAlgs.Add(X9ObjectIdentifiers.IdDsa.Id, "DSA"); + encryptionAlgs.Add(PkcsObjectIdentifiers.RsaEncryption.Id, "RSA"); + encryptionAlgs.Add(TeleTrusTObjectIdentifiers.TeleTrusTRsaSignatureAlgorithm, "RSA"); + encryptionAlgs.Add(X509ObjectIdentifiers.IdEARsa.Id, "RSA"); + encryptionAlgs.Add(CmsSignedGenerator.EncryptionRsaPss, "RSAandMGF1"); + encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x94.Id, "GOST3410"); + encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x2001.Id, "ECGOST3410"); + encryptionAlgs.Add("1.3.6.1.4.1.5849.1.6.2", "ECGOST3410"); + encryptionAlgs.Add("1.3.6.1.4.1.5849.1.1.5", "GOST3410"); + + digestAlgs.Add(PkcsObjectIdentifiers.MD2.Id, "MD2"); + digestAlgs.Add(PkcsObjectIdentifiers.MD4.Id, "MD4"); + digestAlgs.Add(PkcsObjectIdentifiers.MD5.Id, "MD5"); + digestAlgs.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1"); + digestAlgs.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224"); + digestAlgs.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256"); + digestAlgs.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384"); + digestAlgs.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512"); + digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128"); + digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160"); + digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256"); + digestAlgs.Add(CryptoProObjectIdentifiers.GostR3411.Id, "GOST3411"); + digestAlgs.Add("1.3.6.1.4.1.5849.1.2.1", "GOST3411"); + + digestAliases.Add("SHA1", new string[] { "SHA-1" }); + digestAliases.Add("SHA224", new string[] { "SHA-224" }); + digestAliases.Add("SHA256", new string[] { "SHA-256" }); + digestAliases.Add("SHA384", new string[] { "SHA-384" }); + digestAliases.Add("SHA512", new string[] { "SHA-512" }); + } + + /** + * Return the digest algorithm using one of the standard JCA string + * representations rather than the algorithm identifier (if possible). + */ + internal string GetDigestAlgName( + string digestAlgOid) + { + string algName = (string)digestAlgs[digestAlgOid]; + + if (algName != null) + { + return algName; + } + + return digestAlgOid; + } + + internal string[] GetDigestAliases( + string algName) + { + string[] aliases = (string[]) digestAliases[algName]; + + return aliases == null ? new String[0] : (string[]) aliases.Clone(); + } + + /** + * Return the digest encryption algorithm using one of the standard + * JCA string representations rather than the algorithm identifier (if + * possible). + */ + internal string GetEncryptionAlgName( + string encryptionAlgOid) + { + string algName = (string) encryptionAlgs[encryptionAlgOid]; + + if (algName != null) + { + return algName; + } + + return encryptionAlgOid; + } + + internal IDigest GetDigestInstance( + string algorithm) + { + try + { + return DigestUtilities.GetDigest(algorithm); + } + catch (SecurityUtilityException e) + { + // This is probably superfluous on C#, since no provider infrastructure, + // assuming DigestUtilities already knows all the aliases + foreach (string alias in GetDigestAliases(algorithm)) + { + try { return DigestUtilities.GetDigest(alias); } + catch (SecurityUtilityException) {} + } + throw e; + } + } + + internal ISigner GetSignatureInstance( + string algorithm) + { + return SignerUtilities.GetSigner(algorithm); + } + + internal IX509Store CreateAttributeStore( + string type, + Asn1Set certSet) + { + IList certs = Platform.CreateArrayList(); + + if (certSet != null) + { + foreach (Asn1Encodable ae in certSet) + { + try + { + Asn1Object obj = ae.ToAsn1Object(); + + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tagged = (Asn1TaggedObject)obj; + + if (tagged.TagNo == 2) + { + certs.Add( + new X509V2AttributeCertificate( + Asn1Sequence.GetInstance(tagged, false).GetEncoded())); + } + } + } + catch (Exception ex) + { + throw new CmsException("can't re-encode attribute certificate!", ex); + } + } + } + + try + { + return X509StoreFactory.Create( + "AttributeCertificate/" + type, + new X509CollectionStoreParameters(certs)); + } + catch (ArgumentException e) + { + throw new CmsException("can't setup the X509Store", e); + } + } + + internal IX509Store CreateCertificateStore( + string type, + Asn1Set certSet) + { + IList certs = Platform.CreateArrayList(); + + if (certSet != null) + { + AddCertsFromSet(certs, certSet); + } + + try + { + return X509StoreFactory.Create( + "Certificate/" + type, + new X509CollectionStoreParameters(certs)); + } + catch (ArgumentException e) + { + throw new CmsException("can't setup the X509Store", e); + } + } + + internal IX509Store CreateCrlStore( + string type, + Asn1Set crlSet) + { + IList crls = Platform.CreateArrayList(); + + if (crlSet != null) + { + AddCrlsFromSet(crls, crlSet); + } + + try + { + return X509StoreFactory.Create( + "CRL/" + type, + new X509CollectionStoreParameters(crls)); + } + catch (ArgumentException e) + { + throw new CmsException("can't setup the X509Store", e); + } + } + + private void AddCertsFromSet( + IList certs, + Asn1Set certSet) + { + X509CertificateParser cf = new X509CertificateParser(); + + foreach (Asn1Encodable ae in certSet) + { + try + { + Asn1Object obj = ae.ToAsn1Object(); + + if (obj is Asn1Sequence) + { + // TODO Build certificate directly from sequence? + certs.Add(cf.ReadCertificate(obj.GetEncoded())); + } + } + catch (Exception ex) + { + throw new CmsException("can't re-encode certificate!", ex); + } + } + } + + private void AddCrlsFromSet( + IList crls, + Asn1Set crlSet) + { + X509CrlParser cf = new X509CrlParser(); + + foreach (Asn1Encodable ae in crlSet) + { + try + { + // TODO Build CRL directly from ae.ToAsn1Object()? + crls.Add(cf.ReadCrl(ae.GetEncoded())); + } + catch (Exception ex) + { + throw new CmsException("can't re-encode CRL!", ex); + } + } + } + + internal AlgorithmIdentifier FixAlgID( + AlgorithmIdentifier algId) + { + if (algId.Parameters == null) + return new AlgorithmIdentifier(algId.ObjectID, DerNull.Instance); + + return algId; + } + } +} diff --git a/crypto/src/cms/CMSStreamException.cs b/crypto/src/cms/CMSStreamException.cs new file mode 100644 index 000000000..bf0a6adf4 --- /dev/null +++ b/crypto/src/cms/CMSStreamException.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Cms +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CmsStreamException + : IOException + { + public CmsStreamException() + { + } + + public CmsStreamException( + string name) + : base(name) + { + } + + public CmsStreamException( + string name, + Exception e) + : base(name, e) + { + } + } +} diff --git a/crypto/src/cms/CMSTypedStream.cs b/crypto/src/cms/CMSTypedStream.cs new file mode 100644 index 000000000..9cb314211 --- /dev/null +++ b/crypto/src/cms/CMSTypedStream.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + public class CmsTypedStream + { + private const int BufferSize = 32 * 1024; + + private readonly string _oid; + private readonly Stream _in; + + public CmsTypedStream( + Stream inStream) + : this(PkcsObjectIdentifiers.Data.Id, inStream, BufferSize) + { + } + + public CmsTypedStream( + string oid, + Stream inStream) + : this(oid, inStream, BufferSize) + { + } + + public CmsTypedStream( + string oid, + Stream inStream, + int bufSize) + { + _oid = oid; +#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT + _in = new FullReaderStream(inStream); +#else + _in = new FullReaderStream(new BufferedStream(inStream, bufSize)); +#endif + } + + public string ContentType + { + get { return _oid; } + } + + public Stream ContentStream + { + get { return _in; } + } + + public void Drain() + { + Streams.Drain(_in); + _in.Close(); + } + + private class FullReaderStream : FilterStream + { + internal FullReaderStream(Stream input) + : base(input) + { + } + + public override int Read(byte[] buf, int off, int len) + { + return Streams.ReadFully(base.s, buf, off, len); + } + } + } +} diff --git a/crypto/src/cms/CMSUtils.cs b/crypto/src/cms/CMSUtils.cs new file mode 100644 index 000000000..95d710607 --- /dev/null +++ b/crypto/src/cms/CMSUtils.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + internal class CmsUtilities + { + // TODO Is there a .NET equivalent to this? +// private static readonly Runtime RUNTIME = Runtime.getRuntime(); + + internal static int MaximumMemory + { + get + { + // TODO Is there a .NET equivalent to this? + long maxMem = int.MaxValue;//RUNTIME.maxMemory(); + + if (maxMem > int.MaxValue) + { + return int.MaxValue; + } + + return (int)maxMem; + } + } + + internal static ContentInfo ReadContentInfo( + byte[] input) + { + // enforce limit checking as from a byte array + return ReadContentInfo(new Asn1InputStream(input)); + } + + internal static ContentInfo ReadContentInfo( + Stream input) + { + // enforce some limit checking + return ReadContentInfo(new Asn1InputStream(input, MaximumMemory)); + } + + private static ContentInfo ReadContentInfo( + Asn1InputStream aIn) + { + try + { + return ContentInfo.GetInstance(aIn.ReadObject()); + } + catch (IOException e) + { + throw new CmsException("IOException reading content.", e); + } + catch (InvalidCastException e) + { + throw new CmsException("Malformed content.", e); + } + catch (ArgumentException e) + { + throw new CmsException("Malformed content.", e); + } + } + + public static byte[] StreamToByteArray( + Stream inStream) + { + return Streams.ReadAll(inStream); + } + + public static byte[] StreamToByteArray( + Stream inStream, + int limit) + { + return Streams.ReadAllLimited(inStream, limit); + } + + public static IList GetCertificatesFromStore( + IX509Store certStore) + { + try + { + IList certs = Platform.CreateArrayList(); + + if (certStore != null) + { + foreach (X509Certificate c in certStore.GetMatches(null)) + { + certs.Add( + X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(c.GetEncoded()))); + } + } + + return certs; + } + catch (CertificateEncodingException e) + { + throw new CmsException("error encoding certs", e); + } + catch (Exception e) + { + throw new CmsException("error processing certs", e); + } + } + + public static IList GetCrlsFromStore( + IX509Store crlStore) + { + try + { + IList crls = Platform.CreateArrayList(); + + if (crlStore != null) + { + foreach (X509Crl c in crlStore.GetMatches(null)) + { + crls.Add( + CertificateList.GetInstance( + Asn1Object.FromByteArray(c.GetEncoded()))); + } + } + + return crls; + } + catch (CrlException e) + { + throw new CmsException("error encoding crls", e); + } + catch (Exception e) + { + throw new CmsException("error processing crls", e); + } + } + + public static Asn1Set CreateBerSetFromList( + IList berObjects) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + foreach (Asn1Encodable ae in berObjects) + { + v.Add(ae); + } + + return new BerSet(v); + } + + public static Asn1Set CreateDerSetFromList( + IList derObjects) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + foreach (Asn1Encodable ae in derObjects) + { + v.Add(ae); + } + + return new DerSet(v); + } + + internal static Stream CreateBerOctetOutputStream(Stream s, int tagNo, bool isExplicit, int bufferSize) + { + BerOctetStringGenerator octGen = new BerOctetStringGenerator(s, tagNo, isExplicit); + return octGen.GetOctetOutputStream(bufferSize); + } + + internal static TbsCertificateStructure GetTbsCertificateStructure(X509Certificate cert) + { + return TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetTbsCertificate())); + } + + internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(X509Certificate cert) + { + TbsCertificateStructure tbsCert = GetTbsCertificateStructure(cert); + return new IssuerAndSerialNumber(tbsCert.Issuer, tbsCert.SerialNumber.Value); + } + } +} diff --git a/crypto/src/cms/CounterSignatureDigestCalculator.cs b/crypto/src/cms/CounterSignatureDigestCalculator.cs new file mode 100644 index 000000000..6f8bf65a2 --- /dev/null +++ b/crypto/src/cms/CounterSignatureDigestCalculator.cs @@ -0,0 +1,28 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + internal class CounterSignatureDigestCalculator + : IDigestCalculator + { + private readonly string alg; + private readonly byte[] data; + + internal CounterSignatureDigestCalculator( + string alg, + byte[] data) + { + this.alg = alg; + this.data = data; + } + + public byte[] GetDigest() + { + IDigest digest = CmsSignedHelper.Instance.GetDigestInstance(alg); + return DigestUtilities.DoFinal(digest, data); + } + } +} diff --git a/crypto/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs b/crypto/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs new file mode 100644 index 000000000..d49b1d9d2 --- /dev/null +++ b/crypto/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + /** + * Default authenticated attributes generator. + */ + public class DefaultAuthenticatedAttributeTableGenerator + : CmsAttributeTableGenerator + { + private readonly IDictionary table; + + /** + * Initialise to use all defaults + */ + public DefaultAuthenticatedAttributeTableGenerator() + { + table = Platform.CreateHashtable(); + } + + /** + * Initialise with some extra attributes or overrides. + * + * @param attributeTable initial attribute table to use. + */ + public DefaultAuthenticatedAttributeTableGenerator( + AttributeTable attributeTable) + { + if (attributeTable != null) + { + table = attributeTable.ToDictionary(); + } + else + { + table = Platform.CreateHashtable(); + } + } + + /** + * Create a standard attribute table from the passed in parameters - this will + * normally include contentType and messageDigest. If the constructor + * using an AttributeTable was used, entries in it for contentType and + * messageDigest will override the generated ones. + * + * @param parameters source parameters for table generation. + * + * @return a filled in IDictionary of attributes. + */ + protected virtual IDictionary CreateStandardAttributeTable( + IDictionary parameters) + { + IDictionary std = Platform.CreateHashtable(table); + + if (!std.Contains(CmsAttributes.ContentType)) + { + DerObjectIdentifier contentType = (DerObjectIdentifier) + parameters[CmsAttributeTableParameter.ContentType]; + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType, + new DerSet(contentType)); + std[attr.AttrType] = attr; + } + + if (!std.Contains(CmsAttributes.MessageDigest)) + { + byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest]; + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest, + new DerSet(new DerOctetString(messageDigest))); + std[attr.AttrType] = attr; + } + + return std; + } + + /** + * @param parameters source parameters + * @return the populated attribute table + */ + public virtual AttributeTable GetAttributes( + IDictionary parameters) + { + IDictionary table = CreateStandardAttributeTable(parameters); + return new AttributeTable(table); + } + } +} diff --git a/crypto/src/cms/DefaultSignedAttributeTableGenerator.cs b/crypto/src/cms/DefaultSignedAttributeTableGenerator.cs new file mode 100644 index 000000000..055de8957 --- /dev/null +++ b/crypto/src/cms/DefaultSignedAttributeTableGenerator.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + /** + * Default signed attributes generator. + */ + public class DefaultSignedAttributeTableGenerator + : CmsAttributeTableGenerator + { + private readonly IDictionary table; + + /** + * Initialise to use all defaults + */ + public DefaultSignedAttributeTableGenerator() + { + table = Platform.CreateHashtable(); + } + + /** + * Initialise with some extra attributes or overrides. + * + * @param attributeTable initial attribute table to use. + */ + public DefaultSignedAttributeTableGenerator( + AttributeTable attributeTable) + { + if (attributeTable != null) + { + table = attributeTable.ToDictionary(); + } + else + { + table = Platform.CreateHashtable(); + } + } + +#if SILVERLIGHT + /** + * Create a standard attribute table from the passed in parameters - this will + * normally include contentType, signingTime, and messageDigest. If the constructor + * using an AttributeTable was used, entries in it for contentType, signingTime, and + * messageDigest will override the generated ones. + * + * @param parameters source parameters for table generation. + * + * @return a filled in Hashtable of attributes. + */ + protected virtual IDictionary createStandardAttributeTable( + IDictionary parameters) + { + IDictionary std = Platform.CreateHashtable(table); + DoCreateStandardAttributeTable(parameters, std); + return std; + } +#else + /** + * Create a standard attribute table from the passed in parameters - this will + * normally include contentType, signingTime, and messageDigest. If the constructor + * using an AttributeTable was used, entries in it for contentType, signingTime, and + * messageDigest will override the generated ones. + * + * @param parameters source parameters for table generation. + * + * @return a filled in Hashtable of attributes. + */ + protected virtual Hashtable createStandardAttributeTable( + IDictionary parameters) + { + Hashtable std = new Hashtable(table); + DoCreateStandardAttributeTable(parameters, std); + return std; + } +#endif + + private void DoCreateStandardAttributeTable(IDictionary parameters, IDictionary std) + { + // contentType will be absent if we're trying to generate a counter signature. + if (parameters.Contains(CmsAttributeTableParameter.ContentType)) + { + if (!std.Contains(CmsAttributes.ContentType)) + { + DerObjectIdentifier contentType = (DerObjectIdentifier) + parameters[CmsAttributeTableParameter.ContentType]; + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType, + new DerSet(contentType)); + std[attr.AttrType] = attr; + } + } + + if (!std.Contains(CmsAttributes.SigningTime)) + { + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.SigningTime, + new DerSet(new Time(DateTime.UtcNow))); + std[attr.AttrType] = attr; + } + + if (!std.Contains(CmsAttributes.MessageDigest)) + { + byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest]; + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest, + new DerSet(new DerOctetString(messageDigest))); + std[attr.AttrType] = attr; + } + } + + /** + * @param parameters source parameters + * @return the populated attribute table + */ + public virtual AttributeTable GetAttributes( + IDictionary parameters) + { + IDictionary table = createStandardAttributeTable(parameters); + return new AttributeTable(table); + } + } +} diff --git a/crypto/src/cms/DigOutputStream.cs b/crypto/src/cms/DigOutputStream.cs new file mode 100644 index 000000000..103b45cac --- /dev/null +++ b/crypto/src/cms/DigOutputStream.cs @@ -0,0 +1,28 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + internal class DigOutputStream + : BaseOutputStream + { + private readonly IDigest dig; + + internal DigOutputStream(IDigest dig) + { + this.dig = dig; + } + + public override void WriteByte(byte b) + { + dig.Update(b); + } + + public override void Write(byte[] b, int off, int len) + { + dig.BlockUpdate(b, off, len); + } + } +} diff --git a/crypto/src/cms/IDigestCalculator.cs b/crypto/src/cms/IDigestCalculator.cs new file mode 100644 index 000000000..3661e4023 --- /dev/null +++ b/crypto/src/cms/IDigestCalculator.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.Cms +{ + internal interface IDigestCalculator + { + byte[] GetDigest(); + } +} diff --git a/crypto/src/cms/KEKRecipientInfoGenerator.cs b/crypto/src/cms/KEKRecipientInfoGenerator.cs new file mode 100644 index 000000000..a9bedade6 --- /dev/null +++ b/crypto/src/cms/KEKRecipientInfoGenerator.cs @@ -0,0 +1,137 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + internal class KekRecipientInfoGenerator : RecipientInfoGenerator + { + private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; + + private KeyParameter keyEncryptionKey; + // TODO Can get this from keyEncryptionKey? + private string keyEncryptionKeyOID; + private KekIdentifier kekIdentifier; + + // Derived + private AlgorithmIdentifier keyEncryptionAlgorithm; + + internal KekRecipientInfoGenerator() + { + } + + internal KekIdentifier KekIdentifier + { + set { this.kekIdentifier = value; } + } + + internal KeyParameter KeyEncryptionKey + { + set + { + this.keyEncryptionKey = value; + this.keyEncryptionAlgorithm = DetermineKeyEncAlg(keyEncryptionKeyOID, keyEncryptionKey); + } + } + + internal string KeyEncryptionKeyOID + { + set { this.keyEncryptionKeyOID = value; } + } + + public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + + IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id); + keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random)); + Asn1OctetString encryptedKey = new DerOctetString( + keyWrapper.Wrap(keyBytes, 0, keyBytes.Length)); + + return new RecipientInfo(new KekRecipientInfo(kekIdentifier, keyEncryptionAlgorithm, encryptedKey)); + } + + private static AlgorithmIdentifier DetermineKeyEncAlg( + string algorithm, KeyParameter key) + { + if (algorithm.StartsWith("DES")) + { + return new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdAlgCms3DesWrap, + DerNull.Instance); + } + else if (algorithm.StartsWith("RC2")) + { + return new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdAlgCmsRC2Wrap, + new DerInteger(58)); + } + else if (algorithm.StartsWith("AES")) + { + int length = key.GetKey().Length * 8; + DerObjectIdentifier wrapOid; + + if (length == 128) + { + wrapOid = NistObjectIdentifiers.IdAes128Wrap; + } + else if (length == 192) + { + wrapOid = NistObjectIdentifiers.IdAes192Wrap; + } + else if (length == 256) + { + wrapOid = NistObjectIdentifiers.IdAes256Wrap; + } + else + { + throw new ArgumentException("illegal keysize in AES"); + } + + return new AlgorithmIdentifier(wrapOid); // parameters absent + } + else if (algorithm.StartsWith("SEED")) + { + // parameters absent + return new AlgorithmIdentifier(KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap); + } + else if (algorithm.StartsWith("CAMELLIA")) + { + int length = key.GetKey().Length * 8; + DerObjectIdentifier wrapOid; + + if (length == 128) + { + wrapOid = NttObjectIdentifiers.IdCamellia128Wrap; + } + else if (length == 192) + { + wrapOid = NttObjectIdentifiers.IdCamellia192Wrap; + } + else if (length == 256) + { + wrapOid = NttObjectIdentifiers.IdCamellia256Wrap; + } + else + { + throw new ArgumentException("illegal keysize in Camellia"); + } + + return new AlgorithmIdentifier(wrapOid); // parameters must be absent + } + else + { + throw new ArgumentException("unknown algorithm"); + } + } + } +} diff --git a/crypto/src/cms/KEKRecipientInformation.cs b/crypto/src/cms/KEKRecipientInformation.cs new file mode 100644 index 000000000..f960197d6 --- /dev/null +++ b/crypto/src/cms/KEKRecipientInformation.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + /** + * the RecipientInfo class for a recipient who has been sent a message + * encrypted using a secret key known to the other side. + */ + public class KekRecipientInformation + : RecipientInformation + { + private KekRecipientInfo info; + + internal KekRecipientInformation( + KekRecipientInfo info, + CmsSecureReadable secureReadable) + : base(info.KeyEncryptionAlgorithm, secureReadable) + { + this.info = info; + this.rid = new RecipientID(); + + KekIdentifier kekId = info.KekID; + + rid.KeyIdentifier = kekId.KeyIdentifier.GetOctets(); + } + + /** + * decrypt the content and return an input stream. + */ + public override CmsTypedStream GetContentStream( + ICipherParameters key) + { + try + { + byte[] encryptedKey = info.EncryptedKey.GetOctets(); + IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncAlg.ObjectID.Id); + + keyWrapper.Init(false, key); + + KeyParameter sKey = ParameterUtilities.CreateKeyParameter( + GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length)); + + return GetContentFromSessionKey(sKey); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + } + } +} diff --git a/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs new file mode 100644 index 000000000..4fafb7c6e --- /dev/null +++ b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Cms.Ecc; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator + { + private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; + + private DerObjectIdentifier keyAgreementOID; + private DerObjectIdentifier keyEncryptionOID; + private IList recipientCerts; + private AsymmetricCipherKeyPair senderKeyPair; + + internal KeyAgreeRecipientInfoGenerator() + { + } + + internal DerObjectIdentifier KeyAgreementOID + { + set { this.keyAgreementOID = value; } + } + + internal DerObjectIdentifier KeyEncryptionOID + { + set { this.keyEncryptionOID = value; } + } + + internal ICollection RecipientCerts + { + set { this.recipientCerts = Platform.CreateArrayList(value); } + } + + internal AsymmetricCipherKeyPair SenderKeyPair + { + set { this.senderKeyPair = value; } + } + + public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + + AsymmetricKeyParameter senderPublicKey = senderKeyPair.Public; + ICipherParameters senderPrivateParams = senderKeyPair.Private; + + + OriginatorIdentifierOrKey originator; + try + { + originator = new OriginatorIdentifierOrKey( + CreateOriginatorPublicKey(senderPublicKey)); + } + catch (IOException e) + { + throw new InvalidKeyException("cannot extract originator public key: " + e); + } + + + Asn1OctetString ukm = null; + if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) + { + try + { + IAsymmetricCipherKeyPairGenerator ephemKPG = + GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID); + ephemKPG.Init( + ((ECPublicKeyParameters)senderPublicKey).CreateKeyGenerationParameters(random)); + + AsymmetricCipherKeyPair ephemKP = ephemKPG.GenerateKeyPair(); + + ukm = new DerOctetString( + new MQVuserKeyingMaterial( + CreateOriginatorPublicKey(ephemKP.Public), null)); + + senderPrivateParams = new MqvPrivateParameters( + (ECPrivateKeyParameters)senderPrivateParams, + (ECPrivateKeyParameters)ephemKP.Private, + (ECPublicKeyParameters)ephemKP.Public); + } + catch (IOException e) + { + throw new InvalidKeyException("cannot extract MQV ephemeral public key: " + e); + } + catch (SecurityUtilityException e) + { + throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + e); + } + } + + + DerSequence paramSeq = new DerSequence( + keyEncryptionOID, + DerNull.Instance); + AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyAgreementOID, paramSeq); + + + Asn1EncodableVector recipientEncryptedKeys = new Asn1EncodableVector(); + foreach (X509Certificate recipientCert in recipientCerts) + { + TbsCertificateStructure tbsCert; + try + { + tbsCert = TbsCertificateStructure.GetInstance( + Asn1Object.FromByteArray(recipientCert.GetTbsCertificate())); + } + catch (Exception) + { + throw new ArgumentException("can't extract TBS structure from certificate"); + } + + // TODO Should there be a SubjectKeyIdentifier-based alternative? + IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber( + tbsCert.Issuer, tbsCert.SerialNumber.Value); + KeyAgreeRecipientIdentifier karid = new KeyAgreeRecipientIdentifier(issuerSerial); + + ICipherParameters recipientPublicParams = recipientCert.GetPublicKey(); + if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) + { + recipientPublicParams = new MqvPublicParameters( + (ECPublicKeyParameters)recipientPublicParams, + (ECPublicKeyParameters)recipientPublicParams); + } + + // Use key agreement to choose a wrap key for this recipient + IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreementWithKdf( + keyAgreementOID, keyEncryptionOID.Id); + keyAgreement.Init(new ParametersWithRandom(senderPrivateParams, random)); + BigInteger agreedValue = keyAgreement.CalculateAgreement(recipientPublicParams); + + int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8; + byte[] keyEncryptionKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, keyEncryptionKeySize); + KeyParameter keyEncryptionKey = ParameterUtilities.CreateKeyParameter( + keyEncryptionOID, keyEncryptionKeyBytes); + + // Wrap the content encryption key with the agreement key + IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionOID.Id); + keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random)); + byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); + + Asn1OctetString encryptedKey = new DerOctetString(encryptedKeyBytes); + + recipientEncryptedKeys.Add(new RecipientEncryptedKey(karid, encryptedKey)); + } + + return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg, + new DerSequence(recipientEncryptedKeys))); + } + + private static OriginatorPublicKey CreateOriginatorPublicKey( + AsymmetricKeyParameter publicKey) + { + SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); + return new OriginatorPublicKey( + new AlgorithmIdentifier(spki.AlgorithmID.ObjectID, DerNull.Instance), + spki.PublicKeyData.GetBytes()); + } + } +} diff --git a/crypto/src/cms/KeyAgreeRecipientInformation.cs b/crypto/src/cms/KeyAgreeRecipientInformation.cs new file mode 100644 index 000000000..38a94b0a4 --- /dev/null +++ b/crypto/src/cms/KeyAgreeRecipientInformation.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Cms.Ecc; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * the RecipientInfo class for a recipient who has been sent a message + * encrypted using key agreement. + */ + public class KeyAgreeRecipientInformation + : RecipientInformation + { + private KeyAgreeRecipientInfo info; + private Asn1OctetString encryptedKey; + + internal static void ReadRecipientInfo(IList infos, KeyAgreeRecipientInfo info, + CmsSecureReadable secureReadable) + { + try + { + foreach (Asn1Encodable rek in info.RecipientEncryptedKeys) + { + RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object()); + + RecipientID rid = new RecipientID(); + + Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier; + + Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber; + if (iAndSN != null) + { + rid.Issuer = iAndSN.Name; + rid.SerialNumber = iAndSN.SerialNumber.Value; + } + else + { + Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID; + + // Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational + + rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets(); + } + + infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey, + secureReadable)); + } + } + catch (IOException e) + { + throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e); + } + } + + internal KeyAgreeRecipientInformation( + KeyAgreeRecipientInfo info, + RecipientID rid, + Asn1OctetString encryptedKey, + CmsSecureReadable secureReadable) + : base(info.KeyEncryptionAlgorithm, secureReadable) + { + this.info = info; + this.rid = rid; + this.encryptedKey = encryptedKey; + } + + private AsymmetricKeyParameter GetSenderPublicKey( + AsymmetricKeyParameter receiverPrivateKey, + OriginatorIdentifierOrKey originator) + { + OriginatorPublicKey opk = originator.OriginatorPublicKey; + if (opk != null) + { + return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk); + } + + OriginatorID origID = new OriginatorID(); + + Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber; + if (iAndSN != null) + { + origID.Issuer = iAndSN.Name; + origID.SerialNumber = iAndSN.SerialNumber.Value; + } + else + { + SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier; + + origID.SubjectKeyIdentifier = ski.GetKeyIdentifier(); + } + + return GetPublicKeyFromOriginatorID(origID); + } + + private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey( + AsymmetricKeyParameter receiverPrivateKey, + OriginatorPublicKey originatorPublicKey) + { + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey); + SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo( + privInfo.AlgorithmID, + originatorPublicKey.PublicKey.GetBytes()); + return PublicKeyFactory.CreateKey(pubInfo); + } + + private AsymmetricKeyParameter GetPublicKeyFromOriginatorID( + OriginatorID origID) + { + // TODO Support all alternatives for OriginatorIdentifierOrKey + // see RFC 3852 6.2.2 + throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier"); + } + + private KeyParameter CalculateAgreedWrapKey( + string wrapAlg, + AsymmetricKeyParameter senderPublicKey, + AsymmetricKeyParameter receiverPrivateKey) + { + DerObjectIdentifier agreeAlgID = keyEncAlg.ObjectID; + + ICipherParameters senderPublicParams = senderPublicKey; + ICipherParameters receiverPrivateParams = receiverPrivateKey; + + if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) + { + byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets(); + MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance( + Asn1Object.FromByteArray(ukmEncoding)); + + AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey( + receiverPrivateKey, ukm.EphemeralPublicKey); + + senderPublicParams = new MqvPublicParameters( + (ECPublicKeyParameters)senderPublicParams, + (ECPublicKeyParameters)ephemeralKey); + receiverPrivateParams = new MqvPrivateParameters( + (ECPrivateKeyParameters)receiverPrivateParams, + (ECPrivateKeyParameters)receiverPrivateParams); + } + + IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf( + agreeAlgID, wrapAlg); + agreement.Init(receiverPrivateParams); + BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams); + + int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8; + byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize); + return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes); + } + + private KeyParameter UnwrapSessionKey( + string wrapAlg, + KeyParameter agreedKey) + { + byte[] encKeyOctets = encryptedKey.GetOctets(); + + IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg); + keyCipher.Init(false, agreedKey); + byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length); + return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes); + } + + internal KeyParameter GetSessionKey( + AsymmetricKeyParameter receiverPrivateKey) + { + try + { + string wrapAlg = DerObjectIdentifier.GetInstance( + Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id; + + AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey( + receiverPrivateKey, info.Originator); + + KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg, + senderPublicKey, receiverPrivateKey); + + return UnwrapSessionKey(wrapAlg, agreedWrapKey); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (Exception e) + { + throw new CmsException("originator key invalid.", e); + } + } + + /** + * decrypt the content and return an input stream. + */ + public override CmsTypedStream GetContentStream( + ICipherParameters key) + { + if (!(key is AsymmetricKeyParameter)) + throw new ArgumentException("KeyAgreement requires asymmetric key", "key"); + + AsymmetricKeyParameter receiverPrivateKey = (AsymmetricKeyParameter) key; + + if (!receiverPrivateKey.IsPrivate) + throw new ArgumentException("Expected private key", "key"); + + KeyParameter sKey = GetSessionKey(receiverPrivateKey); + + return GetContentFromSessionKey(sKey); + } + } +} diff --git a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs new file mode 100644 index 000000000..0992e6da6 --- /dev/null +++ b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs @@ -0,0 +1,87 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + internal class KeyTransRecipientInfoGenerator : RecipientInfoGenerator + { + private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; + + private TbsCertificateStructure recipientTbsCert; + private AsymmetricKeyParameter recipientPublicKey; + private Asn1OctetString subjectKeyIdentifier; + + // Derived fields + private SubjectPublicKeyInfo info; + + internal KeyTransRecipientInfoGenerator() + { + } + + internal X509Certificate RecipientCert + { + set + { + this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value); + this.recipientPublicKey = value.GetPublicKey(); + this.info = recipientTbsCert.SubjectPublicKeyInfo; + } + } + + internal AsymmetricKeyParameter RecipientPublicKey + { + set + { + this.recipientPublicKey = value; + + try + { + info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( + recipientPublicKey); + } + catch (IOException) + { + throw new ArgumentException("can't extract key algorithm from this key"); + } + } + } + + internal Asn1OctetString SubjectKeyIdentifier + { + set { this.subjectKeyIdentifier = value; } + } + + public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID; + + IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id); + keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random)); + byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length); + + RecipientIdentifier recipId; + if (recipientTbsCert != null) + { + IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber( + recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value); + recipId = new RecipientIdentifier(issuerAndSerial); + } + else + { + recipId = new RecipientIdentifier(subjectKeyIdentifier); + } + + return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm, + new DerOctetString(encryptedKeyBytes))); + } + } +} diff --git a/crypto/src/cms/KeyTransRecipientInformation.cs b/crypto/src/cms/KeyTransRecipientInformation.cs new file mode 100644 index 000000000..24121cb2c --- /dev/null +++ b/crypto/src/cms/KeyTransRecipientInformation.cs @@ -0,0 +1,113 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Asn1Pkcs = Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * the KeyTransRecipientInformation class for a recipient who has been sent a secret + * key encrypted using their public key that needs to be used to + * extract the message. + */ + public class KeyTransRecipientInformation + : RecipientInformation + { + private KeyTransRecipientInfo info; + + internal KeyTransRecipientInformation( + KeyTransRecipientInfo info, + CmsSecureReadable secureReadable) + : base(info.KeyEncryptionAlgorithm, secureReadable) + { + this.info = info; + this.rid = new RecipientID(); + + RecipientIdentifier r = info.RecipientIdentifier; + + try + { + if (r.IsTagged) + { + Asn1OctetString octs = Asn1OctetString.GetInstance(r.ID); + + rid.SubjectKeyIdentifier = octs.GetOctets(); + } + else + { + IssuerAndSerialNumber iAnds = IssuerAndSerialNumber.GetInstance(r.ID); + + rid.Issuer = iAnds.Name; + rid.SerialNumber = iAnds.SerialNumber.Value; + } + } + catch (IOException) + { + throw new ArgumentException("invalid rid in KeyTransRecipientInformation"); + } + } + + private string GetExchangeEncryptionAlgorithmName( + DerObjectIdentifier oid) + { + if (Asn1Pkcs.PkcsObjectIdentifiers.RsaEncryption.Equals(oid)) + { + return "RSA//PKCS1Padding"; + } + + return oid.Id; + } + + internal KeyParameter UnwrapKey(ICipherParameters key) + { + byte[] encryptedKey = info.EncryptedKey.GetOctets(); + string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg.ObjectID); + + try + { + IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyExchangeAlgorithm); + keyWrapper.Init(false, key); + + // FIXME Support for MAC algorithm parameters similar to cipher parameters + return ParameterUtilities.CreateKeyParameter( + GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length)); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } +// catch (IllegalBlockSizeException e) + catch (DataLengthException e) + { + throw new CmsException("illegal blocksize in message.", e); + } +// catch (BadPaddingException e) + catch (InvalidCipherTextException e) + { + throw new CmsException("bad padding in message.", e); + } + } + + /** + * decrypt the content and return it as a byte array. + */ + public override CmsTypedStream GetContentStream( + ICipherParameters key) + { + KeyParameter sKey = UnwrapKey(key); + + return GetContentFromSessionKey(sKey); + } + } +} diff --git a/crypto/src/cms/MacOutputStream.cs b/crypto/src/cms/MacOutputStream.cs new file mode 100644 index 000000000..8891dbc2c --- /dev/null +++ b/crypto/src/cms/MacOutputStream.cs @@ -0,0 +1,28 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + internal class MacOutputStream + : BaseOutputStream + { + private readonly IMac mac; + + internal MacOutputStream(IMac mac) + { + this.mac = mac; + } + + public override void Write(byte[] b, int off, int len) + { + mac.BlockUpdate(b, off, len); + } + + public override void WriteByte(byte b) + { + mac.Update(b); + } + } +} diff --git a/crypto/src/cms/NullOutputStream.cs b/crypto/src/cms/NullOutputStream.cs new file mode 100644 index 000000000..ed937bdeb --- /dev/null +++ b/crypto/src/cms/NullOutputStream.cs @@ -0,0 +1,20 @@ +using System; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Cms +{ + internal class NullOutputStream + : BaseOutputStream + { + public override void WriteByte(byte b) + { + // do nothing + } + + public override void Write(byte[] buffer, int offset, int count) + { + // do nothing + } + } +} diff --git a/crypto/src/cms/OriginatorId.cs b/crypto/src/cms/OriginatorId.cs new file mode 100644 index 000000000..5a3b7374d --- /dev/null +++ b/crypto/src/cms/OriginatorId.cs @@ -0,0 +1,51 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + /** + * a basic index for an originator. + */ + public class OriginatorID + : X509CertStoreSelector + { + public override int GetHashCode() + { + int code = Arrays.GetHashCode(this.SubjectKeyIdentifier); + + BigInteger serialNumber = this.SerialNumber; + if (serialNumber != null) + { + code ^= serialNumber.GetHashCode(); + } + + X509Name issuer = this.Issuer; + if (issuer != null) + { + code ^= issuer.GetHashCode(); + } + + return code; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return false; + + OriginatorID id = obj as OriginatorID; + + if (id == null) + return false; + + return Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier) + && Platform.Equals(SerialNumber, id.SerialNumber) + && IssuersMatch(Issuer, id.Issuer); + } + } +} diff --git a/crypto/src/cms/OriginatorInfoGenerator.cs b/crypto/src/cms/OriginatorInfoGenerator.cs new file mode 100644 index 000000000..6bf108799 --- /dev/null +++ b/crypto/src/cms/OriginatorInfoGenerator.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + public class OriginatorInfoGenerator + { + private readonly IList origCerts; + private readonly IList origCrls; + + public OriginatorInfoGenerator(X509Certificate origCert) + { + this.origCerts = Platform.CreateArrayList(1); + this.origCrls = null; + origCerts.Add(origCert.CertificateStructure); + } + + public OriginatorInfoGenerator(IX509Store origCerts) + : this(origCerts, null) + { + } + + public OriginatorInfoGenerator(IX509Store origCerts, IX509Store origCrls) + { + this.origCerts = CmsUtilities.GetCertificatesFromStore(origCerts); + this.origCrls = origCrls == null ? null : CmsUtilities.GetCrlsFromStore(origCrls); + } + + public virtual OriginatorInfo Generate() + { + Asn1Set certSet = CmsUtilities.CreateDerSetFromList(origCerts); + Asn1Set crlSet = origCrls == null ? null : CmsUtilities.CreateDerSetFromList(origCrls); + return new OriginatorInfo(certSet, crlSet); + } + } +} diff --git a/crypto/src/cms/OriginatorInformation.cs b/crypto/src/cms/OriginatorInformation.cs new file mode 100644 index 000000000..618add6e0 --- /dev/null +++ b/crypto/src/cms/OriginatorInformation.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + public class OriginatorInformation + { + private readonly OriginatorInfo originatorInfo; + + internal OriginatorInformation(OriginatorInfo originatorInfo) + { + this.originatorInfo = originatorInfo; + } + + /** + * Return the certificates stored in the underlying OriginatorInfo object. + * + * @return a Store of X509CertificateHolder objects. + */ + public virtual IX509Store GetCertificates() + { + Asn1Set certSet = originatorInfo.Certificates; + + if (certSet != null) + { + IList certList = Platform.CreateArrayList(certSet.Count); + + foreach (Asn1Encodable enc in certSet) + { + Asn1Object obj = enc.ToAsn1Object(); + if (obj is Asn1Sequence) + { + certList.Add(new X509Certificate(X509CertificateStructure.GetInstance(obj))); + } + } + + return X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + } + + return X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(Platform.CreateArrayList())); + } + + /** + * Return the CRLs stored in the underlying OriginatorInfo object. + * + * @return a Store of X509CRLHolder objects. + */ + public virtual IX509Store GetCrls() + { + Asn1Set crlSet = originatorInfo.Certificates; + + if (crlSet != null) + { + IList crlList = Platform.CreateArrayList(crlSet.Count); + + foreach (Asn1Encodable enc in crlSet) + { + Asn1Object obj = enc.ToAsn1Object(); + if (obj is Asn1Sequence) + { + crlList.Add(new X509Crl(CertificateList.GetInstance(obj))); + } + } + + return X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + } + + return X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(Platform.CreateArrayList())); + } + + /** + * Return the underlying ASN.1 object defining this SignerInformation object. + * + * @return a OriginatorInfo. + */ + public virtual OriginatorInfo ToAsn1Structure() + { + return originatorInfo; + } + } +} diff --git a/crypto/src/cms/PKCS5Scheme2PBEKey.cs b/crypto/src/cms/PKCS5Scheme2PBEKey.cs new file mode 100644 index 000000000..08b8518a1 --- /dev/null +++ b/crypto/src/cms/PKCS5Scheme2PBEKey.cs @@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Cms +{ + /// + /// PKCS5 scheme-2 - password converted to bytes assuming ASCII. + /// + public class Pkcs5Scheme2PbeKey + : CmsPbeKey + { + [Obsolete("Use version taking 'char[]' instead")] + public Pkcs5Scheme2PbeKey( + string password, + byte[] salt, + int iterationCount) + : this(password.ToCharArray(), salt, iterationCount) + { + } + + [Obsolete("Use version taking 'char[]' instead")] + public Pkcs5Scheme2PbeKey( + string password, + AlgorithmIdentifier keyDerivationAlgorithm) + : this(password.ToCharArray(), keyDerivationAlgorithm) + { + } + + public Pkcs5Scheme2PbeKey( + char[] password, + byte[] salt, + int iterationCount) + : base(password, salt, iterationCount) + { + } + + public Pkcs5Scheme2PbeKey( + char[] password, + AlgorithmIdentifier keyDerivationAlgorithm) + : base(password, keyDerivationAlgorithm) + { + } + + internal override KeyParameter GetEncoded( + string algorithmOid) + { + Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator(); + + gen.Init( + PbeParametersGenerator.Pkcs5PasswordToBytes(password), + salt, + iterationCount); + + return (KeyParameter) gen.GenerateDerivedParameters( + algorithmOid, + CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid)); + } + } +} diff --git a/crypto/src/cms/PKCS5Scheme2UTF8PBEKey.cs b/crypto/src/cms/PKCS5Scheme2UTF8PBEKey.cs new file mode 100644 index 000000000..7aecc2978 --- /dev/null +++ b/crypto/src/cms/PKCS5Scheme2UTF8PBEKey.cs @@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Cms +{ + /** + * PKCS5 scheme-2 - password converted to bytes using UTF-8. + */ + public class Pkcs5Scheme2Utf8PbeKey + : CmsPbeKey + { + [Obsolete("Use version taking 'char[]' instead")] + public Pkcs5Scheme2Utf8PbeKey( + string password, + byte[] salt, + int iterationCount) + : this(password.ToCharArray(), salt, iterationCount) + { + } + + [Obsolete("Use version taking 'char[]' instead")] + public Pkcs5Scheme2Utf8PbeKey( + string password, + AlgorithmIdentifier keyDerivationAlgorithm) + : this(password.ToCharArray(), keyDerivationAlgorithm) + { + } + + public Pkcs5Scheme2Utf8PbeKey( + char[] password, + byte[] salt, + int iterationCount) + : base(password, salt, iterationCount) + { + } + + public Pkcs5Scheme2Utf8PbeKey( + char[] password, + AlgorithmIdentifier keyDerivationAlgorithm) + : base(password, keyDerivationAlgorithm) + { + } + + internal override KeyParameter GetEncoded( + string algorithmOid) + { + Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator(); + + gen.Init( + PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(password), + salt, + iterationCount); + + return (KeyParameter) gen.GenerateDerivedParameters( + algorithmOid, + CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid)); + } + } +} diff --git a/crypto/src/cms/PasswordRecipientInfoGenerator.cs b/crypto/src/cms/PasswordRecipientInfoGenerator.cs new file mode 100644 index 000000000..0a0b27b53 --- /dev/null +++ b/crypto/src/cms/PasswordRecipientInfoGenerator.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + internal class PasswordRecipientInfoGenerator : RecipientInfoGenerator + { + private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance; + + private AlgorithmIdentifier keyDerivationAlgorithm; + private KeyParameter keyEncryptionKey; + // TODO Can get this from keyEncryptionKey? + private string keyEncryptionKeyOID; + + internal PasswordRecipientInfoGenerator() + { + } + + internal AlgorithmIdentifier KeyDerivationAlgorithm + { + set { this.keyDerivationAlgorithm = value; } + } + + internal KeyParameter KeyEncryptionKey + { + set { this.keyEncryptionKey = value; } + } + + internal string KeyEncryptionKeyOID + { + set { this.keyEncryptionKeyOID = value; } + } + + public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) + { + byte[] keyBytes = contentEncryptionKey.GetKey(); + + string rfc3211WrapperName = Helper.GetRfc3211WrapperName(keyEncryptionKeyOID); + IWrapper keyWrapper = Helper.CreateWrapper(rfc3211WrapperName); + + // Note: In Java build, the IV is automatically generated in JCE layer + int ivLength = rfc3211WrapperName.StartsWith("DESEDE") ? 8 : 16; + byte[] iv = new byte[ivLength]; + random.NextBytes(iv); + + ICipherParameters parameters = new ParametersWithIV(keyEncryptionKey, iv); + keyWrapper.Init(true, new ParametersWithRandom(parameters, random)); + Asn1OctetString encryptedKey = new DerOctetString( + keyWrapper.Wrap(keyBytes, 0, keyBytes.Length)); + + DerSequence seq = new DerSequence( + new DerObjectIdentifier(keyEncryptionKeyOID), + new DerOctetString(iv)); + + AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdAlgPwriKek, seq); + + return new RecipientInfo(new PasswordRecipientInfo( + keyDerivationAlgorithm, keyEncryptionAlgorithm, encryptedKey)); + } + } +} diff --git a/crypto/src/cms/PasswordRecipientInformation.cs b/crypto/src/cms/PasswordRecipientInformation.cs new file mode 100644 index 000000000..f629caba6 --- /dev/null +++ b/crypto/src/cms/PasswordRecipientInformation.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + /** + * the RecipientInfo class for a recipient who has been sent a message + * encrypted using a password. + */ + public class PasswordRecipientInformation + : RecipientInformation + { + private readonly PasswordRecipientInfo info; + + internal PasswordRecipientInformation( + PasswordRecipientInfo info, + CmsSecureReadable secureReadable) + : base(info.KeyEncryptionAlgorithm, secureReadable) + { + this.info = info; + this.rid = new RecipientID(); + } + + /** + * return the object identifier for the key derivation algorithm, or null + * if there is none present. + * + * @return OID for key derivation algorithm, if present. + */ + public virtual AlgorithmIdentifier KeyDerivationAlgorithm + { + get { return info.KeyDerivationAlgorithm; } + } + + /** + * decrypt the content and return an input stream. + */ + public override CmsTypedStream GetContentStream( + ICipherParameters key) + { + try + { + AlgorithmIdentifier kekAlg = AlgorithmIdentifier.GetInstance(info.KeyEncryptionAlgorithm); + Asn1Sequence kekAlgParams = (Asn1Sequence)kekAlg.Parameters; + byte[] encryptedKey = info.EncryptedKey.GetOctets(); + string kekAlgName = DerObjectIdentifier.GetInstance(kekAlgParams[0]).Id; + string cName = CmsEnvelopedHelper.Instance.GetRfc3211WrapperName(kekAlgName); + IWrapper keyWrapper = WrapperUtilities.GetWrapper(cName); + + byte[] iv = Asn1OctetString.GetInstance(kekAlgParams[1]).GetOctets(); + + ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName); + parameters = new ParametersWithIV(parameters, iv); + + keyWrapper.Init(false, parameters); + + KeyParameter sKey = ParameterUtilities.CreateKeyParameter( + GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length)); + + return GetContentFromSessionKey(sKey); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + } + } +} diff --git a/crypto/src/cms/RecipientId.cs b/crypto/src/cms/RecipientId.cs new file mode 100644 index 000000000..9b6eb093b --- /dev/null +++ b/crypto/src/cms/RecipientId.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + public class RecipientID + : X509CertStoreSelector + { + private byte[] keyIdentifier; + + public byte[] KeyIdentifier + { + get { return Arrays.Clone(keyIdentifier); } + set { keyIdentifier = Arrays.Clone(value); } + } + + public override int GetHashCode() + { + int code = Arrays.GetHashCode(keyIdentifier) + ^ Arrays.GetHashCode(this.SubjectKeyIdentifier); + + BigInteger serialNumber = this.SerialNumber; + if (serialNumber != null) + { + code ^= serialNumber.GetHashCode(); + } + + X509Name issuer = this.Issuer; + if (issuer != null) + { + code ^= issuer.GetHashCode(); + } + + return code; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + RecipientID id = obj as RecipientID; + + if (id == null) + return false; + + return Arrays.AreEqual(keyIdentifier, id.keyIdentifier) + && Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier) + && Platform.Equals(SerialNumber, id.SerialNumber) + && IssuersMatch(Issuer, id.Issuer); + } + } +} diff --git a/crypto/src/cms/RecipientInfoGenerator.cs b/crypto/src/cms/RecipientInfoGenerator.cs new file mode 100644 index 000000000..c41db6122 --- /dev/null +++ b/crypto/src/cms/RecipientInfoGenerator.cs @@ -0,0 +1,26 @@ +using System; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + interface RecipientInfoGenerator + { + /// + /// Generate a RecipientInfo object for the given key. + /// + /// + /// A + /// + /// + /// A + /// + /// + /// A + /// + /// + RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random); + } +} diff --git a/crypto/src/cms/RecipientInformation.cs b/crypto/src/cms/RecipientInformation.cs new file mode 100644 index 000000000..8b0316be4 --- /dev/null +++ b/crypto/src/cms/RecipientInformation.cs @@ -0,0 +1,126 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Cms +{ + public abstract class RecipientInformation + { + internal RecipientID rid = new RecipientID(); + internal AlgorithmIdentifier keyEncAlg; + internal CmsSecureReadable secureReadable; + + private byte[] resultMac; + + internal RecipientInformation( + AlgorithmIdentifier keyEncAlg, + CmsSecureReadable secureReadable) + { + this.keyEncAlg = keyEncAlg; + this.secureReadable = secureReadable; + } + + internal string GetContentAlgorithmName() + { + AlgorithmIdentifier algorithm = secureReadable.Algorithm; +// return CmsEnvelopedHelper.Instance.GetSymmetricCipherName(algorithm.ObjectID.Id); + return algorithm.ObjectID.Id; + } + + public RecipientID RecipientID + { + get { return rid; } + } + + public AlgorithmIdentifier KeyEncryptionAlgorithmID + { + get { return keyEncAlg; } + } + + /** + * return the object identifier for the key encryption algorithm. + * + * @return OID for key encryption algorithm. + */ + public string KeyEncryptionAlgOid + { + get { return keyEncAlg.ObjectID.Id; } + } + + /** + * return the ASN.1 encoded key encryption algorithm parameters, or null if + * there aren't any. + * + * @return ASN.1 encoding of key encryption algorithm parameters. + */ + public Asn1Object KeyEncryptionAlgParams + { + get + { + Asn1Encodable ae = keyEncAlg.Parameters; + + return ae == null ? null : ae.ToAsn1Object(); + } + } + + internal CmsTypedStream GetContentFromSessionKey( + KeyParameter sKey) + { + CmsReadable readable = secureReadable.GetReadable(sKey); + + try + { + return new CmsTypedStream(readable.GetInputStream()); + } + catch (IOException e) + { + throw new CmsException("error getting .", e); + } + } + + public byte[] GetContent( + ICipherParameters key) + { + try + { + return CmsUtilities.StreamToByteArray(GetContentStream(key).ContentStream); + } + catch (IOException e) + { + throw new Exception("unable to parse internal stream: " + e); + } + } + + /** + * Return the MAC calculated for the content stream. Note: this call is only meaningful once all + * the content has been read. + * + * @return byte array containing the mac. + */ + public byte[] GetMac() + { + if (resultMac == null) + { + object cryptoObject = secureReadable.CryptoObject; + if (cryptoObject is IMac) + { + resultMac = MacUtilities.DoFinal((IMac)cryptoObject); + } + } + + return Arrays.Clone(resultMac); + } + + public abstract CmsTypedStream GetContentStream(ICipherParameters key); + } +} diff --git a/crypto/src/cms/RecipientInformationStore.cs b/crypto/src/cms/RecipientInformationStore.cs new file mode 100644 index 000000000..33b472f9d --- /dev/null +++ b/crypto/src/cms/RecipientInformationStore.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + public class RecipientInformationStore + { + private readonly IList all; //ArrayList[RecipientInformation] + private readonly IDictionary table = Platform.CreateHashtable(); // Hashtable[RecipientID, ArrayList[RecipientInformation]] + + public RecipientInformationStore( + ICollection recipientInfos) + { + foreach (RecipientInformation recipientInformation in recipientInfos) + { + RecipientID rid = recipientInformation.RecipientID; + IList list = (IList)table[rid]; + + if (list == null) + { + table[rid] = list = Platform.CreateArrayList(1); + } + + list.Add(recipientInformation); + } + + this.all = Platform.CreateArrayList(recipientInfos); + } + + public RecipientInformation this[RecipientID selector] + { + get { return GetFirstRecipient(selector); } + } + + /** + * Return the first RecipientInformation object that matches the + * passed in selector. Null if there are no matches. + * + * @param selector to identify a recipient + * @return a single RecipientInformation object. Null if none matches. + */ + public RecipientInformation GetFirstRecipient( + RecipientID selector) + { + IList list = (IList) table[selector]; + + return list == null ? null : (RecipientInformation) list[0]; + } + + /** + * Return the number of recipients in the collection. + * + * @return number of recipients identified. + */ + public int Count + { + get { return all.Count; } + } + + /** + * Return all recipients in the collection + * + * @return a collection of recipients. + */ + public ICollection GetRecipients() + { + return Platform.CreateArrayList(all); + } + + /** + * Return possible empty collection with recipients matching the passed in RecipientID + * + * @param selector a recipient id to select against. + * @return a collection of RecipientInformation objects. + */ + public ICollection GetRecipients( + RecipientID selector) + { + IList list = (IList)table[selector]; + + return list == null ? Platform.CreateArrayList() : Platform.CreateArrayList(list); + } + } +} diff --git a/crypto/src/cms/SigOutputStream.cs b/crypto/src/cms/SigOutputStream.cs new file mode 100644 index 000000000..a807fa7fc --- /dev/null +++ b/crypto/src/cms/SigOutputStream.cs @@ -0,0 +1,43 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Cms +{ + internal class SigOutputStream + : BaseOutputStream + { + private readonly ISigner sig; + + internal SigOutputStream(ISigner sig) + { + this.sig = sig; + } + + public override void WriteByte(byte b) + { + try + { + sig.Update(b); + } + catch (SignatureException e) + { + throw new CmsStreamException("signature problem: " + e); + } + } + + public override void Write(byte[] b, int off, int len) + { + try + { + sig.BlockUpdate(b, off, len); + } + catch (SignatureException e) + { + throw new CmsStreamException("signature problem: " + e); + } + } + } +} \ No newline at end of file diff --git a/crypto/src/cms/SignerId.cs b/crypto/src/cms/SignerId.cs new file mode 100644 index 000000000..baac9369b --- /dev/null +++ b/crypto/src/cms/SignerId.cs @@ -0,0 +1,51 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms +{ + /** + * a basic index for a signer. + */ + public class SignerID + : X509CertStoreSelector + { + public override int GetHashCode() + { + int code = Arrays.GetHashCode(this.SubjectKeyIdentifier); + + BigInteger serialNumber = this.SerialNumber; + if (serialNumber != null) + { + code ^= serialNumber.GetHashCode(); + } + + X509Name issuer = this.Issuer; + if (issuer != null) + { + code ^= issuer.GetHashCode(); + } + + return code; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return false; + + SignerID id = obj as SignerID; + + if (id == null) + return false; + + return Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier) + && Platform.Equals(SerialNumber, id.SerialNumber) + && IssuersMatch(Issuer, id.Issuer); + } + } +} diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs new file mode 100644 index 000000000..f78cf2c01 --- /dev/null +++ b/crypto/src/cms/SignerInfoGenerator.cs @@ -0,0 +1,14 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Cms +{ + internal interface SignerInfoGenerator + { + SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm, + byte[] calculatedDigest); + } +} diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs new file mode 100644 index 000000000..20af29a50 --- /dev/null +++ b/crypto/src/cms/SignerInformation.cs @@ -0,0 +1,758 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms +{ + /** + * an expanded SignerInfo block from a CMS Signed message + */ + public class SignerInformation + { + private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance; + + private SignerID sid; + private SignerInfo info; + private AlgorithmIdentifier digestAlgorithm; + private AlgorithmIdentifier encryptionAlgorithm; + private readonly Asn1Set signedAttributeSet; + private readonly Asn1Set unsignedAttributeSet; + private CmsProcessable content; + private byte[] signature; + private DerObjectIdentifier contentType; + private IDigestCalculator digestCalculator; + private byte[] resultDigest; + + // Derived + private Asn1.Cms.AttributeTable signedAttributeTable; + private Asn1.Cms.AttributeTable unsignedAttributeTable; + private readonly bool isCounterSignature; + + internal SignerInformation( + SignerInfo info, + DerObjectIdentifier contentType, + CmsProcessable content, + IDigestCalculator digestCalculator) + { + this.info = info; + this.sid = new SignerID(); + this.contentType = contentType; + this.isCounterSignature = contentType == null; + + try + { + SignerIdentifier s = info.SignerID; + + if (s.IsTagged) + { + Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID); + + sid.SubjectKeyIdentifier = octs.GetEncoded(); + } + else + { + Asn1.Cms.IssuerAndSerialNumber iAnds = + Asn1.Cms.IssuerAndSerialNumber.GetInstance(s.ID); + + sid.Issuer = iAnds.Name; + sid.SerialNumber = iAnds.SerialNumber.Value; + } + } + catch (IOException) + { + throw new ArgumentException("invalid sid in SignerInfo"); + } + + this.digestAlgorithm = info.DigestAlgorithm; + this.signedAttributeSet = info.AuthenticatedAttributes; + this.unsignedAttributeSet = info.UnauthenticatedAttributes; + this.encryptionAlgorithm = info.DigestEncryptionAlgorithm; + this.signature = info.EncryptedDigest.GetOctets(); + + this.content = content; + this.digestCalculator = digestCalculator; + } + + public bool IsCounterSignature + { + get { return isCounterSignature; } + } + + public DerObjectIdentifier ContentType + { + get { return contentType; } + } + + public SignerID SignerID + { + get { return sid; } + } + + /** + * return the version number for this objects underlying SignerInfo structure. + */ + public int Version + { + get { return info.Version.Value.IntValue; } + } + + public AlgorithmIdentifier DigestAlgorithmID + { + get { return digestAlgorithm; } + } + + /** + * return the object identifier for the signature. + */ + public string DigestAlgOid + { + get { return digestAlgorithm.ObjectID.Id; } + } + + /** + * return the signature parameters, or null if there aren't any. + */ + public Asn1Object DigestAlgParams + { + get + { + Asn1Encodable ae = digestAlgorithm.Parameters; + + return ae == null ? null : ae.ToAsn1Object(); + } + } + + /** + * return the content digest that was calculated during verification. + */ + public byte[] GetContentDigest() + { + if (resultDigest == null) + { + throw new InvalidOperationException("method can only be called after verify."); + } + + return (byte[])resultDigest.Clone(); + } + + public AlgorithmIdentifier EncryptionAlgorithmID + { + get { return encryptionAlgorithm; } + } + + /** + * return the object identifier for the signature. + */ + public string EncryptionAlgOid + { + get { return encryptionAlgorithm.ObjectID.Id; } + } + + /** + * return the signature/encryption algorithm parameters, or null if + * there aren't any. + */ + public Asn1Object EncryptionAlgParams + { + get + { + Asn1Encodable ae = encryptionAlgorithm.Parameters; + + return ae == null ? null : ae.ToAsn1Object(); + } + } + + /** + * return a table of the signed attributes - indexed by + * the OID of the attribute. + */ + public Asn1.Cms.AttributeTable SignedAttributes + { + get + { + if (signedAttributeSet != null && signedAttributeTable == null) + { + signedAttributeTable = new Asn1.Cms.AttributeTable(signedAttributeSet); + } + return signedAttributeTable; + } + } + + /** + * return a table of the unsigned attributes indexed by + * the OID of the attribute. + */ + public Asn1.Cms.AttributeTable UnsignedAttributes + { + get + { + if (unsignedAttributeSet != null && unsignedAttributeTable == null) + { + unsignedAttributeTable = new Asn1.Cms.AttributeTable(unsignedAttributeSet); + } + return unsignedAttributeTable; + } + } + + /** + * return the encoded signature + */ + public byte[] GetSignature() + { + return (byte[]) signature.Clone(); + } + + /** + * Return a SignerInformationStore containing the counter signatures attached to this + * signer. If no counter signatures are present an empty store is returned. + */ + public SignerInformationStore GetCounterSignatures() + { + // TODO There are several checks implied by the RFC3852 comments that are missing + + /* + The countersignature attribute MUST be an unsigned attribute; it MUST + NOT be a signed attribute, an authenticated attribute, an + unauthenticated attribute, or an unprotected attribute. + */ + Asn1.Cms.AttributeTable unsignedAttributeTable = UnsignedAttributes; + if (unsignedAttributeTable == null) + { + return new SignerInformationStore(Platform.CreateArrayList(0)); + } + + IList counterSignatures = Platform.CreateArrayList(); + + /* + The UnsignedAttributes syntax is defined as a SET OF Attributes. The + UnsignedAttributes in a signerInfo may include multiple instances of + the countersignature attribute. + */ + Asn1EncodableVector allCSAttrs = unsignedAttributeTable.GetAll(CmsAttributes.CounterSignature); + + foreach (Asn1.Cms.Attribute counterSignatureAttribute in allCSAttrs) + { + /* + A countersignature attribute can have multiple attribute values. The + syntax is defined as a SET OF AttributeValue, and there MUST be one + or more instances of AttributeValue present. + */ + Asn1Set values = counterSignatureAttribute.AttrValues; + if (values.Count < 1) + { + // TODO Throw an appropriate exception? + } + + foreach (Asn1Encodable asn1Obj in values) + { + /* + Countersignature values have the same meaning as SignerInfo values + for ordinary signatures, except that: + + 1. The signedAttributes field MUST NOT contain a content-type + attribute; there is no content type for countersignatures. + + 2. The signedAttributes field MUST contain a message-digest + attribute if it contains any other attributes. + + 3. The input to the message-digesting process is the contents + octets of the DER encoding of the signatureValue field of the + SignerInfo value with which the attribute is associated. + */ + SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object()); + + string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.ObjectID.Id); + + counterSignatures.Add(new SignerInformation(si, null, null, new CounterSignatureDigestCalculator(digestName, GetSignature()))); + } + } + + return new SignerInformationStore(counterSignatures); + } + + /** + * return the DER encoding of the signed attributes. + * @throws IOException if an encoding error occurs. + */ + public byte[] GetEncodedSignedAttributes() + { + return signedAttributeSet == null + ? null + : signedAttributeSet.GetEncoded(Asn1Encodable.Der); + } + + private bool DoVerify( + AsymmetricKeyParameter key) + { + string digestName = Helper.GetDigestAlgName(this.DigestAlgOid); + IDigest digest = Helper.GetDigestInstance(digestName); + + DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID; + Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters; + ISigner sig; + + if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss)) + { + // RFC 4056 2.2 + // When the id-RSASSA-PSS algorithm identifier is used for a signature, + // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params. + if (sigParams == null) + throw new CmsException("RSASSA-PSS signature must specify algorithm parameters"); + + try + { + // TODO Provide abstract configuration mechanism + // (via alternate SignerUtilities.GetSigner method taking ASN.1 params) + + Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance( + sigParams.ToAsn1Object()); + + if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID)) + throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm"); + if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1)) + throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF"); + + IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID); + int saltLength = pss.SaltLength.Value.IntValue; + byte trailerField = (byte) pss.TrailerField.Value.IntValue; + + // RFC 4055 3.1 + // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC + if (trailerField != 1) + throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1"); + + sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength); + } + catch (Exception e) + { + throw new CmsException("failed to set RSASSA-PSS signature parameters", e); + } + } + else + { + // TODO Probably too strong a check at the moment +// if (sigParams != null) +// throw new CmsException("unrecognised signature parameters provided"); + + string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid); + + sig = Helper.GetSignatureInstance(signatureName); + } + + try + { + if (digestCalculator != null) + { + resultDigest = digestCalculator.GetDigest(); + } + else + { + if (content != null) + { + content.Write(new DigOutputStream(digest)); + } + else if (signedAttributeSet == null) + { + // TODO Get rid of this exception and just treat content==null as empty not missing? + throw new CmsException("data not encapsulated in signature - use detached constructor."); + } + + resultDigest = DigestUtilities.DoFinal(digest); + } + } + catch (IOException e) + { + throw new CmsException("can't process mime object to create signature.", e); + } + + // RFC 3852 11.1 Check the content-type attribute is correct + { + Asn1Object validContentType = GetSingleValuedSignedAttribute( + CmsAttributes.ContentType, "content-type"); + if (validContentType == null) + { + if (!isCounterSignature && signedAttributeSet != null) + throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); + } + else + { + if (isCounterSignature) + throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); + + if (!(validContentType is DerObjectIdentifier)) + throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); + + DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType; + + if (!signedContentType.Equals(contentType)) + throw new CmsException("content-type attribute value does not match eContentType"); + } + } + + // RFC 3852 11.2 Check the message-digest attribute is correct + { + Asn1Object validMessageDigest = GetSingleValuedSignedAttribute( + CmsAttributes.MessageDigest, "message-digest"); + if (validMessageDigest == null) + { + if (signedAttributeSet != null) + throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present"); + } + else + { + if (!(validMessageDigest is Asn1OctetString)) + { + throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); + } + + Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest; + + if (!Arrays.AreEqual(resultDigest, signedMessageDigest.GetOctets())) + throw new CmsException("message-digest attribute value does not match calculated value"); + } + } + + // RFC 3852 11.4 Validate countersignature attribute(s) + { + Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes; + if (signedAttrTable != null + && signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0) + { + throw new CmsException("A countersignature attribute MUST NOT be a signed attribute"); + } + + Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes; + if (unsignedAttrTable != null) + { + foreach (Asn1.Cms.Attribute csAttr in unsignedAttrTable.GetAll(CmsAttributes.CounterSignature)) + { + if (csAttr.AttrValues.Count < 1) + throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue"); + + // Note: We don't recursively validate the countersignature value + } + } + } + + try + { + sig.Init(false, key); + + if (signedAttributeSet == null) + { + if (digestCalculator != null) + { + // need to decrypt signature and check message bytes + return VerifyDigest(resultDigest, key, this.GetSignature()); + } + else if (content != null) + { + // TODO Use raw signature of the hash value instead + content.Write(new SigOutputStream(sig)); + } + } + else + { + byte[] tmp = this.GetEncodedSignedAttributes(); + sig.BlockUpdate(tmp, 0, tmp.Length); + } + + return sig.VerifySignature(this.GetSignature()); + } + catch (InvalidKeyException e) + { + throw new CmsException("key not appropriate to signature in message.", e); + } + catch (IOException e) + { + throw new CmsException("can't process mime object to create signature.", e); + } + catch (SignatureException e) + { + throw new CmsException("invalid signature format in message: " + e.Message, e); + } + } + + private bool IsNull( + Asn1Encodable o) + { + return (o is Asn1Null) || (o == null); + } + + private DigestInfo DerDecode( + byte[] encoding) + { + if (encoding[0] != (int)(Asn1Tags.Constructed | Asn1Tags.Sequence)) + { + throw new IOException("not a digest info object"); + } + + DigestInfo digInfo = DigestInfo.GetInstance(Asn1Object.FromByteArray(encoding)); + + // length check to avoid Bleichenbacher vulnerability + + if (digInfo.GetEncoded().Length != encoding.Length) + { + throw new CmsException("malformed RSA signature"); + } + + return digInfo; + } + + private bool VerifyDigest( + byte[] digest, + AsymmetricKeyParameter key, + byte[] signature) + { + string algorithm = Helper.GetEncryptionAlgName(this.EncryptionAlgOid); + + try + { + if (algorithm.Equals("RSA")) + { + IBufferedCipher c = CmsEnvelopedHelper.Instance.CreateAsymmetricCipher("RSA/ECB/PKCS1Padding"); + + c.Init(false, key); + + byte[] decrypt = c.DoFinal(signature); + + DigestInfo digInfo = DerDecode(decrypt); + + if (!digInfo.AlgorithmID.ObjectID.Equals(digestAlgorithm.ObjectID)) + { + return false; + } + + if (!IsNull(digInfo.AlgorithmID.Parameters)) + { + return false; + } + + byte[] sigHash = digInfo.GetDigest(); + + return Arrays.ConstantTimeAreEqual(digest, sigHash); + } + else if (algorithm.Equals("DSA")) + { + ISigner sig = SignerUtilities.GetSigner("NONEwithDSA"); + + sig.Init(false, key); + + sig.BlockUpdate(digest, 0, digest.Length); + + return sig.VerifySignature(signature); + } + else + { + throw new CmsException("algorithm: " + algorithm + " not supported in base signatures."); + } + } + catch (SecurityUtilityException e) + { + throw e; + } + catch (GeneralSecurityException e) + { + throw new CmsException("Exception processing signature: " + e, e); + } + catch (IOException e) + { + throw new CmsException("Exception decoding signature: " + e, e); + } + } + + /** + * verify that the given public key successfully handles and confirms the + * signature associated with this signer. + */ + public bool Verify( + AsymmetricKeyParameter pubKey) + { + if (pubKey.IsPrivate) + throw new ArgumentException("Expected public key", "pubKey"); + + // Optional, but still need to validate if present + GetSigningTime(); + + return DoVerify(pubKey); + } + + /** + * verify that the given certificate successfully handles and confirms + * the signature associated with this signer and, if a signingTime + * attribute is available, that the certificate was valid at the time the + * signature was generated. + */ + public bool Verify( + X509Certificate cert) + { + Asn1.Cms.Time signingTime = GetSigningTime(); + if (signingTime != null) + { + cert.CheckValidity(signingTime.Date); + } + + return DoVerify(cert.GetPublicKey()); + } + + /** + * Return the base ASN.1 CMS structure that this object contains. + * + * @return an object containing a CMS SignerInfo structure. + */ + public SignerInfo ToSignerInfo() + { + return info; + } + + private Asn1Object GetSingleValuedSignedAttribute( + DerObjectIdentifier attrOID, string printableName) + { + + Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes; + if (unsignedAttrTable != null + && unsignedAttrTable.GetAll(attrOID).Count > 0) + { + throw new CmsException("The " + printableName + + " attribute MUST NOT be an unsigned attribute"); + } + + Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes; + if (signedAttrTable == null) + { + return null; + } + + Asn1EncodableVector v = signedAttrTable.GetAll(attrOID); + switch (v.Count) + { + case 0: + return null; + case 1: + Asn1.Cms.Attribute t = (Asn1.Cms.Attribute) v[0]; + Asn1Set attrValues = t.AttrValues; + + if (attrValues.Count != 1) + throw new CmsException("A " + printableName + + " attribute MUST have a single attribute value"); + + return attrValues[0].ToAsn1Object(); + default: + throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the " + + printableName + " attribute"); + } + } + + private Asn1.Cms.Time GetSigningTime() + { + Asn1Object validSigningTime = GetSingleValuedSignedAttribute( + CmsAttributes.SigningTime, "signing-time"); + + if (validSigningTime == null) + return null; + + try + { + return Asn1.Cms.Time.GetInstance(validSigningTime); + } + catch (ArgumentException) + { + throw new CmsException("signing-time attribute value not a valid 'Time' structure"); + } + } + + /** + * Return a signer information object with the passed in unsigned + * attributes replacing the ones that are current associated with + * the object passed in. + * + * @param signerInformation the signerInfo to be used as the basis. + * @param unsignedAttributes the unsigned attributes to add. + * @return a copy of the original SignerInformationObject with the changed attributes. + */ + public static SignerInformation ReplaceUnsignedAttributes( + SignerInformation signerInformation, + Asn1.Cms.AttributeTable unsignedAttributes) + { + SignerInfo sInfo = signerInformation.info; + Asn1Set unsignedAttr = null; + + if (unsignedAttributes != null) + { + unsignedAttr = new DerSet(unsignedAttributes.ToAsn1EncodableVector()); + } + + return new SignerInformation( + new SignerInfo( + sInfo.SignerID, + sInfo.DigestAlgorithm, + sInfo.AuthenticatedAttributes, + sInfo.DigestEncryptionAlgorithm, + sInfo.EncryptedDigest, + unsignedAttr), + signerInformation.contentType, + signerInformation.content, + null); + } + + /** + * Return a signer information object with passed in SignerInformationStore representing counter + * signatures attached as an unsigned attribute. + * + * @param signerInformation the signerInfo to be used as the basis. + * @param counterSigners signer info objects carrying counter signature. + * @return a copy of the original SignerInformationObject with the changed attributes. + */ + public static SignerInformation AddCounterSigners( + SignerInformation signerInformation, + SignerInformationStore counterSigners) + { + // TODO Perform checks from RFC 3852 11.4 + + SignerInfo sInfo = signerInformation.info; + Asn1.Cms.AttributeTable unsignedAttr = signerInformation.UnsignedAttributes; + Asn1EncodableVector v; + + if (unsignedAttr != null) + { + v = unsignedAttr.ToAsn1EncodableVector(); + } + else + { + v = new Asn1EncodableVector(); + } + + Asn1EncodableVector sigs = new Asn1EncodableVector(); + + foreach (SignerInformation sigInf in counterSigners.GetSigners()) + { + sigs.Add(sigInf.ToSignerInfo()); + } + + v.Add(new Asn1.Cms.Attribute(CmsAttributes.CounterSignature, new DerSet(sigs))); + + return new SignerInformation( + new SignerInfo( + sInfo.SignerID, + sInfo.DigestAlgorithm, + sInfo.AuthenticatedAttributes, + sInfo.DigestEncryptionAlgorithm, + sInfo.EncryptedDigest, + new DerSet(v)), + signerInformation.contentType, + signerInformation.content, + null); + } + } +} diff --git a/crypto/src/cms/SignerInformationStore.cs b/crypto/src/cms/SignerInformationStore.cs new file mode 100644 index 000000000..bd613843d --- /dev/null +++ b/crypto/src/cms/SignerInformationStore.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Cms +{ + public class SignerInformationStore + { + private readonly IList all; //ArrayList[SignerInformation] + private readonly IDictionary table = Platform.CreateHashtable(); // Hashtable[SignerID, ArrayList[SignerInformation]] + + public SignerInformationStore( + ICollection signerInfos) + { + foreach (SignerInformation signer in signerInfos) + { + SignerID sid = signer.SignerID; + IList list = (IList)table[sid]; + + if (list == null) + { + table[sid] = list = Platform.CreateArrayList(1); + } + + list.Add(signer); + } + + this.all = Platform.CreateArrayList(signerInfos); + } + + /** + * Return the first SignerInformation object that matches the + * passed in selector. Null if there are no matches. + * + * @param selector to identify a signer + * @return a single SignerInformation object. Null if none matches. + */ + public SignerInformation GetFirstSigner( + SignerID selector) + { + IList list = (IList) table[selector]; + + return list == null ? null : (SignerInformation) list[0]; + } + + /// The number of signers in the collection. + public int Count + { + get { return all.Count; } + } + + /// An ICollection of all signers in the collection + public ICollection GetSigners() + { + return Platform.CreateArrayList(all); + } + + /** + * Return possible empty collection with signers matching the passed in SignerID + * + * @param selector a signer id to select against. + * @return a collection of SignerInformation objects. + */ + public ICollection GetSigners( + SignerID selector) + { + IList list = (IList) table[selector]; + + return list == null ? Platform.CreateArrayList() : Platform.CreateArrayList(list); + } + } +} diff --git a/crypto/src/cms/SimpleAttributeTableGenerator.cs b/crypto/src/cms/SimpleAttributeTableGenerator.cs new file mode 100644 index 000000000..b3df21c29 --- /dev/null +++ b/crypto/src/cms/SimpleAttributeTableGenerator.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Cms +{ + /** + * Basic generator that just returns a preconstructed attribute table + */ + public class SimpleAttributeTableGenerator + : CmsAttributeTableGenerator + { + private readonly AttributeTable attributes; + + public SimpleAttributeTableGenerator( + AttributeTable attributes) + { + this.attributes = attributes; + } + + public virtual AttributeTable GetAttributes( + IDictionary parameters) + { + return attributes; + } + } +} diff --git a/crypto/src/crypto/AsymmetricCipherKeyPair.cs b/crypto/src/crypto/AsymmetricCipherKeyPair.cs new file mode 100644 index 000000000..b00a3dc02 --- /dev/null +++ b/crypto/src/crypto/AsymmetricCipherKeyPair.cs @@ -0,0 +1,52 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * a holding class for public/private parameter pairs. + */ + public class AsymmetricCipherKeyPair + { + private readonly AsymmetricKeyParameter publicParameter; + private readonly AsymmetricKeyParameter privateParameter; + + /** + * basic constructor. + * + * @param publicParam a public key parameters object. + * @param privateParam the corresponding private key parameters. + */ + public AsymmetricCipherKeyPair( + AsymmetricKeyParameter publicParameter, + AsymmetricKeyParameter privateParameter) + { + if (publicParameter.IsPrivate) + throw new ArgumentException("Expected a public key", "publicParameter"); + if (!privateParameter.IsPrivate) + throw new ArgumentException("Expected a private key", "privateParameter"); + + this.publicParameter = publicParameter; + this.privateParameter = privateParameter; + } + + /** + * return the public key parameters. + * + * @return the public key parameters. + */ + public AsymmetricKeyParameter Public + { + get { return publicParameter; } + } + + /** + * return the private key parameters. + * + * @return the private key parameters. + */ + public AsymmetricKeyParameter Private + { + get { return privateParameter; } + } + } +} diff --git a/crypto/src/crypto/AsymmetricKeyParameter.cs b/crypto/src/crypto/AsymmetricKeyParameter.cs new file mode 100644 index 000000000..7502ee305 --- /dev/null +++ b/crypto/src/crypto/AsymmetricKeyParameter.cs @@ -0,0 +1,47 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto +{ + public abstract class AsymmetricKeyParameter + : ICipherParameters + { + private readonly bool privateKey; + + protected AsymmetricKeyParameter( + bool privateKey) + { + this.privateKey = privateKey; + } + + public bool IsPrivate + { + get { return privateKey; } + } + + public override bool Equals( + object obj) + { + AsymmetricKeyParameter other = obj as AsymmetricKeyParameter; + + if (other == null) + { + return false; + } + + return Equals(other); + } + + protected bool Equals( + AsymmetricKeyParameter other) + { + return privateKey == other.privateKey; + } + + public override int GetHashCode() + { + return privateKey.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/BufferedAeadBlockCipher.cs b/crypto/src/crypto/BufferedAeadBlockCipher.cs new file mode 100644 index 000000000..04bcb88ed --- /dev/null +++ b/crypto/src/crypto/BufferedAeadBlockCipher.cs @@ -0,0 +1,247 @@ +using System; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto +{ + /** + * The AEAD block ciphers already handle buffering internally, so this class + * just takes care of implementing IBufferedCipher methods. + */ + public class BufferedAeadBlockCipher + : BufferedCipherBase + { + private readonly IAeadBlockCipher cipher; + + public BufferedAeadBlockCipher( + IAeadBlockCipher cipher) + { + if (cipher == null) + throw new ArgumentNullException("cipher"); + + this.cipher = cipher; + } + + public override string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + /** + * 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. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + cipher.Init(forEncryption, parameters); + } + + /** + * return the blocksize for the underlying cipher. + * + * @return the blocksize for the underlying cipher. + */ + public override 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 override int GetUpdateOutputSize( + int length) + { + return cipher.GetUpdateOutputSize(length); + } + + /** + * 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 override int GetOutputSize( + int length) + { + return cipher.GetOutputSize(length); + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessByte( + byte input, + byte[] output, + int outOff) + { + return cipher.ProcessByte(input, output, outOff); + } + + public override byte[] ProcessByte( + byte input) + { + int outLength = GetUpdateOutputSize(1); + + byte[] outBytes = outLength > 0 ? new byte[outLength] : null; + + int pos = ProcessByte(input, outBytes, 0); + + if (outLength > 0 && pos < outLength) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + public override byte[] ProcessBytes( + byte[] input, + int inOff, + int length) + { + if (input == null) + throw new ArgumentNullException("input"); + if (length < 1) + return null; + + int outLength = GetUpdateOutputSize(length); + + byte[] outBytes = outLength > 0 ? new byte[outLength] : null; + + int pos = ProcessBytes(input, inOff, length, outBytes, 0); + + if (outLength > 0 && pos < outLength) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + return cipher.ProcessBytes(input, inOff, length, output, outOff); + } + + public override byte[] DoFinal() + { + byte[] outBytes = new byte[GetOutputSize(0)]; + + int pos = DoFinal(outBytes, 0); + + if (pos < outBytes.Length) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + public override byte[] DoFinal( + byte[] input, + int inOff, + int inLen) + { + if (input == null) + throw new ArgumentNullException("input"); + + byte[] outBytes = new byte[GetOutputSize(inLen)]; + + int pos = (inLen > 0) + ? ProcessBytes(input, inOff, inLen, outBytes, 0) + : 0; + + pos += DoFinal(outBytes, pos); + + if (pos < outBytes.Length) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + /** + * 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 InvalidOperationException 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 override int DoFinal( + byte[] output, + int outOff) + { + return cipher.DoFinal(output, outOff); + } + + /** + * 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 override void Reset() + { + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs new file mode 100644 index 000000000..09ec59f69 --- /dev/null +++ b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs @@ -0,0 +1,152 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Engines; + +namespace 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 + : BufferedCipherBase + { + private readonly IAsymmetricBlockCipher cipher; + + private byte[] buffer; + private int bufOff; + + /** + * base constructor. + * + * @param cipher the cipher this buffering object wraps. + */ + public BufferedAsymmetricBlockCipher( + IAsymmetricBlockCipher cipher) + { + this.cipher = cipher; + } + + /** + * return the amount of data sitting in the buffer. + * + * @return the amount of data sitting in the buffer. + */ + internal int GetBufferPosition() + { + return bufOff; + } + + public override string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + public override int GetBlockSize() + { + return cipher.GetInputBlockSize(); + } + + public override int GetOutputSize( + int length) + { + return cipher.GetOutputBlockSize(); + } + + public override int GetUpdateOutputSize( + int length) + { + return 0; + } + + /** + * initialise the buffer and the underlying 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 override void Init( + bool forEncryption, + ICipherParameters parameters) + { + Reset(); + + cipher.Init(forEncryption, parameters); + + // + // we allow for an extra byte where people are using their own padding + // mechanisms on a raw cipher. + // + this.buffer = new byte[cipher.GetInputBlockSize() + (forEncryption ? 1 : 0)]; + this.bufOff = 0; + } + + public override byte[] ProcessByte( + byte input) + { + if (bufOff >= buffer.Length) + throw new DataLengthException("attempt to process message to long for cipher"); + + buffer[bufOff++] = input; + return null; + } + + public override byte[] ProcessBytes( + byte[] input, + int inOff, + int length) + { + if (length < 1) + return null; + + if (input == null) + throw new ArgumentNullException("input"); + if (bufOff + length > buffer.Length) + throw new DataLengthException("attempt to process message to long for cipher"); + + Array.Copy(input, inOff, buffer, bufOff, length); + bufOff += length; + return null; + } + + /** + * 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 override byte[] DoFinal() + { + byte[] outBytes = bufOff > 0 + ? cipher.ProcessBlock(buffer, 0, bufOff) + : EmptyBuffer; + + Reset(); + + return outBytes; + } + + public override byte[] DoFinal( + byte[] input, + int inOff, + int length) + { + ProcessBytes(input, inOff, length); + return DoFinal(); + } + + /// Reset the buffer + public override void Reset() + { + if (buffer != null) + { + Array.Clear(buffer, 0, buffer.Length); + bufOff = 0; + } + } + } +} diff --git a/crypto/src/crypto/BufferedBlockCipher.cs b/crypto/src/crypto/BufferedBlockCipher.cs new file mode 100644 index 000000000..3a98798a2 --- /dev/null +++ b/crypto/src/crypto/BufferedBlockCipher.cs @@ -0,0 +1,377 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace 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. + *

+ * 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 + : BufferedCipherBase + { + internal byte[] buf; + internal int bufOff; + internal bool forEncryption; + internal IBlockCipher cipher; + + /** + * constructor for subclasses + */ + protected BufferedBlockCipher() + { + } + + /** + * Create a buffered block cipher without padding. + * + * @param cipher the underlying block cipher this buffering object wraps. + * false otherwise. + */ + public BufferedBlockCipher( + IBlockCipher cipher) + { + if (cipher == null) + throw new ArgumentNullException("cipher"); + + this.cipher = cipher; + buf = new byte[cipher.GetBlockSize()]; + bufOff = 0; + } + + public override string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + /** + * 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. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + // Note: This doubles as the Init in the event that this cipher is being used as an IWrapper + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + ParametersWithRandom pwr = parameters as ParametersWithRandom; + if (pwr != null) + parameters = pwr.Parameters; + + Reset(); + + cipher.Init(forEncryption, parameters); + } + + /** + * return the blocksize for the underlying cipher. + * + * @return the blocksize for the underlying cipher. + */ + public override 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 override int GetUpdateOutputSize( + int length) + { + int total = length + bufOff; + int 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 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 override int GetOutputSize( + int length) + { + // Note: Can assume IsPartialBlockOkay 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessByte( + byte input, + byte[] output, + int outOff) + { + buf[bufOff++] = input; + + if (bufOff == buf.Length) + { + if ((outOff + buf.Length) > output.Length) + throw new DataLengthException("output buffer too short"); + + bufOff = 0; + return cipher.ProcessBlock(buf, 0, output, outOff); + } + + return 0; + } + + public override byte[] ProcessByte( + byte input) + { + int outLength = GetUpdateOutputSize(1); + + byte[] outBytes = outLength > 0 ? new byte[outLength] : null; + + int pos = ProcessByte(input, outBytes, 0); + + if (outLength > 0 && pos < outLength) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + public override byte[] ProcessBytes( + byte[] input, + int inOff, + int length) + { + if (input == null) + throw new ArgumentNullException("input"); + if (length < 1) + return null; + + int outLength = GetUpdateOutputSize(length); + + byte[] outBytes = outLength > 0 ? new byte[outLength] : null; + + int pos = ProcessBytes(input, inOff, length, outBytes, 0); + + if (outLength > 0 && pos < outLength) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + + return outBytes; + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + if (length < 1) + { + if (length < 0) + throw new ArgumentException("Can't have a negative input length!"); + + return 0; + } + + int blockSize = GetBlockSize(); + int outLength = GetUpdateOutputSize(length); + + if (outLength > 0) + { + if ((outOff + outLength) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + } + + int resultLen = 0; + int gapLen = buf.Length - bufOff; + if (length > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + resultLen += cipher.ProcessBlock(buf, 0, output, outOff); + bufOff = 0; + length -= gapLen; + inOff += gapLen; + while (length > buf.Length) + { + resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen); + length -= blockSize; + inOff += blockSize; + } + } + Array.Copy(input, inOff, buf, bufOff, length); + bufOff += length; + if (bufOff == buf.Length) + { + resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen); + bufOff = 0; + } + return resultLen; + } + + public override byte[] DoFinal() + { + byte[] outBytes = EmptyBuffer; + + int length = GetOutputSize(0); + if (length > 0) + { + outBytes = new byte[length]; + + int pos = DoFinal(outBytes, 0); + if (pos < outBytes.Length) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + } + else + { + Reset(); + } + + return outBytes; + } + + public override byte[] DoFinal( + byte[] input, + int inOff, + int inLen) + { + if (input == null) + throw new ArgumentNullException("input"); + + int length = GetOutputSize(inLen); + + byte[] outBytes = EmptyBuffer; + + if (length > 0) + { + outBytes = new byte[length]; + + int pos = (inLen > 0) + ? ProcessBytes(input, inOff, inLen, outBytes, 0) + : 0; + + pos += DoFinal(outBytes, pos); + + if (pos < outBytes.Length) + { + byte[] tmp = new byte[pos]; + Array.Copy(outBytes, 0, tmp, 0, pos); + outBytes = tmp; + } + } + else + { + Reset(); + } + + return outBytes; + } + + /** + * 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 InvalidOperationException 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 override int DoFinal( + byte[] output, + int outOff) + { + try + { + if (bufOff != 0) + { + if (!cipher.IsPartialBlockOkay) + { + throw new DataLengthException("data not block size aligned"); + } + + if (outOff + bufOff > output.Length) + { + throw new DataLengthException("output buffer too short for DoFinal()"); + } + + // NB: Can't copy directly, or we may write too much output + cipher.ProcessBlock(buf, 0, buf, 0); + Array.Copy(buf, 0, output, outOff, bufOff); + } + + return bufOff; + } + 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 override void Reset() + { + Array.Clear(buf, 0, buf.Length); + bufOff = 0; + + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/BufferedCipherBase.cs b/crypto/src/crypto/BufferedCipherBase.cs new file mode 100644 index 000000000..9d8610211 --- /dev/null +++ b/crypto/src/crypto/BufferedCipherBase.cs @@ -0,0 +1,113 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + public abstract class BufferedCipherBase + : IBufferedCipher + { + protected static readonly byte[] EmptyBuffer = new byte[0]; + + public abstract string AlgorithmName { get; } + + public abstract void Init(bool forEncryption, ICipherParameters parameters); + + public abstract int GetBlockSize(); + + public abstract int GetOutputSize(int inputLen); + public abstract int GetUpdateOutputSize(int inputLen); + + public abstract byte[] ProcessByte(byte input); + + public virtual int ProcessByte( + byte input, + byte[] output, + int outOff) + { + byte[] outBytes = ProcessByte(input); + if (outBytes == null) + return 0; + if (outOff + outBytes.Length > output.Length) + throw new DataLengthException("output buffer too short"); + outBytes.CopyTo(output, outOff); + return outBytes.Length; + } + + public virtual byte[] ProcessBytes( + byte[] input) + { + return ProcessBytes(input, 0, input.Length); + } + + public abstract byte[] ProcessBytes(byte[] input, int inOff, int length); + + public virtual int ProcessBytes( + byte[] input, + byte[] output, + int outOff) + { + return ProcessBytes(input, 0, input.Length, output, outOff); + } + + public virtual int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + byte[] outBytes = ProcessBytes(input, inOff, length); + if (outBytes == null) + return 0; + if (outOff + outBytes.Length > output.Length) + throw new DataLengthException("output buffer too short"); + outBytes.CopyTo(output, outOff); + return outBytes.Length; + } + + public abstract byte[] DoFinal(); + + public virtual byte[] DoFinal( + byte[] input) + { + return DoFinal(input, 0, input.Length); + } + + public abstract byte[] DoFinal( + byte[] input, + int inOff, + int length); + + public virtual int DoFinal( + byte[] output, + int outOff) + { + byte[] outBytes = DoFinal(); + if (outOff + outBytes.Length > output.Length) + throw new DataLengthException("output buffer too short"); + outBytes.CopyTo(output, outOff); + return outBytes.Length; + } + + public virtual int DoFinal( + byte[] input, + byte[] output, + int outOff) + { + return DoFinal(input, 0, input.Length, output, outOff); + } + + public virtual int DoFinal( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + int len = ProcessBytes(input, inOff, length, output, outOff); + len += DoFinal(output, outOff + len); + return len; + } + + public abstract void Reset(); + } +} diff --git a/crypto/src/crypto/BufferedIesCipher.cs b/crypto/src/crypto/BufferedIesCipher.cs new file mode 100644 index 000000000..6dab4ae33 --- /dev/null +++ b/crypto/src/crypto/BufferedIesCipher.cs @@ -0,0 +1,113 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto +{ + public class BufferedIesCipher + : BufferedCipherBase + { + private readonly IesEngine engine; + private bool forEncryption; + private MemoryStream buffer = new MemoryStream(); + + public BufferedIesCipher( + IesEngine engine) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + this.engine = engine; + } + + public override string AlgorithmName + { + // TODO Create IESEngine.AlgorithmName + get { return "IES"; } + } + + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + // TODO + throw Platform.CreateNotImplementedException("IES"); + } + + public override int GetBlockSize() + { + return 0; + } + + public override int GetOutputSize( + int inputLen) + { + if (engine == null) + throw new InvalidOperationException("cipher not initialised"); + + int baseLen = inputLen + (int) buffer.Length; + return forEncryption + ? baseLen + 20 + : baseLen - 20; + } + + public override int GetUpdateOutputSize( + int inputLen) + { + return 0; + } + + public override byte[] ProcessByte( + byte input) + { + buffer.WriteByte(input); + return null; + } + + public override byte[] ProcessBytes( + byte[] input, + int inOff, + int length) + { + if (input == null) + throw new ArgumentNullException("input"); + if (inOff < 0) + throw new ArgumentException("inOff"); + if (length < 0) + throw new ArgumentException("length"); + if (inOff + length > input.Length) + throw new ArgumentException("invalid offset/length specified for input array"); + + buffer.Write(input, inOff, length); + return null; + } + + public override byte[] DoFinal() + { + byte[] buf = buffer.ToArray(); + + Reset(); + + return engine.ProcessBlock(buf, 0, buf.Length); + } + + public override byte[] DoFinal( + byte[] input, + int inOff, + int length) + { + ProcessBytes(input, inOff, length); + return DoFinal(); + } + + public override void Reset() + { + buffer.SetLength(0); + } + } +} diff --git a/crypto/src/crypto/BufferedStreamCipher.cs b/crypto/src/crypto/BufferedStreamCipher.cs new file mode 100644 index 000000000..2d4987bba --- /dev/null +++ b/crypto/src/crypto/BufferedStreamCipher.cs @@ -0,0 +1,131 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto +{ + public class BufferedStreamCipher + : BufferedCipherBase + { + private readonly IStreamCipher cipher; + + public BufferedStreamCipher( + IStreamCipher cipher) + { + if (cipher == null) + throw new ArgumentNullException("cipher"); + + this.cipher = cipher; + } + + public override string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + cipher.Init(forEncryption, parameters); + } + + public override int GetBlockSize() + { + return 0; + } + + public override int GetOutputSize( + int inputLen) + { + return inputLen; + } + + public override int GetUpdateOutputSize( + int inputLen) + { + return inputLen; + } + + public override byte[] ProcessByte( + byte input) + { + return new byte[]{ cipher.ReturnByte(input) }; + } + + public override int ProcessByte( + byte input, + byte[] output, + int outOff) + { + if (outOff >= output.Length) + throw new DataLengthException("output buffer too short"); + + output[outOff] = cipher.ReturnByte(input); + return 1; + } + + public override byte[] ProcessBytes( + byte[] input, + int inOff, + int length) + { + if (length < 1) + return null; + + byte[] output = new byte[length]; + cipher.ProcessBytes(input, inOff, length, output, 0); + return output; + } + + public override int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + if (length < 1) + return 0; + + if (length > 0) + { + cipher.ProcessBytes(input, inOff, length, output, outOff); + } + + return length; + } + + public override byte[] DoFinal() + { + Reset(); + + return EmptyBuffer; + } + + public override byte[] DoFinal( + byte[] input, + int inOff, + int length) + { + if (length < 1) + return EmptyBuffer; + + byte[] output = ProcessBytes(input, inOff, length); + + Reset(); + + return output; + } + + public override void Reset() + { + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/CipherKeyGenerator.cs b/crypto/src/crypto/CipherKeyGenerator.cs new file mode 100644 index 000000000..5d00d34dd --- /dev/null +++ b/crypto/src/crypto/CipherKeyGenerator.cs @@ -0,0 +1,83 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto +{ + /** + * The base class for symmetric, or secret, cipher key generators. + */ + public class CipherKeyGenerator + { + protected internal SecureRandom random; + protected internal int strength; + private bool uninitialised = true; + private int defaultStrength; + + public CipherKeyGenerator() + { + } + + internal CipherKeyGenerator( + int defaultStrength) + { + if (defaultStrength < 1) + throw new ArgumentException("strength must be a positive value", "defaultStrength"); + + this.defaultStrength = defaultStrength; + } + + public int DefaultStrength + { + get { return defaultStrength; } + } + + /** + * initialise the key generator. + * + * @param param the parameters to be used for key generation + */ + public void Init( + KeyGenerationParameters parameters) + { + if (parameters == null) + throw new ArgumentNullException("parameters"); + + this.uninitialised = false; + + engineInit(parameters); + } + + protected virtual void engineInit( + KeyGenerationParameters parameters) + { + this.random = parameters.Random; + this.strength = (parameters.Strength + 7) / 8; + } + + /** + * Generate a secret key. + * + * @return a byte array containing the key value. + */ + public byte[] GenerateKey() + { + if (uninitialised) + { + if (defaultStrength < 1) + throw new InvalidOperationException("Generator has not been initialised"); + + uninitialised = false; + + engineInit(new KeyGenerationParameters(new SecureRandom(), defaultStrength)); + } + + return engineGenerateKey(); + } + + protected virtual byte[] engineGenerateKey() + { + return random.GenerateSeed(strength); + } + } +} diff --git a/crypto/src/crypto/CryptoException.cs b/crypto/src/crypto/CryptoException.cs new file mode 100644 index 000000000..67f0d86f2 --- /dev/null +++ b/crypto/src/crypto/CryptoException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CryptoException + : Exception + { + public CryptoException() + { + } + + public CryptoException( + string message) + : base(message) + { + } + + public CryptoException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/crypto/DataLengthException.cs b/crypto/src/crypto/DataLengthException.cs new file mode 100644 index 000000000..e9efc0bd3 --- /dev/null +++ b/crypto/src/crypto/DataLengthException.cs @@ -0,0 +1,42 @@ +using System; + +namespace 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. + */ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class DataLengthException + : CryptoException + { + /** + * 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) + : base(message) + { + } + + public DataLengthException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/crypto/IAsymmetricBlockCipher.cs b/crypto/src/crypto/IAsymmetricBlockCipher.cs new file mode 100644 index 000000000..455cfaa69 --- /dev/null +++ b/crypto/src/crypto/IAsymmetricBlockCipher.cs @@ -0,0 +1,30 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// Base interface for a public/private key block cipher. + public interface IAsymmetricBlockCipher + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// Initialise for encryption if true, for decryption if false. + /// The key or other data required by the cipher. + void Init(bool forEncryption, ICipherParameters parameters); + + /// The maximum size, in bytes, an input block may be. + int GetInputBlockSize(); + + /// The maximum size, in bytes, an output block will be. + int GetOutputBlockSize(); + + /// Process a block. + /// The input buffer. + /// The offset into inBuf that the input block begins. + /// The length of the input block. + /// Input decrypts improperly. + /// Input is too large for the cipher. + byte[] ProcessBlock(byte[] inBuf, int inOff, int inLen); + } +} diff --git a/crypto/src/crypto/IAsymmetricCipherKeyPairGenerator.cs b/crypto/src/crypto/IAsymmetricCipherKeyPairGenerator.cs new file mode 100644 index 000000000..9ec5dfada --- /dev/null +++ b/crypto/src/crypto/IAsymmetricCipherKeyPairGenerator.cs @@ -0,0 +1,24 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * interface that a public/private key pair generator should conform to. + */ + public interface IAsymmetricCipherKeyPairGenerator + { + /** + * intialise the key pair generator. + * + * @param the parameters the key pair is to be initialised with. + */ + void Init(KeyGenerationParameters parameters); + + /** + * return an AsymmetricCipherKeyPair containing the Generated keys. + * + * @return an AsymmetricCipherKeyPair containing the Generated keys. + */ + AsymmetricCipherKeyPair GenerateKeyPair(); + } +} diff --git a/crypto/src/crypto/IBasicAgreement.cs b/crypto/src/crypto/IBasicAgreement.cs new file mode 100644 index 000000000..7dfc618d6 --- /dev/null +++ b/crypto/src/crypto/IBasicAgreement.cs @@ -0,0 +1,29 @@ +using System; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto +{ + /** + * The basic interface that basic Diffie-Hellman implementations + * conforms to. + */ + public interface IBasicAgreement + { + /** + * initialise the agreement engine. + */ + void Init(ICipherParameters parameters); + + /** + * 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(ICipherParameters pubKey); + } + +} diff --git a/crypto/src/crypto/IBlockCipher.cs b/crypto/src/crypto/IBlockCipher.cs new file mode 100644 index 000000000..a3ad6d6e5 --- /dev/null +++ b/crypto/src/crypto/IBlockCipher.cs @@ -0,0 +1,36 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// Base interface for a symmetric key block cipher. + public interface IBlockCipher + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// Initialise for encryption if true, for decryption if false. + /// The key or other data required by the cipher. + void Init(bool forEncryption, ICipherParameters parameters); + + /// The block size for this cipher, in bytes. + int GetBlockSize(); + + /// Indicates whether this cipher can handle partial blocks. + bool IsPartialBlockOkay { get; } + + /// Process a block. + /// The input buffer. + /// The offset into inBuf that the input block begins. + /// The output buffer. + /// The offset into outBuf to write the output block. + /// If input block is wrong size, or outBuf too small. + /// The number of bytes processed and produced. + int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff); + + /// + /// Reset the cipher to the same state as it was after the last init (if there was one). + /// + void Reset(); + } +} diff --git a/crypto/src/crypto/IBufferedCipher.cs b/crypto/src/crypto/IBufferedCipher.cs new file mode 100644 index 000000000..69dec9596 --- /dev/null +++ b/crypto/src/crypto/IBufferedCipher.cs @@ -0,0 +1,44 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// Block cipher engines are expected to conform to this interface. + public interface IBufferedCipher + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// If true the cipher is initialised for encryption, + /// if false for decryption. + /// The key and other data required by the cipher. + void Init(bool forEncryption, ICipherParameters parameters); + + int GetBlockSize(); + + int GetOutputSize(int inputLen); + + int GetUpdateOutputSize(int inputLen); + + byte[] ProcessByte(byte input); + int ProcessByte(byte input, byte[] output, int outOff); + + byte[] ProcessBytes(byte[] input); + byte[] ProcessBytes(byte[] input, int inOff, int length); + int ProcessBytes(byte[] input, byte[] output, int outOff); + int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff); + + byte[] DoFinal(); + byte[] DoFinal(byte[] input); + byte[] DoFinal(byte[] input, int inOff, int length); + int DoFinal(byte[] output, int outOff); + int DoFinal(byte[] input, byte[] output, int outOff); + int DoFinal(byte[] input, int inOff, int length, byte[] output, int outOff); + + /// + /// Reset the cipher. After resetting the cipher is in the same state + /// as it was after the last init (if there was one). + /// + void Reset(); + } +} diff --git a/crypto/src/crypto/ICipherParameters.cs b/crypto/src/crypto/ICipherParameters.cs new file mode 100644 index 000000000..fff0941c7 --- /dev/null +++ b/crypto/src/crypto/ICipherParameters.cs @@ -0,0 +1,11 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * all parameter classes implement this. + */ + public interface ICipherParameters + { + } +} diff --git a/crypto/src/crypto/IDSA.cs b/crypto/src/crypto/IDSA.cs new file mode 100644 index 000000000..46056d8ca --- /dev/null +++ b/crypto/src/crypto/IDSA.cs @@ -0,0 +1,40 @@ +using System; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto +{ + /** + * interface for classes implementing the Digital Signature Algorithm + */ + public interface IDsa + { + string AlgorithmName { get; } + + /** + * 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. + */ + void Init(bool forSigning, ICipherParameters parameters); + + /** + * 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. + */ + 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. + */ + bool VerifySignature(byte[] message, BigInteger r, BigInteger s); + } +} diff --git a/crypto/src/crypto/IDerivationFunction.cs b/crypto/src/crypto/IDerivationFunction.cs new file mode 100644 index 000000000..7f289f790 --- /dev/null +++ b/crypto/src/crypto/IDerivationFunction.cs @@ -0,0 +1,24 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * base interface for general purpose byte derivation functions. + */ + public interface IDerivationFunction + { + void Init(IDerivationParameters parameters); + + /** + * return the message digest used as the basis for the function + */ + IDigest Digest + { + get; + } + + int GenerateBytes(byte[] output, int outOff, int length); + //throws DataLengthException, ArgumentException; + } + +} diff --git a/crypto/src/crypto/IDerivationParameters.cs b/crypto/src/crypto/IDerivationParameters.cs new file mode 100644 index 000000000..f1c848568 --- /dev/null +++ b/crypto/src/crypto/IDerivationParameters.cs @@ -0,0 +1,11 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * Parameters for key/byte stream derivation classes + */ + public interface IDerivationParameters + { + } +} diff --git a/crypto/src/crypto/IDigest.cs b/crypto/src/crypto/IDigest.cs new file mode 100644 index 000000000..6769dcc42 --- /dev/null +++ b/crypto/src/crypto/IDigest.cs @@ -0,0 +1,61 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * interface that a message digest conforms to. + */ + public interface IDigest + { + /** + * return the algorithm name + * + * @return the algorithm name + */ + string AlgorithmName { get; } + + /** + * 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. + */ + int GetDigestSize(); + + /** + * return the size, in bytes, of the internal buffer used by this digest. + * + * @return the size, in bytes, of the internal buffer used by this digest. + */ + int GetByteLength(); + + /** + * update the message digest with a single byte. + * + * @param inByte the input byte to be entered. + */ + void Update(byte input); + + /** + * update the message digest with a block of bytes. + * + * @param input 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. + */ + void BlockUpdate(byte[] input, int inOff, int length); + + /** + * Close the digest, producing the final digest value. The doFinal + * call leaves the digest reset. + * + * @param output the array the digest is to be copied into. + * @param outOff the offset into the out array the digest is to start at. + */ + int DoFinal(byte[] output, int outOff); + + /** + * reset the digest back to it's initial state. + */ + void Reset(); + } +} diff --git a/crypto/src/crypto/IMac.cs b/crypto/src/crypto/IMac.cs new file mode 100644 index 000000000..03a86e8b6 --- /dev/null +++ b/crypto/src/crypto/IMac.cs @@ -0,0 +1,69 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * The base interface for implementations of message authentication codes (MACs). + */ + public interface IMac + { + /** + * Initialise the MAC. + * + * @param param the key and other data required by the MAC. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + void Init(ICipherParameters parameters); + + /** + * Return the name of the algorithm the MAC implements. + * + * @return the name of the algorithm the MAC implements. + */ + string AlgorithmName { get; } + + /** + * Return the block size for this MAC (in bytes). + * + * @return the block size for this MAC in bytes. + */ + int GetMacSize(); + + /** + * add a single byte to the mac for processing. + * + * @param in the byte to be processed. + * @exception InvalidOperationException if the MAC is not initialised. + */ + void Update(byte input); + + /** + * @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 InvalidOperationException if the MAC is not initialised. + * @exception DataLengthException if there isn't enough data in in. + */ + void BlockUpdate(byte[] input, int inOff, int len); + + /** + * Compute the final stage of the MAC writing the output to the out + * parameter. + *

+ * 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 InvalidOperationException if the MAC is not initialised. + */ + int DoFinal(byte[] output, int outOff); + + /** + * 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). + */ + void Reset(); + } +} diff --git a/crypto/src/crypto/ISigner.cs b/crypto/src/crypto/ISigner.cs new file mode 100644 index 000000000..e03bbf4d3 --- /dev/null +++ b/crypto/src/crypto/ISigner.cs @@ -0,0 +1,50 @@ + +using System; +using System.Text; + +namespace Org.BouncyCastle.Crypto +{ + public interface ISigner + { + /** + * Return the name of the algorithm the signer implements. + * + * @return the name of the algorithm the signer implements. + */ + string AlgorithmName { get; } + + /** + * Initialise the signer for signing or verification. + * + * @param forSigning true if for signing, false otherwise + * @param param necessary parameters. + */ + void Init(bool forSigning, ICipherParameters parameters); + + /** + * update the internal digest with the byte b + */ + void Update(byte input); + + /** + * update the internal digest with the byte array in + */ + void BlockUpdate(byte[] input, int inOff, int length); + + /** + * Generate a signature for the message we've been loaded with using + * the key we were initialised with. + */ + byte[] GenerateSignature(); + /** + * return true if the internal state represents the signature described + * in the passed in array. + */ + bool VerifySignature(byte[] signature); + + /** + * reset the internal state + */ + void Reset(); + } +} diff --git a/crypto/src/crypto/ISignerWithRecovery.cs b/crypto/src/crypto/ISignerWithRecovery.cs new file mode 100644 index 000000000..024f5cef5 --- /dev/null +++ b/crypto/src/crypto/ISignerWithRecovery.cs @@ -0,0 +1,37 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Crypto +{ + /** + * Signer with message recovery. + */ + public interface ISignerWithRecovery + : ISigner + { + /** + * Returns true if the signer has recovered the full message as + * part of signature verification. + * + * @return true if full message recovered. + */ + bool HasFullMessage(); + + /** + * Returns a reference to what message was recovered (if any). + * + * @return full/partial message, null if nothing. + */ + 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 + */ + void UpdateWithRecoveredMessage(byte[] signature); + } +} diff --git a/crypto/src/crypto/IStreamCipher.cs b/crypto/src/crypto/IStreamCipher.cs new file mode 100644 index 000000000..8e575a7e5 --- /dev/null +++ b/crypto/src/crypto/IStreamCipher.cs @@ -0,0 +1,45 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// The interface stream ciphers conform to. + public interface IStreamCipher + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// If true the cipher is initialised for encryption, + /// if false for decryption. + /// The key and other data required by the cipher. + /// + /// If the parameters argument is inappropriate. + /// + void Init(bool forEncryption, ICipherParameters parameters); + + /// encrypt/decrypt a single byte returning the result. + /// the byte to be processed. + /// the result of processing the input byte. + byte ReturnByte(byte input); + + /// + /// Process a block of bytes from input putting the result into output. + /// + /// The input byte array. + /// + /// The offset into input where the data to be processed starts. + /// + /// The number of bytes to be processed. + /// The output buffer the processed bytes go into. + /// + /// The offset into output the processed data starts at. + /// + /// If the output buffer is too small. + void ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff); + + /// + /// Reset the cipher to the same state as it was after the last init (if there was one). + /// + void Reset(); + } +} diff --git a/crypto/src/crypto/IWrapper.cs b/crypto/src/crypto/IWrapper.cs new file mode 100644 index 000000000..58202b302 --- /dev/null +++ b/crypto/src/crypto/IWrapper.cs @@ -0,0 +1,18 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto +{ + public interface IWrapper + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + void Init(bool forWrapping, ICipherParameters parameters); + + byte[] Wrap(byte[] input, int inOff, int length); + + byte[] Unwrap(byte[] input, int inOff, int length); + } +} diff --git a/crypto/src/crypto/InvalidCipherTextException.cs b/crypto/src/crypto/InvalidCipherTextException.cs new file mode 100644 index 000000000..4d2252654 --- /dev/null +++ b/crypto/src/crypto/InvalidCipherTextException.cs @@ -0,0 +1,40 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /** + * this exception is thrown whenever we find something we don't expect in a + * message. + */ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class InvalidCipherTextException + : 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) + : base(message) + { + } + + public InvalidCipherTextException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/crypto/KeyGenerationParameters.cs b/crypto/src/crypto/KeyGenerationParameters.cs new file mode 100644 index 000000000..0cb6b07c7 --- /dev/null +++ b/crypto/src/crypto/KeyGenerationParameters.cs @@ -0,0 +1,55 @@ +using System; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto +{ + /** + * 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) + { + if (random == null) + throw new ArgumentNullException("random"); + if (strength < 1) + throw new ArgumentException("strength must be a positive value", "strength"); + + this.random = random; + this.strength = strength; + } + + /** + * return the random source associated with this + * generator. + * + * @return the generators random source. + */ + public SecureRandom Random + { + get { 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 Strength + { + get { return strength; } + } + } +} diff --git a/crypto/src/crypto/MaxBytesExceededException.cs b/crypto/src/crypto/MaxBytesExceededException.cs new file mode 100644 index 000000000..be078cb13 --- /dev/null +++ b/crypto/src/crypto/MaxBytesExceededException.cs @@ -0,0 +1,32 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// + /// This exception is thrown whenever a cipher requires a change of key, iv + /// or similar after x amount of bytes enciphered + /// +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class MaxBytesExceededException + : CryptoException + { + public MaxBytesExceededException() + { + } + + public MaxBytesExceededException( + string message) + : base(message) + { + } + + public MaxBytesExceededException( + string message, + Exception e) + : base(message, e) + { + } + } +} diff --git a/crypto/src/crypto/PbeParametersGenerator.cs b/crypto/src/crypto/PbeParametersGenerator.cs new file mode 100644 index 000000000..21679d45e --- /dev/null +++ b/crypto/src/crypto/PbeParametersGenerator.cs @@ -0,0 +1,202 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto +{ + /** + * super class for all Password Based Encyrption (Pbe) parameter generator classes. + */ + public abstract class PbeParametersGenerator + { + protected byte[] mPassword; + protected byte[] mSalt; + protected int mIterationCount; + + /** + * 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 virtual void Init( + byte[] password, + byte[] salt, + int iterationCount) + { + if (password == null) + throw new ArgumentNullException("password"); + if (salt == null) + throw new ArgumentNullException("salt"); + + this.mPassword = Arrays.Clone(password); + this.mSalt = Arrays.Clone(salt); + this.mIterationCount = iterationCount; + } + + public virtual byte[] Password + { + get { return Arrays.Clone(mPassword); } + } + + /** + * return the password byte array. + * + * @return the password byte array. + */ + [Obsolete("Use 'Password' property")] + public byte[] GetPassword() + { + return Password; + } + + public virtual byte[] Salt + { + get { return Arrays.Clone(mSalt); } + } + + /** + * return the salt byte array. + * + * @return the salt byte array. + */ + [Obsolete("Use 'Salt' property")] + public byte[] GetSalt() + { + return Salt; + } + + /** + * return the iteration count. + * + * @return the iteration count. + */ + public virtual int IterationCount + { + get { return mIterationCount; } + } + + /** + * 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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public abstract ICipherParameters GenerateDerivedParameters(int keySize); + public abstract ICipherParameters GenerateDerivedParameters(string algorithm, 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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public abstract ICipherParameters GenerateDerivedParameters(int keySize, int ivSize); + public abstract ICipherParameters GenerateDerivedParameters(string algorithm, 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 ICipherParameters 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) + return new byte[0]; + + return Strings.ToAsciiByteArray(password); + } + + [Obsolete("Use version taking 'char[]' instead")] + public static byte[] Pkcs5PasswordToBytes( + string password) + { + if (password == null) + return new byte[0]; + + return Strings.ToAsciiByteArray(password); + } + + /** + * 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 new byte[0]; + + return Encoding.UTF8.GetBytes(password); + } + + [Obsolete("Use version taking 'char[]' instead")] + public static byte[] Pkcs5PasswordToUtf8Bytes( + string password) + { + if (password == null) + return new byte[0]; + + return Encoding.UTF8.GetBytes(password); + } + + /** + * 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) + { + return Pkcs12PasswordToBytes(password, false); + } + + public static byte[] Pkcs12PasswordToBytes( + char[] password, + bool wrongPkcs12Zero) + { + if (password == null || password.Length < 1) + { + return new byte[wrongPkcs12Zero ? 2 : 0]; + } + + // +1 for extra 2 pad bytes. + byte[] bytes = new byte[(password.Length + 1) * 2]; + + Encoding.BigEndianUnicode.GetBytes(password, 0, password.Length, bytes, 0); + + return bytes; + } + } +} diff --git a/crypto/src/crypto/StreamBlockCipher.cs b/crypto/src/crypto/StreamBlockCipher.cs new file mode 100644 index 000000000..ef2a8b68a --- /dev/null +++ b/crypto/src/crypto/StreamBlockCipher.cs @@ -0,0 +1,109 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto +{ + /** + * a wrapper for block ciphers with a single byte block size, so that they + * can be treated like stream ciphers. + */ + public class StreamBlockCipher + : IStreamCipher + { + private readonly IBlockCipher cipher; + private readonly byte[] oneByte = new byte[1]; + + /** + * basic constructor. + * + * @param cipher the block cipher to be wrapped. + * @exception ArgumentException if the cipher has a block size other than + * one. + */ + public StreamBlockCipher( + IBlockCipher cipher) + { + if (cipher == null) + throw new ArgumentNullException("cipher"); + if (cipher.GetBlockSize() != 1) + throw new ArgumentException("block cipher block size != 1.", "cipher"); + + this.cipher = cipher; + } + + /** + * initialise the underlying cipher. + * + * @param forEncryption true if we are setting up for encryption, false otherwise. + * @param param the necessary parameters for the underlying cipher to be initialised. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + cipher.Init(forEncryption, parameters); + } + + /** + * return the name of the algorithm we are wrapping. + * + * @return the name of the algorithm we are wrapping. + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + /** + * 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 input) + { + oneByte[0] = input; + + cipher.ProcessBlock(oneByte, 0, oneByte, 0); + + return oneByte[0]; + } + + /** + * process a block of bytes from in putting the result into out. + * + * @param in the input byte array. + * @param inOff the offset into the in array where the data to be processed starts. + * @param len the number of bytes to be processed. + * @param out the output buffer the processed bytes go into. + * @param outOff the offset into the output byte array the processed data stars at. + * @exception DataLengthException if the output buffer is too small. + */ + public void ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + if (outOff + length > output.Length) + throw new DataLengthException("output buffer too small in ProcessBytes()"); + + for (int i = 0; i != length; i++) + { + cipher.ProcessBlock(input, inOff + i, output, outOff + i); + } + } + + /** + * reset the underlying cipher. This leaves it in the same state + * it was at after the last init (if there was one). + */ + public void Reset() + { + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/agreement/DHAgreement.cs b/crypto/src/crypto/agreement/DHAgreement.cs new file mode 100644 index 000000000..d214caafe --- /dev/null +++ b/crypto/src/crypto/agreement/DHAgreement.cs @@ -0,0 +1,93 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + /** + * a Diffie-Hellman key exchange engine. + *

+ * 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.

+ *

+ * 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( + ICipherParameters parameters) + { + AsymmetricKeyParameter kParam; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + + this.random = rParam.Random; + kParam = (AsymmetricKeyParameter)rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + kParam = (AsymmetricKeyParameter)parameters; + } + + if (!(kParam is DHPrivateKeyParameters)) + { + throw new ArgumentException("DHEngine expects DHPrivateKeyParameters"); + } + + this.key = (DHPrivateKeyParameters)kParam; + this.dhParams = key.Parameters; + } + + /** + * 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.Private).X; + + return ((DHPublicKeyParameters)dhPair.Public).Y; + } + + /** + * 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 == null) + throw new ArgumentNullException("pub"); + if (message == null) + throw new ArgumentNullException("message"); + + if (!pub.Parameters.Equals(dhParams)) + { + throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); + } + + BigInteger p = dhParams.P; + + return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p); + } + } +} diff --git a/crypto/src/crypto/agreement/DHBasicAgreement.cs b/crypto/src/crypto/agreement/DHBasicAgreement.cs new file mode 100644 index 000000000..75b5e9db5 --- /dev/null +++ b/crypto/src/crypto/agreement/DHBasicAgreement.cs @@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + /** + * a Diffie-Hellman key agreement class. + *

+ * 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 + : IBasicAgreement + { + private DHPrivateKeyParameters key; + private DHParameters dhParams; + + public virtual void Init( + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + if (!(parameters is DHPrivateKeyParameters)) + { + throw new ArgumentException("DHEngine expects DHPrivateKeyParameters"); + } + + this.key = (DHPrivateKeyParameters) parameters; + this.dhParams = key.Parameters; + } + + public virtual int GetFieldSize() + { + return (key.Parameters.P.BitLength + 7) / 8; + } + + /** + * given a short term public key from a given party calculate the next + * message in the agreement sequence. + */ + public virtual BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + if (this.key == null) + throw new InvalidOperationException("Agreement algorithm not initialised"); + + DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey; + + if (!pub.Parameters.Equals(dhParams)) + { + throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); + } + + return pub.Y.ModPow(key.X, dhParams.P); + } + } +} diff --git a/crypto/src/crypto/agreement/ECDHBasicAgreement.cs b/crypto/src/crypto/agreement/ECDHBasicAgreement.cs new file mode 100644 index 000000000..fa587b234 --- /dev/null +++ b/crypto/src/crypto/agreement/ECDHBasicAgreement.cs @@ -0,0 +1,54 @@ +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + /** + * 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 + : IBasicAgreement + { + protected internal ECPrivateKeyParameters privKey; + + public virtual void Init( + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom)parameters).Parameters; + } + + this.privKey = (ECPrivateKeyParameters)parameters; + } + + public virtual int GetFieldSize() + { + return (privKey.Parameters.Curve.FieldSize + 7) / 8; + } + + public virtual BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey; + ECPoint P = pub.Q.Multiply(privKey.D); + + // if ( p.IsInfinity ) throw new Exception("d*Q == infinity"); + + return P.X.ToBigInteger(); + } + } +} diff --git a/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs b/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs new file mode 100644 index 000000000..e1c572373 --- /dev/null +++ b/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs @@ -0,0 +1,62 @@ +using System; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + /** + * 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). + *

+ * 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 + : IBasicAgreement + { + private ECPrivateKeyParameters key; + + public virtual void Init( + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + this.key = (ECPrivateKeyParameters)parameters; + } + + public virtual int GetFieldSize() + { + return (key.Parameters.Curve.FieldSize + 7) / 8; + } + + public virtual BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey; + ECDomainParameters parameters = pub.Parameters; + ECPoint P = pub.Q.Multiply(parameters.H.Multiply(key.D)); + + // if ( p.IsInfinity ) throw new Exception("Invalid public key"); + + return P.X.ToBigInteger(); + } + } +} diff --git a/crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs b/crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs new file mode 100644 index 000000000..28437a268 --- /dev/null +++ b/crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.Agreement.Kdf; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + public class ECDHWithKdfBasicAgreement + : ECDHBasicAgreement + { + private readonly string algorithm; + private readonly IDerivationFunction kdf; + + public ECDHWithKdfBasicAgreement( + string algorithm, + IDerivationFunction kdf) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (kdf == null) + throw new ArgumentNullException("kdf"); + + this.algorithm = algorithm; + this.kdf = kdf; + } + + public override BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + // Note that the ec.KeyAgreement class in JCE only uses kdf in one + // of the engineGenerateSecret methods. + + BigInteger result = base.CalculateAgreement(pubKey); + + int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm); + + DHKdfParameters dhKdfParams = new DHKdfParameters( + new DerObjectIdentifier(algorithm), + keySize, + bigIntToBytes(result)); + + kdf.Init(dhKdfParams); + + byte[] keyBytes = new byte[keySize / 8]; + kdf.GenerateBytes(keyBytes, 0, keyBytes.Length); + + return new BigInteger(1, keyBytes); + } + + private byte[] bigIntToBytes( + BigInteger r) + { + int byteLength = X9IntegerConverter.GetByteLength(privKey.Parameters.G.X); + return X9IntegerConverter.IntegerToBytes(r, byteLength); + } + } +} diff --git a/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs b/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs new file mode 100644 index 000000000..3559d3e81 --- /dev/null +++ b/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs @@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + public class ECMqvBasicAgreement + : IBasicAgreement + { + protected internal MqvPrivateParameters privParams; + + public virtual void Init( + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom)parameters).Parameters; + } + + this.privParams = (MqvPrivateParameters)parameters; + } + + public virtual int GetFieldSize() + { + return (privParams.StaticPrivateKey.Parameters.Curve.FieldSize + 7) / 8; + } + + public virtual BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + MqvPublicParameters pubParams = (MqvPublicParameters)pubKey; + + ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey; + + ECPoint agreement = calculateMqvAgreement(staticPrivateKey.Parameters, staticPrivateKey, + privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey, + pubParams.StaticPublicKey, pubParams.EphemeralPublicKey); + + return agreement.X.ToBigInteger(); + } + + // The ECMQV Primitive as described in SEC-1, 3.4 + private static ECPoint calculateMqvAgreement( + ECDomainParameters parameters, + ECPrivateKeyParameters d1U, + ECPrivateKeyParameters d2U, + ECPublicKeyParameters Q2U, + ECPublicKeyParameters Q1V, + ECPublicKeyParameters Q2V) + { + BigInteger n = parameters.N; + int e = (n.BitLength + 1) / 2; + BigInteger powE = BigInteger.One.ShiftLeft(e); + + // The Q2U public key is optional + ECPoint q; + if (Q2U == null) + { + q = parameters.G.Multiply(d2U.D); + } + else + { + q = Q2U.Q; + } + + BigInteger x = q.X.ToBigInteger(); + BigInteger xBar = x.Mod(powE); + BigInteger Q2UBar = xBar.SetBit(e); + BigInteger s = d1U.D.Multiply(Q2UBar).Mod(n).Add(d2U.D).Mod(n); + + BigInteger xPrime = Q2V.Q.X.ToBigInteger(); + BigInteger xPrimeBar = xPrime.Mod(powE); + BigInteger Q2VBar = xPrimeBar.SetBit(e); + + BigInteger hs = parameters.H.Multiply(s).Mod(n); + + //ECPoint p = Q1V.Q.Multiply(Q2VBar).Add(Q2V.Q).Multiply(hs); + ECPoint p = ECAlgorithms.SumOfTwoMultiplies( + Q1V.Q, Q2VBar.Multiply(hs).Mod(n), Q2V.Q, hs); + + if (p.IsInfinity) + throw new InvalidOperationException("Infinity is not a valid agreement value for MQV"); + + return p; + } + } +} diff --git a/crypto/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs b/crypto/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs new file mode 100644 index 000000000..093ce4056 --- /dev/null +++ b/crypto/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.Agreement.Kdf; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + public class ECMqvWithKdfBasicAgreement + : ECMqvBasicAgreement + { + private readonly string algorithm; + private readonly IDerivationFunction kdf; + + public ECMqvWithKdfBasicAgreement( + string algorithm, + IDerivationFunction kdf) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (kdf == null) + throw new ArgumentNullException("kdf"); + + this.algorithm = algorithm; + this.kdf = kdf; + } + + public override BigInteger CalculateAgreement( + ICipherParameters pubKey) + { + // Note that the ec.KeyAgreement class in JCE only uses kdf in one + // of the engineGenerateSecret methods. + + BigInteger result = base.CalculateAgreement(pubKey); + + int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm); + + DHKdfParameters dhKdfParams = new DHKdfParameters( + new DerObjectIdentifier(algorithm), + keySize, + bigIntToBytes(result)); + + kdf.Init(dhKdfParams); + + byte[] keyBytes = new byte[keySize / 8]; + kdf.GenerateBytes(keyBytes, 0, keyBytes.Length); + + return new BigInteger(1, keyBytes); + } + + private byte[] bigIntToBytes( + BigInteger r) + { + int byteLength = X9IntegerConverter.GetByteLength(privParams.StaticPrivateKey.Parameters.G.X); + return X9IntegerConverter.IntegerToBytes(r, byteLength); + } + } +} diff --git a/crypto/src/crypto/agreement/kdf/DHKdfParameters.cs b/crypto/src/crypto/agreement/kdf/DHKdfParameters.cs new file mode 100644 index 000000000..f6c9e6079 --- /dev/null +++ b/crypto/src/crypto/agreement/kdf/DHKdfParameters.cs @@ -0,0 +1,57 @@ +using System; + +using Org.BouncyCastle.Asn1; + +namespace Org.BouncyCastle.Crypto.Agreement.Kdf +{ + public class DHKdfParameters + : IDerivationParameters + { + private readonly DerObjectIdentifier algorithm; + private readonly int keySize; + private readonly byte[] z; + private readonly byte[] extraInfo; + + public DHKdfParameters( + DerObjectIdentifier algorithm, + int keySize, + byte[] z) + : this(algorithm, keySize, z, null) + { + } + + public DHKdfParameters( + DerObjectIdentifier algorithm, + int keySize, + byte[] z, + byte[] extraInfo) + { + this.algorithm = algorithm; + this.keySize = keySize; + this.z = z; // TODO Clone? + this.extraInfo = extraInfo; + } + + public DerObjectIdentifier Algorithm + { + get { return algorithm; } + } + + public int KeySize + { + get { return keySize; } + } + + public byte[] GetZ() + { + // TODO Clone? + return z; + } + + public byte[] GetExtraInfo() + { + // TODO Clone? + return extraInfo; + } + } +} diff --git a/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs new file mode 100644 index 000000000..259e21e69 --- /dev/null +++ b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs @@ -0,0 +1,112 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Agreement.Kdf +{ + /** + * RFC 2631 Diffie-hellman KEK derivation function. + */ + public class DHKekGenerator + : IDerivationFunction + { + private readonly IDigest digest; + + private DerObjectIdentifier algorithm; + private int keySize; + private byte[] z; + private byte[] partyAInfo; + + public DHKekGenerator(IDigest digest) + { + this.digest = digest; + } + + public virtual void Init(IDerivationParameters param) + { + DHKdfParameters parameters = (DHKdfParameters)param; + + this.algorithm = parameters.Algorithm; + this.keySize = parameters.KeySize; + this.z = parameters.GetZ(); // TODO Clone? + this.partyAInfo = parameters.GetExtraInfo(); // TODO Clone? + } + + public virtual IDigest Digest + { + get { return digest; } + } + + public virtual int GenerateBytes(byte[] outBytes, int outOff, int len) + { + if ((outBytes.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 ArgumentException("Output length too large"); + } + + int cThreshold = (int)((oBytes + outLen - 1) / outLen); + + byte[] dig = new byte[digest.GetDigestSize()]; + + uint counter = 1; + + for (int i = 0; i < cThreshold; i++) + { + digest.BlockUpdate(z, 0, z.Length); + + // KeySpecificInfo + DerSequence keyInfo = new DerSequence( + algorithm, + new DerOctetString(Pack.UInt32_To_BE(counter))); + + // OtherInfo + Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo); + + if (partyAInfo != null) + { + v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo))); + } + + v1.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize)))); + + byte[] other = new DerSequence(v1).GetDerEncoded(); + + digest.BlockUpdate(other, 0, other.Length); + + digest.DoFinal(dig, 0); + + if (len > outLen) + { + Array.Copy(dig, 0, outBytes, outOff, outLen); + outOff += outLen; + len -= outLen; + } + else + { + Array.Copy(dig, 0, outBytes, outOff, len); + } + + counter++; + } + + digest.Reset(); + + return (int)oBytes; + } + } +} diff --git a/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs b/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs new file mode 100644 index 000000000..74464574c --- /dev/null +++ b/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs @@ -0,0 +1,55 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Agreement.Kdf +{ + /** + * X9.63 based key derivation function for ECDH CMS. + */ + public class ECDHKekGenerator + : IDerivationFunction + { + private readonly IDerivationFunction kdf; + + private DerObjectIdentifier algorithm; + private int keySize; + private byte[] z; + + public ECDHKekGenerator(IDigest digest) + { + this.kdf = new Kdf2BytesGenerator(digest); + } + + public virtual void Init(IDerivationParameters param) + { + DHKdfParameters parameters = (DHKdfParameters)param; + + this.algorithm = parameters.Algorithm; + this.keySize = parameters.KeySize; + this.z = parameters.GetZ(); // TODO Clone? + } + + public virtual IDigest Digest + { + get { return kdf.Digest; } + } + + public virtual int GenerateBytes(byte[] outBytes, int outOff, int len) + { + // TODO Create an ASN.1 class for this (RFC3278) + // ECC-CMS-SharedInfo + DerSequence s = new DerSequence( + new AlgorithmIdentifier(algorithm, DerNull.Instance), + new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize)))); + + kdf.Init(new KdfParameters(z, s.GetDerEncoded())); + + return kdf.GenerateBytes(outBytes, outOff, len); + } + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6Client.cs b/crypto/src/crypto/agreement/srp/SRP6Client.cs new file mode 100644 index 000000000..309736564 --- /dev/null +++ b/crypto/src/crypto/agreement/srp/SRP6Client.cs @@ -0,0 +1,93 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + /** + * 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 privA; + protected BigInteger pubA; + + protected BigInteger B; + + protected BigInteger x; + protected BigInteger u; + protected BigInteger S; + + protected IDigest 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 virtual void Init(BigInteger N, BigInteger g, IDigest 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 virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password) + { + this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password); + this.privA = SelectPrivateValue(); + this.pubA = g.ModPow(privA, N); + + return pubA; + } + + /** + * Generates client's verification message 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 virtual BigInteger CalculateSecret(BigInteger serverB) + { + this.B = Srp6Utilities.ValidatePublicValue(N, serverB); + this.u = Srp6Utilities.CalculateU(digest, N, pubA, B); + this.S = CalculateS(); + + return S; + } + + protected virtual BigInteger SelectPrivateValue() + { + return Srp6Utilities.GeneratePrivateValue(digest, N, g, random); + } + + private BigInteger CalculateS() + { + BigInteger k = Srp6Utilities.CalculateK(digest, N, g); + BigInteger exp = u.Multiply(x).Add(privA); + BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N); + return B.Subtract(tmp).Mod(N).ModPow(exp, N); + } + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6Server.cs b/crypto/src/crypto/agreement/srp/SRP6Server.cs new file mode 100644 index 000000000..35b96d488 --- /dev/null +++ b/crypto/src/crypto/agreement/srp/SRP6Server.cs @@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + /** + * 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 IDigest digest; + + protected BigInteger A; + + protected BigInteger privB; + protected BigInteger pubB; + + protected BigInteger u; + protected BigInteger S; + + 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 virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest 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 virtual BigInteger GenerateServerCredentials() + { + BigInteger k = Srp6Utilities.CalculateK(digest, N, g); + this.privB = SelectPrivateValue(); + this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N); + + return pubB; + } + + /** + * 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 virtual BigInteger CalculateSecret(BigInteger clientA) + { + this.A = Srp6Utilities.ValidatePublicValue(N, clientA); + this.u = Srp6Utilities.CalculateU(digest, N, A, pubB); + this.S = CalculateS(); + + return S; + } + + protected virtual BigInteger SelectPrivateValue() + { + return Srp6Utilities.GeneratePrivateValue(digest, N, g, random); + } + + private BigInteger CalculateS() + { + return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N); + } + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs new file mode 100644 index 000000000..4e790f572 --- /dev/null +++ b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs @@ -0,0 +1,85 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + public class Srp6Utilities + { + public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g) + { + return HashPaddedPair(digest, N, N, g); + } + + public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B) + { + return HashPaddedPair(digest, N, A, B); + } + + public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password) + { + byte[] output = new byte[digest.GetDigestSize()]; + + digest.BlockUpdate(identity, 0, identity.Length); + digest.Update((byte)':'); + digest.BlockUpdate(password, 0, password.Length); + digest.DoFinal(output, 0); + + digest.BlockUpdate(salt, 0, salt.Length); + digest.BlockUpdate(output, 0, output.Length); + digest.DoFinal(output, 0); + + return new BigInteger(1, output); + } + + public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random) + { + int minBits = System.Math.Min(256, N.BitLength / 2); + BigInteger min = BigInteger.One.ShiftLeft(minBits - 1); + BigInteger max = N.Subtract(BigInteger.One); + + return BigIntegers.CreateRandomInRange(min, max, random); + } + + public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val) + { + val = val.Mod(N); + + // Check that val % N != 0 + if (val.Equals(BigInteger.Zero)) + throw new CryptoException("Invalid public value: 0"); + + return val; + } + + private static BigInteger HashPaddedPair(IDigest 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.BlockUpdate(n1_bytes, 0, n1_bytes.Length); + digest.BlockUpdate(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]; + Array.Copy(bs, 0, tmp, length - bs.Length, bs.Length); + bs = tmp; + } + return bs; + } + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs b/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs new file mode 100644 index 000000000..264833b4d --- /dev/null +++ b/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs @@ -0,0 +1,49 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + /** + * Generates new SRP verifier for user + */ + public class Srp6VerifierGenerator + { + protected BigInteger N; + protected BigInteger g; + protected IDigest 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 virtual void Init(BigInteger N, BigInteger g, IDigest 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 virtual BigInteger GenerateVerifier(byte[] salt, byte[] identity, byte[] password) + { + BigInteger x = Srp6Utilities.CalculateX(digest, N, salt, identity, password); + + return g.ModPow(x, N); + } + } +} + diff --git a/crypto/src/crypto/digests/GOST3411Digest.cs b/crypto/src/crypto/digests/GOST3411Digest.cs new file mode 100644 index 000000000..9f0bec9e6 --- /dev/null +++ b/crypto/src/crypto/digests/GOST3411Digest.cs @@ -0,0 +1,343 @@ +using System; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of GOST R 34.11-94 + */ + public class Gost3411Digest + : IDigest + { + private const 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 = MakeC(); + + private byte[] xBuf = new byte[32]; + private int xBufOff; + private ulong byteCount; + + private readonly IBlockCipher cipher = new Gost28147Engine(); + private readonly byte[] sBox; + + private static byte[][] MakeC() + { + byte[][] c = new byte[4][]; + for (int i = 0; i < 4; ++i) + { + c[i] = new byte[32]; + } + return c; + } + + /** + * 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) + { + this.sBox = t.sBox; + cipher.Init(true, new ParametersWithSBox(null, sBox)); + + Reset(); + + Array.Copy(t.H, 0, this.H, 0, t.H.Length); + Array.Copy(t.L, 0, this.L, 0, t.L.Length); + Array.Copy(t.M, 0, this.M, 0, t.M.Length); + Array.Copy(t.Sum, 0, this.Sum, 0, t.Sum.Length); + Array.Copy(t.C[1], 0, this.C[1], 0, t.C[1].Length); + Array.Copy(t.C[2], 0, this.C[2], 0, t.C[2].Length); + Array.Copy(t.C[3], 0, this.C[3], 0, t.C[3].Length); + Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.Length); + + this.xBufOff = t.xBufOff; + this.byteCount = t.byteCount; + } + + public string AlgorithmName + { + get { return "Gost3411"; } + } + + public int GetDigestSize() + { + return DIGEST_LENGTH; + } + + public void Update( + byte input) + { + xBuf[xBufOff++] = input; + if (xBufOff == xBuf.Length) + { + sumByteArray(xBuf); // calc sum M + processBlock(xBuf, 0); + xBufOff = 0; + } + byteCount++; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int length) + { + while ((xBufOff != 0) && (length > 0)) + { + Update(input[inOff]); + inOff++; + length--; + } + + while (length > xBuf.Length) + { + Array.Copy(input, inOff, xBuf, 0, xBuf.Length); + + sumByteArray(xBuf); // calc sum M + processBlock(xBuf, 0); + inOff += xBuf.Length; + length -= xBuf.Length; + byteCount += (uint)xBuf.Length; + } + + // load in the remainder. + while (length > 0) + { + Update(input[inOff]); + inOff++; + length--; + } + } + + // (i + 1 + 4(k - 1)) = 8i + k i = 0-3, k = 1-8 + private byte[] K = new byte[32]; + + private byte[] P(byte[] input) + { + int fourK = 0; + for(int k = 0; k < 8; k++) + { + K[fourK++] = input[k]; + K[fourK++] = input[8 + k]; + K[fourK++] = input[16 + k]; + K[fourK++] = input[24 + k]; + } + + return K; + } + + //A (x) = (x0 ^ x1) || x3 || x2 || x1 + byte[] a = new byte[8]; + private byte[] A(byte[] input) + { + for(int j=0; j<8; j++) + { + a[j]=(byte)(input[j] ^ input[j+8]); + } + + Array.Copy(input, 8, input, 0, 24); + Array.Copy(a, 0, input, 24, 8); + + return input; + } + + //Encrypt function, ECB mode + private void E(byte[] key, byte[] s, int sOff, byte[] input, int inOff) + { + cipher.Init(true, new KeyParameter(key)); + + cipher.ProcessBlock(input, inOff, s, sOff); + } + + // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2 + internal short[] wS = new short[16], w_S = new short[16]; + + private void fw(byte[] input) + { + cpyBytesToShort(input, wS); + w_S[15] = (short)(wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]); + Array.Copy(wS, 1, w_S, 0, 15); + cpyShortToBytes(w_S, input); + } + + // block processing + internal byte[] S = new byte[32], U = new byte[32], V = new byte[32], W = new byte[32]; + + private void processBlock(byte[] input, int inOff) + { + Array.Copy(input, inOff, M, 0, 32); + + //key step 1 + + // H = h3 || h2 || h1 || h0 + // S = s3 || s2 || s1 || s0 + H.CopyTo(U, 0); + M.CopyTo(V, 0); + 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); + } + Array.Copy(S, 0, H, 0, H.Length); + } + + private void finish() + { + ulong bitCount = byteCount * 8; + Pack.UInt64_To_LE(bitCount, L); + + while (xBufOff != 0) + { + Update((byte)0); + } + + processBlock(L, 0); + processBlock(Sum, 0); + } + + public int DoFinal( + byte[] output, + int outOff) + { + finish(); + + H.CopyTo(output, outOff); + + Reset(); + + return DIGEST_LENGTH; + } + + /** + * reset the chaining variables to the IV values. + */ + private static readonly 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; + + Array.Clear(H, 0, H.Length); + Array.Clear(L, 0, L.Length); + Array.Clear(M, 0, M.Length); + Array.Clear(C[1], 0, C[1].Length); // real index C = +1 because index array with 0. + Array.Clear(C[3], 0, C[3].Length); + Array.Clear(Sum, 0, Sum.Length); + Array.Clear(xBuf, 0, xBuf.Length); + + C2.CopyTo(C[2], 0); + } + + // 256 bitsblock modul -> (Sum + a mod (2^256)) + private void sumByteArray( + byte[] input) + { + int carry = 0; + + for (int i = 0; i != Sum.Length; i++) + { + int sum = (Sum[i] & 0xff) + (input[i] & 0xff) + carry; + + Sum[i] = (byte)sum; + + carry = sum >> 8; + } + } + + private static 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 static void cpyShortToBytes(short[] wS, byte[] S) + { + for(int i=0; i> 8); + S[i*2] = (byte)wS[i]; + } + } + + public int GetByteLength() + { + return 32; + } + } +} diff --git a/crypto/src/crypto/digests/GeneralDigest.cs b/crypto/src/crypto/digests/GeneralDigest.cs new file mode 100644 index 000000000..77c17ed58 --- /dev/null +++ b/crypto/src/crypto/digests/GeneralDigest.cs @@ -0,0 +1,118 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * base implementation of MD4 family style digest as outlined in + * "Handbook of Applied Cryptography", pages 344 - 347. + */ + public abstract class GeneralDigest + : IDigest + { + private const int BYTE_LENGTH = 64; + + private byte[] xBuf; + private int xBufOff; + + private long byteCount; + + internal GeneralDigest() + { + xBuf = new byte[4]; + } + + internal GeneralDigest(GeneralDigest t) + { + xBuf = new byte[t.xBuf.Length]; + Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length); + + xBufOff = t.xBufOff; + byteCount = t.byteCount; + } + + public void Update(byte input) + { + xBuf[xBufOff++] = input; + + if (xBufOff == xBuf.Length) + { + ProcessWord(xBuf, 0); + xBufOff = 0; + } + + byteCount++; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int length) + { + // + // fill the current word + // + while ((xBufOff != 0) && (length > 0)) + { + Update(input[inOff]); + inOff++; + length--; + } + + // + // process whole words. + // + while (length > xBuf.Length) + { + ProcessWord(input, inOff); + + inOff += xBuf.Length; + length -= xBuf.Length; + byteCount += xBuf.Length; + } + + // + // load in the remainder. + // + while (length > 0) + { + Update(input[inOff]); + + inOff++; + length--; + } + } + + public void Finish() + { + long bitLength = (byteCount << 3); + + // + // add the pad bytes. + // + Update((byte)128); + + while (xBufOff != 0) Update((byte)0); + ProcessLength(bitLength); + ProcessBlock(); + } + + public virtual void Reset() + { + byteCount = 0; + xBufOff = 0; + Array.Clear(xBuf, 0, xBuf.Length); + } + + public int GetByteLength() + { + return BYTE_LENGTH; + } + + internal abstract void ProcessWord(byte[] input, int inOff); + internal abstract void ProcessLength(long bitLength); + internal abstract void ProcessBlock(); + public abstract string AlgorithmName { get; } + public abstract int GetDigestSize(); + public abstract int DoFinal(byte[] output, int outOff); + } +} diff --git a/crypto/src/crypto/digests/LongDigest.cs b/crypto/src/crypto/digests/LongDigest.cs new file mode 100644 index 000000000..702753b2b --- /dev/null +++ b/crypto/src/crypto/digests/LongDigest.cs @@ -0,0 +1,346 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Base class for SHA-384 and SHA-512. + */ + public abstract class LongDigest + : IDigest + { + private int MyByteLength = 128; + + private byte[] xBuf; + private int xBufOff; + + private long byteCount1; + private long byteCount2; + + internal ulong H1, H2, H3, H4, H5, H6, H7, H8; + + private ulong[] W = new ulong[80]; + private int wOff; + + /** + * Constructor for variable length word + */ + internal LongDigest() + { + xBuf = new byte[8]; + + Reset(); + } + + /** + * Copy constructor. We are using copy constructors in place + * of the object.Clone() interface as this interface is not + * supported by J2ME. + */ + internal LongDigest( + LongDigest t) + { + xBuf = new byte[t.xBuf.Length]; + Array.Copy(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; + + Array.Copy(t.W, 0, W, 0, t.W.Length); + wOff = t.wOff; + } + + public void Update( + byte input) + { + xBuf[xBufOff++] = input; + + if (xBufOff == xBuf.Length) + { + ProcessWord(xBuf, 0); + xBufOff = 0; + } + + byteCount1++; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int length) + { + // + // fill the current word + // + while ((xBufOff != 0) && (length > 0)) + { + Update(input[inOff]); + + inOff++; + length--; + } + + // + // process whole words. + // + while (length > xBuf.Length) + { + ProcessWord(input, inOff); + + inOff += xBuf.Length; + length -= xBuf.Length; + byteCount1 += xBuf.Length; + } + + // + // load in the remainder. + // + while (length > 0) + { + Update(input[inOff]); + + inOff++; + length--; + } + } + + 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 virtual void Reset() + { + byteCount1 = 0; + byteCount2 = 0; + + xBufOff = 0; + for ( int i = 0; i < xBuf.Length; i++ ) + { + xBuf[i] = 0; + } + + wOff = 0; + Array.Clear(W, 0, W.Length); + } + + internal void ProcessWord( + byte[] input, + int inOff) + { + W[wOff] = Pack.BE_To_UInt64(input, 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 += (long) ((ulong) byteCount1 >> 61); + byteCount1 &= 0x1fffffffffffffffL; + } + } + + internal void ProcessLength( + long lowW, + long hiW) + { + if (wOff > 14) + { + ProcessBlock(); + } + + W[14] = (ulong)hiW; + W[15] = (ulong)lowW; + } + + internal void ProcessBlock() + { + AdjustByteCounts(); + + // + // expand 16 word block into 80 word blocks. + // + for (int ti = 16; ti <= 79; ++ti) + { + W[ti] = Sigma1(W[ti - 2]) + W[ti - 7] + Sigma0(W[ti - 15]) + W[ti - 16]; + } + + // + // set up working variables. + // + ulong a = H1; + ulong b = H2; + ulong c = H3; + ulong d = H4; + ulong e = H5; + ulong f = H6; + ulong g = H7; + ulong 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; + Array.Clear(W, 0, 16); + } + + /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */ + private static ulong Ch(ulong x, ulong y, ulong z) + { + return (x & y) ^ (~x & z); + } + + private static ulong Maj(ulong x, ulong y, ulong z) + { + return (x & y) ^ (x & z) ^ (y & z); + } + + private static ulong Sum0(ulong x) + { + return ((x << 36) | (x >> 28)) ^ ((x << 30) | (x >> 34)) ^ ((x << 25) | (x >> 39)); + } + + private static ulong Sum1(ulong x) + { + return ((x << 50) | (x >> 14)) ^ ((x << 46) | (x >> 18)) ^ ((x << 23) | (x >> 41)); + } + + private static ulong Sigma0(ulong x) + { + return ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7); + } + + private static ulong Sigma1(ulong 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) + */ + internal static readonly ulong[] K = + { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + }; + + public int GetByteLength() + { + return MyByteLength; + } + + public abstract string AlgorithmName { get; } + public abstract int GetDigestSize(); + public abstract int DoFinal(byte[] output, int outOff); + } +} diff --git a/crypto/src/crypto/digests/MD2Digest.cs b/crypto/src/crypto/digests/MD2Digest.cs new file mode 100644 index 000000000..78c696f33 --- /dev/null +++ b/crypto/src/crypto/digests/MD2Digest.cs @@ -0,0 +1,247 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Digests +{ + + /** + * implementation of MD2 + * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992 + */ + public class MD2Digest + : IDigest + { + private const int DigestLength = 16; + private const int BYTE_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) + { + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + Array.Copy(t.M, 0, M, 0, t.M.Length); + mOff = t.mOff; + Array.Copy(t.C, 0, C, 0, t.C.Length); + COff = t.COff; + } + /** + * return the algorithm name + * + * @return the algorithm name + */ + public string AlgorithmName + { + get { return "MD2"; } + } + + public int GetDigestSize() + { + return DigestLength; + } + + public int GetByteLength() + { + return BYTE_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[] output, int outOff) + { + // add padding + byte paddingByte = (byte)(M.Length - mOff); + for (int i=mOff;i 0)) + { + Update(input[inOff]); + inOff++; + length--; + } + + // + // process whole words. + // + while (length > 16) + { + Array.Copy(input,inOff,M,0,16); + ProcessChecksum(M); + ProcessBlock(M); + length -= 16; + inOff += 16; + } + + // + // load in the remainder. + // + while (length > 0) + { + Update(input[inOff]); + inOff++; + length--; + } + } + + internal 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]; + } + } + internal 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 readonly 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 + }; + } + +} diff --git a/crypto/src/crypto/digests/MD4Digest.cs b/crypto/src/crypto/digests/MD4Digest.cs new file mode 100644 index 000000000..bc4eae0fd --- /dev/null +++ b/crypto/src/crypto/digests/MD4Digest.cs @@ -0,0 +1,271 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for + * Computer Science and RSA Data Security, Inc. + *

+ * NOTE: This algorithm is only included for backwards compatibility + * with legacy applications, it's not secure, don't use it for anything new!

+ */ + public class MD4Digest + : GeneralDigest + { + private const int DigestLength = 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) : base(t) + { + H1 = t.H1; + H2 = t.H2; + H3 = t.H3; + H4 = t.H4; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "MD4"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) + | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + + if (xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (int)(bitLength & 0xffffffff); + X[15] = (int)((ulong) bitLength >> 32); + } + + private void UnpackWord( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)word; + outBytes[outOff + 1] = (byte)((uint) word >> 8); + outBytes[outOff + 2] = (byte)((uint) word >> 16); + outBytes[outOff + 3] = (byte)((uint) word >> 24); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + UnpackWord(H1, output, outOff); + UnpackWord(H2, output, outOff + 4); + UnpackWord(H3, output, outOff + 8); + UnpackWord(H4, output, outOff + 12); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables to the IV values. + */ + public override void Reset() + { + base.Reset(); + + H1 = unchecked((int) 0x67452301); + H2 = unchecked((int) 0xefcdab89); + H3 = unchecked((int) 0x98badcfe); + H4 = unchecked((int) 0x10325476); + + xOff = 0; + + for (int i = 0; i != X.Length; i++) + { + X[i] = 0; + } + } + + // + // round 1 left rotates + // + private const int S11 = 3; + private const int S12 = 7; + private const int S13 = 11; + private const int S14 = 19; + + // + // round 2 left rotates + // + private const int S21 = 3; + private const int S22 = 5; + private const int S23 = 9; + private const int S24 = 13; + + // + // round 3 left rotates + // + private const int S31 = 3; + private const int S32 = 9; + private const int S33 = 11; + private const int S34 = 15; + + /* + * rotate int x left n bits. + */ + private int RotateLeft( + int x, + int n) + { + return (x << n) | (int) ((uint) 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; + } + + internal override 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; + } + } + } + +} diff --git a/crypto/src/crypto/digests/MD5Digest.cs b/crypto/src/crypto/digests/MD5Digest.cs new file mode 100644 index 000000000..2116d64f0 --- /dev/null +++ b/crypto/src/crypto/digests/MD5Digest.cs @@ -0,0 +1,293 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. + */ + public class MD5Digest + : GeneralDigest + { + private const int DigestLength = 16; + + private uint H1, H2, H3, H4; // IV's + + private uint[] X = new uint[16]; + private int xOff; + + public MD5Digest() + { + Reset(); + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public MD5Digest(MD5Digest t) + : base(t) + { + H1 = t.H1; + H2 = t.H2; + H3 = t.H3; + H4 = t.H4; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "MD5"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff] = Pack.LE_To_UInt32(input, inOff); + + if (++xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + if (xOff == 15) + X[15] = 0; + + ProcessBlock(); + } + + for (int i = xOff; i < 14; ++i) + { + X[i] = 0; + } + + X[14] = (uint)((ulong)bitLength); + X[15] = (uint)((ulong)bitLength >> 32); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt32_To_LE(H1, output, outOff); + Pack.UInt32_To_LE(H2, output, outOff + 4); + Pack.UInt32_To_LE(H3, output, outOff + 8); + Pack.UInt32_To_LE(H4, output, outOff + 12); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables to the IV values. + */ + public override void Reset() + { + base.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 readonly int S11 = 7; + private static readonly int S12 = 12; + private static readonly int S13 = 17; + private static readonly int S14 = 22; + + // + // round 2 left rotates + // + private static readonly int S21 = 5; + private static readonly int S22 = 9; + private static readonly int S23 = 14; + private static readonly int S24 = 20; + + // + // round 3 left rotates + // + private static readonly int S31 = 4; + private static readonly int S32 = 11; + private static readonly int S33 = 16; + private static readonly int S34 = 23; + + // + // round 4 left rotates + // + private static readonly int S41 = 6; + private static readonly int S42 = 10; + private static readonly int S43 = 15; + private static readonly int S44 = 21; + + /* + * rotate int x left n bits. + */ + private static uint RotateLeft( + uint x, + int n) + { + return (x << n) | (x >> (32 - n)); + } + + /* + * F, G, H and I are the basic MD5 functions. + */ + private static uint F( + uint u, + uint v, + uint w) + { + return (u & v) | (~u & w); + } + + private static uint G( + uint u, + uint v, + uint w) + { + return (u & w) | (v & ~w); + } + + private static uint H( + uint u, + uint v, + uint w) + { + return u ^ v ^ w; + } + + private static uint K( + uint u, + uint v, + uint w) + { + return v ^ (u | ~w); + } + + internal override void ProcessBlock() + { + uint a = H1; + uint b = H2; + uint c = H3; + uint 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; + + xOff = 0; + } + } + +} + diff --git a/crypto/src/crypto/digests/NullDigest.cs b/crypto/src/crypto/digests/NullDigest.cs new file mode 100644 index 000000000..e598cb145 --- /dev/null +++ b/crypto/src/crypto/digests/NullDigest.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Digests +{ + public class NullDigest : IDigest + { + private readonly MemoryStream bOut = new MemoryStream(); + + public string AlgorithmName + { + get { return "NULL"; } + } + + public int GetByteLength() + { + // TODO Is this okay? + return 0; + } + + public int GetDigestSize() + { + return (int) bOut.Length; + } + + public void Update(byte b) + { + bOut.WriteByte(b); + } + + public void BlockUpdate(byte[] inBytes, int inOff, int len) + { + bOut.Write(inBytes, inOff, len); + } + + public int DoFinal(byte[] outBytes, int outOff) + { + byte[] res = bOut.ToArray(); + res.CopyTo(outBytes, outOff); + Reset(); + return res.Length; + } + + public void Reset() + { + bOut.SetLength(0); + } + } +} diff --git a/crypto/src/crypto/digests/RipeMD128Digest.cs b/crypto/src/crypto/digests/RipeMD128Digest.cs new file mode 100644 index 000000000..8977583a4 --- /dev/null +++ b/crypto/src/crypto/digests/RipeMD128Digest.cs @@ -0,0 +1,462 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of RipeMD128 + */ + public class RipeMD128Digest + : GeneralDigest + { + private const int DigestLength = 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) : base(t) + { + H0 = t.H0; + H1 = t.H1; + H2 = t.H2; + H3 = t.H3; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "RIPEMD128"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) + | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + + if (xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (int)(bitLength & 0xffffffff); + X[15] = (int)((ulong) bitLength >> 32); + } + + private void UnpackWord( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)word; + outBytes[outOff + 1] = (byte)((uint) word >> 8); + outBytes[outOff + 2] = (byte)((uint) word >> 16); + outBytes[outOff + 3] = (byte)((uint) word >> 24); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + UnpackWord(H0, output, outOff); + UnpackWord(H1, output, outOff + 4); + UnpackWord(H2, output, outOff + 8); + UnpackWord(H3, output, outOff + 12); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables to the IV values. + */ + public override void Reset() + { + base.Reset(); + + H0 = unchecked((int) 0x67452301); + H1 = unchecked((int) 0xefcdab89); + H2 = unchecked((int) 0x98badcfe); + H3 = unchecked((int) 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) | (int) ((uint) 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 + unchecked((int) 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 + unchecked((int) 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 + unchecked((int) 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 + unchecked((int) 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 + unchecked((int) 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 + unchecked((int) 0x50a28be6), s); + } + + internal override 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; + } + } + } + +} diff --git a/crypto/src/crypto/digests/RipeMD160Digest.cs b/crypto/src/crypto/digests/RipeMD160Digest.cs new file mode 100644 index 000000000..8ce52ae58 --- /dev/null +++ b/crypto/src/crypto/digests/RipeMD160Digest.cs @@ -0,0 +1,423 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of RipeMD see, + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + */ + public class RipeMD160Digest + : GeneralDigest + { + private const int DigestLength = 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) : base(t) + { + H0 = t.H0; + H1 = t.H1; + H2 = t.H2; + H3 = t.H3; + H4 = t.H4; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "RIPEMD160"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) + | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + + if (xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (int)(bitLength & 0xffffffff); + X[15] = (int)((ulong) bitLength >> 32); + } + + private void UnpackWord( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)word; + outBytes[outOff + 1] = (byte)((uint) word >> 8); + outBytes[outOff + 2] = (byte)((uint) word >> 16); + outBytes[outOff + 3] = (byte)((uint) word >> 24); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + UnpackWord(H0, output, outOff); + UnpackWord(H1, output, outOff + 4); + UnpackWord(H2, output, outOff + 8); + UnpackWord(H3, output, outOff + 12); + UnpackWord(H4, output, outOff + 16); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables to the IV values. + */ + public override void Reset() + { + base.Reset(); + + H0 = unchecked((int) 0x67452301); + H1 = unchecked((int) 0xefcdab89); + H2 = unchecked((int) 0x98badcfe); + H3 = unchecked((int) 0x10325476); + H4 = unchecked((int) 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) | (int) ((uint) 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); + } + + internal override 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] + unchecked((int) 0x50a28be6), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa,bb,cc) + X[14] + unchecked((int) 0x50a28be6), 9) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee,aa,bb) + X[ 7] + unchecked((int) 0x50a28be6), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd,ee,aa) + X[ 0] + unchecked((int) 0x50a28be6), 11) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc,dd,ee) + X[ 9] + unchecked((int) 0x50a28be6), 13) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb,cc,dd) + X[ 2] + unchecked((int) 0x50a28be6), 15) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa,bb,cc) + X[11] + unchecked((int) 0x50a28be6), 15) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee,aa,bb) + X[ 4] + unchecked((int) 0x50a28be6), 5) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd,ee,aa) + X[13] + unchecked((int) 0x50a28be6), 7) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc,dd,ee) + X[ 6] + unchecked((int) 0x50a28be6), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb,cc,dd) + X[15] + unchecked((int) 0x50a28be6), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa,bb,cc) + X[ 8] + unchecked((int) 0x50a28be6), 11) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee,aa,bb) + X[ 1] + unchecked((int) 0x50a28be6), 14) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd,ee,aa) + X[10] + unchecked((int) 0x50a28be6), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc,dd,ee) + X[ 3] + unchecked((int) 0x50a28be6), 12) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb,cc,dd) + X[12] + unchecked((int) 0x50a28be6), 6) + ee; cc = RL(cc, 10); + + // + // Rounds 16-31 + // + // left + e = RL(e + F2(a,b,c) + X[ 7] + unchecked((int) 0x5a827999), 7) + d; b = RL(b, 10); + d = RL(d + F2(e,a,b) + X[ 4] + unchecked((int) 0x5a827999), 6) + c; a = RL(a, 10); + c = RL(c + F2(d,e,a) + X[13] + unchecked((int) 0x5a827999), 8) + b; e = RL(e, 10); + b = RL(b + F2(c,d,e) + X[ 1] + unchecked((int) 0x5a827999), 13) + a; d = RL(d, 10); + a = RL(a + F2(b,c,d) + X[10] + unchecked((int) 0x5a827999), 11) + e; c = RL(c, 10); + e = RL(e + F2(a,b,c) + X[ 6] + unchecked((int) 0x5a827999), 9) + d; b = RL(b, 10); + d = RL(d + F2(e,a,b) + X[15] + unchecked((int) 0x5a827999), 7) + c; a = RL(a, 10); + c = RL(c + F2(d,e,a) + X[ 3] + unchecked((int) 0x5a827999), 15) + b; e = RL(e, 10); + b = RL(b + F2(c,d,e) + X[12] + unchecked((int) 0x5a827999), 7) + a; d = RL(d, 10); + a = RL(a + F2(b,c,d) + X[ 0] + unchecked((int) 0x5a827999), 12) + e; c = RL(c, 10); + e = RL(e + F2(a,b,c) + X[ 9] + unchecked((int) 0x5a827999), 15) + d; b = RL(b, 10); + d = RL(d + F2(e,a,b) + X[ 5] + unchecked((int) 0x5a827999), 9) + c; a = RL(a, 10); + c = RL(c + F2(d,e,a) + X[ 2] + unchecked((int) 0x5a827999), 11) + b; e = RL(e, 10); + b = RL(b + F2(c,d,e) + X[14] + unchecked((int) 0x5a827999), 7) + a; d = RL(d, 10); + a = RL(a + F2(b,c,d) + X[11] + unchecked((int) 0x5a827999), 13) + e; c = RL(c, 10); + e = RL(e + F2(a,b,c) + X[ 8] + unchecked((int) 0x5a827999), 12) + d; b = RL(b, 10); + + // right + ee = RL(ee + F4(aa,bb,cc) + X[ 6] + unchecked((int) 0x5c4dd124), 9) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee,aa,bb) + X[11] + unchecked((int) 0x5c4dd124), 13) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd,ee,aa) + X[ 3] + unchecked((int) 0x5c4dd124), 15) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc,dd,ee) + X[ 7] + unchecked((int) 0x5c4dd124), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb,cc,dd) + X[ 0] + unchecked((int) 0x5c4dd124), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa,bb,cc) + X[13] + unchecked((int) 0x5c4dd124), 8) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee,aa,bb) + X[ 5] + unchecked((int) 0x5c4dd124), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd,ee,aa) + X[10] + unchecked((int) 0x5c4dd124), 11) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc,dd,ee) + X[14] + unchecked((int) 0x5c4dd124), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb,cc,dd) + X[15] + unchecked((int) 0x5c4dd124), 7) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa,bb,cc) + X[ 8] + unchecked((int) 0x5c4dd124), 12) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee,aa,bb) + X[12] + unchecked((int) 0x5c4dd124), 7) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd,ee,aa) + X[ 4] + unchecked((int) 0x5c4dd124), 6) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc,dd,ee) + X[ 9] + unchecked((int) 0x5c4dd124), 15) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb,cc,dd) + X[ 1] + unchecked((int) 0x5c4dd124), 13) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa,bb,cc) + X[ 2] + unchecked((int) 0x5c4dd124), 11) + dd; bb = RL(bb, 10); + + // + // Rounds 32-47 + // + // left + d = RL(d + F3(e,a,b) + X[ 3] + unchecked((int) 0x6ed9eba1), 11) + c; a = RL(a, 10); + c = RL(c + F3(d,e,a) + X[10] + unchecked((int) 0x6ed9eba1), 13) + b; e = RL(e, 10); + b = RL(b + F3(c,d,e) + X[14] + unchecked((int) 0x6ed9eba1), 6) + a; d = RL(d, 10); + a = RL(a + F3(b,c,d) + X[ 4] + unchecked((int) 0x6ed9eba1), 7) + e; c = RL(c, 10); + e = RL(e + F3(a,b,c) + X[ 9] + unchecked((int) 0x6ed9eba1), 14) + d; b = RL(b, 10); + d = RL(d + F3(e,a,b) + X[15] + unchecked((int) 0x6ed9eba1), 9) + c; a = RL(a, 10); + c = RL(c + F3(d,e,a) + X[ 8] + unchecked((int) 0x6ed9eba1), 13) + b; e = RL(e, 10); + b = RL(b + F3(c,d,e) + X[ 1] + unchecked((int) 0x6ed9eba1), 15) + a; d = RL(d, 10); + a = RL(a + F3(b,c,d) + X[ 2] + unchecked((int) 0x6ed9eba1), 14) + e; c = RL(c, 10); + e = RL(e + F3(a,b,c) + X[ 7] + unchecked((int) 0x6ed9eba1), 8) + d; b = RL(b, 10); + d = RL(d + F3(e,a,b) + X[ 0] + unchecked((int) 0x6ed9eba1), 13) + c; a = RL(a, 10); + c = RL(c + F3(d,e,a) + X[ 6] + unchecked((int) 0x6ed9eba1), 6) + b; e = RL(e, 10); + b = RL(b + F3(c,d,e) + X[13] + unchecked((int) 0x6ed9eba1), 5) + a; d = RL(d, 10); + a = RL(a + F3(b,c,d) + X[11] + unchecked((int) 0x6ed9eba1), 12) + e; c = RL(c, 10); + e = RL(e + F3(a,b,c) + X[ 5] + unchecked((int) 0x6ed9eba1), 7) + d; b = RL(b, 10); + d = RL(d + F3(e,a,b) + X[12] + unchecked((int) 0x6ed9eba1), 5) + c; a = RL(a, 10); + + // right + dd = RL(dd + F3(ee,aa,bb) + X[15] + unchecked((int) 0x6d703ef3), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd,ee,aa) + X[ 5] + unchecked((int) 0x6d703ef3), 7) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc,dd,ee) + X[ 1] + unchecked((int) 0x6d703ef3), 15) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb,cc,dd) + X[ 3] + unchecked((int) 0x6d703ef3), 11) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa,bb,cc) + X[ 7] + unchecked((int) 0x6d703ef3), 8) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee,aa,bb) + X[14] + unchecked((int) 0x6d703ef3), 6) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd,ee,aa) + X[ 6] + unchecked((int) 0x6d703ef3), 6) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc,dd,ee) + X[ 9] + unchecked((int) 0x6d703ef3), 14) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb,cc,dd) + X[11] + unchecked((int) 0x6d703ef3), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa,bb,cc) + X[ 8] + unchecked((int) 0x6d703ef3), 13) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee,aa,bb) + X[12] + unchecked((int) 0x6d703ef3), 5) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd,ee,aa) + X[ 2] + unchecked((int) 0x6d703ef3), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc,dd,ee) + X[10] + unchecked((int) 0x6d703ef3), 13) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb,cc,dd) + X[ 0] + unchecked((int) 0x6d703ef3), 13) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa,bb,cc) + X[ 4] + unchecked((int) 0x6d703ef3), 7) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee,aa,bb) + X[13] + unchecked((int) 0x6d703ef3), 5) + cc; aa = RL(aa, 10); + + // + // Rounds 48-63 + // + // left + c = RL(c + F4(d,e,a) + X[ 1] + unchecked((int) 0x8f1bbcdc), 11) + b; e = RL(e, 10); + b = RL(b + F4(c,d,e) + X[ 9] + unchecked((int) 0x8f1bbcdc), 12) + a; d = RL(d, 10); + a = RL(a + F4(b,c,d) + X[11] + unchecked((int) 0x8f1bbcdc), 14) + e; c = RL(c, 10); + e = RL(e + F4(a,b,c) + X[10] + unchecked((int) 0x8f1bbcdc), 15) + d; b = RL(b, 10); + d = RL(d + F4(e,a,b) + X[ 0] + unchecked((int) 0x8f1bbcdc), 14) + c; a = RL(a, 10); + c = RL(c + F4(d,e,a) + X[ 8] + unchecked((int) 0x8f1bbcdc), 15) + b; e = RL(e, 10); + b = RL(b + F4(c,d,e) + X[12] + unchecked((int) 0x8f1bbcdc), 9) + a; d = RL(d, 10); + a = RL(a + F4(b,c,d) + X[ 4] + unchecked((int) 0x8f1bbcdc), 8) + e; c = RL(c, 10); + e = RL(e + F4(a,b,c) + X[13] + unchecked((int) 0x8f1bbcdc), 9) + d; b = RL(b, 10); + d = RL(d + F4(e,a,b) + X[ 3] + unchecked((int) 0x8f1bbcdc), 14) + c; a = RL(a, 10); + c = RL(c + F4(d,e,a) + X[ 7] + unchecked((int) 0x8f1bbcdc), 5) + b; e = RL(e, 10); + b = RL(b + F4(c,d,e) + X[15] + unchecked((int) 0x8f1bbcdc), 6) + a; d = RL(d, 10); + a = RL(a + F4(b,c,d) + X[14] + unchecked((int) 0x8f1bbcdc), 8) + e; c = RL(c, 10); + e = RL(e + F4(a,b,c) + X[ 5] + unchecked((int) 0x8f1bbcdc), 6) + d; b = RL(b, 10); + d = RL(d + F4(e,a,b) + X[ 6] + unchecked((int) 0x8f1bbcdc), 5) + c; a = RL(a, 10); + c = RL(c + F4(d,e,a) + X[ 2] + unchecked((int) 0x8f1bbcdc), 12) + b; e = RL(e, 10); + + // right + cc = RL(cc + F2(dd,ee,aa) + X[ 8] + unchecked((int) 0x7a6d76e9), 15) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc,dd,ee) + X[ 6] + unchecked((int) 0x7a6d76e9), 5) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb,cc,dd) + X[ 4] + unchecked((int) 0x7a6d76e9), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa,bb,cc) + X[ 1] + unchecked((int) 0x7a6d76e9), 11) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee,aa,bb) + X[ 3] + unchecked((int) 0x7a6d76e9), 14) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd,ee,aa) + X[11] + unchecked((int) 0x7a6d76e9), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc,dd,ee) + X[15] + unchecked((int) 0x7a6d76e9), 6) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb,cc,dd) + X[ 0] + unchecked((int) 0x7a6d76e9), 14) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa,bb,cc) + X[ 5] + unchecked((int) 0x7a6d76e9), 6) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee,aa,bb) + X[12] + unchecked((int) 0x7a6d76e9), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd,ee,aa) + X[ 2] + unchecked((int) 0x7a6d76e9), 12) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc,dd,ee) + X[13] + unchecked((int) 0x7a6d76e9), 9) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb,cc,dd) + X[ 9] + unchecked((int) 0x7a6d76e9), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa,bb,cc) + X[ 7] + unchecked((int) 0x7a6d76e9), 5) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee,aa,bb) + X[10] + unchecked((int) 0x7a6d76e9), 15) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd,ee,aa) + X[14] + unchecked((int) 0x7a6d76e9), 8) + bb; ee = RL(ee, 10); + + // + // Rounds 64-79 + // + // left + b = RL(b + F5(c,d,e) + X[ 4] + unchecked((int) 0xa953fd4e), 9) + a; d = RL(d, 10); + a = RL(a + F5(b,c,d) + X[ 0] + unchecked((int) 0xa953fd4e), 15) + e; c = RL(c, 10); + e = RL(e + F5(a,b,c) + X[ 5] + unchecked((int) 0xa953fd4e), 5) + d; b = RL(b, 10); + d = RL(d + F5(e,a,b) + X[ 9] + unchecked((int) 0xa953fd4e), 11) + c; a = RL(a, 10); + c = RL(c + F5(d,e,a) + X[ 7] + unchecked((int) 0xa953fd4e), 6) + b; e = RL(e, 10); + b = RL(b + F5(c,d,e) + X[12] + unchecked((int) 0xa953fd4e), 8) + a; d = RL(d, 10); + a = RL(a + F5(b,c,d) + X[ 2] + unchecked((int) 0xa953fd4e), 13) + e; c = RL(c, 10); + e = RL(e + F5(a,b,c) + X[10] + unchecked((int) 0xa953fd4e), 12) + d; b = RL(b, 10); + d = RL(d + F5(e,a,b) + X[14] + unchecked((int) 0xa953fd4e), 5) + c; a = RL(a, 10); + c = RL(c + F5(d,e,a) + X[ 1] + unchecked((int) 0xa953fd4e), 12) + b; e = RL(e, 10); + b = RL(b + F5(c,d,e) + X[ 3] + unchecked((int) 0xa953fd4e), 13) + a; d = RL(d, 10); + a = RL(a + F5(b,c,d) + X[ 8] + unchecked((int) 0xa953fd4e), 14) + e; c = RL(c, 10); + e = RL(e + F5(a,b,c) + X[11] + unchecked((int) 0xa953fd4e), 11) + d; b = RL(b, 10); + d = RL(d + F5(e,a,b) + X[ 6] + unchecked((int) 0xa953fd4e), 8) + c; a = RL(a, 10); + c = RL(c + F5(d,e,a) + X[15] + unchecked((int) 0xa953fd4e), 5) + b; e = RL(e, 10); + b = RL(b + F5(c,d,e) + X[13] + unchecked((int) 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; + } + } + } + +} diff --git a/crypto/src/crypto/digests/RipeMD256Digest.cs b/crypto/src/crypto/digests/RipeMD256Digest.cs new file mode 100644 index 000000000..950e94f80 --- /dev/null +++ b/crypto/src/crypto/digests/RipeMD256Digest.cs @@ -0,0 +1,409 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /// + ///

Implementation of RipeMD256.

+ ///

Note: this algorithm offers the same level of security as RipeMD128.

+ ///
+ public class RipeMD256Digest + : GeneralDigest + { + public override string AlgorithmName + { + get { return "RIPEMD256"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + private const int DigestLength = 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):base(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; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) + | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + + if (xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (int)(bitLength & 0xffffffff); + X[15] = (int)((ulong)bitLength >> 32); + } + + private void UnpackWord( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)(uint)word; + outBytes[outOff + 1] = (byte)((uint)word >> 8); + outBytes[outOff + 2] = (byte)((uint)word >> 16); + outBytes[outOff + 3] = (byte)((uint)word >> 24); + } + + public override int DoFinal(byte[] output, int outOff) + { + Finish(); + + UnpackWord(H0, output, outOff); + UnpackWord(H1, output, outOff + 4); + UnpackWord(H2, output, outOff + 8); + UnpackWord(H3, output, outOff + 12); + UnpackWord(H4, output, outOff + 16); + UnpackWord(H5, output, outOff + 20); + UnpackWord(H6, output, outOff + 24); + UnpackWord(H7, output, outOff + 28); + + Reset(); + + return DigestLength; + } + + /// reset the chaining variables to the IV values. + public override void Reset() + { + base.Reset(); + + H0 = unchecked((int)0x67452301); + H1 = unchecked((int)0xefcdab89); + H2 = unchecked((int)0x98badcfe); + H3 = unchecked((int)0x10325476); + H4 = unchecked((int)0x76543210); + H5 = unchecked((int)0xFEDCBA98); + H6 = unchecked((int)0x89ABCDEF); + H7 = unchecked((int)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) | (int)((uint)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 + unchecked((int)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 + unchecked((int)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 + unchecked((int)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 + unchecked((int)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 + unchecked((int)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 + unchecked((int)0x50a28be6), s); + } + + internal override 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; + } + } + } +} diff --git a/crypto/src/crypto/digests/RipeMD320Digest.cs b/crypto/src/crypto/digests/RipeMD320Digest.cs new file mode 100644 index 000000000..25c74baef --- /dev/null +++ b/crypto/src/crypto/digests/RipeMD320Digest.cs @@ -0,0 +1,438 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /// + ///

Implementation of RipeMD 320.

+ ///

Note: this algorithm offers the same level of security as RipeMD160.

+ ///
+ public class RipeMD320Digest + : GeneralDigest + { + public override string AlgorithmName + { + get { return "RIPEMD320"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + private const int DigestLength = 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) + : base(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; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) + | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + + if (xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (int)(bitLength & 0xffffffff); + X[15] = (int)((ulong)bitLength >> 32); + } + + private void UnpackWord( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)word; + outBytes[outOff + 1] = (byte)((uint)word >> 8); + outBytes[outOff + 2] = (byte)((uint)word >> 16); + outBytes[outOff + 3] = (byte)((uint)word >> 24); + } + + public override int DoFinal(byte[] output, int outOff) + { + Finish(); + + UnpackWord(H0, output, outOff); + UnpackWord(H1, output, outOff + 4); + UnpackWord(H2, output, outOff + 8); + UnpackWord(H3, output, outOff + 12); + UnpackWord(H4, output, outOff + 16); + UnpackWord(H5, output, outOff + 20); + UnpackWord(H6, output, outOff + 24); + UnpackWord(H7, output, outOff + 28); + UnpackWord(H8, output, outOff + 32); + UnpackWord(H9, output, outOff + 36); + + Reset(); + + return DigestLength; + } + + /// reset the chaining variables to the IV values. + public override void Reset() + { + base.Reset(); + + H0 = unchecked((int) 0x67452301); + H1 = unchecked((int) 0xefcdab89); + H2 = unchecked((int) 0x98badcfe); + H3 = unchecked((int) 0x10325476); + H4 = unchecked((int) 0xc3d2e1f0); + H5 = unchecked((int) 0x76543210); + H6 = unchecked((int) 0xFEDCBA98); + H7 = unchecked((int) 0x89ABCDEF); + H8 = unchecked((int) 0x01234567); + H9 = unchecked((int) 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) | (int)(((uint)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); + } + + internal override 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] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa, bb, cc) + X[14] + unchecked((int)0x50a28be6), 9) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee, aa, bb) + X[7] + unchecked((int)0x50a28be6), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd, ee, aa) + X[0] + unchecked((int)0x50a28be6), 11) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc, dd, ee) + X[9] + unchecked((int)0x50a28be6), 13) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb, cc, dd) + X[2] + unchecked((int)0x50a28be6), 15) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa, bb, cc) + X[11] + unchecked((int)0x50a28be6), 15) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee, aa, bb) + X[4] + unchecked((int)0x50a28be6), 5) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd, ee, aa) + X[13] + unchecked((int)0x50a28be6), 7) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc, dd, ee) + X[6] + unchecked((int)0x50a28be6), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb, cc, dd) + X[15] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F5(aa, bb, cc) + X[8] + unchecked((int)0x50a28be6), 11) + dd; bb = RL(bb, 10); + dd = RL(dd + F5(ee, aa, bb) + X[1] + unchecked((int)0x50a28be6), 14) + cc; aa = RL(aa, 10); + cc = RL(cc + F5(dd, ee, aa) + X[10] + unchecked((int)0x50a28be6), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F5(cc, dd, ee) + X[3] + unchecked((int)0x50a28be6), 12) + aa; dd = RL(dd, 10); + aa = RL(aa + F5(bb, cc, dd) + X[12] + unchecked((int)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] + unchecked((int)0x5a827999), 7) + d; b = RL(b, 10); + d = RL(d + F2(e, a, b) + X[4] + unchecked((int)0x5a827999), 6) + c; a = RL(a, 10); + c = RL(c + F2(d, e, a) + X[13] + unchecked((int)0x5a827999), 8) + b; e = RL(e, 10); + b = RL(b + F2(c, d, e) + X[1] + unchecked((int)0x5a827999), 13) + a; d = RL(d, 10); + a = RL(a + F2(b, c, d) + X[10] + unchecked((int)0x5a827999), 11) + e; c = RL(c, 10); + e = RL(e + F2(a, b, c) + X[6] + unchecked((int)0x5a827999), 9) + d; b = RL(b, 10); + d = RL(d + F2(e, a, b) + X[15] + unchecked((int)0x5a827999), 7) + c; a = RL(a, 10); + c = RL(c + F2(d, e, a) + X[3] + unchecked((int)0x5a827999), 15) + b; e = RL(e, 10); + b = RL(b + F2(c, d, e) + X[12] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10); + a = RL(a + F2(b, c, d) + X[0] + unchecked((int)0x5a827999), 12) + e; c = RL(c, 10); + e = RL(e + F2(a, b, c) + X[9] + unchecked((int)0x5a827999), 15) + d; b = RL(b, 10); + d = RL(d + F2(e, a, b) + X[5] + unchecked((int)0x5a827999), 9) + c; a = RL(a, 10); + c = RL(c + F2(d, e, a) + X[2] + unchecked((int)0x5a827999), 11) + b; e = RL(e, 10); + b = RL(b + F2(c, d, e) + X[14] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10); + a = RL(a + F2(b, c, d) + X[11] + unchecked((int)0x5a827999), 13) + e; c = RL(c, 10); + e = RL(e + F2(a, b, c) + X[8] + unchecked((int)0x5a827999), 12) + d; b = RL(b, 10); + + // right + ee = RL(ee + F4(aa, bb, cc) + X[6] + unchecked((int)0x5c4dd124), 9) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee, aa, bb) + X[11] + unchecked((int)0x5c4dd124), 13) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd, ee, aa) + X[3] + unchecked((int)0x5c4dd124), 15) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc, dd, ee) + X[7] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb, cc, dd) + X[0] + unchecked((int)0x5c4dd124), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa, bb, cc) + X[13] + unchecked((int)0x5c4dd124), 8) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee, aa, bb) + X[5] + unchecked((int)0x5c4dd124), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd, ee, aa) + X[10] + unchecked((int)0x5c4dd124), 11) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc, dd, ee) + X[14] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb, cc, dd) + X[15] + unchecked((int)0x5c4dd124), 7) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa, bb, cc) + X[8] + unchecked((int)0x5c4dd124), 12) + dd; bb = RL(bb, 10); + dd = RL(dd + F4(ee, aa, bb) + X[12] + unchecked((int)0x5c4dd124), 7) + cc; aa = RL(aa, 10); + cc = RL(cc + F4(dd, ee, aa) + X[4] + unchecked((int)0x5c4dd124), 6) + bb; ee = RL(ee, 10); + bb = RL(bb + F4(cc, dd, ee) + X[9] + unchecked((int)0x5c4dd124), 15) + aa; dd = RL(dd, 10); + aa = RL(aa + F4(bb, cc, dd) + X[1] + unchecked((int)0x5c4dd124), 13) + ee; cc = RL(cc, 10); + ee = RL(ee + F4(aa, bb, cc) + X[2] + unchecked((int)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] + unchecked((int)0x6ed9eba1), 11) + c; a = RL(a, 10); + c = RL(c + F3(d, e, a) + X[10] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10); + b = RL(b + F3(c, d, e) + X[14] + unchecked((int)0x6ed9eba1), 6) + a; d = RL(d, 10); + a = RL(a + F3(b, c, d) + X[4] + unchecked((int)0x6ed9eba1), 7) + e; c = RL(c, 10); + e = RL(e + F3(a, b, c) + X[9] + unchecked((int)0x6ed9eba1), 14) + d; b = RL(b, 10); + d = RL(d + F3(e, a, b) + X[15] + unchecked((int)0x6ed9eba1), 9) + c; a = RL(a, 10); + c = RL(c + F3(d, e, a) + X[8] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10); + b = RL(b + F3(c, d, e) + X[1] + unchecked((int)0x6ed9eba1), 15) + a; d = RL(d, 10); + a = RL(a + F3(b, c, d) + X[2] + unchecked((int)0x6ed9eba1), 14) + e; c = RL(c, 10); + e = RL(e + F3(a, b, c) + X[7] + unchecked((int)0x6ed9eba1), 8) + d; b = RL(b, 10); + d = RL(d + F3(e, a, b) + X[0] + unchecked((int)0x6ed9eba1), 13) + c; a = RL(a, 10); + c = RL(c + F3(d, e, a) + X[6] + unchecked((int)0x6ed9eba1), 6) + b; e = RL(e, 10); + b = RL(b + F3(c, d, e) + X[13] + unchecked((int)0x6ed9eba1), 5) + a; d = RL(d, 10); + a = RL(a + F3(b, c, d) + X[11] + unchecked((int)0x6ed9eba1), 12) + e; c = RL(c, 10); + e = RL(e + F3(a, b, c) + X[5] + unchecked((int)0x6ed9eba1), 7) + d; b = RL(b, 10); + d = RL(d + F3(e, a, b) + X[12] + unchecked((int)0x6ed9eba1), 5) + c; a = RL(a, 10); + + // right + dd = RL(dd + F3(ee, aa, bb) + X[15] + unchecked((int)0x6d703ef3), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd, ee, aa) + X[5] + unchecked((int)0x6d703ef3), 7) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc, dd, ee) + X[1] + unchecked((int)0x6d703ef3), 15) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb, cc, dd) + X[3] + unchecked((int)0x6d703ef3), 11) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa, bb, cc) + X[7] + unchecked((int)0x6d703ef3), 8) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee, aa, bb) + X[14] + unchecked((int)0x6d703ef3), 6) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd, ee, aa) + X[6] + unchecked((int)0x6d703ef3), 6) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc, dd, ee) + X[9] + unchecked((int)0x6d703ef3), 14) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb, cc, dd) + X[11] + unchecked((int)0x6d703ef3), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa, bb, cc) + X[8] + unchecked((int)0x6d703ef3), 13) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee, aa, bb) + X[12] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10); + cc = RL(cc + F3(dd, ee, aa) + X[2] + unchecked((int)0x6d703ef3), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F3(cc, dd, ee) + X[10] + unchecked((int)0x6d703ef3), 13) + aa; dd = RL(dd, 10); + aa = RL(aa + F3(bb, cc, dd) + X[0] + unchecked((int)0x6d703ef3), 13) + ee; cc = RL(cc, 10); + ee = RL(ee + F3(aa, bb, cc) + X[4] + unchecked((int)0x6d703ef3), 7) + dd; bb = RL(bb, 10); + dd = RL(dd + F3(ee, aa, bb) + X[13] + unchecked((int)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] + unchecked((int)0x8f1bbcdc), 11) + b; e = RL(e, 10); + b = RL(b + F4(c, d, e) + X[9] + unchecked((int)0x8f1bbcdc), 12) + a; d = RL(d, 10); + a = RL(a + F4(b, c, d) + X[11] + unchecked((int)0x8f1bbcdc), 14) + e; c = RL(c, 10); + e = RL(e + F4(a, b, c) + X[10] + unchecked((int)0x8f1bbcdc), 15) + d; b = RL(b, 10); + d = RL(d + F4(e, a, b) + X[0] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10); + c = RL(c + F4(d, e, a) + X[8] + unchecked((int)0x8f1bbcdc), 15) + b; e = RL(e, 10); + b = RL(b + F4(c, d, e) + X[12] + unchecked((int)0x8f1bbcdc), 9) + a; d = RL(d, 10); + a = RL(a + F4(b, c, d) + X[4] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10); + e = RL(e + F4(a, b, c) + X[13] + unchecked((int)0x8f1bbcdc), 9) + d; b = RL(b, 10); + d = RL(d + F4(e, a, b) + X[3] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10); + c = RL(c + F4(d, e, a) + X[7] + unchecked((int)0x8f1bbcdc), 5) + b; e = RL(e, 10); + b = RL(b + F4(c, d, e) + X[15] + unchecked((int)0x8f1bbcdc), 6) + a; d = RL(d, 10); + a = RL(a + F4(b, c, d) + X[14] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10); + e = RL(e + F4(a, b, c) + X[5] + unchecked((int)0x8f1bbcdc), 6) + d; b = RL(b, 10); + d = RL(d + F4(e, a, b) + X[6] + unchecked((int)0x8f1bbcdc), 5) + c; a = RL(a, 10); + c = RL(c + F4(d, e, a) + X[2] + unchecked((int)0x8f1bbcdc), 12) + b; e = RL(e, 10); + + // right + cc = RL(cc + F2(dd, ee, aa) + X[8] + unchecked((int)0x7a6d76e9), 15) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc, dd, ee) + X[6] + unchecked((int)0x7a6d76e9), 5) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb, cc, dd) + X[4] + unchecked((int)0x7a6d76e9), 8) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa, bb, cc) + X[1] + unchecked((int)0x7a6d76e9), 11) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee, aa, bb) + X[3] + unchecked((int)0x7a6d76e9), 14) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd, ee, aa) + X[11] + unchecked((int)0x7a6d76e9), 14) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc, dd, ee) + X[15] + unchecked((int)0x7a6d76e9), 6) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb, cc, dd) + X[0] + unchecked((int)0x7a6d76e9), 14) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa, bb, cc) + X[5] + unchecked((int)0x7a6d76e9), 6) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee, aa, bb) + X[12] + unchecked((int)0x7a6d76e9), 9) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd, ee, aa) + X[2] + unchecked((int)0x7a6d76e9), 12) + bb; ee = RL(ee, 10); + bb = RL(bb + F2(cc, dd, ee) + X[13] + unchecked((int)0x7a6d76e9), 9) + aa; dd = RL(dd, 10); + aa = RL(aa + F2(bb, cc, dd) + X[9] + unchecked((int)0x7a6d76e9), 12) + ee; cc = RL(cc, 10); + ee = RL(ee + F2(aa, bb, cc) + X[7] + unchecked((int)0x7a6d76e9), 5) + dd; bb = RL(bb, 10); + dd = RL(dd + F2(ee, aa, bb) + X[10] + unchecked((int)0x7a6d76e9), 15) + cc; aa = RL(aa, 10); + cc = RL(cc + F2(dd, ee, aa) + X[14] + unchecked((int)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] + unchecked((int)0xa953fd4e), 9) + a; d = RL(d, 10); + a = RL(a + F5(b, c, d) + X[0] + unchecked((int)0xa953fd4e), 15) + e; c = RL(c, 10); + e = RL(e + F5(a, b, c) + X[5] + unchecked((int)0xa953fd4e), 5) + d; b = RL(b, 10); + d = RL(d + F5(e, a, b) + X[9] + unchecked((int)0xa953fd4e), 11) + c; a = RL(a, 10); + c = RL(c + F5(d, e, a) + X[7] + unchecked((int)0xa953fd4e), 6) + b; e = RL(e, 10); + b = RL(b + F5(c, d, e) + X[12] + unchecked((int)0xa953fd4e), 8) + a; d = RL(d, 10); + a = RL(a + F5(b, c, d) + X[2] + unchecked((int)0xa953fd4e), 13) + e; c = RL(c, 10); + e = RL(e + F5(a, b, c) + X[10] + unchecked((int)0xa953fd4e), 12) + d; b = RL(b, 10); + d = RL(d + F5(e, a, b) + X[14] + unchecked((int)0xa953fd4e), 5) + c; a = RL(a, 10); + c = RL(c + F5(d, e, a) + X[1] + unchecked((int)0xa953fd4e), 12) + b; e = RL(e, 10); + b = RL(b + F5(c, d, e) + X[3] + unchecked((int)0xa953fd4e), 13) + a; d = RL(d, 10); + a = RL(a + F5(b, c, d) + X[8] + unchecked((int)0xa953fd4e), 14) + e; c = RL(c, 10); + e = RL(e + F5(a, b, c) + X[11] + unchecked((int)0xa953fd4e), 11) + d; b = RL(b, 10); + d = RL(d + F5(e, a, b) + X[6] + unchecked((int)0xa953fd4e), 8) + c; a = RL(a, 10); + c = RL(c + F5(d, e, a) + X[15] + unchecked((int)0xa953fd4e), 5) + b; e = RL(e, 10); + b = RL(b + F5(c, d, e) + X[13] + unchecked((int)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; + } + } + } +} diff --git a/crypto/src/crypto/digests/SHA3Digest.cs b/crypto/src/crypto/digests/SHA3Digest.cs new file mode 100644 index 000000000..a115495f4 --- /dev/null +++ b/crypto/src/crypto/digests/SHA3Digest.cs @@ -0,0 +1,541 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /// + /// Implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ + /// + /// + /// Following the naming conventions used in the C source code to enable easy review of the implementation. + /// + public class Sha3Digest + : IDigest + { + private static readonly ulong[] KeccakRoundConstants = KeccakInitializeRoundConstants(); + + private static readonly int[] KeccakRhoOffsets = KeccakInitializeRhoOffsets(); + + private static ulong[] KeccakInitializeRoundConstants() + { + ulong[] keccakRoundConstants = new ulong[24]; + byte LFSRState = 0x01; + + for (int i = 0; i < 24; i++) + { + keccakRoundConstants[i] = 0; + for (int j = 0; j < 7; j++) + { + int bitPosition = (1 << j) - 1; + + // LFSR86540 + + bool loBit = (LFSRState & 0x01) != 0; + if (loBit) + { + keccakRoundConstants[i] ^= 1UL << bitPosition; + } + + bool hiBit = (LFSRState & 0x80) != 0; + LFSRState <<= 1; + if (hiBit) + { + LFSRState ^= 0x71; + } + + } + } + + return keccakRoundConstants; + } + + private static int[] KeccakInitializeRhoOffsets() + { + int[] keccakRhoOffsets = new int[25]; + int x, y, t, newX, newY; + + int rhoOffset = 0; + keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = rhoOffset; + x = 1; + y = 0; + for (t = 1; t < 25; t++) + { + //rhoOffset = ((t + 1) * (t + 2) / 2) % 64; + rhoOffset = (rhoOffset + t) & 63; + keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = rhoOffset; + 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 bool 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) + { + Array.Copy(source.state, 0, this.state, 0, source.state.Length); + Array.Copy(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 virtual string AlgorithmName + { + get { return "SHA3-" + fixedOutputLength; } + } + + public virtual int GetDigestSize() + { + return fixedOutputLength / 8; + } + + public virtual void Update(byte input) + { + oneByte[0] = input; + + DoUpdate(oneByte, 0, 8L); + } + + public virtual void BlockUpdate(byte[] input, int inOff, int len) + { + DoUpdate(input, inOff, len * 8L); + } + + public virtual int DoFinal(byte[] output, int outOff) + { + Squeeze(output, outOff, fixedOutputLength); + + Reset(); + + return GetDigestSize(); + } + + public virtual 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 virtual 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 ArgumentException("must be one of 224, 256, 384, or 512.", "bitLength"); + } + } + + 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)] >> (int)(8 - (databitlen % 8))); + Absorb(lastByte, off, databitlen % 8); + } + } + + private void InitSponge(int rate, int capacity) + { + if (rate + capacity != 1600) + { + throw new InvalidOperationException("rate + capacity != 1600"); + } + if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) + { + throw new InvalidOperationException("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 InvalidOperationException("attempt to absorb with odd length queue."); + } + if (squeezing) + { + throw new InvalidOperationException("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++) + { + Array.Copy(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; + Array.Copy(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] |= (byte)(1U << (bitsInQueue % 8)); + AbsorbQueue(); + ClearDataQueueSection(0, rate / 8); + } + else + { + ClearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8); + dataQueue[bitsInQueue / 8] |= (byte)(1U << (bitsInQueue % 8)); + } + dataQueue[(rate - 1) / 8] |= (byte)(1U << ((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 InvalidOperationException("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); + } + + Array.Copy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8); + bitsAvailableForSqueezing -= partialBlock; + i += partialBlock; + } + } + + private static void FromBytesToWords(ulong[] 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] |= ((ulong)state[index + j] & 0xff) << ((8 * j)); + } + } + } + + private static void FromWordsToBytes(byte[] state, ulong[] 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)); + } + } + } + + private void KeccakPermutation(byte[] state) + { + ulong[] longState = new ulong[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) + { + for (int i = 0; i < dataLengthInBytes; i++) + { + state[i] ^= data[i]; + } + + KeccakPermutation(state); + } + + private void KeccakPermutationOnWords(ulong[] 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); + } + } + + ulong[] C = new ulong[5]; + + private void Theta(ulong[] 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++) + { + ulong 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(ulong[] 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]); + } + } + } + + ulong[] tempA = new ulong[25]; + + private void Pi(ulong[] A) + { + Array.Copy(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]; + } + } + } + + ulong[] chiC = new ulong[5]; + + private void Chi(ulong[] 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 static void Iota(ulong[] 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) + { + Array.Copy(byteState, 0, data, 0, 128); + } + + private void KeccakExtract(byte[] byteState, byte[] data, int laneCount) + { + Array.Copy(byteState, 0, data, 0, laneCount * 8); + } + } +} diff --git a/crypto/src/crypto/digests/Sha1Digest.cs b/crypto/src/crypto/digests/Sha1Digest.cs new file mode 100644 index 000000000..e72b84f94 --- /dev/null +++ b/crypto/src/crypto/digests/Sha1Digest.cs @@ -0,0 +1,263 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + + /** + * 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 + : GeneralDigest + { + private const int DigestLength = 20; + + private uint H1, H2, H3, H4, H5; + + private uint[] X = new uint[80]; + private int xOff; + + public Sha1Digest() + { + Reset(); + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public Sha1Digest(Sha1Digest t) + : base(t) + { + H1 = t.H1; + H2 = t.H2; + H3 = t.H3; + H4 = t.H4; + H5 = t.H5; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "SHA-1"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff] = Pack.BE_To_UInt32(input, inOff); + + if (++xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength(long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (uint)((ulong)bitLength >> 32); + X[15] = (uint)((ulong)bitLength); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt32_To_BE(H1, output, outOff); + Pack.UInt32_To_BE(H2, output, outOff + 4); + Pack.UInt32_To_BE(H3, output, outOff + 8); + Pack.UInt32_To_BE(H4, output, outOff + 12); + Pack.UInt32_To_BE(H5, output, outOff + 16); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.Reset(); + + H1 = 0x67452301; + H2 = 0xefcdab89; + H3 = 0x98badcfe; + H4 = 0x10325476; + H5 = 0xc3d2e1f0; + + xOff = 0; + Array.Clear(X, 0, X.Length); + } + + // + // Additive constants + // + private const uint Y1 = 0x5a827999; + private const uint Y2 = 0x6ed9eba1; + private const uint Y3 = 0x8f1bbcdc; + private const uint Y4 = 0xca62c1d6; + + private static uint F(uint u, uint v, uint w) + { + return (u & v) | (~u & w); + } + + private static uint H(uint u, uint v, uint w) + { + return u ^ v ^ w; + } + + private static uint G(uint u, uint v, uint w) + { + return (u & v) | (u & w) | (v & w); + } + + internal override void ProcessBlock() + { + // + // expand 16 word block into 80 word block. + // + for (int i = 16; i < 80; i++) + { + uint t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]; + X[i] = t << 1 | t >> 31; + } + + // + // set up working variables. + // + uint A = H1; + uint B = H2; + uint C = H3; + uint D = H4; + uint 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 < 4; 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; + Array.Clear(X, 0, 16); + } + } +} diff --git a/crypto/src/crypto/digests/Sha224Digest.cs b/crypto/src/crypto/digests/Sha224Digest.cs new file mode 100644 index 000000000..66ecd4ecd --- /dev/null +++ b/crypto/src/crypto/digests/Sha224Digest.cs @@ -0,0 +1,268 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * SHA-224 as described in RFC 3874 + *
+     *         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
+     * 
+ */ + public class Sha224Digest + : GeneralDigest + { + private const int DigestLength = 28; + + private uint H1, H2, H3, H4, H5, H6, H7, H8; + + private uint[] X = new uint[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) + : base(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; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "SHA-224"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff] = Pack.BE_To_UInt32(input, inOff); + + if (++xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (uint)((ulong)bitLength >> 32); + X[15] = (uint)((ulong)bitLength); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt32_To_BE(H1, output, outOff); + Pack.UInt32_To_BE(H2, output, outOff + 4); + Pack.UInt32_To_BE(H3, output, outOff + 8); + Pack.UInt32_To_BE(H4, output, outOff + 12); + Pack.UInt32_To_BE(H5, output, outOff + 16); + Pack.UInt32_To_BE(H6, output, outOff + 20); + Pack.UInt32_To_BE(H7, output, outOff + 24); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.Reset(); + + /* SHA-224 initial hash value + */ + H1 = 0xc1059ed8; + H2 = 0x367cd507; + H3 = 0x3070dd17; + H4 = 0xf70e5939; + H5 = 0xffc00b31; + H6 = 0x68581511; + H7 = 0x64f98fa7; + H8 = 0xbefa4fa4; + + xOff = 0; + Array.Clear(X, 0, X.Length); + } + + internal override void ProcessBlock() + { + // + // expand 16 word block into 64 word blocks. + // + for (int ti = 16; ti <= 63; ti++) + { + X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16]; + } + + // + // set up working variables. + // + uint a = H1; + uint b = H2; + uint c = H3; + uint d = H4; + uint e = H5; + uint f = H6; + uint g = H7; + uint 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; + Array.Clear(X, 0, 16); + } + + /* SHA-224 functions */ + private static uint Ch(uint x, uint y, uint z) + { + return (x & y) ^ (~x & z); + } + + private static uint Maj(uint x, uint y, uint z) + { + return (x & y) ^ (x & z) ^ (y & z); + } + + private static uint Sum0(uint x) + { + return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)); + } + + private static uint Sum1(uint x) + { + return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)); + } + + private static uint Theta0(uint x) + { + return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3); + } + + private static uint Theta1(uint 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) + */ + internal static readonly uint[] 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 + }; + } +} diff --git a/crypto/src/crypto/digests/Sha256Digest.cs b/crypto/src/crypto/digests/Sha256Digest.cs new file mode 100644 index 000000000..1c00ab71f --- /dev/null +++ b/crypto/src/crypto/digests/Sha256Digest.cs @@ -0,0 +1,309 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Draft FIPS 180-2 implementation of SHA-256. Note: As this is + * based on a draft this implementation is subject to change. + * + *
+    *         block  word  digest
+    * SHA-1   512    32    160
+    * SHA-256 512    32    256
+    * SHA-384 1024   64    384
+    * SHA-512 1024   64    512
+    * 
+ */ + public class Sha256Digest + : GeneralDigest + { + private const int DigestLength = 32; + + private uint H1, H2, H3, H4, H5, H6, H7, H8; + private uint[] X = new uint[64]; + private int xOff; + + public Sha256Digest() + { + initHs(); + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public Sha256Digest(Sha256Digest t) : base(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; + + Array.Copy(t.X, 0, X, 0, t.X.Length); + xOff = t.xOff; + } + + public override string AlgorithmName + { + get { return "SHA-256"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + internal override void ProcessWord( + byte[] input, + int inOff) + { + X[xOff] = Pack.BE_To_UInt32(input, inOff); + + if (++xOff == 16) + { + ProcessBlock(); + } + } + + internal override void ProcessLength( + long bitLength) + { + if (xOff > 14) + { + ProcessBlock(); + } + + X[14] = (uint)((ulong)bitLength >> 32); + X[15] = (uint)((ulong)bitLength); + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt32_To_BE((uint)H1, output, outOff); + Pack.UInt32_To_BE((uint)H2, output, outOff + 4); + Pack.UInt32_To_BE((uint)H3, output, outOff + 8); + Pack.UInt32_To_BE((uint)H4, output, outOff + 12); + Pack.UInt32_To_BE((uint)H5, output, outOff + 16); + Pack.UInt32_To_BE((uint)H6, output, outOff + 20); + Pack.UInt32_To_BE((uint)H7, output, outOff + 24); + Pack.UInt32_To_BE((uint)H8, output, outOff + 28); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.Reset(); + + initHs(); + + xOff = 0; + Array.Clear(X, 0, X.Length); + } + + private void initHs() + { + /* 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; + } + + internal override void ProcessBlock() + { + // + // expand 16 word block into 64 word blocks. + // + for (int ti = 16; ti <= 63; ti++) + { + X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16]; + } + + // + // set up working variables. + // + uint a = H1; + uint b = H2; + uint c = H3; + uint d = H4; + uint e = H5; + uint f = H6; + uint g = H7; + uint h = H8; + + int t = 0; + for(int i = 0; i < 8; ++i) + { + // t = 8 * i + h += Sum1Ch(e, f, g) + K[t] + X[t]; + d += h; + h += Sum0Maj(a, b, c); + ++t; + + // t = 8 * i + 1 + g += Sum1Ch(d, e, f) + K[t] + X[t]; + c += g; + g += Sum0Maj(h, a, b); + ++t; + + // t = 8 * i + 2 + f += Sum1Ch(c, d, e) + K[t] + X[t]; + b += f; + f += Sum0Maj(g, h, a); + ++t; + + // t = 8 * i + 3 + e += Sum1Ch(b, c, d) + K[t] + X[t]; + a += e; + e += Sum0Maj(f, g, h); + ++t; + + // t = 8 * i + 4 + d += Sum1Ch(a, b, c) + K[t] + X[t]; + h += d; + d += Sum0Maj(e, f, g); + ++t; + + // t = 8 * i + 5 + c += Sum1Ch(h, a, b) + K[t] + X[t]; + g += c; + c += Sum0Maj(d, e, f); + ++t; + + // t = 8 * i + 6 + b += Sum1Ch(g, h, a) + K[t] + X[t]; + f += b; + b += Sum0Maj(c, d, e); + ++t; + + // t = 8 * i + 7 + a += Sum1Ch(f, g, h) + K[t] + X[t]; + e += a; + a += Sum0Maj(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; + Array.Clear(X, 0, 16); + } + + private static uint Sum1Ch( + uint x, + uint y, + uint z) + { +// return Sum1(x) + Ch(x, y, z); + return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))) + + ((x & y) ^ ((~x) & z)); + } + + private static uint Sum0Maj( + uint x, + uint y, + uint z) + { +// return Sum0(x) + Maj(x, y, z); + return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))) + + ((x & y) ^ (x & z) ^ (y & z)); + } + +// /* SHA-256 functions */ +// private static uint Ch( +// uint x, +// uint y, +// uint z) +// { +// return ((x & y) ^ ((~x) & z)); +// } +// +// private static uint Maj( +// uint x, +// uint y, +// uint z) +// { +// return ((x & y) ^ (x & z) ^ (y & z)); +// } +// +// private static uint Sum0( +// uint x) +// { +// return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)); +// } +// +// private static uint Sum1( +// uint x) +// { +// return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)); +// } + + private static uint Theta0( + uint x) + { + return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3); + } + + private static uint Theta1( + uint 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) + */ + private static readonly uint[] 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 + }; + } +} diff --git a/crypto/src/crypto/digests/Sha384Digest.cs b/crypto/src/crypto/digests/Sha384Digest.cs new file mode 100644 index 000000000..f1372d0a9 --- /dev/null +++ b/crypto/src/crypto/digests/Sha384Digest.cs @@ -0,0 +1,87 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Draft FIPS 180-2 implementation of SHA-384. Note: As this is + * based on a draft this implementation is subject to change. + * + *
+     *         block  word  digest
+     * SHA-1   512    32    160
+     * SHA-256 512    32    256
+     * SHA-384 1024   64    384
+     * SHA-512 1024   64    512
+     * 
+ */ + public class Sha384Digest + : LongDigest + { + private const int DigestLength = 48; + + public Sha384Digest() + { + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public Sha384Digest( + Sha384Digest t) + : base(t) + { + } + + public override string AlgorithmName + { + get { return "SHA-384"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt64_To_BE(H1, output, outOff); + Pack.UInt64_To_BE(H2, output, outOff + 8); + Pack.UInt64_To_BE(H3, output, outOff + 16); + Pack.UInt64_To_BE(H4, output, outOff + 24); + Pack.UInt64_To_BE(H5, output, outOff + 32); + Pack.UInt64_To_BE(H6, output, outOff + 40); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.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 = 0xcbbb9d5dc1059ed8; + H2 = 0x629a292a367cd507; + H3 = 0x9159015a3070dd17; + H4 = 0x152fecd8f70e5939; + H5 = 0x67332667ffc00b31; + H6 = 0x8eb44a8768581511; + H7 = 0xdb0c2e0d64f98fa7; + H8 = 0x47b5481dbefa4fa4; + } + } +} diff --git a/crypto/src/crypto/digests/Sha512Digest.cs b/crypto/src/crypto/digests/Sha512Digest.cs new file mode 100644 index 000000000..b38ff8ee7 --- /dev/null +++ b/crypto/src/crypto/digests/Sha512Digest.cs @@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Draft FIPS 180-2 implementation of SHA-512. Note: As this is + * based on a draft this implementation is subject to change. + * + *
+     *         block  word  digest
+     * SHA-1   512    32    160
+     * SHA-256 512    32    256
+     * SHA-384 1024   64    384
+     * SHA-512 1024   64    512
+     * 
+ */ + public class Sha512Digest + : LongDigest + { + private const int DigestLength = 64; + + public Sha512Digest() + { + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public Sha512Digest( + Sha512Digest t) + : base(t) + { + } + + public override string AlgorithmName + { + get { return "SHA-512"; } + } + + public override int GetDigestSize() + { + return DigestLength; + } + + public override int DoFinal( + byte[] output, + int outOff) + { + Finish(); + + Pack.UInt64_To_BE(H1, output, outOff); + Pack.UInt64_To_BE(H2, output, outOff + 8); + Pack.UInt64_To_BE(H3, output, outOff + 16); + Pack.UInt64_To_BE(H4, output, outOff + 24); + Pack.UInt64_To_BE(H5, output, outOff + 32); + Pack.UInt64_To_BE(H6, output, outOff + 40); + Pack.UInt64_To_BE(H7, output, outOff + 48); + Pack.UInt64_To_BE(H8, output, outOff + 56); + + Reset(); + + return DigestLength; + + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.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 = 0x6a09e667f3bcc908; + H2 = 0xbb67ae8584caa73b; + H3 = 0x3c6ef372fe94f82b; + H4 = 0xa54ff53a5f1d36f1; + H5 = 0x510e527fade682d1; + H6 = 0x9b05688c2b3e6c1f; + H7 = 0x1f83d9abfb41bd6b; + H8 = 0x5be0cd19137e2179; + } + } +} diff --git a/crypto/src/crypto/digests/Sha512tDigest.cs b/crypto/src/crypto/digests/Sha512tDigest.cs new file mode 100644 index 000000000..7580d6267 --- /dev/null +++ b/crypto/src/crypto/digests/Sha512tDigest.cs @@ -0,0 +1,179 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * FIPS 180-4 implementation of SHA-512/t + */ + public class Sha512tDigest + : LongDigest + { + private const ulong A5 = 0xa5a5a5a5a5a5a5a5UL; + + private readonly int digestLength; + + private ulong H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t; + + /** + * Standard constructor + */ + public Sha512tDigest(int bitLength) + { + if (bitLength >= 512) + throw new ArgumentException("cannot be >= 512", "bitLength"); + if (bitLength % 8 != 0) + throw new ArgumentException("needs to be a multiple of 8", "bitLength"); + if (bitLength == 384) + throw new ArgumentException("cannot be 384 use SHA384 instead", "bitLength"); + + this.digestLength = bitLength / 8; + + tIvGenerate(digestLength * 8); + + Reset(); + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public Sha512tDigest(Sha512tDigest t) + : base(t) + { + this.digestLength = t.digestLength; + + 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 override string AlgorithmName + { + get { return "SHA-512/" + (digestLength * 8); } + } + + public override int GetDigestSize() + { + return digestLength; + } + + public override int DoFinal(byte[] output, int outOff) + { + Finish(); + + UInt64_To_BE(H1, output, outOff, digestLength); + UInt64_To_BE(H2, output, outOff + 8, digestLength - 8); + UInt64_To_BE(H3, output, outOff + 16, digestLength - 16); + UInt64_To_BE(H4, output, outOff + 24, digestLength - 24); + UInt64_To_BE(H5, output, outOff + 32, digestLength - 32); + UInt64_To_BE(H6, output, outOff + 40, digestLength - 40); + UInt64_To_BE(H7, output, outOff + 48, digestLength - 48); + UInt64_To_BE(H8, output, outOff + 56, digestLength - 56); + + Reset(); + + return digestLength; + } + + /** + * reset the chaining variables + */ + public override void Reset() + { + base.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 = 0x6a09e667f3bcc908UL ^ A5; + H2 = 0xbb67ae8584caa73bUL ^ A5; + H3 = 0x3c6ef372fe94f82bUL ^ A5; + H4 = 0xa54ff53a5f1d36f1UL ^ A5; + H5 = 0x510e527fade682d1UL ^ A5; + H6 = 0x9b05688c2b3e6c1fUL ^ A5; + H7 = 0x1f83d9abfb41bd6bUL ^ A5; + H8 = 0x5be0cd19137e2179UL ^ A5; + + Update(0x53); + Update(0x48); + Update(0x41); + Update(0x2D); + Update(0x35); + Update(0x31); + Update(0x32); + Update(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 UInt64_To_BE(ulong n, byte[] bs, int off, int max) + { + if (max > 0) + { + UInt32_To_BE((uint)(n >> 32), bs, off, max); + + if (max > 4) + { + UInt32_To_BE((uint)n, bs, off + 4, max - 4); + } + } + } + + private static void UInt32_To_BE(uint n, byte[] bs, int off, int max) + { + int num = System.Math.Min(4, max); + while (--num >= 0) + { + int shift = 8 * (3 - num); + bs[off + num] = (byte)(n >> shift); + } + } + } +} diff --git a/crypto/src/crypto/digests/ShortenedDigest.cs b/crypto/src/crypto/digests/ShortenedDigest.cs new file mode 100644 index 000000000..9e4d99e7b --- /dev/null +++ b/crypto/src/crypto/digests/ShortenedDigest.cs @@ -0,0 +1,82 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Wrapper class that reduces the output length of a particular digest to + * only the first n bytes of the digest function. + */ + public class ShortenedDigest + : IDigest + { + private IDigest baseDigest; + private int length; + + /** + * Base constructor. + * + * @param baseDigest underlying digest to use. + * @param length length in bytes of the output of doFinal. + * @exception ArgumentException if baseDigest is null, or length is greater than baseDigest.GetDigestSize(). + */ + public ShortenedDigest( + IDigest baseDigest, + int length) + { + if (baseDigest == null) + { + throw new ArgumentNullException("baseDigest"); + } + + if (length > baseDigest.GetDigestSize()) + { + throw new ArgumentException("baseDigest output not large enough to support length"); + } + + this.baseDigest = baseDigest; + this.length = length; + } + + public string AlgorithmName + { + get { return baseDigest.AlgorithmName + "(" + length * 8 + ")"; } + } + + public int GetDigestSize() + { + return length; + } + + public void Update(byte input) + { + baseDigest.Update(input); + } + + public void BlockUpdate(byte[] input, int inOff, int length) + { + baseDigest.BlockUpdate(input, inOff, length); + } + + public int DoFinal(byte[] output, int outOff) + { + byte[] tmp = new byte[baseDigest.GetDigestSize()]; + + baseDigest.DoFinal(tmp, 0); + + Array.Copy(tmp, 0, output, outOff, length); + + return length; + } + + public void Reset() + { + baseDigest.Reset(); + } + + public int GetByteLength() + { + return baseDigest.GetByteLength(); + } + } +} diff --git a/crypto/src/crypto/digests/TigerDigest.cs b/crypto/src/crypto/digests/TigerDigest.cs new file mode 100644 index 000000000..b8c9a7664 --- /dev/null +++ b/crypto/src/crypto/digests/TigerDigest.cs @@ -0,0 +1,868 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * implementation of Tiger based on: + * + * http://www.cs.technion.ac.il/~biham/Reports/Tiger + */ + public class TigerDigest + : IDigest + { + private const int MyByteLength = 64; + + /* + * S-Boxes. + */ + private static readonly long[] t1 = { + unchecked((long) 0x02AAB17CF7E90C5EL) /* 0 */, unchecked((long) 0xAC424B03E243A8ECL) /* 1 */, + unchecked((long) 0x72CD5BE30DD5FCD3L) /* 2 */, unchecked((long) 0x6D019B93F6F97F3AL) /* 3 */, + unchecked((long) 0xCD9978FFD21F9193L) /* 4 */, unchecked((long) 0x7573A1C9708029E2L) /* 5 */, + unchecked((long) 0xB164326B922A83C3L) /* 6 */, unchecked((long) 0x46883EEE04915870L) /* 7 */, + unchecked((long) 0xEAACE3057103ECE6L) /* 8 */, unchecked((long) 0xC54169B808A3535CL) /* 9 */, + unchecked((long) 0x4CE754918DDEC47CL) /* 10 */, unchecked((long) 0x0AA2F4DFDC0DF40CL) /* 11 */, + unchecked((long) 0x10B76F18A74DBEFAL) /* 12 */, unchecked((long) 0xC6CCB6235AD1AB6AL) /* 13 */, + unchecked((long) 0x13726121572FE2FFL) /* 14 */, unchecked((long) 0x1A488C6F199D921EL) /* 15 */, + unchecked((long) 0x4BC9F9F4DA0007CAL) /* 16 */, unchecked((long) 0x26F5E6F6E85241C7L) /* 17 */, + unchecked((long) 0x859079DBEA5947B6L) /* 18 */, unchecked((long) 0x4F1885C5C99E8C92L) /* 19 */, + unchecked((long) 0xD78E761EA96F864BL) /* 20 */, unchecked((long) 0x8E36428C52B5C17DL) /* 21 */, + unchecked((long) 0x69CF6827373063C1L) /* 22 */, unchecked((long) 0xB607C93D9BB4C56EL) /* 23 */, + unchecked((long) 0x7D820E760E76B5EAL) /* 24 */, unchecked((long) 0x645C9CC6F07FDC42L) /* 25 */, + unchecked((long) 0xBF38A078243342E0L) /* 26 */, unchecked((long) 0x5F6B343C9D2E7D04L) /* 27 */, + unchecked((long) 0xF2C28AEB600B0EC6L) /* 28 */, unchecked((long) 0x6C0ED85F7254BCACL) /* 29 */, + unchecked((long) 0x71592281A4DB4FE5L) /* 30 */, unchecked((long) 0x1967FA69CE0FED9FL) /* 31 */, + unchecked((long) 0xFD5293F8B96545DBL) /* 32 */, unchecked((long) 0xC879E9D7F2A7600BL) /* 33 */, + unchecked((long) 0x860248920193194EL) /* 34 */, unchecked((long) 0xA4F9533B2D9CC0B3L) /* 35 */, + unchecked((long) 0x9053836C15957613L) /* 36 */, unchecked((long) 0xDB6DCF8AFC357BF1L) /* 37 */, + unchecked((long) 0x18BEEA7A7A370F57L) /* 38 */, unchecked((long) 0x037117CA50B99066L) /* 39 */, + unchecked((long) 0x6AB30A9774424A35L) /* 40 */, unchecked((long) 0xF4E92F02E325249BL) /* 41 */, + unchecked((long) 0x7739DB07061CCAE1L) /* 42 */, unchecked((long) 0xD8F3B49CECA42A05L) /* 43 */, + unchecked((long) 0xBD56BE3F51382F73L) /* 44 */, unchecked((long) 0x45FAED5843B0BB28L) /* 45 */, + unchecked((long) 0x1C813D5C11BF1F83L) /* 46 */, unchecked((long) 0x8AF0E4B6D75FA169L) /* 47 */, + unchecked((long) 0x33EE18A487AD9999L) /* 48 */, unchecked((long) 0x3C26E8EAB1C94410L) /* 49 */, + unchecked((long) 0xB510102BC0A822F9L) /* 50 */, unchecked((long) 0x141EEF310CE6123BL) /* 51 */, + unchecked((long) 0xFC65B90059DDB154L) /* 52 */, unchecked((long) 0xE0158640C5E0E607L) /* 53 */, + unchecked((long) 0x884E079826C3A3CFL) /* 54 */, unchecked((long) 0x930D0D9523C535FDL) /* 55 */, + unchecked((long) 0x35638D754E9A2B00L) /* 56 */, unchecked((long) 0x4085FCCF40469DD5L) /* 57 */, + unchecked((long) 0xC4B17AD28BE23A4CL) /* 58 */, unchecked((long) 0xCAB2F0FC6A3E6A2EL) /* 59 */, + unchecked((long) 0x2860971A6B943FCDL) /* 60 */, unchecked((long) 0x3DDE6EE212E30446L) /* 61 */, + unchecked((long) 0x6222F32AE01765AEL) /* 62 */, unchecked((long) 0x5D550BB5478308FEL) /* 63 */, + unchecked((long) 0xA9EFA98DA0EDA22AL) /* 64 */, unchecked((long) 0xC351A71686C40DA7L) /* 65 */, + unchecked((long) 0x1105586D9C867C84L) /* 66 */, unchecked((long) 0xDCFFEE85FDA22853L) /* 67 */, + unchecked((long) 0xCCFBD0262C5EEF76L) /* 68 */, unchecked((long) 0xBAF294CB8990D201L) /* 69 */, + unchecked((long) 0xE69464F52AFAD975L) /* 70 */, unchecked((long) 0x94B013AFDF133E14L) /* 71 */, + unchecked((long) 0x06A7D1A32823C958L) /* 72 */, unchecked((long) 0x6F95FE5130F61119L) /* 73 */, + unchecked((long) 0xD92AB34E462C06C0L) /* 74 */, unchecked((long) 0xED7BDE33887C71D2L) /* 75 */, + unchecked((long) 0x79746D6E6518393EL) /* 76 */, unchecked((long) 0x5BA419385D713329L) /* 77 */, + unchecked((long) 0x7C1BA6B948A97564L) /* 78 */, unchecked((long) 0x31987C197BFDAC67L) /* 79 */, + unchecked((long) 0xDE6C23C44B053D02L) /* 80 */, unchecked((long) 0x581C49FED002D64DL) /* 81 */, + unchecked((long) 0xDD474D6338261571L) /* 82 */, unchecked((long) 0xAA4546C3E473D062L) /* 83 */, + unchecked((long) 0x928FCE349455F860L) /* 84 */, unchecked((long) 0x48161BBACAAB94D9L) /* 85 */, + unchecked((long) 0x63912430770E6F68L) /* 86 */, unchecked((long) 0x6EC8A5E602C6641CL) /* 87 */, + unchecked((long) 0x87282515337DDD2BL) /* 88 */, unchecked((long) 0x2CDA6B42034B701BL) /* 89 */, + unchecked((long) 0xB03D37C181CB096DL) /* 90 */, unchecked((long) 0xE108438266C71C6FL) /* 91 */, + unchecked((long) 0x2B3180C7EB51B255L) /* 92 */, unchecked((long) 0xDF92B82F96C08BBCL) /* 93 */, + unchecked((long) 0x5C68C8C0A632F3BAL) /* 94 */, unchecked((long) 0x5504CC861C3D0556L) /* 95 */, + unchecked((long) 0xABBFA4E55FB26B8FL) /* 96 */, unchecked((long) 0x41848B0AB3BACEB4L) /* 97 */, + unchecked((long) 0xB334A273AA445D32L) /* 98 */, unchecked((long) 0xBCA696F0A85AD881L) /* 99 */, + unchecked((long) 0x24F6EC65B528D56CL) /* 100 */, unchecked((long) 0x0CE1512E90F4524AL) /* 101 */, + unchecked((long) 0x4E9DD79D5506D35AL) /* 102 */, unchecked((long) 0x258905FAC6CE9779L) /* 103 */, + unchecked((long) 0x2019295B3E109B33L) /* 104 */, unchecked((long) 0xF8A9478B73A054CCL) /* 105 */, + unchecked((long) 0x2924F2F934417EB0L) /* 106 */, unchecked((long) 0x3993357D536D1BC4L) /* 107 */, + unchecked((long) 0x38A81AC21DB6FF8BL) /* 108 */, unchecked((long) 0x47C4FBF17D6016BFL) /* 109 */, + unchecked((long) 0x1E0FAADD7667E3F5L) /* 110 */, unchecked((long) 0x7ABCFF62938BEB96L) /* 111 */, + unchecked((long) 0xA78DAD948FC179C9L) /* 112 */, unchecked((long) 0x8F1F98B72911E50DL) /* 113 */, + unchecked((long) 0x61E48EAE27121A91L) /* 114 */, unchecked((long) 0x4D62F7AD31859808L) /* 115 */, + unchecked((long) 0xECEBA345EF5CEAEBL) /* 116 */, unchecked((long) 0xF5CEB25EBC9684CEL) /* 117 */, + unchecked((long) 0xF633E20CB7F76221L) /* 118 */, unchecked((long) 0xA32CDF06AB8293E4L) /* 119 */, + unchecked((long) 0x985A202CA5EE2CA4L) /* 120 */, unchecked((long) 0xCF0B8447CC8A8FB1L) /* 121 */, + unchecked((long) 0x9F765244979859A3L) /* 122 */, unchecked((long) 0xA8D516B1A1240017L) /* 123 */, + unchecked((long) 0x0BD7BA3EBB5DC726L) /* 124 */, unchecked((long) 0xE54BCA55B86ADB39L) /* 125 */, + unchecked((long) 0x1D7A3AFD6C478063L) /* 126 */, unchecked((long) 0x519EC608E7669EDDL) /* 127 */, + unchecked((long) 0x0E5715A2D149AA23L) /* 128 */, unchecked((long) 0x177D4571848FF194L) /* 129 */, + unchecked((long) 0xEEB55F3241014C22L) /* 130 */, unchecked((long) 0x0F5E5CA13A6E2EC2L) /* 131 */, + unchecked((long) 0x8029927B75F5C361L) /* 132 */, unchecked((long) 0xAD139FABC3D6E436L) /* 133 */, + unchecked((long) 0x0D5DF1A94CCF402FL) /* 134 */, unchecked((long) 0x3E8BD948BEA5DFC8L) /* 135 */, + unchecked((long) 0xA5A0D357BD3FF77EL) /* 136 */, unchecked((long) 0xA2D12E251F74F645L) /* 137 */, + unchecked((long) 0x66FD9E525E81A082L) /* 138 */, unchecked((long) 0x2E0C90CE7F687A49L) /* 139 */, + unchecked((long) 0xC2E8BCBEBA973BC5L) /* 140 */, unchecked((long) 0x000001BCE509745FL) /* 141 */, + unchecked((long) 0x423777BBE6DAB3D6L) /* 142 */, unchecked((long) 0xD1661C7EAEF06EB5L) /* 143 */, + unchecked((long) 0xA1781F354DAACFD8L) /* 144 */, unchecked((long) 0x2D11284A2B16AFFCL) /* 145 */, + unchecked((long) 0xF1FC4F67FA891D1FL) /* 146 */, unchecked((long) 0x73ECC25DCB920ADAL) /* 147 */, + unchecked((long) 0xAE610C22C2A12651L) /* 148 */, unchecked((long) 0x96E0A810D356B78AL) /* 149 */, + unchecked((long) 0x5A9A381F2FE7870FL) /* 150 */, unchecked((long) 0xD5AD62EDE94E5530L) /* 151 */, + unchecked((long) 0xD225E5E8368D1427L) /* 152 */, unchecked((long) 0x65977B70C7AF4631L) /* 153 */, + unchecked((long) 0x99F889B2DE39D74FL) /* 154 */, unchecked((long) 0x233F30BF54E1D143L) /* 155 */, + unchecked((long) 0x9A9675D3D9A63C97L) /* 156 */, unchecked((long) 0x5470554FF334F9A8L) /* 157 */, + unchecked((long) 0x166ACB744A4F5688L) /* 158 */, unchecked((long) 0x70C74CAAB2E4AEADL) /* 159 */, + unchecked((long) 0xF0D091646F294D12L) /* 160 */, unchecked((long) 0x57B82A89684031D1L) /* 161 */, + unchecked((long) 0xEFD95A5A61BE0B6BL) /* 162 */, unchecked((long) 0x2FBD12E969F2F29AL) /* 163 */, + unchecked((long) 0x9BD37013FEFF9FE8L) /* 164 */, unchecked((long) 0x3F9B0404D6085A06L) /* 165 */, + unchecked((long) 0x4940C1F3166CFE15L) /* 166 */, unchecked((long) 0x09542C4DCDF3DEFBL) /* 167 */, + unchecked((long) 0xB4C5218385CD5CE3L) /* 168 */, unchecked((long) 0xC935B7DC4462A641L) /* 169 */, + unchecked((long) 0x3417F8A68ED3B63FL) /* 170 */, unchecked((long) 0xB80959295B215B40L) /* 171 */, + unchecked((long) 0xF99CDAEF3B8C8572L) /* 172 */, unchecked((long) 0x018C0614F8FCB95DL) /* 173 */, + unchecked((long) 0x1B14ACCD1A3ACDF3L) /* 174 */, unchecked((long) 0x84D471F200BB732DL) /* 175 */, + unchecked((long) 0xC1A3110E95E8DA16L) /* 176 */, unchecked((long) 0x430A7220BF1A82B8L) /* 177 */, + unchecked((long) 0xB77E090D39DF210EL) /* 178 */, unchecked((long) 0x5EF4BD9F3CD05E9DL) /* 179 */, + unchecked((long) 0x9D4FF6DA7E57A444L) /* 180 */, unchecked((long) 0xDA1D60E183D4A5F8L) /* 181 */, + unchecked((long) 0xB287C38417998E47L) /* 182 */, unchecked((long) 0xFE3EDC121BB31886L) /* 183 */, + unchecked((long) 0xC7FE3CCC980CCBEFL) /* 184 */, unchecked((long) 0xE46FB590189BFD03L) /* 185 */, + unchecked((long) 0x3732FD469A4C57DCL) /* 186 */, unchecked((long) 0x7EF700A07CF1AD65L) /* 187 */, + unchecked((long) 0x59C64468A31D8859L) /* 188 */, unchecked((long) 0x762FB0B4D45B61F6L) /* 189 */, + unchecked((long) 0x155BAED099047718L) /* 190 */, unchecked((long) 0x68755E4C3D50BAA6L) /* 191 */, + unchecked((long) 0xE9214E7F22D8B4DFL) /* 192 */, unchecked((long) 0x2ADDBF532EAC95F4L) /* 193 */, + unchecked((long) 0x32AE3909B4BD0109L) /* 194 */, unchecked((long) 0x834DF537B08E3450L) /* 195 */, + unchecked((long) 0xFA209DA84220728DL) /* 196 */, unchecked((long) 0x9E691D9B9EFE23F7L) /* 197 */, + unchecked((long) 0x0446D288C4AE8D7FL) /* 198 */, unchecked((long) 0x7B4CC524E169785BL) /* 199 */, + unchecked((long) 0x21D87F0135CA1385L) /* 200 */, unchecked((long) 0xCEBB400F137B8AA5L) /* 201 */, + unchecked((long) 0x272E2B66580796BEL) /* 202 */, unchecked((long) 0x3612264125C2B0DEL) /* 203 */, + unchecked((long) 0x057702BDAD1EFBB2L) /* 204 */, unchecked((long) 0xD4BABB8EACF84BE9L) /* 205 */, + unchecked((long) 0x91583139641BC67BL) /* 206 */, unchecked((long) 0x8BDC2DE08036E024L) /* 207 */, + unchecked((long) 0x603C8156F49F68EDL) /* 208 */, unchecked((long) 0xF7D236F7DBEF5111L) /* 209 */, + unchecked((long) 0x9727C4598AD21E80L) /* 210 */, unchecked((long) 0xA08A0896670A5FD7L) /* 211 */, + unchecked((long) 0xCB4A8F4309EBA9CBL) /* 212 */, unchecked((long) 0x81AF564B0F7036A1L) /* 213 */, + unchecked((long) 0xC0B99AA778199ABDL) /* 214 */, unchecked((long) 0x959F1EC83FC8E952L) /* 215 */, + unchecked((long) 0x8C505077794A81B9L) /* 216 */, unchecked((long) 0x3ACAAF8F056338F0L) /* 217 */, + unchecked((long) 0x07B43F50627A6778L) /* 218 */, unchecked((long) 0x4A44AB49F5ECCC77L) /* 219 */, + unchecked((long) 0x3BC3D6E4B679EE98L) /* 220 */, unchecked((long) 0x9CC0D4D1CF14108CL) /* 221 */, + unchecked((long) 0x4406C00B206BC8A0L) /* 222 */, unchecked((long) 0x82A18854C8D72D89L) /* 223 */, + unchecked((long) 0x67E366B35C3C432CL) /* 224 */, unchecked((long) 0xB923DD61102B37F2L) /* 225 */, + unchecked((long) 0x56AB2779D884271DL) /* 226 */, unchecked((long) 0xBE83E1B0FF1525AFL) /* 227 */, + unchecked((long) 0xFB7C65D4217E49A9L) /* 228 */, unchecked((long) 0x6BDBE0E76D48E7D4L) /* 229 */, + unchecked((long) 0x08DF828745D9179EL) /* 230 */, unchecked((long) 0x22EA6A9ADD53BD34L) /* 231 */, + unchecked((long) 0xE36E141C5622200AL) /* 232 */, unchecked((long) 0x7F805D1B8CB750EEL) /* 233 */, + unchecked((long) 0xAFE5C7A59F58E837L) /* 234 */, unchecked((long) 0xE27F996A4FB1C23CL) /* 235 */, + unchecked((long) 0xD3867DFB0775F0D0L) /* 236 */, unchecked((long) 0xD0E673DE6E88891AL) /* 237 */, + unchecked((long) 0x123AEB9EAFB86C25L) /* 238 */, unchecked((long) 0x30F1D5D5C145B895L) /* 239 */, + unchecked((long) 0xBB434A2DEE7269E7L) /* 240 */, unchecked((long) 0x78CB67ECF931FA38L) /* 241 */, + unchecked((long) 0xF33B0372323BBF9CL) /* 242 */, unchecked((long) 0x52D66336FB279C74L) /* 243 */, + unchecked((long) 0x505F33AC0AFB4EAAL) /* 244 */, unchecked((long) 0xE8A5CD99A2CCE187L) /* 245 */, + unchecked((long) 0x534974801E2D30BBL) /* 246 */, unchecked((long) 0x8D2D5711D5876D90L) /* 247 */, + unchecked((long) 0x1F1A412891BC038EL) /* 248 */, unchecked((long) 0xD6E2E71D82E56648L) /* 249 */, + unchecked((long) 0x74036C3A497732B7L) /* 250 */, unchecked((long) 0x89B67ED96361F5ABL) /* 251 */, + unchecked((long) 0xFFED95D8F1EA02A2L) /* 252 */, unchecked((long) 0xE72B3BD61464D43DL) /* 253 */, + unchecked((long) 0xA6300F170BDC4820L) /* 254 */, unchecked((long) 0xEBC18760ED78A77AL) /* 255 */, + }; + + private static readonly long[] t2 = { + unchecked((long) 0xE6A6BE5A05A12138L) /* 256 */, unchecked((long) 0xB5A122A5B4F87C98L) /* 257 */, + unchecked((long) 0x563C6089140B6990L) /* 258 */, unchecked((long) 0x4C46CB2E391F5DD5L) /* 259 */, + unchecked((long) 0xD932ADDBC9B79434L) /* 260 */, unchecked((long) 0x08EA70E42015AFF5L) /* 261 */, + unchecked((long) 0xD765A6673E478CF1L) /* 262 */, unchecked((long) 0xC4FB757EAB278D99L) /* 263 */, + unchecked((long) 0xDF11C6862D6E0692L) /* 264 */, unchecked((long) 0xDDEB84F10D7F3B16L) /* 265 */, + unchecked((long) 0x6F2EF604A665EA04L) /* 266 */, unchecked((long) 0x4A8E0F0FF0E0DFB3L) /* 267 */, + unchecked((long) 0xA5EDEEF83DBCBA51L) /* 268 */, unchecked((long) 0xFC4F0A2A0EA4371EL) /* 269 */, + unchecked((long) 0xE83E1DA85CB38429L) /* 270 */, unchecked((long) 0xDC8FF882BA1B1CE2L) /* 271 */, + unchecked((long) 0xCD45505E8353E80DL) /* 272 */, unchecked((long) 0x18D19A00D4DB0717L) /* 273 */, + unchecked((long) 0x34A0CFEDA5F38101L) /* 274 */, unchecked((long) 0x0BE77E518887CAF2L) /* 275 */, + unchecked((long) 0x1E341438B3C45136L) /* 276 */, unchecked((long) 0xE05797F49089CCF9L) /* 277 */, + unchecked((long) 0xFFD23F9DF2591D14L) /* 278 */, unchecked((long) 0x543DDA228595C5CDL) /* 279 */, + unchecked((long) 0x661F81FD99052A33L) /* 280 */, unchecked((long) 0x8736E641DB0F7B76L) /* 281 */, + unchecked((long) 0x15227725418E5307L) /* 282 */, unchecked((long) 0xE25F7F46162EB2FAL) /* 283 */, + unchecked((long) 0x48A8B2126C13D9FEL) /* 284 */, unchecked((long) 0xAFDC541792E76EEAL) /* 285 */, + unchecked((long) 0x03D912BFC6D1898FL) /* 286 */, unchecked((long) 0x31B1AAFA1B83F51BL) /* 287 */, + unchecked((long) 0xF1AC2796E42AB7D9L) /* 288 */, unchecked((long) 0x40A3A7D7FCD2EBACL) /* 289 */, + unchecked((long) 0x1056136D0AFBBCC5L) /* 290 */, unchecked((long) 0x7889E1DD9A6D0C85L) /* 291 */, + unchecked((long) 0xD33525782A7974AAL) /* 292 */, unchecked((long) 0xA7E25D09078AC09BL) /* 293 */, + unchecked((long) 0xBD4138B3EAC6EDD0L) /* 294 */, unchecked((long) 0x920ABFBE71EB9E70L) /* 295 */, + unchecked((long) 0xA2A5D0F54FC2625CL) /* 296 */, unchecked((long) 0xC054E36B0B1290A3L) /* 297 */, + unchecked((long) 0xF6DD59FF62FE932BL) /* 298 */, unchecked((long) 0x3537354511A8AC7DL) /* 299 */, + unchecked((long) 0xCA845E9172FADCD4L) /* 300 */, unchecked((long) 0x84F82B60329D20DCL) /* 301 */, + unchecked((long) 0x79C62CE1CD672F18L) /* 302 */, unchecked((long) 0x8B09A2ADD124642CL) /* 303 */, + unchecked((long) 0xD0C1E96A19D9E726L) /* 304 */, unchecked((long) 0x5A786A9B4BA9500CL) /* 305 */, + unchecked((long) 0x0E020336634C43F3L) /* 306 */, unchecked((long) 0xC17B474AEB66D822L) /* 307 */, + unchecked((long) 0x6A731AE3EC9BAAC2L) /* 308 */, unchecked((long) 0x8226667AE0840258L) /* 309 */, + unchecked((long) 0x67D4567691CAECA5L) /* 310 */, unchecked((long) 0x1D94155C4875ADB5L) /* 311 */, + unchecked((long) 0x6D00FD985B813FDFL) /* 312 */, unchecked((long) 0x51286EFCB774CD06L) /* 313 */, + unchecked((long) 0x5E8834471FA744AFL) /* 314 */, unchecked((long) 0xF72CA0AEE761AE2EL) /* 315 */, + unchecked((long) 0xBE40E4CDAEE8E09AL) /* 316 */, unchecked((long) 0xE9970BBB5118F665L) /* 317 */, + unchecked((long) 0x726E4BEB33DF1964L) /* 318 */, unchecked((long) 0x703B000729199762L) /* 319 */, + unchecked((long) 0x4631D816F5EF30A7L) /* 320 */, unchecked((long) 0xB880B5B51504A6BEL) /* 321 */, + unchecked((long) 0x641793C37ED84B6CL) /* 322 */, unchecked((long) 0x7B21ED77F6E97D96L) /* 323 */, + unchecked((long) 0x776306312EF96B73L) /* 324 */, unchecked((long) 0xAE528948E86FF3F4L) /* 325 */, + unchecked((long) 0x53DBD7F286A3F8F8L) /* 326 */, unchecked((long) 0x16CADCE74CFC1063L) /* 327 */, + unchecked((long) 0x005C19BDFA52C6DDL) /* 328 */, unchecked((long) 0x68868F5D64D46AD3L) /* 329 */, + unchecked((long) 0x3A9D512CCF1E186AL) /* 330 */, unchecked((long) 0x367E62C2385660AEL) /* 331 */, + unchecked((long) 0xE359E7EA77DCB1D7L) /* 332 */, unchecked((long) 0x526C0773749ABE6EL) /* 333 */, + unchecked((long) 0x735AE5F9D09F734BL) /* 334 */, unchecked((long) 0x493FC7CC8A558BA8L) /* 335 */, + unchecked((long) 0xB0B9C1533041AB45L) /* 336 */, unchecked((long) 0x321958BA470A59BDL) /* 337 */, + unchecked((long) 0x852DB00B5F46C393L) /* 338 */, unchecked((long) 0x91209B2BD336B0E5L) /* 339 */, + unchecked((long) 0x6E604F7D659EF19FL) /* 340 */, unchecked((long) 0xB99A8AE2782CCB24L) /* 341 */, + unchecked((long) 0xCCF52AB6C814C4C7L) /* 342 */, unchecked((long) 0x4727D9AFBE11727BL) /* 343 */, + unchecked((long) 0x7E950D0C0121B34DL) /* 344 */, unchecked((long) 0x756F435670AD471FL) /* 345 */, + unchecked((long) 0xF5ADD442615A6849L) /* 346 */, unchecked((long) 0x4E87E09980B9957AL) /* 347 */, + unchecked((long) 0x2ACFA1DF50AEE355L) /* 348 */, unchecked((long) 0xD898263AFD2FD556L) /* 349 */, + unchecked((long) 0xC8F4924DD80C8FD6L) /* 350 */, unchecked((long) 0xCF99CA3D754A173AL) /* 351 */, + unchecked((long) 0xFE477BACAF91BF3CL) /* 352 */, unchecked((long) 0xED5371F6D690C12DL) /* 353 */, + unchecked((long) 0x831A5C285E687094L) /* 354 */, unchecked((long) 0xC5D3C90A3708A0A4L) /* 355 */, + unchecked((long) 0x0F7F903717D06580L) /* 356 */, unchecked((long) 0x19F9BB13B8FDF27FL) /* 357 */, + unchecked((long) 0xB1BD6F1B4D502843L) /* 358 */, unchecked((long) 0x1C761BA38FFF4012L) /* 359 */, + unchecked((long) 0x0D1530C4E2E21F3BL) /* 360 */, unchecked((long) 0x8943CE69A7372C8AL) /* 361 */, + unchecked((long) 0xE5184E11FEB5CE66L) /* 362 */, unchecked((long) 0x618BDB80BD736621L) /* 363 */, + unchecked((long) 0x7D29BAD68B574D0BL) /* 364 */, unchecked((long) 0x81BB613E25E6FE5BL) /* 365 */, + unchecked((long) 0x071C9C10BC07913FL) /* 366 */, unchecked((long) 0xC7BEEB7909AC2D97L) /* 367 */, + unchecked((long) 0xC3E58D353BC5D757L) /* 368 */, unchecked((long) 0xEB017892F38F61E8L) /* 369 */, + unchecked((long) 0xD4EFFB9C9B1CC21AL) /* 370 */, unchecked((long) 0x99727D26F494F7ABL) /* 371 */, + unchecked((long) 0xA3E063A2956B3E03L) /* 372 */, unchecked((long) 0x9D4A8B9A4AA09C30L) /* 373 */, + unchecked((long) 0x3F6AB7D500090FB4L) /* 374 */, unchecked((long) 0x9CC0F2A057268AC0L) /* 375 */, + unchecked((long) 0x3DEE9D2DEDBF42D1L) /* 376 */, unchecked((long) 0x330F49C87960A972L) /* 377 */, + unchecked((long) 0xC6B2720287421B41L) /* 378 */, unchecked((long) 0x0AC59EC07C00369CL) /* 379 */, + unchecked((long) 0xEF4EAC49CB353425L) /* 380 */, unchecked((long) 0xF450244EEF0129D8L) /* 381 */, + unchecked((long) 0x8ACC46E5CAF4DEB6L) /* 382 */, unchecked((long) 0x2FFEAB63989263F7L) /* 383 */, + unchecked((long) 0x8F7CB9FE5D7A4578L) /* 384 */, unchecked((long) 0x5BD8F7644E634635L) /* 385 */, + unchecked((long) 0x427A7315BF2DC900L) /* 386 */, unchecked((long) 0x17D0C4AA2125261CL) /* 387 */, + unchecked((long) 0x3992486C93518E50L) /* 388 */, unchecked((long) 0xB4CBFEE0A2D7D4C3L) /* 389 */, + unchecked((long) 0x7C75D6202C5DDD8DL) /* 390 */, unchecked((long) 0xDBC295D8E35B6C61L) /* 391 */, + unchecked((long) 0x60B369D302032B19L) /* 392 */, unchecked((long) 0xCE42685FDCE44132L) /* 393 */, + unchecked((long) 0x06F3DDB9DDF65610L) /* 394 */, unchecked((long) 0x8EA4D21DB5E148F0L) /* 395 */, + unchecked((long) 0x20B0FCE62FCD496FL) /* 396 */, unchecked((long) 0x2C1B912358B0EE31L) /* 397 */, + unchecked((long) 0xB28317B818F5A308L) /* 398 */, unchecked((long) 0xA89C1E189CA6D2CFL) /* 399 */, + unchecked((long) 0x0C6B18576AAADBC8L) /* 400 */, unchecked((long) 0xB65DEAA91299FAE3L) /* 401 */, + unchecked((long) 0xFB2B794B7F1027E7L) /* 402 */, unchecked((long) 0x04E4317F443B5BEBL) /* 403 */, + unchecked((long) 0x4B852D325939D0A6L) /* 404 */, unchecked((long) 0xD5AE6BEEFB207FFCL) /* 405 */, + unchecked((long) 0x309682B281C7D374L) /* 406 */, unchecked((long) 0xBAE309A194C3B475L) /* 407 */, + unchecked((long) 0x8CC3F97B13B49F05L) /* 408 */, unchecked((long) 0x98A9422FF8293967L) /* 409 */, + unchecked((long) 0x244B16B01076FF7CL) /* 410 */, unchecked((long) 0xF8BF571C663D67EEL) /* 411 */, + unchecked((long) 0x1F0D6758EEE30DA1L) /* 412 */, unchecked((long) 0xC9B611D97ADEB9B7L) /* 413 */, + unchecked((long) 0xB7AFD5887B6C57A2L) /* 414 */, unchecked((long) 0x6290AE846B984FE1L) /* 415 */, + unchecked((long) 0x94DF4CDEACC1A5FDL) /* 416 */, unchecked((long) 0x058A5BD1C5483AFFL) /* 417 */, + unchecked((long) 0x63166CC142BA3C37L) /* 418 */, unchecked((long) 0x8DB8526EB2F76F40L) /* 419 */, + unchecked((long) 0xE10880036F0D6D4EL) /* 420 */, unchecked((long) 0x9E0523C9971D311DL) /* 421 */, + unchecked((long) 0x45EC2824CC7CD691L) /* 422 */, unchecked((long) 0x575B8359E62382C9L) /* 423 */, + unchecked((long) 0xFA9E400DC4889995L) /* 424 */, unchecked((long) 0xD1823ECB45721568L) /* 425 */, + unchecked((long) 0xDAFD983B8206082FL) /* 426 */, unchecked((long) 0xAA7D29082386A8CBL) /* 427 */, + unchecked((long) 0x269FCD4403B87588L) /* 428 */, unchecked((long) 0x1B91F5F728BDD1E0L) /* 429 */, + unchecked((long) 0xE4669F39040201F6L) /* 430 */, unchecked((long) 0x7A1D7C218CF04ADEL) /* 431 */, + unchecked((long) 0x65623C29D79CE5CEL) /* 432 */, unchecked((long) 0x2368449096C00BB1L) /* 433 */, + unchecked((long) 0xAB9BF1879DA503BAL) /* 434 */, unchecked((long) 0xBC23ECB1A458058EL) /* 435 */, + unchecked((long) 0x9A58DF01BB401ECCL) /* 436 */, unchecked((long) 0xA070E868A85F143DL) /* 437 */, + unchecked((long) 0x4FF188307DF2239EL) /* 438 */, unchecked((long) 0x14D565B41A641183L) /* 439 */, + unchecked((long) 0xEE13337452701602L) /* 440 */, unchecked((long) 0x950E3DCF3F285E09L) /* 441 */, + unchecked((long) 0x59930254B9C80953L) /* 442 */, unchecked((long) 0x3BF299408930DA6DL) /* 443 */, + unchecked((long) 0xA955943F53691387L) /* 444 */, unchecked((long) 0xA15EDECAA9CB8784L) /* 445 */, + unchecked((long) 0x29142127352BE9A0L) /* 446 */, unchecked((long) 0x76F0371FFF4E7AFBL) /* 447 */, + unchecked((long) 0x0239F450274F2228L) /* 448 */, unchecked((long) 0xBB073AF01D5E868BL) /* 449 */, + unchecked((long) 0xBFC80571C10E96C1L) /* 450 */, unchecked((long) 0xD267088568222E23L) /* 451 */, + unchecked((long) 0x9671A3D48E80B5B0L) /* 452 */, unchecked((long) 0x55B5D38AE193BB81L) /* 453 */, + unchecked((long) 0x693AE2D0A18B04B8L) /* 454 */, unchecked((long) 0x5C48B4ECADD5335FL) /* 455 */, + unchecked((long) 0xFD743B194916A1CAL) /* 456 */, unchecked((long) 0x2577018134BE98C4L) /* 457 */, + unchecked((long) 0xE77987E83C54A4ADL) /* 458 */, unchecked((long) 0x28E11014DA33E1B9L) /* 459 */, + unchecked((long) 0x270CC59E226AA213L) /* 460 */, unchecked((long) 0x71495F756D1A5F60L) /* 461 */, + unchecked((long) 0x9BE853FB60AFEF77L) /* 462 */, unchecked((long) 0xADC786A7F7443DBFL) /* 463 */, + unchecked((long) 0x0904456173B29A82L) /* 464 */, unchecked((long) 0x58BC7A66C232BD5EL) /* 465 */, + unchecked((long) 0xF306558C673AC8B2L) /* 466 */, unchecked((long) 0x41F639C6B6C9772AL) /* 467 */, + unchecked((long) 0x216DEFE99FDA35DAL) /* 468 */, unchecked((long) 0x11640CC71C7BE615L) /* 469 */, + unchecked((long) 0x93C43694565C5527L) /* 470 */, unchecked((long) 0xEA038E6246777839L) /* 471 */, + unchecked((long) 0xF9ABF3CE5A3E2469L) /* 472 */, unchecked((long) 0x741E768D0FD312D2L) /* 473 */, + unchecked((long) 0x0144B883CED652C6L) /* 474 */, unchecked((long) 0xC20B5A5BA33F8552L) /* 475 */, + unchecked((long) 0x1AE69633C3435A9DL) /* 476 */, unchecked((long) 0x97A28CA4088CFDECL) /* 477 */, + unchecked((long) 0x8824A43C1E96F420L) /* 478 */, unchecked((long) 0x37612FA66EEEA746L) /* 479 */, + unchecked((long) 0x6B4CB165F9CF0E5AL) /* 480 */, unchecked((long) 0x43AA1C06A0ABFB4AL) /* 481 */, + unchecked((long) 0x7F4DC26FF162796BL) /* 482 */, unchecked((long) 0x6CBACC8E54ED9B0FL) /* 483 */, + unchecked((long) 0xA6B7FFEFD2BB253EL) /* 484 */, unchecked((long) 0x2E25BC95B0A29D4FL) /* 485 */, + unchecked((long) 0x86D6A58BDEF1388CL) /* 486 */, unchecked((long) 0xDED74AC576B6F054L) /* 487 */, + unchecked((long) 0x8030BDBC2B45805DL) /* 488 */, unchecked((long) 0x3C81AF70E94D9289L) /* 489 */, + unchecked((long) 0x3EFF6DDA9E3100DBL) /* 490 */, unchecked((long) 0xB38DC39FDFCC8847L) /* 491 */, + unchecked((long) 0x123885528D17B87EL) /* 492 */, unchecked((long) 0xF2DA0ED240B1B642L) /* 493 */, + unchecked((long) 0x44CEFADCD54BF9A9L) /* 494 */, unchecked((long) 0x1312200E433C7EE6L) /* 495 */, + unchecked((long) 0x9FFCC84F3A78C748L) /* 496 */, unchecked((long) 0xF0CD1F72248576BBL) /* 497 */, + unchecked((long) 0xEC6974053638CFE4L) /* 498 */, unchecked((long) 0x2BA7B67C0CEC4E4CL) /* 499 */, + unchecked((long) 0xAC2F4DF3E5CE32EDL) /* 500 */, unchecked((long) 0xCB33D14326EA4C11L) /* 501 */, + unchecked((long) 0xA4E9044CC77E58BCL) /* 502 */, unchecked((long) 0x5F513293D934FCEFL) /* 503 */, + unchecked((long) 0x5DC9645506E55444L) /* 504 */, unchecked((long) 0x50DE418F317DE40AL) /* 505 */, + unchecked((long) 0x388CB31A69DDE259L) /* 506 */, unchecked((long) 0x2DB4A83455820A86L) /* 507 */, + unchecked((long) 0x9010A91E84711AE9L) /* 508 */, unchecked((long) 0x4DF7F0B7B1498371L) /* 509 */, + unchecked((long) 0xD62A2EABC0977179L) /* 510 */, unchecked((long) 0x22FAC097AA8D5C0EL) /* 511 */, + }; + + private static readonly long[] t3 = { + unchecked((long) 0xF49FCC2FF1DAF39BL) /* 512 */, unchecked((long) 0x487FD5C66FF29281L) /* 513 */, + unchecked((long) 0xE8A30667FCDCA83FL) /* 514 */, unchecked((long) 0x2C9B4BE3D2FCCE63L) /* 515 */, + unchecked((long) 0xDA3FF74B93FBBBC2L) /* 516 */, unchecked((long) 0x2FA165D2FE70BA66L) /* 517 */, + unchecked((long) 0xA103E279970E93D4L) /* 518 */, unchecked((long) 0xBECDEC77B0E45E71L) /* 519 */, + unchecked((long) 0xCFB41E723985E497L) /* 520 */, unchecked((long) 0xB70AAA025EF75017L) /* 521 */, + unchecked((long) 0xD42309F03840B8E0L) /* 522 */, unchecked((long) 0x8EFC1AD035898579L) /* 523 */, + unchecked((long) 0x96C6920BE2B2ABC5L) /* 524 */, unchecked((long) 0x66AF4163375A9172L) /* 525 */, + unchecked((long) 0x2174ABDCCA7127FBL) /* 526 */, unchecked((long) 0xB33CCEA64A72FF41L) /* 527 */, + unchecked((long) 0xF04A4933083066A5L) /* 528 */, unchecked((long) 0x8D970ACDD7289AF5L) /* 529 */, + unchecked((long) 0x8F96E8E031C8C25EL) /* 530 */, unchecked((long) 0xF3FEC02276875D47L) /* 531 */, + unchecked((long) 0xEC7BF310056190DDL) /* 532 */, unchecked((long) 0xF5ADB0AEBB0F1491L) /* 533 */, + unchecked((long) 0x9B50F8850FD58892L) /* 534 */, unchecked((long) 0x4975488358B74DE8L) /* 535 */, + unchecked((long) 0xA3354FF691531C61L) /* 536 */, unchecked((long) 0x0702BBE481D2C6EEL) /* 537 */, + unchecked((long) 0x89FB24057DEDED98L) /* 538 */, unchecked((long) 0xAC3075138596E902L) /* 539 */, + unchecked((long) 0x1D2D3580172772EDL) /* 540 */, unchecked((long) 0xEB738FC28E6BC30DL) /* 541 */, + unchecked((long) 0x5854EF8F63044326L) /* 542 */, unchecked((long) 0x9E5C52325ADD3BBEL) /* 543 */, + unchecked((long) 0x90AA53CF325C4623L) /* 544 */, unchecked((long) 0xC1D24D51349DD067L) /* 545 */, + unchecked((long) 0x2051CFEEA69EA624L) /* 546 */, unchecked((long) 0x13220F0A862E7E4FL) /* 547 */, + unchecked((long) 0xCE39399404E04864L) /* 548 */, unchecked((long) 0xD9C42CA47086FCB7L) /* 549 */, + unchecked((long) 0x685AD2238A03E7CCL) /* 550 */, unchecked((long) 0x066484B2AB2FF1DBL) /* 551 */, + unchecked((long) 0xFE9D5D70EFBF79ECL) /* 552 */, unchecked((long) 0x5B13B9DD9C481854L) /* 553 */, + unchecked((long) 0x15F0D475ED1509ADL) /* 554 */, unchecked((long) 0x0BEBCD060EC79851L) /* 555 */, + unchecked((long) 0xD58C6791183AB7F8L) /* 556 */, unchecked((long) 0xD1187C5052F3EEE4L) /* 557 */, + unchecked((long) 0xC95D1192E54E82FFL) /* 558 */, unchecked((long) 0x86EEA14CB9AC6CA2L) /* 559 */, + unchecked((long) 0x3485BEB153677D5DL) /* 560 */, unchecked((long) 0xDD191D781F8C492AL) /* 561 */, + unchecked((long) 0xF60866BAA784EBF9L) /* 562 */, unchecked((long) 0x518F643BA2D08C74L) /* 563 */, + unchecked((long) 0x8852E956E1087C22L) /* 564 */, unchecked((long) 0xA768CB8DC410AE8DL) /* 565 */, + unchecked((long) 0x38047726BFEC8E1AL) /* 566 */, unchecked((long) 0xA67738B4CD3B45AAL) /* 567 */, + unchecked((long) 0xAD16691CEC0DDE19L) /* 568 */, unchecked((long) 0xC6D4319380462E07L) /* 569 */, + unchecked((long) 0xC5A5876D0BA61938L) /* 570 */, unchecked((long) 0x16B9FA1FA58FD840L) /* 571 */, + unchecked((long) 0x188AB1173CA74F18L) /* 572 */, unchecked((long) 0xABDA2F98C99C021FL) /* 573 */, + unchecked((long) 0x3E0580AB134AE816L) /* 574 */, unchecked((long) 0x5F3B05B773645ABBL) /* 575 */, + unchecked((long) 0x2501A2BE5575F2F6L) /* 576 */, unchecked((long) 0x1B2F74004E7E8BA9L) /* 577 */, + unchecked((long) 0x1CD7580371E8D953L) /* 578 */, unchecked((long) 0x7F6ED89562764E30L) /* 579 */, + unchecked((long) 0xB15926FF596F003DL) /* 580 */, unchecked((long) 0x9F65293DA8C5D6B9L) /* 581 */, + unchecked((long) 0x6ECEF04DD690F84CL) /* 582 */, unchecked((long) 0x4782275FFF33AF88L) /* 583 */, + unchecked((long) 0xE41433083F820801L) /* 584 */, unchecked((long) 0xFD0DFE409A1AF9B5L) /* 585 */, + unchecked((long) 0x4325A3342CDB396BL) /* 586 */, unchecked((long) 0x8AE77E62B301B252L) /* 587 */, + unchecked((long) 0xC36F9E9F6655615AL) /* 588 */, unchecked((long) 0x85455A2D92D32C09L) /* 589 */, + unchecked((long) 0xF2C7DEA949477485L) /* 590 */, unchecked((long) 0x63CFB4C133A39EBAL) /* 591 */, + unchecked((long) 0x83B040CC6EBC5462L) /* 592 */, unchecked((long) 0x3B9454C8FDB326B0L) /* 593 */, + unchecked((long) 0x56F56A9E87FFD78CL) /* 594 */, unchecked((long) 0x2DC2940D99F42BC6L) /* 595 */, + unchecked((long) 0x98F7DF096B096E2DL) /* 596 */, unchecked((long) 0x19A6E01E3AD852BFL) /* 597 */, + unchecked((long) 0x42A99CCBDBD4B40BL) /* 598 */, unchecked((long) 0xA59998AF45E9C559L) /* 599 */, + unchecked((long) 0x366295E807D93186L) /* 600 */, unchecked((long) 0x6B48181BFAA1F773L) /* 601 */, + unchecked((long) 0x1FEC57E2157A0A1DL) /* 602 */, unchecked((long) 0x4667446AF6201AD5L) /* 603 */, + unchecked((long) 0xE615EBCACFB0F075L) /* 604 */, unchecked((long) 0xB8F31F4F68290778L) /* 605 */, + unchecked((long) 0x22713ED6CE22D11EL) /* 606 */, unchecked((long) 0x3057C1A72EC3C93BL) /* 607 */, + unchecked((long) 0xCB46ACC37C3F1F2FL) /* 608 */, unchecked((long) 0xDBB893FD02AAF50EL) /* 609 */, + unchecked((long) 0x331FD92E600B9FCFL) /* 610 */, unchecked((long) 0xA498F96148EA3AD6L) /* 611 */, + unchecked((long) 0xA8D8426E8B6A83EAL) /* 612 */, unchecked((long) 0xA089B274B7735CDCL) /* 613 */, + unchecked((long) 0x87F6B3731E524A11L) /* 614 */, unchecked((long) 0x118808E5CBC96749L) /* 615 */, + unchecked((long) 0x9906E4C7B19BD394L) /* 616 */, unchecked((long) 0xAFED7F7E9B24A20CL) /* 617 */, + unchecked((long) 0x6509EADEEB3644A7L) /* 618 */, unchecked((long) 0x6C1EF1D3E8EF0EDEL) /* 619 */, + unchecked((long) 0xB9C97D43E9798FB4L) /* 620 */, unchecked((long) 0xA2F2D784740C28A3L) /* 621 */, + unchecked((long) 0x7B8496476197566FL) /* 622 */, unchecked((long) 0x7A5BE3E6B65F069DL) /* 623 */, + unchecked((long) 0xF96330ED78BE6F10L) /* 624 */, unchecked((long) 0xEEE60DE77A076A15L) /* 625 */, + unchecked((long) 0x2B4BEE4AA08B9BD0L) /* 626 */, unchecked((long) 0x6A56A63EC7B8894EL) /* 627 */, + unchecked((long) 0x02121359BA34FEF4L) /* 628 */, unchecked((long) 0x4CBF99F8283703FCL) /* 629 */, + unchecked((long) 0x398071350CAF30C8L) /* 630 */, unchecked((long) 0xD0A77A89F017687AL) /* 631 */, + unchecked((long) 0xF1C1A9EB9E423569L) /* 632 */, unchecked((long) 0x8C7976282DEE8199L) /* 633 */, + unchecked((long) 0x5D1737A5DD1F7ABDL) /* 634 */, unchecked((long) 0x4F53433C09A9FA80L) /* 635 */, + unchecked((long) 0xFA8B0C53DF7CA1D9L) /* 636 */, unchecked((long) 0x3FD9DCBC886CCB77L) /* 637 */, + unchecked((long) 0xC040917CA91B4720L) /* 638 */, unchecked((long) 0x7DD00142F9D1DCDFL) /* 639 */, + unchecked((long) 0x8476FC1D4F387B58L) /* 640 */, unchecked((long) 0x23F8E7C5F3316503L) /* 641 */, + unchecked((long) 0x032A2244E7E37339L) /* 642 */, unchecked((long) 0x5C87A5D750F5A74BL) /* 643 */, + unchecked((long) 0x082B4CC43698992EL) /* 644 */, unchecked((long) 0xDF917BECB858F63CL) /* 645 */, + unchecked((long) 0x3270B8FC5BF86DDAL) /* 646 */, unchecked((long) 0x10AE72BB29B5DD76L) /* 647 */, + unchecked((long) 0x576AC94E7700362BL) /* 648 */, unchecked((long) 0x1AD112DAC61EFB8FL) /* 649 */, + unchecked((long) 0x691BC30EC5FAA427L) /* 650 */, unchecked((long) 0xFF246311CC327143L) /* 651 */, + unchecked((long) 0x3142368E30E53206L) /* 652 */, unchecked((long) 0x71380E31E02CA396L) /* 653 */, + unchecked((long) 0x958D5C960AAD76F1L) /* 654 */, unchecked((long) 0xF8D6F430C16DA536L) /* 655 */, + unchecked((long) 0xC8FFD13F1BE7E1D2L) /* 656 */, unchecked((long) 0x7578AE66004DDBE1L) /* 657 */, + unchecked((long) 0x05833F01067BE646L) /* 658 */, unchecked((long) 0xBB34B5AD3BFE586DL) /* 659 */, + unchecked((long) 0x095F34C9A12B97F0L) /* 660 */, unchecked((long) 0x247AB64525D60CA8L) /* 661 */, + unchecked((long) 0xDCDBC6F3017477D1L) /* 662 */, unchecked((long) 0x4A2E14D4DECAD24DL) /* 663 */, + unchecked((long) 0xBDB5E6D9BE0A1EEBL) /* 664 */, unchecked((long) 0x2A7E70F7794301ABL) /* 665 */, + unchecked((long) 0xDEF42D8A270540FDL) /* 666 */, unchecked((long) 0x01078EC0A34C22C1L) /* 667 */, + unchecked((long) 0xE5DE511AF4C16387L) /* 668 */, unchecked((long) 0x7EBB3A52BD9A330AL) /* 669 */, + unchecked((long) 0x77697857AA7D6435L) /* 670 */, unchecked((long) 0x004E831603AE4C32L) /* 671 */, + unchecked((long) 0xE7A21020AD78E312L) /* 672 */, unchecked((long) 0x9D41A70C6AB420F2L) /* 673 */, + unchecked((long) 0x28E06C18EA1141E6L) /* 674 */, unchecked((long) 0xD2B28CBD984F6B28L) /* 675 */, + unchecked((long) 0x26B75F6C446E9D83L) /* 676 */, unchecked((long) 0xBA47568C4D418D7FL) /* 677 */, + unchecked((long) 0xD80BADBFE6183D8EL) /* 678 */, unchecked((long) 0x0E206D7F5F166044L) /* 679 */, + unchecked((long) 0xE258A43911CBCA3EL) /* 680 */, unchecked((long) 0x723A1746B21DC0BCL) /* 681 */, + unchecked((long) 0xC7CAA854F5D7CDD3L) /* 682 */, unchecked((long) 0x7CAC32883D261D9CL) /* 683 */, + unchecked((long) 0x7690C26423BA942CL) /* 684 */, unchecked((long) 0x17E55524478042B8L) /* 685 */, + unchecked((long) 0xE0BE477656A2389FL) /* 686 */, unchecked((long) 0x4D289B5E67AB2DA0L) /* 687 */, + unchecked((long) 0x44862B9C8FBBFD31L) /* 688 */, unchecked((long) 0xB47CC8049D141365L) /* 689 */, + unchecked((long) 0x822C1B362B91C793L) /* 690 */, unchecked((long) 0x4EB14655FB13DFD8L) /* 691 */, + unchecked((long) 0x1ECBBA0714E2A97BL) /* 692 */, unchecked((long) 0x6143459D5CDE5F14L) /* 693 */, + unchecked((long) 0x53A8FBF1D5F0AC89L) /* 694 */, unchecked((long) 0x97EA04D81C5E5B00L) /* 695 */, + unchecked((long) 0x622181A8D4FDB3F3L) /* 696 */, unchecked((long) 0xE9BCD341572A1208L) /* 697 */, + unchecked((long) 0x1411258643CCE58AL) /* 698 */, unchecked((long) 0x9144C5FEA4C6E0A4L) /* 699 */, + unchecked((long) 0x0D33D06565CF620FL) /* 700 */, unchecked((long) 0x54A48D489F219CA1L) /* 701 */, + unchecked((long) 0xC43E5EAC6D63C821L) /* 702 */, unchecked((long) 0xA9728B3A72770DAFL) /* 703 */, + unchecked((long) 0xD7934E7B20DF87EFL) /* 704 */, unchecked((long) 0xE35503B61A3E86E5L) /* 705 */, + unchecked((long) 0xCAE321FBC819D504L) /* 706 */, unchecked((long) 0x129A50B3AC60BFA6L) /* 707 */, + unchecked((long) 0xCD5E68EA7E9FB6C3L) /* 708 */, unchecked((long) 0xB01C90199483B1C7L) /* 709 */, + unchecked((long) 0x3DE93CD5C295376CL) /* 710 */, unchecked((long) 0xAED52EDF2AB9AD13L) /* 711 */, + unchecked((long) 0x2E60F512C0A07884L) /* 712 */, unchecked((long) 0xBC3D86A3E36210C9L) /* 713 */, + unchecked((long) 0x35269D9B163951CEL) /* 714 */, unchecked((long) 0x0C7D6E2AD0CDB5FAL) /* 715 */, + unchecked((long) 0x59E86297D87F5733L) /* 716 */, unchecked((long) 0x298EF221898DB0E7L) /* 717 */, + unchecked((long) 0x55000029D1A5AA7EL) /* 718 */, unchecked((long) 0x8BC08AE1B5061B45L) /* 719 */, + unchecked((long) 0xC2C31C2B6C92703AL) /* 720 */, unchecked((long) 0x94CC596BAF25EF42L) /* 721 */, + unchecked((long) 0x0A1D73DB22540456L) /* 722 */, unchecked((long) 0x04B6A0F9D9C4179AL) /* 723 */, + unchecked((long) 0xEFFDAFA2AE3D3C60L) /* 724 */, unchecked((long) 0xF7C8075BB49496C4L) /* 725 */, + unchecked((long) 0x9CC5C7141D1CD4E3L) /* 726 */, unchecked((long) 0x78BD1638218E5534L) /* 727 */, + unchecked((long) 0xB2F11568F850246AL) /* 728 */, unchecked((long) 0xEDFABCFA9502BC29L) /* 729 */, + unchecked((long) 0x796CE5F2DA23051BL) /* 730 */, unchecked((long) 0xAAE128B0DC93537CL) /* 731 */, + unchecked((long) 0x3A493DA0EE4B29AEL) /* 732 */, unchecked((long) 0xB5DF6B2C416895D7L) /* 733 */, + unchecked((long) 0xFCABBD25122D7F37L) /* 734 */, unchecked((long) 0x70810B58105DC4B1L) /* 735 */, + unchecked((long) 0xE10FDD37F7882A90L) /* 736 */, unchecked((long) 0x524DCAB5518A3F5CL) /* 737 */, + unchecked((long) 0x3C9E85878451255BL) /* 738 */, unchecked((long) 0x4029828119BD34E2L) /* 739 */, + unchecked((long) 0x74A05B6F5D3CECCBL) /* 740 */, unchecked((long) 0xB610021542E13ECAL) /* 741 */, + unchecked((long) 0x0FF979D12F59E2ACL) /* 742 */, unchecked((long) 0x6037DA27E4F9CC50L) /* 743 */, + unchecked((long) 0x5E92975A0DF1847DL) /* 744 */, unchecked((long) 0xD66DE190D3E623FEL) /* 745 */, + unchecked((long) 0x5032D6B87B568048L) /* 746 */, unchecked((long) 0x9A36B7CE8235216EL) /* 747 */, + unchecked((long) 0x80272A7A24F64B4AL) /* 748 */, unchecked((long) 0x93EFED8B8C6916F7L) /* 749 */, + unchecked((long) 0x37DDBFF44CCE1555L) /* 750 */, unchecked((long) 0x4B95DB5D4B99BD25L) /* 751 */, + unchecked((long) 0x92D3FDA169812FC0L) /* 752 */, unchecked((long) 0xFB1A4A9A90660BB6L) /* 753 */, + unchecked((long) 0x730C196946A4B9B2L) /* 754 */, unchecked((long) 0x81E289AA7F49DA68L) /* 755 */, + unchecked((long) 0x64669A0F83B1A05FL) /* 756 */, unchecked((long) 0x27B3FF7D9644F48BL) /* 757 */, + unchecked((long) 0xCC6B615C8DB675B3L) /* 758 */, unchecked((long) 0x674F20B9BCEBBE95L) /* 759 */, + unchecked((long) 0x6F31238275655982L) /* 760 */, unchecked((long) 0x5AE488713E45CF05L) /* 761 */, + unchecked((long) 0xBF619F9954C21157L) /* 762 */, unchecked((long) 0xEABAC46040A8EAE9L) /* 763 */, + unchecked((long) 0x454C6FE9F2C0C1CDL) /* 764 */, unchecked((long) 0x419CF6496412691CL) /* 765 */, + unchecked((long) 0xD3DC3BEF265B0F70L) /* 766 */, unchecked((long) 0x6D0E60F5C3578A9EL) /* 767 */, + }; + + private static readonly long[] t4 = { + unchecked((long) 0x5B0E608526323C55L) /* 768 */, unchecked((long) 0x1A46C1A9FA1B59F5L) /* 769 */, + unchecked((long) 0xA9E245A17C4C8FFAL) /* 770 */, unchecked((long) 0x65CA5159DB2955D7L) /* 771 */, + unchecked((long) 0x05DB0A76CE35AFC2L) /* 772 */, unchecked((long) 0x81EAC77EA9113D45L) /* 773 */, + unchecked((long) 0x528EF88AB6AC0A0DL) /* 774 */, unchecked((long) 0xA09EA253597BE3FFL) /* 775 */, + unchecked((long) 0x430DDFB3AC48CD56L) /* 776 */, unchecked((long) 0xC4B3A67AF45CE46FL) /* 777 */, + unchecked((long) 0x4ECECFD8FBE2D05EL) /* 778 */, unchecked((long) 0x3EF56F10B39935F0L) /* 779 */, + unchecked((long) 0x0B22D6829CD619C6L) /* 780 */, unchecked((long) 0x17FD460A74DF2069L) /* 781 */, + unchecked((long) 0x6CF8CC8E8510ED40L) /* 782 */, unchecked((long) 0xD6C824BF3A6ECAA7L) /* 783 */, + unchecked((long) 0x61243D581A817049L) /* 784 */, unchecked((long) 0x048BACB6BBC163A2L) /* 785 */, + unchecked((long) 0xD9A38AC27D44CC32L) /* 786 */, unchecked((long) 0x7FDDFF5BAAF410ABL) /* 787 */, + unchecked((long) 0xAD6D495AA804824BL) /* 788 */, unchecked((long) 0xE1A6A74F2D8C9F94L) /* 789 */, + unchecked((long) 0xD4F7851235DEE8E3L) /* 790 */, unchecked((long) 0xFD4B7F886540D893L) /* 791 */, + unchecked((long) 0x247C20042AA4BFDAL) /* 792 */, unchecked((long) 0x096EA1C517D1327CL) /* 793 */, + unchecked((long) 0xD56966B4361A6685L) /* 794 */, unchecked((long) 0x277DA5C31221057DL) /* 795 */, + unchecked((long) 0x94D59893A43ACFF7L) /* 796 */, unchecked((long) 0x64F0C51CCDC02281L) /* 797 */, + unchecked((long) 0x3D33BCC4FF6189DBL) /* 798 */, unchecked((long) 0xE005CB184CE66AF1L) /* 799 */, + unchecked((long) 0xFF5CCD1D1DB99BEAL) /* 800 */, unchecked((long) 0xB0B854A7FE42980FL) /* 801 */, + unchecked((long) 0x7BD46A6A718D4B9FL) /* 802 */, unchecked((long) 0xD10FA8CC22A5FD8CL) /* 803 */, + unchecked((long) 0xD31484952BE4BD31L) /* 804 */, unchecked((long) 0xC7FA975FCB243847L) /* 805 */, + unchecked((long) 0x4886ED1E5846C407L) /* 806 */, unchecked((long) 0x28CDDB791EB70B04L) /* 807 */, + unchecked((long) 0xC2B00BE2F573417FL) /* 808 */, unchecked((long) 0x5C9590452180F877L) /* 809 */, + unchecked((long) 0x7A6BDDFFF370EB00L) /* 810 */, unchecked((long) 0xCE509E38D6D9D6A4L) /* 811 */, + unchecked((long) 0xEBEB0F00647FA702L) /* 812 */, unchecked((long) 0x1DCC06CF76606F06L) /* 813 */, + unchecked((long) 0xE4D9F28BA286FF0AL) /* 814 */, unchecked((long) 0xD85A305DC918C262L) /* 815 */, + unchecked((long) 0x475B1D8732225F54L) /* 816 */, unchecked((long) 0x2D4FB51668CCB5FEL) /* 817 */, + unchecked((long) 0xA679B9D9D72BBA20L) /* 818 */, unchecked((long) 0x53841C0D912D43A5L) /* 819 */, + unchecked((long) 0x3B7EAA48BF12A4E8L) /* 820 */, unchecked((long) 0x781E0E47F22F1DDFL) /* 821 */, + unchecked((long) 0xEFF20CE60AB50973L) /* 822 */, unchecked((long) 0x20D261D19DFFB742L) /* 823 */, + unchecked((long) 0x16A12B03062A2E39L) /* 824 */, unchecked((long) 0x1960EB2239650495L) /* 825 */, + unchecked((long) 0x251C16FED50EB8B8L) /* 826 */, unchecked((long) 0x9AC0C330F826016EL) /* 827 */, + unchecked((long) 0xED152665953E7671L) /* 828 */, unchecked((long) 0x02D63194A6369570L) /* 829 */, + unchecked((long) 0x5074F08394B1C987L) /* 830 */, unchecked((long) 0x70BA598C90B25CE1L) /* 831 */, + unchecked((long) 0x794A15810B9742F6L) /* 832 */, unchecked((long) 0x0D5925E9FCAF8C6CL) /* 833 */, + unchecked((long) 0x3067716CD868744EL) /* 834 */, unchecked((long) 0x910AB077E8D7731BL) /* 835 */, + unchecked((long) 0x6A61BBDB5AC42F61L) /* 836 */, unchecked((long) 0x93513EFBF0851567L) /* 837 */, + unchecked((long) 0xF494724B9E83E9D5L) /* 838 */, unchecked((long) 0xE887E1985C09648DL) /* 839 */, + unchecked((long) 0x34B1D3C675370CFDL) /* 840 */, unchecked((long) 0xDC35E433BC0D255DL) /* 841 */, + unchecked((long) 0xD0AAB84234131BE0L) /* 842 */, unchecked((long) 0x08042A50B48B7EAFL) /* 843 */, + unchecked((long) 0x9997C4EE44A3AB35L) /* 844 */, unchecked((long) 0x829A7B49201799D0L) /* 845 */, + unchecked((long) 0x263B8307B7C54441L) /* 846 */, unchecked((long) 0x752F95F4FD6A6CA6L) /* 847 */, + unchecked((long) 0x927217402C08C6E5L) /* 848 */, unchecked((long) 0x2A8AB754A795D9EEL) /* 849 */, + unchecked((long) 0xA442F7552F72943DL) /* 850 */, unchecked((long) 0x2C31334E19781208L) /* 851 */, + unchecked((long) 0x4FA98D7CEAEE6291L) /* 852 */, unchecked((long) 0x55C3862F665DB309L) /* 853 */, + unchecked((long) 0xBD0610175D53B1F3L) /* 854 */, unchecked((long) 0x46FE6CB840413F27L) /* 855 */, + unchecked((long) 0x3FE03792DF0CFA59L) /* 856 */, unchecked((long) 0xCFE700372EB85E8FL) /* 857 */, + unchecked((long) 0xA7BE29E7ADBCE118L) /* 858 */, unchecked((long) 0xE544EE5CDE8431DDL) /* 859 */, + unchecked((long) 0x8A781B1B41F1873EL) /* 860 */, unchecked((long) 0xA5C94C78A0D2F0E7L) /* 861 */, + unchecked((long) 0x39412E2877B60728L) /* 862 */, unchecked((long) 0xA1265EF3AFC9A62CL) /* 863 */, + unchecked((long) 0xBCC2770C6A2506C5L) /* 864 */, unchecked((long) 0x3AB66DD5DCE1CE12L) /* 865 */, + unchecked((long) 0xE65499D04A675B37L) /* 866 */, unchecked((long) 0x7D8F523481BFD216L) /* 867 */, + unchecked((long) 0x0F6F64FCEC15F389L) /* 868 */, unchecked((long) 0x74EFBE618B5B13C8L) /* 869 */, + unchecked((long) 0xACDC82B714273E1DL) /* 870 */, unchecked((long) 0xDD40BFE003199D17L) /* 871 */, + unchecked((long) 0x37E99257E7E061F8L) /* 872 */, unchecked((long) 0xFA52626904775AAAL) /* 873 */, + unchecked((long) 0x8BBBF63A463D56F9L) /* 874 */, unchecked((long) 0xF0013F1543A26E64L) /* 875 */, + unchecked((long) 0xA8307E9F879EC898L) /* 876 */, unchecked((long) 0xCC4C27A4150177CCL) /* 877 */, + unchecked((long) 0x1B432F2CCA1D3348L) /* 878 */, unchecked((long) 0xDE1D1F8F9F6FA013L) /* 879 */, + unchecked((long) 0x606602A047A7DDD6L) /* 880 */, unchecked((long) 0xD237AB64CC1CB2C7L) /* 881 */, + unchecked((long) 0x9B938E7225FCD1D3L) /* 882 */, unchecked((long) 0xEC4E03708E0FF476L) /* 883 */, + unchecked((long) 0xFEB2FBDA3D03C12DL) /* 884 */, unchecked((long) 0xAE0BCED2EE43889AL) /* 885 */, + unchecked((long) 0x22CB8923EBFB4F43L) /* 886 */, unchecked((long) 0x69360D013CF7396DL) /* 887 */, + unchecked((long) 0x855E3602D2D4E022L) /* 888 */, unchecked((long) 0x073805BAD01F784CL) /* 889 */, + unchecked((long) 0x33E17A133852F546L) /* 890 */, unchecked((long) 0xDF4874058AC7B638L) /* 891 */, + unchecked((long) 0xBA92B29C678AA14AL) /* 892 */, unchecked((long) 0x0CE89FC76CFAADCDL) /* 893 */, + unchecked((long) 0x5F9D4E0908339E34L) /* 894 */, unchecked((long) 0xF1AFE9291F5923B9L) /* 895 */, + unchecked((long) 0x6E3480F60F4A265FL) /* 896 */, unchecked((long) 0xEEBF3A2AB29B841CL) /* 897 */, + unchecked((long) 0xE21938A88F91B4ADL) /* 898 */, unchecked((long) 0x57DFEFF845C6D3C3L) /* 899 */, + unchecked((long) 0x2F006B0BF62CAAF2L) /* 900 */, unchecked((long) 0x62F479EF6F75EE78L) /* 901 */, + unchecked((long) 0x11A55AD41C8916A9L) /* 902 */, unchecked((long) 0xF229D29084FED453L) /* 903 */, + unchecked((long) 0x42F1C27B16B000E6L) /* 904 */, unchecked((long) 0x2B1F76749823C074L) /* 905 */, + unchecked((long) 0x4B76ECA3C2745360L) /* 906 */, unchecked((long) 0x8C98F463B91691BDL) /* 907 */, + unchecked((long) 0x14BCC93CF1ADE66AL) /* 908 */, unchecked((long) 0x8885213E6D458397L) /* 909 */, + unchecked((long) 0x8E177DF0274D4711L) /* 910 */, unchecked((long) 0xB49B73B5503F2951L) /* 911 */, + unchecked((long) 0x10168168C3F96B6BL) /* 912 */, unchecked((long) 0x0E3D963B63CAB0AEL) /* 913 */, + unchecked((long) 0x8DFC4B5655A1DB14L) /* 914 */, unchecked((long) 0xF789F1356E14DE5CL) /* 915 */, + unchecked((long) 0x683E68AF4E51DAC1L) /* 916 */, unchecked((long) 0xC9A84F9D8D4B0FD9L) /* 917 */, + unchecked((long) 0x3691E03F52A0F9D1L) /* 918 */, unchecked((long) 0x5ED86E46E1878E80L) /* 919 */, + unchecked((long) 0x3C711A0E99D07150L) /* 920 */, unchecked((long) 0x5A0865B20C4E9310L) /* 921 */, + unchecked((long) 0x56FBFC1FE4F0682EL) /* 922 */, unchecked((long) 0xEA8D5DE3105EDF9BL) /* 923 */, + unchecked((long) 0x71ABFDB12379187AL) /* 924 */, unchecked((long) 0x2EB99DE1BEE77B9CL) /* 925 */, + unchecked((long) 0x21ECC0EA33CF4523L) /* 926 */, unchecked((long) 0x59A4D7521805C7A1L) /* 927 */, + unchecked((long) 0x3896F5EB56AE7C72L) /* 928 */, unchecked((long) 0xAA638F3DB18F75DCL) /* 929 */, + unchecked((long) 0x9F39358DABE9808EL) /* 930 */, unchecked((long) 0xB7DEFA91C00B72ACL) /* 931 */, + unchecked((long) 0x6B5541FD62492D92L) /* 932 */, unchecked((long) 0x6DC6DEE8F92E4D5BL) /* 933 */, + unchecked((long) 0x353F57ABC4BEEA7EL) /* 934 */, unchecked((long) 0x735769D6DA5690CEL) /* 935 */, + unchecked((long) 0x0A234AA642391484L) /* 936 */, unchecked((long) 0xF6F9508028F80D9DL) /* 937 */, + unchecked((long) 0xB8E319A27AB3F215L) /* 938 */, unchecked((long) 0x31AD9C1151341A4DL) /* 939 */, + unchecked((long) 0x773C22A57BEF5805L) /* 940 */, unchecked((long) 0x45C7561A07968633L) /* 941 */, + unchecked((long) 0xF913DA9E249DBE36L) /* 942 */, unchecked((long) 0xDA652D9B78A64C68L) /* 943 */, + unchecked((long) 0x4C27A97F3BC334EFL) /* 944 */, unchecked((long) 0x76621220E66B17F4L) /* 945 */, + unchecked((long) 0x967743899ACD7D0BL) /* 946 */, unchecked((long) 0xF3EE5BCAE0ED6782L) /* 947 */, + unchecked((long) 0x409F753600C879FCL) /* 948 */, unchecked((long) 0x06D09A39B5926DB6L) /* 949 */, + unchecked((long) 0x6F83AEB0317AC588L) /* 950 */, unchecked((long) 0x01E6CA4A86381F21L) /* 951 */, + unchecked((long) 0x66FF3462D19F3025L) /* 952 */, unchecked((long) 0x72207C24DDFD3BFBL) /* 953 */, + unchecked((long) 0x4AF6B6D3E2ECE2EBL) /* 954 */, unchecked((long) 0x9C994DBEC7EA08DEL) /* 955 */, + unchecked((long) 0x49ACE597B09A8BC4L) /* 956 */, unchecked((long) 0xB38C4766CF0797BAL) /* 957 */, + unchecked((long) 0x131B9373C57C2A75L) /* 958 */, unchecked((long) 0xB1822CCE61931E58L) /* 959 */, + unchecked((long) 0x9D7555B909BA1C0CL) /* 960 */, unchecked((long) 0x127FAFDD937D11D2L) /* 961 */, + unchecked((long) 0x29DA3BADC66D92E4L) /* 962 */, unchecked((long) 0xA2C1D57154C2ECBCL) /* 963 */, + unchecked((long) 0x58C5134D82F6FE24L) /* 964 */, unchecked((long) 0x1C3AE3515B62274FL) /* 965 */, + unchecked((long) 0xE907C82E01CB8126L) /* 966 */, unchecked((long) 0xF8ED091913E37FCBL) /* 967 */, + unchecked((long) 0x3249D8F9C80046C9L) /* 968 */, unchecked((long) 0x80CF9BEDE388FB63L) /* 969 */, + unchecked((long) 0x1881539A116CF19EL) /* 970 */, unchecked((long) 0x5103F3F76BD52457L) /* 971 */, + unchecked((long) 0x15B7E6F5AE47F7A8L) /* 972 */, unchecked((long) 0xDBD7C6DED47E9CCFL) /* 973 */, + unchecked((long) 0x44E55C410228BB1AL) /* 974 */, unchecked((long) 0xB647D4255EDB4E99L) /* 975 */, + unchecked((long) 0x5D11882BB8AAFC30L) /* 976 */, unchecked((long) 0xF5098BBB29D3212AL) /* 977 */, + unchecked((long) 0x8FB5EA14E90296B3L) /* 978 */, unchecked((long) 0x677B942157DD025AL) /* 979 */, + unchecked((long) 0xFB58E7C0A390ACB5L) /* 980 */, unchecked((long) 0x89D3674C83BD4A01L) /* 981 */, + unchecked((long) 0x9E2DA4DF4BF3B93BL) /* 982 */, unchecked((long) 0xFCC41E328CAB4829L) /* 983 */, + unchecked((long) 0x03F38C96BA582C52L) /* 984 */, unchecked((long) 0xCAD1BDBD7FD85DB2L) /* 985 */, + unchecked((long) 0xBBB442C16082AE83L) /* 986 */, unchecked((long) 0xB95FE86BA5DA9AB0L) /* 987 */, + unchecked((long) 0xB22E04673771A93FL) /* 988 */, unchecked((long) 0x845358C9493152D8L) /* 989 */, + unchecked((long) 0xBE2A488697B4541EL) /* 990 */, unchecked((long) 0x95A2DC2DD38E6966L) /* 991 */, + unchecked((long) 0xC02C11AC923C852BL) /* 992 */, unchecked((long) 0x2388B1990DF2A87BL) /* 993 */, + unchecked((long) 0x7C8008FA1B4F37BEL) /* 994 */, unchecked((long) 0x1F70D0C84D54E503L) /* 995 */, + unchecked((long) 0x5490ADEC7ECE57D4L) /* 996 */, unchecked((long) 0x002B3C27D9063A3AL) /* 997 */, + unchecked((long) 0x7EAEA3848030A2BFL) /* 998 */, unchecked((long) 0xC602326DED2003C0L) /* 999 */, + unchecked((long) 0x83A7287D69A94086L) /* 1000 */, unchecked((long) 0xC57A5FCB30F57A8AL) /* 1001 */, + unchecked((long) 0xB56844E479EBE779L) /* 1002 */, unchecked((long) 0xA373B40F05DCBCE9L) /* 1003 */, + unchecked((long) 0xD71A786E88570EE2L) /* 1004 */, unchecked((long) 0x879CBACDBDE8F6A0L) /* 1005 */, + unchecked((long) 0x976AD1BCC164A32FL) /* 1006 */, unchecked((long) 0xAB21E25E9666D78BL) /* 1007 */, + unchecked((long) 0x901063AAE5E5C33CL) /* 1008 */, unchecked((long) 0x9818B34448698D90L) /* 1009 */, + unchecked((long) 0xE36487AE3E1E8ABBL) /* 1010 */, unchecked((long) 0xAFBDF931893BDCB4L) /* 1011 */, + unchecked((long) 0x6345A0DC5FBBD519L) /* 1012 */, unchecked((long) 0x8628FE269B9465CAL) /* 1013 */, + unchecked((long) 0x1E5D01603F9C51ECL) /* 1014 */, unchecked((long) 0x4DE44006A15049B7L) /* 1015 */, + unchecked((long) 0xBF6C70E5F776CBB1L) /* 1016 */, unchecked((long) 0x411218F2EF552BEDL) /* 1017 */, + unchecked((long) 0xCB0C0708705A36A3L) /* 1018 */, unchecked((long) 0xE74D14754F986044L) /* 1019 */, + unchecked((long) 0xCD56D9430EA8280EL) /* 1020 */, unchecked((long) 0xC12591D7535F5065L) /* 1021 */, + unchecked((long) 0xC83223F1720AEF96L) /* 1022 */, unchecked((long) 0xC3A0396F7363A51FL) /* 1023 */ + }; + + private const int DigestLength = 24; + + // + // registers + // + private long a, b, c; + private long byteCount; + + // + // buffers + // + private byte[] Buffer = new byte[8]; + private int bOff; + + private long[] x = new long[8]; + private int xOff; + + /** + * Standard constructor + */ + public TigerDigest() + { + Reset(); + } + + /** + * Copy constructor. This will copy the state of the provided + * message digest. + */ + public TigerDigest(TigerDigest t) + { + a = t.a; + b = t.b; + c = t.c; + + Array.Copy(t.x, 0, x, 0, t.x.Length); + xOff = t.xOff; + + Array.Copy(t.Buffer, 0, Buffer, 0, t.Buffer.Length); + bOff = t.bOff; + + byteCount = t.byteCount; + } + + public string AlgorithmName + { + get { return "Tiger"; } + } + + public int GetDigestSize() + { + return DigestLength; + } + + public int GetByteLength() + { + return MyByteLength; + } + + 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) + | ((uint)(b[off + 0] & 0xff)); + + if (xOff == x.Length) + { + ProcessBlock(); + } + + bOff = 0; + } + + public void Update( + byte input) + { + Buffer[bOff++] = input; + + if (bOff == Buffer.Length) + { + ProcessWord(Buffer, 0); + } + + byteCount++; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int length) + { + // + // fill the current word + // + while ((bOff != 0) && (length > 0)) + { + Update(input[inOff]); + + inOff++; + length--; + } + + // + // process whole words. + // + while (length > 8) + { + ProcessWord(input, inOff); + + inOff += 8; + length -= 8; + byteCount += 8; + } + + // + // load in the remainder. + // + while (length > 0) + { + Update(input[inOff]); + + inOff++; + length--; + } + } + + 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] ^ unchecked ((long) 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] ^ (long) ((ulong) (~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] ^ (long) ((ulong) (~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; + } + } + + private void UnpackWord( + long r, + byte[] output, + int outOff) + { + output[outOff + 7] = (byte)(r >> 56); + output[outOff + 6] = (byte)(r >> 48); + output[outOff + 5] = (byte)(r >> 40); + output[outOff + 4] = (byte)(r >> 32); + output[outOff + 3] = (byte)(r >> 24); + output[outOff + 2] = (byte)(r >> 16); + output[outOff + 1] = (byte)(r >> 8); + output[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[] output, + int outOff) + { + Finish(); + + UnpackWord(a, output, outOff); + UnpackWord(b, output, outOff + 8); + UnpackWord(c, output, outOff + 16); + + Reset(); + + return DigestLength; + } + + /** + * reset the chaining variables + */ + public void Reset() + { + a = unchecked((long) 0x0123456789ABCDEFL); + b = unchecked((long) 0xFEDCBA9876543210L); + c = unchecked((long) 0xF096A5B4C3B2E187L); + + xOff = 0; + for (int i = 0; i != x.Length; i++) + { + x[i] = 0; + } + + bOff = 0; + for (int i = 0; i != Buffer.Length; i++) + { + Buffer[i] = 0; + } + + byteCount = 0; + } + } +} diff --git a/crypto/src/crypto/digests/WhirlpoolDigest.cs b/crypto/src/crypto/digests/WhirlpoolDigest.cs new file mode 100644 index 000000000..df83f4508 --- /dev/null +++ b/crypto/src/crypto/digests/WhirlpoolDigest.cs @@ -0,0 +1,397 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /** + * Implementation of WhirlpoolDigest, based on Java source published by Barreto + * and Rijmen. + * + */ + public sealed class WhirlpoolDigest : IDigest + { + private const int BYTE_LENGTH = 64; + + private const int DIGEST_LENGTH_BYTES = 512 / 8; + private const int ROUNDS = 10; + private const int REDUCTION_POLYNOMIAL = 0x011d; // 2^8 + 2^4 + 2^3 + 2 + 1; + + private static readonly 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 readonly long[] C0 = new long[256]; + private static readonly long[] C1 = new long[256]; + private static readonly long[] C2 = new long[256]; + private static readonly long[] C3 = new long[256]; + private static readonly long[] C4 = new long[256]; + private static readonly long[] C5 = new long[256]; + private static readonly long[] C6 = new long[256]; + private static readonly long[] C7 = new long[256]; + + private readonly long[] _rc = new long[ROUNDS + 1]; + + /* + * 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 readonly short[] EIGHT = new short[BITCOUNT_ARRAY_SIZE]; + + static WhirlpoolDigest() + { + EIGHT[BITCOUNT_ARRAY_SIZE - 1] = 8; + + 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); + } + } + + public WhirlpoolDigest() + { + _rc[0] = 0L; + for (int r = 1; r <= ROUNDS; r++) + { + int i = 8 * (r - 1); + _rc[r] = (long)((ulong)C0[i] & 0xff00000000000000L) ^ + (C1[i + 1] & (long) 0x00ff000000000000L) ^ + (C2[i + 2] & (long) 0x0000ff0000000000L) ^ + (C3[i + 3] & (long) 0x000000ff00000000L) ^ + (C4[i + 4] & (long) 0x00000000ff000000L) ^ + (C5[i + 5] & (long) 0x0000000000ff0000L) ^ + (C6[i + 6] & (long) 0x000000000000ff00L) ^ + (C7[i + 7] & (long) 0x00000000000000ffL); + } + } + + private static 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 static 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 const int BITCOUNT_ARRAY_SIZE = 32; + private byte[] _buffer = new byte[64]; + private int _bufferPos; + 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) + { + Array.Copy(originalDigest._rc, 0, _rc, 0, _rc.Length); + + Array.Copy(originalDigest._buffer, 0, _buffer, 0, _buffer.Length); + + this._bufferPos = originalDigest._bufferPos; + Array.Copy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.Length); + + // -- internal hash state -- + Array.Copy(originalDigest._hash, 0, _hash, 0, _hash.Length); + Array.Copy(originalDigest._K, 0, _K, 0, _K.Length); + Array.Copy(originalDigest._L, 0, _L, 0, _L.Length); + Array.Copy(originalDigest._block, 0, _block, 0, _block.Length); + Array.Copy(originalDigest._state, 0, _state, 0, _state.Length); + } + + public string AlgorithmName + { + get { return "Whirlpool"; } + } + + public int GetDigestSize() + { + return DIGEST_LENGTH_BYTES; + } + + public int DoFinal(byte[] output, int outOff) + { + // sets output[outOff] .. output[outOff+DIGEST_LENGTH_BYTES] + finish(); + + for (int i = 0; i < 8; i++) + { + convertLongToByteArray(_hash[i], output, outOff + (i * 8)); + } + + Reset(); + + return GetDigestSize(); + } + + /** + * Reset the chaining variables + */ + public void Reset() + { + // set variables to null, blank, whatever + _bufferPos = 0; + Array.Clear(_bitCount, 0, _bitCount.Length); + Array.Clear(_buffer, 0, _buffer.Length); + Array.Clear(_hash, 0, _hash.Length); + Array.Clear(_K, 0, _K.Length); + Array.Clear(_L, 0, _L.Length); + Array.Clear(_block, 0, _block.Length); + Array.Clear(_state, 0, _state.Length); + } + + // this takes a buffer of information and fills the block + private void processFilledBuffer() + { + // copies into the block... + for (int i = 0; i < _state.Length; i++) + { + _block[i] = bytesToLongFromBuffer(_buffer, i * 8); + } + processBlock(); + _bufferPos = 0; + Array.Clear(_buffer, 0, _buffer.Length); + } + + private static 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 static void convertLongToByteArray(long inputLong, byte[] outputArray, int offSet) + { + for (int i = 0; i < 8; i++) + { + outputArray[offSet + i] = (byte)((inputLong >> (56 - (i * 8))) & 0xff); + } + } + + private 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]; + } + + Array.Copy(_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 + Array.Copy(_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 input) + { + _buffer[_bufferPos] = input; + + //Console.WriteLine("adding to buffer = "+_buffer[_bufferPos]); + + ++_bufferPos; + + if (_bufferPos == _buffer.Length) + { + processFilledBuffer(); + } + + increment(); + } + + 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 BlockUpdate(byte[] input, int inOff, int length) + { + while (length > 0) + { + Update(input[inOff]); + ++inOff; + --length; + } + + } + + 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(); + } + + /* + * 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.... + Array.Copy(bitLength, 0, _buffer, 32, bitLength.Length); + + processFilledBuffer(); + } + + 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; + } + } +} diff --git a/crypto/src/crypto/encodings/ISO9796d1Encoding.cs b/crypto/src/crypto/encodings/ISO9796d1Encoding.cs new file mode 100644 index 000000000..30e988356 --- /dev/null +++ b/crypto/src/crypto/encodings/ISO9796d1Encoding.cs @@ -0,0 +1,273 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Encodings +{ + /** + * 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 + : IAsymmetricBlockCipher + { + private static readonly BigInteger Sixteen = BigInteger.ValueOf(16); + private static readonly BigInteger Six = BigInteger.ValueOf(6); + + private static readonly byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf, + 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 }; + private static readonly byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc, + 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 }; + + private readonly IAsymmetricBlockCipher engine; + private bool forEncryption; + private int bitSize; + private int padBits = 0; + private BigInteger modulus; + + public ISO9796d1Encoding( + IAsymmetricBlockCipher cipher) + { + this.engine = cipher; + } + + public string AlgorithmName + { + get { return engine.AlgorithmName + "/ISO9796-1Padding"; } + } + + public IAsymmetricBlockCipher GetUnderlyingCipher() + { + return engine; + } + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + RsaKeyParameters kParam; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + kParam = (RsaKeyParameters)rParam.Parameters; + } + else + { + kParam = (RsaKeyParameters)parameters; + } + + engine.Init(forEncryption, parameters); + + modulus = kParam.Modulus; + 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 ArgumentException("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[] input, + int inOff, + int length) + { + if (forEncryption) + { + return EncodeBlock(input, inOff, length); + } + else + { + return DecodeBlock(input, inOff, length); + } + } + + private byte[] EncodeBlock( + byte[] input, + int inOff, + int inLen) + { + 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) + { + Array.Copy(input, inOff + inLen - (t - i), + block, block.Length - t, t - i); + } + else + { + Array.Copy(input, 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[(uint) (val & 0xff) >> 4] << 4) + | shadows[val & 0x0f]); + block[i + 1] = val; + } + + block[block.Length - 2 * z] ^= (byte) 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] &= (byte) ((ushort) 0xff >> maxBit); + block[0] |= (byte) ((ushort) 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[] input, + int inOff, + int inLen) + { + byte[] block = engine.ProcessBlock(input, 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 + { + iR = modulus.Subtract(iS); + + if (!iR.Mod(Sixteen).Equals(Six)) + throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16"); + } + + block = iR.ToByteArrayUnsigned(); + + if ((block[block.Length - 1] & 0x0f) != 0x6) + throw new InvalidCipherTextException("invalid forcing byte in block"); + + block[block.Length - 1] = + (byte)(((ushort)(block[block.Length - 1] & 0xff) >> 4) + | ((inverse[(block[block.Length - 2] & 0xff) >> 4]) << 4)); + + block[0] = (byte)((shadows[(uint) (block[1] & 0xff) >> 4] << 4) + | shadows[block[1] & 0x0f]); + + bool boundaryFound = false; + int boundary = 0; + + for (int i = block.Length - 1; i >= block.Length - 2 * t; i -= 2) + { + int val = ((shadows[(uint) (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; + } + } +} diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs new file mode 100644 index 000000000..a4d2f0e36 --- /dev/null +++ b/crypto/src/crypto/encodings/OaepEncoding.cs @@ -0,0 +1,349 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Encodings +{ + /** + * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. + */ + public class OaepEncoding + : IAsymmetricBlockCipher + { + private byte[] defHash; + private IDigest hash; + private IDigest mgf1Hash; + + private IAsymmetricBlockCipher engine; + private SecureRandom random; + private bool forEncryption; + + public OaepEncoding( + IAsymmetricBlockCipher cipher) + : this(cipher, new Sha1Digest(), null) + { + } + + public OaepEncoding( + IAsymmetricBlockCipher cipher, + IDigest hash) + : this(cipher, hash, null) + { + } + + public OaepEncoding( + IAsymmetricBlockCipher cipher, + IDigest hash, + byte[] encodingParams) + : this(cipher, hash, hash, encodingParams) + { + } + + public OaepEncoding( + IAsymmetricBlockCipher cipher, + IDigest hash, + IDigest mgf1Hash, + byte[] encodingParams) + { + this.engine = cipher; + this.hash = hash; + this.mgf1Hash = mgf1Hash; + this.defHash = new byte[hash.GetDigestSize()]; + + if (encodingParams != null) + { + hash.BlockUpdate(encodingParams, 0, encodingParams.Length); + } + + hash.DoFinal(defHash, 0); + } + + public IAsymmetricBlockCipher GetUnderlyingCipher() + { + return engine; + } + + public string AlgorithmName + { + get { return engine.AlgorithmName + "/OAEPPadding"; } + } + + public void Init( + bool forEncryption, + ICipherParameters param) + { + if (param is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + this.random = rParam.Random; + } + 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[] inBytes, + int inOff, + int inLen) + { + if (forEncryption) + { + return EncodeBlock(inBytes, inOff, inLen); + } + else + { + return DecodeBlock(inBytes, inOff, inLen); + } + } + + private byte[] EncodeBlock( + byte[] inBytes, + int inOff, + int inLen) + { + byte[] block = new byte[GetInputBlockSize() + 1 + 2 * defHash.Length]; + + // + // copy in the message + // + Array.Copy(inBytes, 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. + // + Array.Copy(defHash, 0, block, defHash.Length, defHash.Length); + + // + // generate the seed. + // + byte[] seed = random.GenerateSeed(defHash.Length); + + // + // 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 + // + Array.Copy(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. + */ + private byte[] DecodeBlock( + byte[] inBytes, + int inOff, + int inLen) + { + byte[] data = engine.ProcessBlock(inBytes, 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()]; + + Array.Copy(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. + // + { + int diff = 0; + for (int i = 0; i < defHash.Length; ++i) + { + diff |= (byte)(defHash[i] ^ block[defHash.Length + i]); + } + + if (diff != 0) + 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]; + + Array.Copy(block, start, output, 0, output.Length); + + return output; + } + + /** + * int to octet string. + */ + private void ItoOSP( + int i, + byte[] sp) + { + sp[0] = (byte)((uint)i >> 24); + sp[1] = (byte)((uint)i >> 16); + sp[2] = (byte)((uint)i >> 8); + sp[3] = (byte)((uint)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; + + hash.Reset(); + + do + { + ItoOSP(counter, C); + + mgf1Hash.BlockUpdate(Z, zOff, zLen); + mgf1Hash.BlockUpdate(C, 0, C.Length); + mgf1Hash.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, hashBuf.Length); + } + while (++counter < (length / hashBuf.Length)); + + if ((counter * hashBuf.Length) < length) + { + ItoOSP(counter, C); + + mgf1Hash.BlockUpdate(Z, zOff, zLen); + mgf1Hash.BlockUpdate(C, 0, C.Length); + mgf1Hash.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, mask.Length - (counter * hashBuf.Length)); + } + + return mask; + } + } +} + diff --git a/crypto/src/crypto/encodings/Pkcs1Encoding.cs b/crypto/src/crypto/encodings/Pkcs1Encoding.cs new file mode 100644 index 000000000..d2225a7d4 --- /dev/null +++ b/crypto/src/crypto/encodings/Pkcs1Encoding.cs @@ -0,0 +1,232 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Encodings +{ + /** + * 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 + : IAsymmetricBlockCipher + { + /** + * 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. + */ + public const string StrictLengthEnabledProperty = "Org.BouncyCastle.Pkcs1.Strict"; + + private const int HeaderLength = 10; + + /** + * The same effect can be achieved by setting the static property directly + *

+ * The static property is checked during construction of the encoding object, it is set to + * true by default. + *

+ */ + public static bool StrictLengthEnabled + { + get { return strictLengthEnabled[0]; } + set { strictLengthEnabled[0] = value; } + } + + private static readonly bool[] strictLengthEnabled; + + static Pkcs1Encoding() + { + string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty); + + strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")}; + } + + + private SecureRandom random; + private IAsymmetricBlockCipher engine; + private bool forEncryption; + private bool forPrivateKey; + private bool useStrictLength; + + /** + * Basic constructor. + * @param cipher + */ + public Pkcs1Encoding( + IAsymmetricBlockCipher cipher) + { + this.engine = cipher; + this.useStrictLength = StrictLengthEnabled; + } + + public IAsymmetricBlockCipher GetUnderlyingCipher() + { + return engine; + } + + public string AlgorithmName + { + get { return engine.AlgorithmName + "/PKCS1Padding"; } + } + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + AsymmetricKeyParameter kParam; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + + this.random = rParam.Random; + kParam = (AsymmetricKeyParameter)rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + kParam = (AsymmetricKeyParameter)parameters; + } + + engine.Init(forEncryption, parameters); + + this.forPrivateKey = kParam.IsPrivate; + this.forEncryption = forEncryption; + } + + public int GetInputBlockSize() + { + int baseBlockSize = engine.GetInputBlockSize(); + + return forEncryption + ? baseBlockSize - HeaderLength + : baseBlockSize; + } + + public int GetOutputBlockSize() + { + int baseBlockSize = engine.GetOutputBlockSize(); + + return forEncryption + ? baseBlockSize + : baseBlockSize - HeaderLength; + } + + public byte[] ProcessBlock( + byte[] input, + int inOff, + int length) + { + return forEncryption + ? EncodeBlock(input, inOff, length) + : DecodeBlock(input, inOff, length); + } + + private byte[] EncodeBlock( + byte[] input, + int inOff, + int inLen) + { + if (inLen > GetInputBlockSize()) + throw new ArgumentException("input data too large", "inLen"); + + 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 + Array.Copy(input, inOff, block, block.Length - inLen, inLen); + + return engine.ProcessBlock(block, 0, block.Length); + } + + /** + * @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format. + */ + private byte[] DecodeBlock( + byte[] input, + int inOff, + int inLen) + { + byte[] block = engine.ProcessBlock(input, inOff, inLen); + + if (block.Length < GetOutputBlockSize()) + { + throw new InvalidCipherTextException("block truncated"); + } + + byte type = block[0]; + + if (type != 1 && type != 2) + { + 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 < HeaderLength) + { + throw new InvalidCipherTextException("no data in block"); + } + + byte[] result = new byte[block.Length - start]; + + Array.Copy(block, start, result, 0, result.Length); + + return result; + } + } + +} diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs new file mode 100644 index 000000000..47eaada3e --- /dev/null +++ b/crypto/src/crypto/engines/AesEngine.cs @@ -0,0 +1,546 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of the AES (Rijndael), from FIPS-197. + *

+ * For further details see: http://csrc.nist.gov/encryption/aes/. + * + * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + * + * 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. + *

+ *

+ * This file contains the middle performance version with 2Kbytes of static tables for round precomputation. + *

+ */ + public class AesEngine + : IBlockCipher + { + // The S box + private static readonly byte[] S = + { + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22, + }; + + // The inverse S-box + private static readonly byte[] Si = + { + 82, 9, 106, 213, 48, 54, 165, 56, + 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, + 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, + 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, + 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, + 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, + 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, + 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, + 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, + 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, + 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, + 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, + 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, + 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, + 225, 105, 20, 99, 85, 33, 12, 125, + }; + + // vector used in calculating key schedule (powers of x in GF(256)) + private static readonly byte[] 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 readonly uint[] 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 readonly uint[] 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 uint Shift(uint r, int shift) + { + return (r >> shift) | (r << (32 - shift)); + } + + /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + + private const uint m1 = 0x80808080; + private const uint m2 = 0x7f7f7f7f; + private const uint m3 = 0x0000001b; + + private static uint FFmulX(uint 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 uint Inv_Mcol(uint x) + { + uint f2 = FFmulX(x); + uint f4 = FFmulX(f2); + uint f8 = FFmulX(f4); + uint f9 = x ^ f8; + + return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + } + + private static uint SubWord(uint x) + { + return (uint)S[x&255] + | (((uint)S[(x>>8)&255]) << 8) + | (((uint)S[(x>>16)&255]) << 16) + | (((uint)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 uint[][] GenerateWorkingKey( + byte[] key, + bool forEncryption) + { + int KC = key.Length / 4; // key length in words + int t; + + if ((KC != 4) && (KC != 6) && (KC != 8)) + throw new ArgumentException("Key length not 128/192/256 bits."); + + ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes + + uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block + for (int i = 0; i <= ROUNDS; ++i) + { + W[i] = new uint[4]; + } + + // + // copy the key into the round key array + // + + t = 0; + for (int i = 0; i < key.Length; t++) + { + W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i); + i+=4; + } + + // + // while not enough round key material calculated + // calculate new values + // + int k = (ROUNDS + 1) << 2; + for (int i = KC; (i < k); i++) + { + uint 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++) + { + uint[] w = W[j]; + for (int i = 0; i < 4; i++) + { + w[i] = Inv_Mcol(w[i]); + } + } + } + + return W; + } + + private int ROUNDS; + private uint[][] WorkingKey; + private uint C0, C1, C2, C3; + private bool forEncryption; + + private const 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 parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + KeyParameter keyParameter = parameters as KeyParameter; + + if (keyParameter == null) + throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name); + + WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption); + + this.forEncryption = forEncryption; + } + + public string AlgorithmName + { + get { return "AES"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (WorkingKey == null) + { + throw new InvalidOperationException("AES engine not initialised"); + } + + if ((inOff + (32 / 2)) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + (32 / 2)) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + UnPackBlock(input, inOff); + + if (forEncryption) + { + EncryptBlock(); + } + else + { + DecryptBlock(); + } + + PackBlock(output, outOff); + + return BLOCK_SIZE; + } + + public void Reset() + { + } + + private void UnPackBlock( + byte[] bytes, + int off) + { + C0 = Pack.LE_To_UInt32(bytes, off); + C1 = Pack.LE_To_UInt32(bytes, off + 4); + C2 = Pack.LE_To_UInt32(bytes, off + 8); + C3 = Pack.LE_To_UInt32(bytes, off + 12); + } + + private void PackBlock( + byte[] bytes, + int off) + { + Pack.UInt32_To_LE(C0, bytes, off); + Pack.UInt32_To_LE(C1, bytes, off + 4); + Pack.UInt32_To_LE(C2, bytes, off + 8); + Pack.UInt32_To_LE(C3, bytes, off + 12); + } + + private void EncryptBlock() + { + uint[][] KW = WorkingKey; + + int r = 0; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r < (ROUNDS - 2)) + { + kw = KW[++r]; + r0 = T0[C0 & 255] ^ Shift(T0[(C1 >> 8) & 255], 24) ^ Shift(T0[(C2 >> 16) & 255], 16) ^ Shift(T0[(C3 >> 24) & 255], 8) ^ kw[0]; + r1 = T0[C1 & 255] ^ Shift(T0[(C2 >> 8) & 255], 24) ^ Shift(T0[(C3 >> 16) & 255], 16) ^ Shift(T0[(C0 >> 24) & 255], 8) ^ kw[1]; + r2 = T0[C2 & 255] ^ Shift(T0[(C3 >> 8) & 255], 24) ^ Shift(T0[(C0 >> 16) & 255], 16) ^ Shift(T0[(C1 >> 24) & 255], 8) ^ kw[2]; + r3 = T0[C3 & 255] ^ Shift(T0[(C0 >> 8) & 255], 24) ^ Shift(T0[(C1 >> 16) & 255], 16) ^ Shift(T0[(C2 >> 24) & 255], 8) ^ kw[3]; + kw = KW[++r]; + C0 = T0[r0 & 255] ^ Shift(T0[(r1 >> 8) & 255], 24) ^ Shift(T0[(r2 >> 16) & 255], 16) ^ Shift(T0[(r3 >> 24) & 255], 8) ^ kw[0]; + C1 = T0[r1 & 255] ^ Shift(T0[(r2 >> 8) & 255], 24) ^ Shift(T0[(r3 >> 16) & 255], 16) ^ Shift(T0[(r0 >> 24) & 255], 8) ^ kw[1]; + C2 = T0[r2 & 255] ^ Shift(T0[(r3 >> 8) & 255], 24) ^ Shift(T0[(r0 >> 16) & 255], 16) ^ Shift(T0[(r1 >> 24) & 255], 8) ^ kw[2]; + C3 = T0[r3 & 255] ^ Shift(T0[(r0 >> 8) & 255], 24) ^ Shift(T0[(r1 >> 16) & 255], 16) ^ Shift(T0[(r2 >> 24) & 255], 8) ^ kw[3]; + } + + kw = KW[++r]; + r0 = T0[C0 & 255] ^ Shift(T0[(C1 >> 8) & 255], 24) ^ Shift(T0[(C2 >> 16) & 255], 16) ^ Shift(T0[(C3 >> 24) & 255], 8) ^ kw[0]; + r1 = T0[C1 & 255] ^ Shift(T0[(C2 >> 8) & 255], 24) ^ Shift(T0[(C3 >> 16) & 255], 16) ^ Shift(T0[(C0 >> 24) & 255], 8) ^ kw[1]; + r2 = T0[C2 & 255] ^ Shift(T0[(C3 >> 8) & 255], 24) ^ Shift(T0[(C0 >> 16) & 255], 16) ^ Shift(T0[(C1 >> 24) & 255], 8) ^ kw[2]; + r3 = T0[C3 & 255] ^ Shift(T0[(C0 >> 8) & 255], 24) ^ Shift(T0[(C1 >> 16) & 255], 16) ^ Shift(T0[(C2 >> 24) & 255], 8) ^ kw[3]; + + // the final round's table is a simple function of S so we don't use a whole other four tables for it + + kw = KW[++r]; + C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0]; + C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1]; + C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2]; + C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3]; + + Debug.Assert(r == ROUNDS); + } + + private void DecryptBlock() + { + uint[][] KW = WorkingKey; + + int r = ROUNDS; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r > 2) + { + kw = KW[--r]; + r0 = Tinv0[C0 & 255] ^ Shift(Tinv0[(C3 >> 8) & 255], 24) ^ Shift(Tinv0[(C2 >> 16) & 255], 16) ^ Shift(Tinv0[(C1 >> 24) & 255], 8) ^ kw[0]; + r1 = Tinv0[C1 & 255] ^ Shift(Tinv0[(C0 >> 8) & 255], 24) ^ Shift(Tinv0[(C3 >> 16) & 255], 16) ^ Shift(Tinv0[(C2 >> 24) & 255], 8) ^ kw[1]; + r2 = Tinv0[C2 & 255] ^ Shift(Tinv0[(C1 >> 8) & 255], 24) ^ Shift(Tinv0[(C0 >> 16) & 255], 16) ^ Shift(Tinv0[(C3 >> 24) & 255], 8) ^ kw[2]; + r3 = Tinv0[C3 & 255] ^ Shift(Tinv0[(C2 >> 8) & 255], 24) ^ Shift(Tinv0[(C1 >> 16) & 255], 16) ^ Shift(Tinv0[(C0 >> 24) & 255], 8) ^ kw[3]; + kw = KW[--r]; + C0 = Tinv0[r0 & 255] ^ Shift(Tinv0[(r3 >> 8) & 255], 24) ^ Shift(Tinv0[(r2 >> 16) & 255], 16) ^ Shift(Tinv0[(r1 >> 24) & 255], 8) ^ kw[0]; + C1 = Tinv0[r1 & 255] ^ Shift(Tinv0[(r0 >> 8) & 255], 24) ^ Shift(Tinv0[(r3 >> 16) & 255], 16) ^ Shift(Tinv0[(r2 >> 24) & 255], 8) ^ kw[1]; + C2 = Tinv0[r2 & 255] ^ Shift(Tinv0[(r1 >> 8) & 255], 24) ^ Shift(Tinv0[(r0 >> 16) & 255], 16) ^ Shift(Tinv0[(r3 >> 24) & 255], 8) ^ kw[2]; + C3 = Tinv0[r3 & 255] ^ Shift(Tinv0[(r2 >> 8) & 255], 24) ^ Shift(Tinv0[(r1 >> 16) & 255], 16) ^ Shift(Tinv0[(r0 >> 24) & 255], 8) ^ kw[3]; + } + + kw = KW[--r]; + r0 = Tinv0[C0 & 255] ^ Shift(Tinv0[(C3 >> 8) & 255], 24) ^ Shift(Tinv0[(C2 >> 16) & 255], 16) ^ Shift(Tinv0[(C1 >> 24) & 255], 8) ^ kw[0]; + r1 = Tinv0[C1 & 255] ^ Shift(Tinv0[(C0 >> 8) & 255], 24) ^ Shift(Tinv0[(C3 >> 16) & 255], 16) ^ Shift(Tinv0[(C2 >> 24) & 255], 8) ^ kw[1]; + r2 = Tinv0[C2 & 255] ^ Shift(Tinv0[(C1 >> 8) & 255], 24) ^ Shift(Tinv0[(C0 >> 16) & 255], 16) ^ Shift(Tinv0[(C3 >> 24) & 255], 8) ^ kw[2]; + r3 = Tinv0[C3 & 255] ^ Shift(Tinv0[(C2 >> 8) & 255], 24) ^ Shift(Tinv0[(C1 >> 16) & 255], 16) ^ Shift(Tinv0[(C0 >> 24) & 255], 8) ^ kw[3]; + + // the final round's table is a simple function of Si so we don't use a whole other four tables for it + + kw = KW[--r]; + C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0]; + C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1]; + C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2]; + C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3]; + + Debug.Assert(r == 0); + } + } +} diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs new file mode 100644 index 000000000..d76955dd8 --- /dev/null +++ b/crypto/src/crypto/engines/AesFastEngine.cs @@ -0,0 +1,878 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of the AES (Rijndael)), from FIPS-197. + *

+ * For further details see: http://csrc.nist.gov/encryption/aes/. + * + * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + * + * 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 + *

+ *

+ * This file contains the fast version with 8Kbytes of static tables for round precomputation + *

+ */ + public class AesFastEngine + : IBlockCipher + { + // The S box + private static readonly byte[] S = + { + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22, + }; + + // The inverse S-box + private static readonly byte[] Si = + { + 82, 9, 106, 213, 48, 54, 165, 56, + 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, + 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, + 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, + 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, + 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, + 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, + 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, + 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, + 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, + 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, + 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, + 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, + 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, + 225, 105, 20, 99, 85, 33, 12, 125, + }; + + // vector used in calculating key schedule (powers of x in GF(256)) + private static readonly byte[] 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 readonly uint[] 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 readonly uint[] 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 + }; + + private static readonly uint[] 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 + }; + + private static readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 + }; + + private static readonly uint[] 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 + }; + + private static readonly uint[] 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 uint Shift(uint r, int shift) + { + return (r >> shift) | (r << (32 - shift)); + } + + /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + + private const uint m1 = 0x80808080; + private const uint m2 = 0x7f7f7f7f; + private const uint m3 = 0x0000001b; + + private static uint FFmulX(uint 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 uint Inv_Mcol(uint x) + { + uint f2 = FFmulX(x); + uint f4 = FFmulX(f2); + uint f8 = FFmulX(f4); + uint f9 = x ^ f8; + + return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + } + + private static uint SubWord(uint x) + { + return (uint)S[x&255] + | (((uint)S[(x>>8)&255]) << 8) + | (((uint)S[(x>>16)&255]) << 16) + | (((uint)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 uint[][] GenerateWorkingKey( + byte[] key, + bool forEncryption) + { + int KC = key.Length / 4; // key length in words + + if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length)) + throw new ArgumentException("Key length not 128/192/256 bits."); + + ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes + + uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block + for (int i = 0; i <= ROUNDS; ++i) + { + W[i] = new uint[4]; + } + + // + // copy the key into the round key array + // + + int t = 0; + for (int i = 0; i < key.Length; t++) + { + W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i); + i+=4; + } + + // + // while not enough round key material calculated + // calculate new values + // + int k = (ROUNDS + 1) << 2; + for (int i = KC; (i < k); i++) + { + uint 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++) + { + uint[] w = W[j]; + for (int i = 0; i < 4; i++) + { + w[i] = Inv_Mcol(w[i]); + } + } + } + + return W; + } + + private int ROUNDS; + private uint[][] WorkingKey; + private uint C0, C1, C2, C3; + private bool forEncryption; + + private const 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 parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + KeyParameter keyParameter = parameters as KeyParameter; + + if (keyParameter == null) + throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name); + + WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption); + + this.forEncryption = forEncryption; + } + + public string AlgorithmName + { + get { return "AES"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (WorkingKey == null) + { + throw new InvalidOperationException("AES engine not initialised"); + } + + if ((inOff + (32 / 2)) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + (32 / 2)) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + UnPackBlock(input, inOff); + + if (forEncryption) + { + EncryptBlock(); + } + else + { + DecryptBlock(); + } + + PackBlock(output, outOff); + + return BLOCK_SIZE; + } + + public void Reset() + { + } + + private void UnPackBlock( + byte[] bytes, + int off) + { + C0 = Pack.LE_To_UInt32(bytes, off); + C1 = Pack.LE_To_UInt32(bytes, off + 4); + C2 = Pack.LE_To_UInt32(bytes, off + 8); + C3 = Pack.LE_To_UInt32(bytes, off + 12); + } + + private void PackBlock( + byte[] bytes, + int off) + { + Pack.UInt32_To_LE(C0, bytes, off); + Pack.UInt32_To_LE(C1, bytes, off + 4); + Pack.UInt32_To_LE(C2, bytes, off + 8); + Pack.UInt32_To_LE(C3, bytes, off + 12); + } + + private void EncryptBlock() + { + uint[][] KW = WorkingKey; + + int r = 0; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r < (ROUNDS - 2)) + { + kw = KW[++r]; + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ kw[0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ kw[1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ kw[2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ kw[3]; + kw = KW[++r]; + C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[r3 >> 24] ^ kw[0]; + C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[r0 >> 24] ^ kw[1]; + C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[r1 >> 24] ^ kw[2]; + C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[r2 >> 24] ^ kw[3]; + } + + kw = KW[++r]; + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ kw[0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ kw[1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ kw[2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ kw[3]; + + // the final round's table is a simple function of S so we don't use a whole other four tables for it + + kw = KW[++r]; + C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ kw[0]; + C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ kw[1]; + C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ kw[2]; + C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ kw[3]; + + Debug.Assert(r == ROUNDS); + } + + private void DecryptBlock() + { + uint[][] KW = WorkingKey; + + int r = ROUNDS; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r > 2) + { + kw = KW[--r]; + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ kw[0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ kw[1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ kw[2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ kw[3]; + kw = KW[--r]; + C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[r1 >> 24] ^ kw[0]; + C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[r2 >> 24] ^ kw[1]; + C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ kw[2]; + C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[r0 >> 24] ^ kw[3]; + } + + kw = KW[--r]; + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ kw[0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ kw[1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ kw[2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ kw[3]; + + // the final round's table is a simple function of Si so we don't use a whole other four tables for it + + kw = KW[--r]; + C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ kw[0]; + C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ kw[1]; + C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ kw[2]; + C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ kw[3]; + + Debug.Assert(r == 0); + } + } +} diff --git a/crypto/src/crypto/engines/AesLightEngine.cs b/crypto/src/crypto/engines/AesLightEngine.cs new file mode 100644 index 000000000..828ceaa33 --- /dev/null +++ b/crypto/src/crypto/engines/AesLightEngine.cs @@ -0,0 +1,441 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of the AES (Rijndael), from FIPS-197. + *

+ * For further details see: http://csrc.nist.gov/encryption/aes/. + * + * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + * + * 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. + *

+ *

+ * This file contains the slowest performance version with no static tables + * for round precomputation, but it has the smallest foot print. + *

+ */ + public class AesLightEngine + : IBlockCipher + { + // The S box + private static readonly byte[] S = + { + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22, + }; + + // The inverse S-box + private static readonly byte[] Si = + { + 82, 9, 106, 213, 48, 54, 165, 56, + 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, + 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, + 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, + 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, + 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, + 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, + 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, + 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, + 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, + 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, + 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, + 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, + 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, + 225, 105, 20, 99, 85, 33, 12, 125, + }; + + // vector used in calculating key schedule (powers of x in GF(256)) + private static readonly byte[] 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 uint Shift(uint r, int shift) + { + return (r >> shift) | (r << (32 - shift)); + } + + /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + + private const uint m1 = 0x80808080; + private const uint m2 = 0x7f7f7f7f; + private const uint m3 = 0x0000001b; + + private static uint FFmulX(uint 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 uint Mcol(uint x) + { + uint f2 = FFmulX(x); + return f2 ^ Shift(x ^ f2, 8) ^ Shift(x, 16) ^ Shift(x, 24); + } + + private static uint Inv_Mcol(uint x) + { + uint f2 = FFmulX(x); + uint f4 = FFmulX(f2); + uint f8 = FFmulX(f4); + uint f9 = x ^ f8; + + return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + } + + private static uint SubWord(uint x) + { + return (uint)S[x&255] + | (((uint)S[(x>>8)&255]) << 8) + | (((uint)S[(x>>16)&255]) << 16) + | (((uint)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 uint[][] GenerateWorkingKey( + byte[] key, + bool forEncryption) + { + int KC = key.Length / 4; // key length in words + int t; + + if ((KC != 4) && (KC != 6) && (KC != 8)) + throw new ArgumentException("Key length not 128/192/256 bits."); + + ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes + + uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block + for (int i = 0; i <= ROUNDS; ++i) + { + W[i] = new uint[4]; + } + + // + // copy the key into the round key array + // + + t = 0; + for (int i = 0; i < key.Length; t++) + { + W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i); + i+=4; + } + + // + // while not enough round key material calculated + // calculate new values + // + int k = (ROUNDS + 1) << 2; + for (int i = KC; (i < k); i++) + { + uint 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++) + { + uint[] w = W[j]; + for (int i = 0; i < 4; i++) + { + w[i] = Inv_Mcol(w[i]); + } + } + } + + return W; + } + + private int ROUNDS; + private uint[][] WorkingKey; + private uint C0, C1, C2, C3; + private bool forEncryption; + + private const 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 parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + KeyParameter keyParameter = parameters as KeyParameter; + + if (keyParameter == null) + throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name); + + WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption); + + this.forEncryption = forEncryption; + } + + public string AlgorithmName + { + get { return "AES"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (WorkingKey == null) + { + throw new InvalidOperationException("AES engine not initialised"); + } + + if ((inOff + (32 / 2)) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + (32 / 2)) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + if (forEncryption) + { + UnPackBlock(input, inOff); + EncryptBlock(); + PackBlock(output, outOff); + } + else + { + UnPackBlock(input, inOff); + DecryptBlock(); + PackBlock(output, outOff); + } + + return BLOCK_SIZE; + } + + public void Reset() + { + } + + private void UnPackBlock( + byte[] bytes, + int off) + { + C0 = Pack.LE_To_UInt32(bytes, off); + C1 = Pack.LE_To_UInt32(bytes, off + 4); + C2 = Pack.LE_To_UInt32(bytes, off + 8); + C3 = Pack.LE_To_UInt32(bytes, off + 12); + } + + private void PackBlock( + byte[] bytes, + int off) + { + Pack.UInt32_To_LE(C0, bytes, off); + Pack.UInt32_To_LE(C1, bytes, off + 4); + Pack.UInt32_To_LE(C2, bytes, off + 8); + Pack.UInt32_To_LE(C3, bytes, off + 12); + } + + private void EncryptBlock() + { + uint[][] KW = WorkingKey; + + int r = 0; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r < (ROUNDS - 2)) + { + kw = KW[++r]; + r0 = Mcol((uint)S[C0 & 255] ^ (((uint)S[(C1 >> 8) & 255]) << 8) ^ (((uint)S[(C2 >> 16) & 255]) << 16) ^ (((uint)S[(C3 >> 24) & 255]) << 24)) ^ kw[0]; + r1 = Mcol((uint)S[C1 & 255] ^ (((uint)S[(C2 >> 8) & 255]) << 8) ^ (((uint)S[(C3 >> 16) & 255]) << 16) ^ (((uint)S[(C0 >> 24) & 255]) << 24)) ^ kw[1]; + r2 = Mcol((uint)S[C2 & 255] ^ (((uint)S[(C3 >> 8) & 255]) << 8) ^ (((uint)S[(C0 >> 16) & 255]) << 16) ^ (((uint)S[(C1 >> 24) & 255]) << 24)) ^ kw[2]; + r3 = Mcol((uint)S[C3 & 255] ^ (((uint)S[(C0 >> 8) & 255]) << 8) ^ (((uint)S[(C1 >> 16) & 255]) << 16) ^ (((uint)S[(C2 >> 24) & 255]) << 24)) ^ kw[3]; + kw = KW[++r]; + C0 = Mcol((uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24)) ^ kw[0]; + C1 = Mcol((uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24)) ^ kw[1]; + C2 = Mcol((uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24)) ^ kw[2]; + C3 = Mcol((uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24)) ^ kw[3]; + } + + kw = KW[++r]; + r0 = Mcol((uint)S[C0 & 255] ^ (((uint)S[(C1 >> 8) & 255]) << 8) ^ (((uint)S[(C2 >> 16) & 255]) << 16) ^ (((uint)S[(C3 >> 24) & 255]) << 24)) ^ kw[0]; + r1 = Mcol((uint)S[C1 & 255] ^ (((uint)S[(C2 >> 8) & 255]) << 8) ^ (((uint)S[(C3 >> 16) & 255]) << 16) ^ (((uint)S[(C0 >> 24) & 255]) << 24)) ^ kw[1]; + r2 = Mcol((uint)S[C2 & 255] ^ (((uint)S[(C3 >> 8) & 255]) << 8) ^ (((uint)S[(C0 >> 16) & 255]) << 16) ^ (((uint)S[(C1 >> 24) & 255]) << 24)) ^ kw[2]; + r3 = Mcol((uint)S[C3 & 255] ^ (((uint)S[(C0 >> 8) & 255]) << 8) ^ (((uint)S[(C1 >> 16) & 255]) << 16) ^ (((uint)S[(C2 >> 24) & 255]) << 24)) ^ kw[3]; + + // the final round is a simple function of S + + kw = KW[++r]; + C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0]; + C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1]; + C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2]; + C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3]; + + Debug.Assert(r == ROUNDS); + } + + private void DecryptBlock() + { + uint[][] KW = WorkingKey; + + int r = ROUNDS; + uint[] kw = KW[r]; + + C0 ^= kw[0]; + C1 ^= kw[1]; + C2 ^= kw[2]; + C3 ^= kw[3]; + + uint r0, r1, r2, r3; + + while (r > 2) + { + kw = KW[--r]; + r0 = Inv_Mcol((uint)Si[C0 & 255] ^ (((uint)Si[(C3 >> 8) & 255]) << 8) ^ (((uint)Si[(C2 >> 16) & 255]) << 16) ^ ((uint)Si[(C1 >> 24) & 255] << 24)) ^ kw[0]; + r1 = Inv_Mcol((uint)Si[C1 & 255] ^ (((uint)Si[(C0 >> 8) & 255]) << 8) ^ (((uint)Si[(C3 >> 16) & 255]) << 16) ^ ((uint)Si[(C2 >> 24) & 255] << 24)) ^ kw[1]; + r2 = Inv_Mcol((uint)Si[C2 & 255] ^ (((uint)Si[(C1 >> 8) & 255]) << 8) ^ (((uint)Si[(C0 >> 16) & 255]) << 16) ^ ((uint)Si[(C3 >> 24) & 255] << 24)) ^ kw[2]; + r3 = Inv_Mcol((uint)Si[C3 & 255] ^ (((uint)Si[(C2 >> 8) & 255]) << 8) ^ (((uint)Si[(C1 >> 16) & 255]) << 16) ^ ((uint)Si[(C0 >> 24) & 255] << 24)) ^ kw[3]; + kw = KW[--r]; + C0 = Inv_Mcol((uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ ((uint)Si[(r1 >> 24) & 255] << 24)) ^ kw[0]; + C1 = Inv_Mcol((uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ ((uint)Si[(r2 >> 24) & 255] << 24)) ^ kw[1]; + C2 = Inv_Mcol((uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ ((uint)Si[(r3 >> 24) & 255] << 24)) ^ kw[2]; + C3 = Inv_Mcol((uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ ((uint)Si[(r0 >> 24) & 255] << 24)) ^ kw[3]; + } + + kw = KW[--r]; + r0 = Inv_Mcol((uint)Si[C0 & 255] ^ (((uint)Si[(C3 >> 8) & 255]) << 8) ^ (((uint)Si[(C2 >> 16) & 255]) << 16) ^ ((uint)Si[(C1 >> 24) & 255] << 24)) ^ kw[0]; + r1 = Inv_Mcol((uint)Si[C1 & 255] ^ (((uint)Si[(C0 >> 8) & 255]) << 8) ^ (((uint)Si[(C3 >> 16) & 255]) << 16) ^ ((uint)Si[(C2 >> 24) & 255] << 24)) ^ kw[1]; + r2 = Inv_Mcol((uint)Si[C2 & 255] ^ (((uint)Si[(C1 >> 8) & 255]) << 8) ^ (((uint)Si[(C0 >> 16) & 255]) << 16) ^ ((uint)Si[(C3 >> 24) & 255] << 24)) ^ kw[2]; + r3 = Inv_Mcol((uint)Si[C3 & 255] ^ (((uint)Si[(C2 >> 8) & 255]) << 8) ^ (((uint)Si[(C1 >> 16) & 255]) << 16) ^ ((uint)Si[(C0 >> 24) & 255] << 24)) ^ kw[3]; + + // the final round's table is a simple function of Si + + kw = KW[--r]; + C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0]; + C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1]; + C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2]; + C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3]; + + Debug.Assert(r == 0); + } + } +} diff --git a/crypto/src/crypto/engines/AesWrapEngine.cs b/crypto/src/crypto/engines/AesWrapEngine.cs new file mode 100644 index 000000000..1ce01542b --- /dev/null +++ b/crypto/src/crypto/engines/AesWrapEngine.cs @@ -0,0 +1,16 @@ +namespace Org.BouncyCastle.Crypto.Engines +{ + /// + /// An implementation of the AES Key Wrapper from the NIST Key Wrap Specification. + ///

+ /// For further details see: http://csrc.nist.gov/encryption/kms/key-wrap.pdf. + /// + public class AesWrapEngine + : Rfc3394WrapEngine + { + public AesWrapEngine() + : base(new AesEngine()) + { + } + } +} diff --git a/crypto/src/crypto/engines/BlowfishEngine.cs b/crypto/src/crypto/engines/BlowfishEngine.cs new file mode 100644 index 000000000..8f80f712e --- /dev/null +++ b/crypto/src/crypto/engines/BlowfishEngine.cs @@ -0,0 +1,561 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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 sealed class BlowfishEngine + : IBlockCipher + { + private readonly static uint[] 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 readonly int ROUNDS = 16; + private const int BLOCK_SIZE = 8; // bytes = 64 bits + private static readonly int SBOX_SK = 256; + private static readonly int P_SZ = ROUNDS+2; + + private readonly uint[] S0, S1, S2, S3; // the s-boxes + private readonly uint[] P; // the p-array + + private bool encrypting; + + private byte[] workingKey; + + public BlowfishEngine() + { + S0 = new uint[SBOX_SK]; + S1 = new uint[SBOX_SK]; + S2 = new uint[SBOX_SK]; + S3 = new uint[SBOX_SK]; + P = new uint[P_SZ]; + } + + /** + * initialise a Blowfish cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to Blowfish init - " + parameters.GetType().ToString()); + + this.encrypting = forEncryption; + this.workingKey = ((KeyParameter)parameters).GetKey(); + SetKey(this.workingKey); + } + + public string AlgorithmName + { + get { return "Blowfish"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + { + throw new InvalidOperationException("Blowfish not initialised"); + } + + if ((inOff + BLOCK_SIZE) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + BLOCK_SIZE) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, outOff); + } + + return BLOCK_SIZE; + } + + public void Reset() + { + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + //================================== + // Private Implementation + //================================== + + private uint F(uint 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( + uint xl, + uint xr, + uint[] 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...) + */ + Array.Copy(KS0, 0, S0, 0, SBOX_SK); + Array.Copy(KS1, 0, S1, 0, SBOX_SK); + Array.Copy(KS2, 0, S2, 0, SBOX_SK); + Array.Copy(KS3, 0, S3, 0, SBOX_SK); + + Array.Copy(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 + uint data = 0x0000000; + for (int j=0; j < 4; j++) + { + // create a 32 bit block + data = (data << 8) | (uint)key[keyIndex++]; + + // 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) + { + uint xl = Pack.BE_To_UInt32(src, srcIndex); + uint xr = Pack.BE_To_UInt32(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]; + + Pack.UInt32_To_BE(xr, dst, dstIndex); + Pack.UInt32_To_BE(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) + { + uint xl = Pack.BE_To_UInt32(src, srcIndex); + uint xr = Pack.BE_To_UInt32(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]; + + Pack.UInt32_To_BE(xr, dst, dstIndex); + Pack.UInt32_To_BE(xl, dst, dstIndex + 4); + } + } +} diff --git a/crypto/src/crypto/engines/CamelliaEngine.cs b/crypto/src/crypto/engines/CamelliaEngine.cs new file mode 100644 index 000000000..8f4a442e9 --- /dev/null +++ b/crypto/src/crypto/engines/CamelliaEngine.cs @@ -0,0 +1,669 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Camellia - based on RFC 3713. + */ + public class CamelliaEngine + : IBlockCipher + { + private bool initialised = false; + private bool _keyIs128; + + private const int BLOCK_SIZE = 16; + + private uint[] subkey = new uint[24 * 4]; + private uint[] kw = new uint[4 * 2]; // for whitening + private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1) + private uint[] state = new uint[4]; // for encryption and decryption + + private static readonly uint[] SIGMA = new uint[]{ + 0xa09e667f, 0x3bcc908b, + 0xb67ae858, 0x4caa73b2, + 0xc6ef372f, 0xe94f82be, + 0x54ff53a5, 0xf1d36f1c, + 0x10e527fa, 0xde682d1d, + 0xb05688c2, 0xb3e6c1fd + }; + + /* + * + * S-box data + * + */ + private static readonly uint[] SBOX1_1110 = new uint[]{ + 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 readonly uint[] SBOX4_4404 = new uint[]{ + 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 readonly uint[] SBOX2_0222 = new uint[]{ + 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 readonly uint[] SBOX3_3033 = new uint[]{ + 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 uint rightRotate(uint x, int s) + { + return ((x >> s) + (x << (32 - s))); + } + + private static uint leftRotate(uint x, int s) + { + return (x << s) + (x >> (32 - s)); + } + + private static void roldq(int rot, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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 static uint bytes2uint(byte[] src, int offset) + { + uint word = 0; + for (int i = 0; i < 4; i++) + { + word = (word << 8) + (uint)src[i + offset]; + } + return word; + } + + private static void uint2bytes(uint word, byte[] dst, int offset) + { + for (int i = 0; i < 4; i++) + { + dst[(3 - i) + offset] = (byte)word; + word >>= 8; + } + } + + private static void camelliaF2(uint[] s, uint[] skey, int keyoff) + { + uint t1, t2, u, v; + + t1 = s[0] ^ skey[0 + keyoff]; + u = SBOX4_4404[(byte)t1]; + u ^= SBOX3_3033[(byte)(t1 >> 8)]; + u ^= SBOX2_0222[(byte)(t1 >> 16)]; + u ^= SBOX1_1110[(byte)(t1 >> 24)]; + t2 = s[1] ^ skey[1 + keyoff]; + v = SBOX1_1110[(byte)t2]; + v ^= SBOX4_4404[(byte)(t2 >> 8)]; + v ^= SBOX3_3033[(byte)(t2 >> 16)]; + v ^= SBOX2_0222[(byte)(t2 >> 24)]; + + s[2] ^= u ^ v; + s[3] ^= u ^ v ^ rightRotate(u, 8); + + t1 = s[2] ^ skey[2 + keyoff]; + u = SBOX4_4404[(byte)t1]; + u ^= SBOX3_3033[(byte)(t1 >> 8)]; + u ^= SBOX2_0222[(byte)(t1 >> 16)]; + u ^= SBOX1_1110[(byte)(t1 >> 24)]; + t2 = s[3] ^ skey[3 + keyoff]; + v = SBOX1_1110[(byte)t2]; + v ^= SBOX4_4404[(byte)(t2 >> 8)]; + v ^= SBOX3_3033[(byte)(t2 >> 16)]; + v ^= SBOX2_0222[(byte)(t2 >> 24)]; + + s[0] ^= u ^ v; + s[1] ^= u ^ v ^ rightRotate(u, 8); + } + + private static void camelliaFLs(uint[] s, uint[] 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(bool forEncryption, byte[] key) + { + uint[] k = new uint[8]; + uint[] ka = new uint[4]; + uint[] kb = new uint[4]; + uint[] t = new uint[4]; + + switch (key.Length) + { + case 16: + _keyIs128 = true; + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = k[5] = k[6] = k[7] = 0; + break; + case 24: + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = bytes2uint(key, 16); + k[5] = bytes2uint(key, 20); + k[6] = ~k[4]; + k[7] = ~k[5]; + _keyIs128 = false; + break; + case 32: + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = bytes2uint(key, 16); + k[5] = bytes2uint(key, 20); + k[6] = bytes2uint(key, 24); + k[7] = bytes2uint(key, 28); + _keyIs128 = false; + break; + default: + throw new ArgumentException("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[] input, int inOff, byte[] output, int outOff) + { + for (int i = 0; i < 4; i++) + { + state[i] = bytes2uint(input, 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]; + + uint2bytes(state[2], output, outOff); + uint2bytes(state[3], output, outOff + 4); + uint2bytes(state[0], output, outOff + 8); + uint2bytes(state[1], output, outOff + 12); + + return BLOCK_SIZE; + } + + private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff) + { + for (int i = 0; i < 4; i++) + { + state[i] = bytes2uint(input, 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]; + + uint2bytes(state[2], output, outOff); + uint2bytes(state[3], output, outOff + 4); + uint2bytes(state[0], output, outOff + 8); + uint2bytes(state[1], output, outOff + 12); + return BLOCK_SIZE; + } + + public CamelliaEngine() + { + } + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("only simple KeyParameter expected."); + + setKey(forEncryption, ((KeyParameter)parameters).GetKey()); + + initialised = true; + } + + public string AlgorithmName + { + get { return "Camellia"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException("Camellia engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (_keyIs128) + { + return processBlock128(input, inOff, output, outOff); + } + else + { + return processBlock192or256(input, inOff, output, outOff); + } + } + + public void Reset() + { + // nothing + } + } +} diff --git a/crypto/src/crypto/engines/CamelliaLightEngine.cs b/crypto/src/crypto/engines/CamelliaLightEngine.cs new file mode 100644 index 000000000..a301eb55e --- /dev/null +++ b/crypto/src/crypto/engines/CamelliaLightEngine.cs @@ -0,0 +1,581 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine. + */ + public class CamelliaLightEngine + : IBlockCipher + { + private const int BLOCK_SIZE = 16; +// private const int MASK8 = 0xff; + private bool initialised; + private bool _keyis128; + + private uint[] subkey = new uint[24 * 4]; + private uint[] kw = new uint[4 * 2]; // for whitening + private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1) + private uint[] state = new uint[4]; // for encryption and decryption + + private static readonly uint[] SIGMA = { + 0xa09e667f, 0x3bcc908b, + 0xb67ae858, 0x4caa73b2, + 0xc6ef372f, 0xe94f82be, + 0x54ff53a5, 0xf1d36f1c, + 0x10e527fa, 0xde682d1d, + 0xb05688c2, 0xb3e6c1fd + }; + + /* + * + * S-box data + * + */ + private static readonly 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 uint rightRotate(uint x, int s) + { + return ((x >> s) + (x << (32 - s))); + } + + private static uint leftRotate(uint x, int s) + { + return (x << s) + (x >> (32 - s)); + } + + private static void roldq(int rot, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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, uint[] ki, int ioff, uint[] 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 static uint bytes2uint(byte[] src, int offset) + { + uint word = 0; + for (int i = 0; i < 4; i++) + { + word = (word << 8) + (uint)src[i + offset]; + } + return word; + } + + private static void uint2bytes(uint 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)(((uint)v << rot) | ((uint)v >> (8 - rot))); + } + + private uint sbox2(int x) + { + return (uint)lRot8(SBOX1[x], 1); + } + + private uint sbox3(int x) + { + return (uint)lRot8(SBOX1[x], 7); + } + + private uint sbox4(int x) + { + return (uint)SBOX1[lRot8((byte)x, 1)]; + } + + private void camelliaF2(uint[] s, uint[] skey, int keyoff) + { + uint t1, t2, u, v; + + t1 = s[0] ^ skey[0 + keyoff]; + u = sbox4((byte)t1); + u |= (sbox3((byte)(t1 >> 8)) << 8); + u |= (sbox2((byte)(t1 >> 16)) << 16); + u |= ((uint)(SBOX1[(byte)(t1 >> 24)]) << 24); + + t2 = s[1] ^ skey[1 + keyoff]; + v = (uint)SBOX1[(byte)t2]; + v |= (sbox4((byte)(t2 >> 8)) << 8); + v |= (sbox3((byte)(t2 >> 16)) << 16); + v |= (sbox2((byte)(t2 >> 24)) << 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((byte)t1); + u |= sbox3((byte)(t1 >> 8)) << 8; + u |= sbox2((byte)(t1 >> 16)) << 16; + u |= ((uint)SBOX1[(byte)(t1 >> 24)]) << 24; + + t2 = s[3] ^ skey[3 + keyoff]; + v = (uint)SBOX1[(byte)t2]; + v |= sbox4((byte)(t2 >> 8)) << 8; + v |= sbox3((byte)(t2 >> 16)) << 16; + v |= sbox2((byte)(t2 >> 24)) << 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(uint[] s, uint[] 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(bool forEncryption, byte[] key) + { + uint[] k = new uint[8]; + uint[] ka = new uint[4]; + uint[] kb = new uint[4]; + uint[] t = new uint[4]; + + switch (key.Length) + { + case 16: + _keyis128 = true; + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = k[5] = k[6] = k[7] = 0; + break; + case 24: + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = bytes2uint(key, 16); + k[5] = bytes2uint(key, 20); + k[6] = ~k[4]; + k[7] = ~k[5]; + _keyis128 = false; + break; + case 32: + k[0] = bytes2uint(key, 0); + k[1] = bytes2uint(key, 4); + k[2] = bytes2uint(key, 8); + k[3] = bytes2uint(key, 12); + k[4] = bytes2uint(key, 16); + k[5] = bytes2uint(key, 20); + k[6] = bytes2uint(key, 24); + k[7] = bytes2uint(key, 28); + _keyis128 = false; + break; + default: + throw new ArgumentException("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[] input, int inOff, byte[] output, int outOff) + { + for (int i = 0; i < 4; i++) + { + state[i] = bytes2uint(input, 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]; + + uint2bytes(state[2], output, outOff); + uint2bytes(state[3], output, outOff + 4); + uint2bytes(state[0], output, outOff + 8); + uint2bytes(state[1], output, outOff + 12); + + return BLOCK_SIZE; + } + + private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff) + { + for (int i = 0; i < 4; i++) + { + state[i] = bytes2uint(input, 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]; + + uint2bytes(state[2], output, outOff); + uint2bytes(state[3], output, outOff + 4); + uint2bytes(state[0], output, outOff + 8); + uint2bytes(state[1], output, outOff + 12); + return BLOCK_SIZE; + } + + public CamelliaLightEngine() + { + initialised = false; + } + + public string AlgorithmName + { + get { return "Camellia"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("only simple KeyParameter expected."); + + setKey(forEncryption, ((KeyParameter)parameters).GetKey()); + + initialised = true; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException("Camellia engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (_keyis128) + { + return processBlock128(input, inOff, output, outOff); + } + else + { + return processBlock192or256(input, inOff, output, outOff); + } + } + + public void Reset() + { + } + } +} diff --git a/crypto/src/crypto/engines/CamelliaWrapEngine.cs b/crypto/src/crypto/engines/CamelliaWrapEngine.cs new file mode 100644 index 000000000..49dc833e6 --- /dev/null +++ b/crypto/src/crypto/engines/CamelliaWrapEngine.cs @@ -0,0 +1,16 @@ +namespace Org.BouncyCastle.Crypto.Engines +{ + /// + /// An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394. + ///

+ /// For further details see: http://www.ietf.org/rfc/rfc3657.txt. + /// + public class CamelliaWrapEngine + : Rfc3394WrapEngine + { + public CamelliaWrapEngine() + : base(new CamelliaEngine()) + { + } + } +} diff --git a/crypto/src/crypto/engines/Cast5Engine.cs b/crypto/src/crypto/engines/Cast5Engine.cs new file mode 100644 index 000000000..4c3f84a55 --- /dev/null +++ b/crypto/src/crypto/engines/Cast5Engine.cs @@ -0,0 +1,802 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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 + : IBlockCipher + { + internal static readonly uint[] 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 + //==================================== + + internal static readonly int MAX_ROUNDS = 16; + internal static readonly int RED_ROUNDS = 12; + + private const int BLOCK_SIZE = 8; // bytes = 64 bits + + private int[] _Kr = new int[17]; // the rotating round key + private uint[] _Km = new uint[17]; // the masking round key + + private bool _encrypting; + + private byte[] _workingKey; + private int _rounds = MAX_ROUNDS; + + public Cast5Engine() + { + } + + /** + * initialise a CAST cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("Invalid parameter passed to "+ AlgorithmName +" init - " + parameters.GetType().ToString()); + + _encrypting = forEncryption; + _workingKey = ((KeyParameter)parameters).GetKey(); + SetKey(_workingKey); + } + + public virtual string AlgorithmName + { + get { return "CAST5"; } + } + + public virtual bool IsPartialBlockOkay + { + get { return false; } + } + + public virtual int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + int blockSize = GetBlockSize(); + if (_workingKey == null) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + if ((inOff + blockSize) > input.Length) + throw new DataLengthException("Input buffer too short"); + if ((outOff + blockSize) > output.Length) + throw new DataLengthException("Output buffer too short"); + + if (_encrypting) + { + return EncryptBlock(input, inOff, output, outOff); + } + else + { + return DecryptBlock(input, inOff, output, outOff); + } + } + + public virtual void Reset() + { + } + + public virtual int GetBlockSize() + { + return BLOCK_SIZE; + } + + //================================== + // Private Implementation + //================================== + + /* + * Creates the subkeys using the same nomenclature + * as described in RFC2144. + * + * See section 2.4 + */ + internal virtual 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]; + + uint z03, z47, z8B, zCF; + uint x03, x47, x8B, xCF; + + /* copy the key into x */ + for (int i=0; i< key.Length; i++) + { + x[i] = (int)(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]=(int)((S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f); + _Kr[ 2]=(int)((S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f); + _Kr[ 3]=(int)((S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f); + _Kr[ 4]=(int)((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]=(int)((S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f); + _Kr[ 6]=(int)((S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f); + _Kr[ 7]=(int)((S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f); + _Kr[ 8]=(int)((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]=(int)((S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f); + _Kr[10]=(int)((S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f); + _Kr[11]=(int)((S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f); + _Kr[12]=(int)((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]=(int)((S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f); + _Kr[14]=(int)((S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f); + _Kr[15]=(int)((S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f); + _Kr[16]=(int)((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 + */ + internal virtual int EncryptBlock( + byte[] src, + int srcIndex, + byte[] dst, + int dstIndex) + { + // 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 + + uint L0 = Pack.BE_To_UInt32(src, srcIndex); + uint R0 = Pack.BE_To_UInt32(src, srcIndex + 4); + + uint[] result = new uint[2]; + CAST_Encipher(L0, R0, result); + + // now stuff them into the destination block + Pack.UInt32_To_BE(result[0], dst, dstIndex); + Pack.UInt32_To_BE(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 + */ + internal virtual int DecryptBlock( + byte[] src, + int srcIndex, + byte[] dst, + int dstIndex) + { + // 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 + uint L16 = Pack.BE_To_UInt32(src, srcIndex); + uint R16 = Pack.BE_To_UInt32(src, srcIndex + 4); + + uint[] result = new uint[2]; + CAST_Decipher(L16, R16, result); + + // now stuff them into the destination block + Pack.UInt32_To_BE(result[0], dst, dstIndex); + Pack.UInt32_To_BE(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 + * + */ + internal static uint F1(uint D, uint Kmi, int Kri) + { + uint 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 + * + */ + internal static uint F2(uint D, uint Kmi, int Kri) + { + uint 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 + * + */ + internal static uint F3(uint D, uint Kmi, int Kri) + { + uint 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 + */ + internal void CAST_Encipher(uint L0, uint R0, uint[] result) + { + uint Lp = L0; // the previous value, equiv to L[i-1] + uint Rp = R0; // equivalent to R[i-1] + + /* + * numbering consistent with paper to make + * checking and validating easier + */ + uint 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; + } + + internal void CAST_Decipher(uint L16, uint R16, uint[] result) + { + uint Lp = L16; // the previous value, equiv to L[i-1] + uint Rp = R16; // equivalent to R[i-1] + + /* + * numbering consistent with paper to make + * checking and validating easier + */ + uint 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; + } + + internal static void Bits32ToInts(uint inData, int[] b, int offset) + { + b[offset + 3] = (int) (inData & 0xff); + b[offset + 2] = (int) ((inData >> 8) & 0xff); + b[offset + 1] = (int) ((inData >> 16) & 0xff); + b[offset] = (int) ((inData >> 24) & 0xff); + } + + internal static uint IntsTo32bits(int[] b, int i) + { + return (uint)(((b[i] & 0xff) << 24) | + ((b[i+1] & 0xff) << 16) | + ((b[i+2] & 0xff) << 8) | + ((b[i+3] & 0xff))); + } + } +} diff --git a/crypto/src/crypto/engines/Cast6Engine.cs b/crypto/src/crypto/engines/Cast6Engine.cs new file mode 100644 index 000000000..c5c419b78 --- /dev/null +++ b/crypto/src/crypto/engines/Cast6Engine.cs @@ -0,0 +1,279 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace 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 sealed class Cast6Engine + : Cast5Engine + { + //==================================== + // Useful constants + //==================================== + private const int ROUNDS = 12; + private const int BLOCK_SIZE = 16; // bytes = 128 bits + + /* + * Put the round and mask keys into an array. + * Kr0[i] => _Kr[i*4 + 0] + */ + private int []_Kr = new int[ROUNDS*4]; // the rotating round key(s) + private uint []_Km = new uint[ROUNDS*4]; // the masking round key(s) + + /* + * Key setup + */ + private int []_Tr = new int[24 * 8]; + private uint []_Tm = new uint[24 * 8]; + private uint[] _workingKey = new uint[8]; + + public Cast6Engine() + { + } + + public override string AlgorithmName + { + get { return "CAST6"; } + } + + public override void Reset() + { + } + + public override int GetBlockSize() + { + return BLOCK_SIZE; + } + + //================================== + // Private Implementation + //================================== + /* + * Creates the subkeys using the same nomenclature + * as described in RFC2612. + * + * See section 2.4 + */ + internal override void SetKey( + byte[] key) + { + uint Cm = 0x5a827999; + uint 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 += Mm; //mod 2^32; + _Tr[i*8 + j] = Cr; + Cr = (Cr + Mr) & 0x1f; // mod 32 + } + } + + byte[] tmpKey = new byte[64]; + key.CopyTo(tmpKey, 0); + + // now create ABCDEFGH + for (int i = 0; i < 8; i++) + { + _workingKey[i] = Pack.BE_To_UInt32(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] = (int)(_workingKey[0] & 0x1f); + _Kr[i*4 + 1] = (int)(_workingKey[2] & 0x1f); + _Kr[i*4 + 2] = (int)(_workingKey[4] & 0x1f); + _Kr[i*4 + 3] = (int)(_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 + */ + internal override int EncryptBlock( + byte[] src, + int srcIndex, + byte[] dst, + int dstIndex) + { + // process the input block + // batch the units up into 4x32 bit chunks and go for it + uint A = Pack.BE_To_UInt32(src, srcIndex); + uint B = Pack.BE_To_UInt32(src, srcIndex + 4); + uint C = Pack.BE_To_UInt32(src, srcIndex + 8); + uint D = Pack.BE_To_UInt32(src, srcIndex + 12); + uint[] result = new uint[4]; + CAST_Encipher(A, B, C, D, result); + // now stuff them into the destination block + Pack.UInt32_To_BE(result[0], dst, dstIndex); + Pack.UInt32_To_BE(result[1], dst, dstIndex + 4); + Pack.UInt32_To_BE(result[2], dst, dstIndex + 8); + Pack.UInt32_To_BE(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 + */ + internal override int DecryptBlock( + byte[] src, + int srcIndex, + byte[] dst, + int dstIndex) + { + // process the input block + // batch the units up into 4x32 bit chunks and go for it + uint A = Pack.BE_To_UInt32(src, srcIndex); + uint B = Pack.BE_To_UInt32(src, srcIndex + 4); + uint C = Pack.BE_To_UInt32(src, srcIndex + 8); + uint D = Pack.BE_To_UInt32(src, srcIndex + 12); + uint[] result = new uint[4]; + CAST_Decipher(A, B, C, D, result); + // now stuff them into the destination block + Pack.UInt32_To_BE(result[0], dst, dstIndex); + Pack.UInt32_To_BE(result[1], dst, dstIndex + 4); + Pack.UInt32_To_BE(result[2], dst, dstIndex + 8); + Pack.UInt32_To_BE(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 + */ + private void CAST_Encipher( + uint A, + uint B, + uint C, + uint D, + uint[] result) + { + for (int i = 0; i < 6; i++) + { + int 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++) + { + int 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 + */ + private void CAST_Decipher( + uint A, + uint B, + uint C, + uint D, + uint[] result) + { + for (int i = 0; i < 6; i++) + { + int 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++) + { + int 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/crypto/src/crypto/engines/DesEdeEngine.cs b/crypto/src/crypto/engines/DesEdeEngine.cs new file mode 100644 index 000000000..eec4ec59d --- /dev/null +++ b/crypto/src/crypto/engines/DesEdeEngine.cs @@ -0,0 +1,100 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /// A class that provides a basic DESede (or Triple DES) engine. + public class DesEdeEngine + : DesEngine + { + private int[] workingKey1, workingKey2, workingKey3; + private bool forEncryption; + + /** + * initialise a DESede cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to DESede init - " + parameters.GetType().ToString()); + + byte[] keyMaster = ((KeyParameter)parameters).GetKey(); + if (keyMaster.Length != 24 && keyMaster.Length != 16) + throw new ArgumentException("key size must be 16 or 24 bytes."); + + this.forEncryption = forEncryption; + + byte[] key1 = new byte[8]; + Array.Copy(keyMaster, 0, key1, 0, key1.Length); + workingKey1 = GenerateWorkingKey(forEncryption, key1); + + byte[] key2 = new byte[8]; + Array.Copy(keyMaster, 8, key2, 0, key2.Length); + workingKey2 = GenerateWorkingKey(!forEncryption, key2); + + if (keyMaster.Length == 24) + { + byte[] key3 = new byte[8]; + Array.Copy(keyMaster, 16, key3, 0, key3.Length); + workingKey3 = GenerateWorkingKey(forEncryption, key3); + } + else // 16 byte key + { + workingKey3 = workingKey1; + } + } + + public override string AlgorithmName + { + get { return "DESede"; } + } + + public override int GetBlockSize() + { + return BLOCK_SIZE; + } + + public override int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey1 == null) + throw new InvalidOperationException("DESede engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + byte[] temp = new byte[BLOCK_SIZE]; + + if (forEncryption) + { + DesFunc(workingKey1, input, inOff, temp, 0); + DesFunc(workingKey2, temp, 0, temp, 0); + DesFunc(workingKey3, temp, 0, output, outOff); + } + else + { + DesFunc(workingKey3, input, inOff, temp, 0); + DesFunc(workingKey2, temp, 0, temp, 0); + DesFunc(workingKey1, temp, 0, output, outOff); + } + + return BLOCK_SIZE; + } + + public override void Reset() + { + } + } +} diff --git a/crypto/src/crypto/engines/DesEdeWrapEngine.cs b/crypto/src/crypto/engines/DesEdeWrapEngine.cs new file mode 100644 index 000000000..fdc71687f --- /dev/null +++ b/crypto/src/crypto/engines/DesEdeWrapEngine.cs @@ -0,0 +1,322 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Wrap keys according to + * + * draft-ietf-smime-key-wrap-01.txt. + *

+ * Note: + *

    + *
  • this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.
  • + *
  • 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.
  • + *
+ *

+ */ + public class DesEdeWrapEngine + : IWrapper + { + /** Field engine */ + private CbcBlockCipher engine; + /** Field param */ + private KeyParameter param; + /** Field paramPlusIV */ + private ParametersWithIV paramPlusIV; + /** Field iv */ + private byte[] iv; + /** Field forWrapping */ + private bool forWrapping; + /** Field IV2 */ + private static readonly byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2, + (byte) 0x2c, (byte) 0x79, (byte) 0xe8, + (byte) 0x21, (byte) 0x05 }; + + // + // checksum digest + // + private readonly IDigest sha1 = new Sha1Digest(); + private readonly byte[] digest = new byte[20]; + + /** + * Method init + * + * @param forWrapping + * @param param + */ + public void Init( + bool forWrapping, + ICipherParameters parameters) + { + this.forWrapping = forWrapping; + this.engine = new CbcBlockCipher(new DesEdeEngine()); + + SecureRandom sr; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom pr = (ParametersWithRandom) parameters; + parameters = pr.Parameters; + sr = pr.Random; + } + else + { + sr = new SecureRandom(); + } + + if (parameters is KeyParameter) + { + this.param = (KeyParameter) parameters; + 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 (parameters is ParametersWithIV) + { + if (!forWrapping) + throw new ArgumentException("You should not supply an IV for unwrapping"); + + this.paramPlusIV = (ParametersWithIV) parameters; + this.iv = this.paramPlusIV.GetIV(); + this.param = (KeyParameter) this.paramPlusIV.Parameters; + + if (this.iv.Length != 8) + throw new ArgumentException("IV is not 8 octets", "parameters"); + } + } + + /** + * Method GetAlgorithmName + * + * @return + */ + public string AlgorithmName + { + get { return "DESede"; } + } + + /** + * Method wrap + * + * @param in + * @param inOff + * @param inLen + * @return + */ + public byte[] Wrap( + byte[] input, + int inOff, + int length) + { + if (!forWrapping) + { + throw new InvalidOperationException("Not initialized for wrapping"); + } + + byte[] keyToBeWrapped = new byte[length]; + Array.Copy(input, inOff, keyToBeWrapped, 0, 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]; + Array.Copy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.Length); + Array.Copy(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 InvalidOperationException("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]; + Array.Copy(this.iv, 0, TEMP2, 0, this.iv.Length); + Array.Copy(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 + * @param inOff + * @param inLen + * @return + * @throws InvalidCipherTextException + */ + public byte[] Unwrap( + byte[] input, + int inOff, + int length) + { + if (forWrapping) + { + throw new InvalidOperationException("Not set for unwrapping"); + } + if (input == null) + { + throw new InvalidCipherTextException("Null pointer as ciphertext"); + } + + int blockSize = engine.GetBlockSize(); + + if (length % 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[length]; + + for (int currentBytePos = 0; currentBytePos != TEMP3.Length; currentBytePos += blockSize) + { + engine.ProcessBlock(input, 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]; + Array.Copy(TEMP2, 0, this.iv, 0, 8); + Array.Copy(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]; + Array.Copy(WKCKS, 0, result, 0, WKCKS.Length - 8); + Array.Copy(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. + * + * @param key + * @return + * @throws Exception + * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + */ + private byte[] CalculateCmsKeyChecksum( + byte[] key) + { + sha1.BlockUpdate(key, 0, key.Length); + sha1.DoFinal(digest, 0); + + byte[] result = new byte[8]; + Array.Copy(digest, 0, result, 0, 8); + return result; + } + + /** + * @param key + * @param checksum + * @return + * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + */ + private bool 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/crypto/src/crypto/engines/DesEngine.cs b/crypto/src/crypto/engines/DesEngine.cs new file mode 100644 index 000000000..067cf45e3 --- /dev/null +++ b/crypto/src/crypto/engines/DesEngine.cs @@ -0,0 +1,475 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /// A class that provides a basic DES engine. + public class DesEngine + : IBlockCipher + { + internal const int BLOCK_SIZE = 8; + + private int[] workingKey; + + public virtual int[] GetWorkingKey() + { + return workingKey; + } + + /** + * initialise a DES cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public virtual void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to DES init - " + parameters.GetType().ToString()); + + workingKey = GenerateWorkingKey(forEncryption, ((KeyParameter)parameters).GetKey()); + } + + public virtual string AlgorithmName + { + get { return "DES"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public virtual int GetBlockSize() + { + return BLOCK_SIZE; + } + + public virtual int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + throw new InvalidOperationException("DES engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + DesFunc(workingKey, input, inOff, output, outOff); + + return BLOCK_SIZE; + } + + public virtual 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 readonly 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 readonly short[] bytebit = + { + 128, 64, 32, 16, 8, 4, 2, 1 + }; + + private static readonly 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 readonly 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 readonly byte[] totrot = + { + 1, 2, 4, 6, 8, 10, 12, 14, + 15, 17, 19, 21, 23, 25, 27, 28 + }; + + private static readonly 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 and Phil Karn. + * (whoever, and wherever they are!). + */ + protected static int[] GenerateWorkingKey( + bool encrypting, + byte[] key) + { + int[] newKey = new int[32]; + bool[] pc1m = new bool[56]; + bool[] pcr = new bool[56]; + + for (int j = 0; j < 56; j++ ) + { + int l = pc1[j]; + + pc1m[j] = ((key[(uint) 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] = (int) ( (uint) ((i1 & 0x00fc0000) << 6) | + (uint) ((i1 & 0x00000fc0) << 10) | + ((uint) (i2 & 0x00fc0000) >> 10) | + ((uint) (i2 & 0x00000fc0) >> 6)); + + newKey[i + 1] = (int) ( (uint) ((i1 & 0x0003f000) << 12) | + (uint) ((i1 & 0x0000003f) << 16) | + ((uint) (i2 & 0x0003f000) >> 4) | + (uint) (i2 & 0x0000003f)); + } + + return newKey; + } + + /** + * the DES engine. + */ + internal static void DesFunc( + int[] wKey, + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + uint left = Pack.BE_To_UInt32(input, inOff); + uint right = Pack.BE_To_UInt32(input, inOff + 4); + uint work; + + 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); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + for (int round = 0; round < 8; round++) + { + uint fval; + + work = (right << 28) | (right >> 4); + work ^= (uint)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 ^ (uint)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 ^= (uint)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 ^ (uint)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); + + Pack.UInt32_To_BE(right, outBytes, outOff); + Pack.UInt32_To_BE(left, outBytes, outOff + 4); + } + } +} diff --git a/crypto/src/crypto/engines/ElGamalEngine.cs b/crypto/src/crypto/engines/ElGamalEngine.cs new file mode 100644 index 000000000..3d256a087 --- /dev/null +++ b/crypto/src/crypto/engines/ElGamalEngine.cs @@ -0,0 +1,178 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * this does your basic ElGamal algorithm. + */ + public class ElGamalEngine + : IAsymmetricBlockCipher + { + private ElGamalKeyParameters key; + private SecureRandom random; + private bool forEncryption; + private int bitSize; + + public string AlgorithmName + { + get { return "ElGamal"; } + } + + /** + * initialise the ElGamal engine. + * + * @param forEncryption true if we are encrypting, false otherwise. + * @param param the necessary ElGamal key parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom p = (ParametersWithRandom) parameters; + + this.key = (ElGamalKeyParameters) p.Parameters; + this.random = p.Random; + } + else + { + this.key = (ElGamalKeyParameters) parameters; + this.random = new SecureRandom(); + } + + this.forEncryption = forEncryption; + this.bitSize = key.Parameters.P.BitLength; + + if (forEncryption) + { + if (!(key is ElGamalPublicKeyParameters)) + { + throw new ArgumentException("ElGamalPublicKeyParameters are required for encryption."); + } + } + else + { + if (!(key is ElGamalPrivateKeyParameters)) + { + throw new ArgumentException("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 length 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[] input, + int inOff, + int length) + { + if (key == null) + throw new InvalidOperationException("ElGamal engine not initialised"); + + int maxLength = forEncryption + ? (bitSize - 1 + 7) / 8 + : GetInputBlockSize(); + + if (length > maxLength) + throw new DataLengthException("input too large for ElGamal cipher.\n"); + + BigInteger p = key.Parameters.P; + + byte[] output; + if (key is ElGamalPrivateKeyParameters) // decryption + { + int halfLength = length / 2; + BigInteger gamma = new BigInteger(1, input, inOff, halfLength); + BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength); + + 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(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p); + + output = m.ToByteArrayUnsigned(); + } + else // encryption + { + BigInteger tmp = new BigInteger(1, input, inOff, length); + + if (tmp.BitLength >= p.BitLength) + throw new DataLengthException("input too large for ElGamal cipher.\n"); + + + ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key; + + BigInteger pSub2 = p.Subtract(BigInteger.Two); + + // TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated + BigInteger k; + do + { + k = new BigInteger(p.BitLength, random); + } + while (k.SignValue == 0 || k.CompareTo(pSub2) > 0); + + BigInteger g = key.Parameters.G; + BigInteger gamma = g.ModPow(k, p); + BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p); + + output = new byte[this.GetOutputBlockSize()]; + + // TODO Add methods to allow writing BigInteger to existing byte array? + byte[] out1 = gamma.ToByteArrayUnsigned(); + byte[] out2 = phi.ToByteArrayUnsigned(); + out1.CopyTo(output, output.Length / 2 - out1.Length); + out2.CopyTo(output, output.Length - out2.Length); + } + + return output; + } + } +} diff --git a/crypto/src/crypto/engines/GOST28147Engine.cs b/crypto/src/crypto/engines/GOST28147Engine.cs new file mode 100644 index 000000000..8eb6f36b5 --- /dev/null +++ b/crypto/src/crypto/engines/GOST28147Engine.cs @@ -0,0 +1,376 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * implementation of GOST 28147-89 + */ + public class Gost28147Engine + : IBlockCipher + { + private const int BlockSize = 8; + private int[] workingKey = null; + private bool 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 readonly 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 readonly 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 readonly 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 readonly 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 readonly 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 readonly 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 readonly 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 readonly 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 readonly IDictionary sBoxes = Platform.CreateHashtable(); + + static Gost28147Engine() + { + 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.Add(Platform.ToUpperInvariant(sBoxName), sBox); + } + + /** + * standard constructor. + */ + public Gost28147Engine() + { + } + + /** + * initialise an Gost28147 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithSBox) + { + ParametersWithSBox param = (ParametersWithSBox)parameters; + + // + // Set the S-Box + // + byte[] sBox = param.GetSBox(); + if (sBox.Length != Sbox_Default.Length) + throw new ArgumentException("invalid S-box passed to GOST28147 init"); + + this.S = Arrays.Clone(sBox); + + // + // set key if there is one + // + if (param.Parameters != null) + { + workingKey = generateWorkingKey(forEncryption, + ((KeyParameter)param.Parameters).GetKey()); + } + } + else if (parameters is KeyParameter) + { + workingKey = generateWorkingKey(forEncryption, + ((KeyParameter)parameters).GetKey()); + } + else if (parameters != null) + { + throw new ArgumentException("invalid parameter passed to Gost28147 init - " + parameters.GetType().Name); + } + } + + public string AlgorithmName + { + get { return "Gost28147"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BlockSize; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + { + throw new InvalidOperationException("Gost28147 engine not initialised"); + } + + if ((inOff + BlockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + BlockSize) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + Gost28147Func(workingKey, input, inOff, output, outOff); + + return BlockSize; + } + + public void Reset() + { + } + + private int[] generateWorkingKey( + bool forEncryption, + byte[] userKey) + { + this.forEncryption = forEncryption; + + if (userKey.Length != 32) + { + throw new ArgumentException("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 + int omLeft = om << 11; + int omRight = (int)(((uint) om) >> (32 - 11)); // Note: Casts required to get unsigned bit rotation + + return omLeft | omRight; + } + + private void Gost28147Func( + int[] workingKey, + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + int N1, N2, tmp; //tmp -> for saving N1 + N1 = bytesToint(inBytes, inOff); + N2 = bytesToint(inBytes, inOff + 4); + + if (this.forEncryption) + { + for(int k = 0; k < 3; k++) // 1-24 steps + { + for(int j = 0; j < 8; j++) + { + tmp = N1; + int step = Gost28147_mainStep(N1, workingKey[j]); + N1 = N2 ^ step; // 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, outBytes, outOff); + intTobytes(N2, outBytes, outOff + 4); + } + + //array of bytes to type int + private static int bytesToint( + byte[] inBytes, + int inOff) + { + return (int)((inBytes[inOff + 3] << 24) & 0xff000000) + ((inBytes[inOff + 2] << 16) & 0xff0000) + + ((inBytes[inOff + 1] << 8) & 0xff00) + (inBytes[inOff] & 0xff); + } + + //int to array of bytes + private static void intTobytes( + int num, + byte[] outBytes, + int outOff) + { + outBytes[outOff + 3] = (byte)(num >> 24); + outBytes[outOff + 2] = (byte)(num >> 16); + outBytes[outOff + 1] = (byte)(num >> 8); + outBytes[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[Platform.ToUpperInvariant(sBoxName)]; + + if (sBox == null) + { + throw new ArgumentException("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/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs new file mode 100644 index 000000000..a2d099f87 --- /dev/null +++ b/crypto/src/crypto/engines/HC128Engine.cs @@ -0,0 +1,235 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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. + *

+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf + *

+ * 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 + *

+ */ + public class HC128Engine + : IStreamCipher + { + private uint[] p = new uint[512]; + private uint[] q = new uint[512]; + private uint cnt = 0; + + private static uint F1(uint x) + { + return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3); + } + + private static uint F2(uint x) + { + return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10); + } + + private uint G1(uint x, uint y, uint z) + { + return (RotateRight(x, 10) ^ RotateRight(z, 23)) + RotateRight(y, 8); + } + + private uint G2(uint x, uint y, uint z) + { + return (RotateLeft(x, 10) ^ RotateLeft(z, 23)) + RotateLeft(y, 8); + } + + private static uint RotateLeft(uint x, int bits) + { + return (x << bits) | (x >> -bits); + } + + private static uint RotateRight(uint x, int bits) + { + return (x >> bits) | (x << -bits); + } + + private uint H1(uint x) + { + return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256]; + } + + private uint H2(uint x) + { + return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256]; + } + + private static uint Mod1024(uint x) + { + return x & 0x3FF; + } + + private static uint Mod512(uint x) + { + return x & 0x1FF; + } + + private static uint Dim(uint x, uint y) + { + return Mod512(x - y); + } + + private uint Step() + { + uint j = Mod512(cnt); + uint 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 bool initialised; + + private void Init() + { + if (key.Length != 16) + throw new ArgumentException("The key must be 128 bits long"); + + cnt = 0; + + uint[] w = new uint[1280]; + + for (int i = 0; i < 16; i++) + { + w[i >> 2] |= ((uint)key[i] << (8 * (i & 0x3))); + } + Array.Copy(w, 0, w, 4, 4); + + for (int i = 0; i < iv.Length && i < 16; i++) + { + w[(i >> 2) + 8] |= ((uint)iv[i] << (8 * (i & 0x3))); + } + Array.Copy(w, 8, w, 12, 4); + + for (uint i = 16; i < 1280; i++) + { + w[i] = F2(w[i - 2]) + w[i - 7] + F1(w[i - 15]) + w[i - 16] + i; + } + + Array.Copy(w, 256, p, 0, 512); + Array.Copy(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 AlgorithmName + { + get { 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 ArgumentException if the params argument is + * inappropriate (ie. the key is not 128 bit long). + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + ICipherParameters keyParam = parameters; + + if (parameters is ParametersWithIV) + { + iv = ((ParametersWithIV)parameters).GetIV(); + keyParam = ((ParametersWithIV)parameters).Parameters; + } + else + { + iv = new byte[0]; + } + + if (keyParam is KeyParameter) + { + key = ((KeyParameter)keyParam).GetKey(); + Init(); + } + else + { + throw new ArgumentException( + "Invalid parameter passed to HC128 init - " + parameters.GetType().Name, + "parameters"); + } + + initialised = true; + } + + private byte[] buf = new byte[4]; + private int idx = 0; + + private byte GetByte() + { + if (idx == 0) + { + Pack.UInt32_To_LE(Step(), buf); + } + byte ret = buf[idx]; + idx = idx + 1 & 0x3; + return ret; + } + + public void ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + if ((inOff + len) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + len) > output.Length) + throw new DataLengthException("output buffer too short"); + + for (int i = 0; i < len; i++) + { + output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); + } + } + + public void Reset() + { + idx = 0; + Init(); + } + + public byte ReturnByte(byte input) + { + return (byte)(input ^ GetByte()); + } + } +} diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs new file mode 100644 index 000000000..da717dab7 --- /dev/null +++ b/crypto/src/crypto/engines/HC256Engine.cs @@ -0,0 +1,224 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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. + *

+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf + *

+ * 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 + *

+ */ + public class HC256Engine + : IStreamCipher + { + private uint[] p = new uint[1024]; + private uint[] q = new uint[1024]; + private uint cnt = 0; + + private uint Step() + { + uint j = cnt & 0x3FF; + uint ret; + if (cnt < 1024) + { + uint x = p[(j - 3 & 0x3FF)]; + uint 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 + { + uint x = q[(j - 3 & 0x3FF)]; + uint 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 bool initialised; + + private void Init() + { + if (key.Length != 32 && key.Length != 16) + throw new ArgumentException("The key must be 128/256 bits long"); + + if (iv.Length < 16) + throw new ArgumentException("The IV must be at least 128 bits long"); + + if (key.Length != 32) + { + byte[] k = new byte[32]; + + Array.Copy(key, 0, k, 0, key.Length); + Array.Copy(key, 0, k, 16, key.Length); + + key = k; + } + + if (iv.Length < 32) + { + byte[] newIV = new byte[32]; + + Array.Copy(iv, 0, newIV, 0, iv.Length); + Array.Copy(iv, 0, newIV, iv.Length, newIV.Length - iv.Length); + + iv = newIV; + } + + cnt = 0; + + uint[] w = new uint[2560]; + + for (int i = 0; i < 32; i++) + { + w[i >> 2] |= ((uint)key[i] << (8 * (i & 0x3))); + } + + for (int i = 0; i < 32; i++) + { + w[(i >> 2) + 8] |= ((uint)iv[i] << (8 * (i & 0x3))); + } + + for (uint i = 16; i < 2560; i++) + { + uint x = w[i - 2]; + uint 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; + } + + Array.Copy(w, 512, p, 0, 1024); + Array.Copy(w, 1536, q, 0, 1024); + + for (int i = 0; i < 4096; i++) + { + Step(); + } + + cnt = 0; + } + + public string AlgorithmName + { + get { 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 ArgumentException if the params argument is + * inappropriate (ie. the key is not 256 bit long). + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + ICipherParameters keyParam = parameters; + + if (parameters is ParametersWithIV) + { + iv = ((ParametersWithIV)parameters).GetIV(); + keyParam = ((ParametersWithIV)parameters).Parameters; + } + else + { + iv = new byte[0]; + } + + if (keyParam is KeyParameter) + { + key = ((KeyParameter)keyParam).GetKey(); + Init(); + } + else + { + throw new ArgumentException( + "Invalid parameter passed to HC256 init - " + parameters.GetType().Name, + "parameters"); + } + + initialised = true; + } + + private byte[] buf = new byte[4]; + private int idx = 0; + + private byte GetByte() + { + if (idx == 0) + { + Pack.UInt32_To_LE(Step(), buf); + } + byte ret = buf[idx]; + idx = idx + 1 & 0x3; + return ret; + } + + public void ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + if ((inOff + len) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + len) > output.Length) + throw new DataLengthException("output buffer too short"); + + for (int i = 0; i < len; i++) + { + output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); + } + } + + public void Reset() + { + idx = 0; + Init(); + } + + public byte ReturnByte(byte input) + { + return (byte)(input ^ GetByte()); + } + + private static uint RotateRight(uint x, int bits) + { + return (x >> bits) | (x << -bits); + } + } +} diff --git a/crypto/src/crypto/engines/ISAACEngine.cs b/crypto/src/crypto/engines/ISAACEngine.cs new file mode 100644 index 000000000..9c58678a0 --- /dev/null +++ b/crypto/src/crypto/engines/ISAACEngine.cs @@ -0,0 +1,212 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count). + * see: http://www.burtleburtle.net/bob/rand/isaacafa.html + */ + public class IsaacEngine + : IStreamCipher + { + // Constants + private static readonly int sizeL = 8, + stateArraySize = sizeL<<5; // 256 + + // Cipher's internal state + private uint[] engineState = null, // mm + results = null; // randrsl + private uint 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 bool 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 ArgumentException if the params argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException( + "invalid parameter passed to ISAAC Init - " + parameters.GetType().Name, + "parameters"); + + /* + * ISAAC encryption and decryption is completely + * symmetrical, so the 'forEncryption' is + * irrelevant. + */ + KeyParameter p = (KeyParameter) parameters; + setKey(p.GetKey()); + } + + public byte ReturnByte( + byte input) + { + if (index == 0) + { + isaac(); + keyStream = Pack.UInt32_To_BE(results); + } + + byte output = (byte)(keyStream[index]^input); + index = (index + 1) & 1023; + + return output; + } + + public void ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + if ((inOff + len) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + len) > output.Length) + throw new DataLengthException("output buffer too short"); + + for (int i = 0; i < len; i++) + { + if (index == 0) + { + isaac(); + keyStream = Pack.UInt32_To_BE(results); + } + output[i+outOff] = (byte)(keyStream[index]^input[i+inOff]); + index = (index + 1) & 1023; + } + } + + public string AlgorithmName + { + get { return "ISAAC"; } + } + + public void Reset() + { + setKey(workingKey); + } + + // Private implementation + private void setKey( + byte[] keyBytes) + { + workingKey = keyBytes; + + if (engineState == null) + { + engineState = new uint[stateArraySize]; + } + + if (results == null) + { + results = new uint[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)]; + Array.Copy(keyBytes, 0, t, 0, keyBytes.Length); + for (i = 0; i < t.Length; i+=4) + { + results[i >> 2] = Pack.LE_To_UInt32(t, i); + } + + // It has begun? + uint[] abcdefgh = new uint[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() + { + uint x, y; + + b += ++c; + for (int 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[(int)((uint)x >> 2) & 0xFF] + a + b; + results[i] = b = engineState[(int)((uint)y >> 10) & 0xFF] + x; + } + } + + private void mix(uint[] 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/crypto/src/crypto/engines/IdeaEngine.cs b/crypto/src/crypto/engines/IdeaEngine.cs new file mode 100644 index 000000000..f763c5939 --- /dev/null +++ b/crypto/src/crypto/engines/IdeaEngine.cs @@ -0,0 +1,341 @@ +#if INCLUDE_IDEA + +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * A class that provides a basic International Data Encryption Algorithm (IDEA) engine. + *

+ * This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM" + * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (baring 1 typo at the + * end of the mulinv function!). + *

+ *

+ * It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/ + *

+ *

+ * Note 1: This algorithm is patented in the USA, Japan, and Europe including + * at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland + * and the United Kingdom. Non-commercial use is free, however any commercial + * products are liable for royalties. Please see + * www.mediacrypt.com for + * further details. This announcement has been included at the request of + * the patent holders. + *

+ *

+ * Note 2: Due to the requests concerning the above, this algorithm is now only + * included in the extended assembly. It is not included in the default distributions. + *

+ */ + public class IdeaEngine + : IBlockCipher + { + private const int BLOCK_SIZE = 8; + private int[] workingKey; + /** + * standard constructor. + */ + public IdeaEngine() + { + } + /** + * initialise an IDEA cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to IDEA init - " + parameters.GetType().ToString()); + + workingKey = GenerateWorkingKey(forEncryption, + ((KeyParameter)parameters).GetKey()); + } + + public string AlgorithmName + { + get { return "IDEA"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + { + throw new InvalidOperationException("IDEA engine not initialised"); + } + if ((inOff + BLOCK_SIZE) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + if ((outOff + BLOCK_SIZE) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + IdeaFunc(workingKey, input, inOff, output, outOff); + return BLOCK_SIZE; + } + public void Reset() + { + } + private static readonly int MASK = 0xffff; + private static readonly int BASE = 0x10001; + private int BytesToWord( + byte[] input, + int inOff) + { + return ((input[inOff] << 8) & 0xff00) + (input[inOff + 1] & 0xff); + } + private void WordToBytes( + int word, + byte[] outBytes, + int outOff) + { + outBytes[outOff] = (byte)((uint) word >> 8); + outBytes[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 = (int) ((uint) p >> 16); + x = y - x + ((y < x) ? 1 : 0); + } + return x & MASK; + } + private void IdeaFunc( + int[] workingKey, + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int x0, x1, x2, x3, t0, t1; + int keyOff = 0; + x0 = BytesToWord(input, inOff); + x1 = BytesToWord(input, inOff + 2); + x2 = BytesToWord(input, inOff + 4); + x3 = BytesToWord(input, 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++]), outBytes, outOff); + WordToBytes(x2 + workingKey[keyOff++], outBytes, outOff + 2); /* NB: Order */ + WordToBytes(x1 + workingKey[keyOff++], outBytes, outOff + 4); + WordToBytes(Mul(x3, workingKey[keyOff]), outBytes, 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]; + Array.Copy(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. + *

+ * 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. + *

+ * 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( + bool forEncryption, + byte[] userKey) + { + if (forEncryption) + { + return ExpandKey(userKey); + } + else + { + return InvertKey(ExpandKey(userKey)); + } + } + } +} + +#endif diff --git a/crypto/src/crypto/engines/IesEngine.cs b/crypto/src/crypto/engines/IesEngine.cs new file mode 100644 index 000000000..6520c86f8 --- /dev/null +++ b/crypto/src/crypto/engines/IesEngine.cs @@ -0,0 +1,233 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * support class for constructing intergrated encryption ciphers + * for doing basic message exchanges on top of key agreement ciphers + */ + public class IesEngine + { + private readonly IBasicAgreement agree; + private readonly IDerivationFunction kdf; + private readonly IMac mac; + private readonly BufferedBlockCipher cipher; + private readonly byte[] macBuf; + + private bool forEncryption; + private ICipherParameters privParam, pubParam; + private IesParameters param; + + /** + * 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( + IBasicAgreement agree, + IDerivationFunction kdf, + IMac 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( + IBasicAgreement agree, + IDerivationFunction kdf, + IMac 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 param encoding and derivation parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters privParameters, + ICipherParameters pubParameters, + ICipherParameters iesParameters) + { + this.forEncryption = forEncryption; + this.privParam = privParameters; + this.pubParam = pubParameters; + this.param = (IesParameters)iesParameters; + } + + private byte[] DecryptBlock( + byte[] in_enc, + int inOff, + int inLen, + byte[] z) + { + byte[] M = null; + KeyParameter macKey = null; + KdfParameters kParam = new KdfParameters(z, param.GetDerivationV()); + int macKeySize = param.MacKeySize; + + kdf.Init(kParam); + + inLen -= mac.GetMacSize(); + + if (cipher == null) // stream mode + { + byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8)); + + M = new byte[inLen]; + + for (int i = 0; i != inLen; i++) + { + M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]); + } + + macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8)); + } + else + { + int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize; + byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8)); + + cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8))); + + M = cipher.DoFinal(in_enc, inOff, inLen); + + macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8)); + } + + byte[] macIV = param.GetEncodingV(); + + mac.Init(macKey); + mac.BlockUpdate(in_enc, inOff, inLen); + mac.BlockUpdate(macIV, 0, macIV.Length); + mac.DoFinal(macBuf, 0); + + inOff += inLen; + + byte[] T1 = Arrays.Copy(in_enc, inOff, macBuf.Length); + + if (!Arrays.ConstantTimeAreEqual(T1, macBuf)) + throw (new InvalidCipherTextException("Invalid MAC.")); + + return M; + } + + private byte[] EncryptBlock( + byte[] input, + int inOff, + int inLen, + byte[] z) + { + byte[] C = null; + KeyParameter macKey = null; + KdfParameters kParam = new KdfParameters(z, param.GetDerivationV()); + int c_text_length = 0; + int macKeySize = param.MacKeySize; + + if (cipher == null) // stream mode + { + byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8)); + + C = new byte[inLen + mac.GetMacSize()]; + c_text_length = inLen; + + for (int i = 0; i != inLen; i++) + { + C[i] = (byte)(input[inOff + i] ^ Buffer[i]); + } + + macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8)); + } + else + { + int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize; + byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8)); + + cipher.Init(true, new KeyParameter(Buffer, 0, (cipherKeySize / 8))); + + c_text_length = cipher.GetOutputSize(inLen); + byte[] tmp = new byte[c_text_length]; + + int len = cipher.ProcessBytes(input, inOff, inLen, tmp, 0); + len += cipher.DoFinal(tmp, len); + + C = new byte[len + mac.GetMacSize()]; + c_text_length = len; + + Array.Copy(tmp, 0, C, 0, len); + + macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8)); + } + + byte[] macIV = param.GetEncodingV(); + + mac.Init(macKey); + mac.BlockUpdate(C, 0, c_text_length); + mac.BlockUpdate(macIV, 0, macIV.Length); + // + // return the message and it's MAC + // + mac.DoFinal(C, c_text_length); + return C; + } + + private byte[] GenerateKdfBytes( + KdfParameters kParam, + int length) + { + byte[] buf = new byte[length]; + + kdf.Init(kParam); + + kdf.GenerateBytes(buf, 0, buf.Length); + + return buf; + } + + public byte[] ProcessBlock( + byte[] input, + int inOff, + int inLen) + { + agree.Init(privParam); + + BigInteger z = agree.CalculateAgreement(pubParam); + + byte[] zBytes = BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z); + + return forEncryption + ? EncryptBlock(input, inOff, inLen, zBytes) + : DecryptBlock(input, inOff, inLen, zBytes); + } + } + +} diff --git a/crypto/src/crypto/engines/NaccacheSternEngine.cs b/crypto/src/crypto/engines/NaccacheSternEngine.cs new file mode 100644 index 000000000..9ca092351 --- /dev/null +++ b/crypto/src/crypto/engines/NaccacheSternEngine.cs @@ -0,0 +1,432 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * NaccacheStern Engine. For details on this cipher, please see + * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf + */ + public class NaccacheSternEngine + : IAsymmetricBlockCipher + { + private bool forEncryption; + + private NaccacheSternKeyParameters key; + + private IList[] lookup = null; + + private bool debug = false; + + public string AlgorithmName + { + get { return "NaccacheStern"; } + } + + /** + * Initializes this algorithm. Must be called before all other Functions. + * + * @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool, + * org.bouncycastle.crypto.CipherParameters) + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + key = (NaccacheSternKeyParameters)parameters; + + // construct lookup table for faster decryption if necessary + if (!this.forEncryption) + { + if (debug) + { + Console.WriteLine("Constructing lookup Array"); + } + NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key; + IList primes = priv.SmallPrimesList; + lookup = new IList[primes.Count]; + for (int i = 0; i < primes.Count; i++) + { + BigInteger actualPrime = (BigInteger) primes[i]; + int actualPrimeValue = actualPrime.IntValue; + + lookup[i] = Platform.CreateArrayList(actualPrimeValue); + lookup[i].Add(BigInteger.One); + + if (debug) + { + Console.WriteLine("Constructing lookup ArrayList for " + actualPrimeValue); + } + + BigInteger accJ = BigInteger.Zero; + + for (int j = 1; j < actualPrimeValue; j++) + { +// BigInteger bigJ = BigInteger.ValueOf(j); +// accJ = priv.PhiN.Multiply(bigJ); + accJ = accJ.Add(priv.PhiN); + BigInteger comp = accJ.Divide(actualPrime); + lookup[i].Add(priv.G.ModPow(comp, priv.Modulus)); + } + } + } + } + + public bool Debug + { + set { this.debug = value; } + } + + /** + * 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.LowerSigmaBound + 7) / 8 - 1; + } + else + { + // We pad to modulus-size bytes for easier decryption. +// return key.Modulus.ToByteArray().Length; + return key.Modulus.BitLength / 8 + 1; + } + } + + /** + * 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.Modulus.ToByteArray().Length; + return key.Modulus.BitLength / 8 + 1; + } + else + { + // decrypted Data has upper limit lowerSigmaBound + return (key.LowerSigmaBound + 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[] inBytes, + int inOff, + int length) + { + if (key == null) + throw new InvalidOperationException("NaccacheStern engine not initialised"); + if (length > (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 (length < GetInputBlockSize()) + { + throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n"); + } + } + + // transform input into BigInteger + BigInteger input = new BigInteger(1, inBytes, inOff, length); + + if (debug) + { + Console.WriteLine("input as BigInteger: " + input); + } + + byte[] output; + if (forEncryption) + { + output = Encrypt(input); + } + else + { + IList plain = Platform.CreateArrayList(); + NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key; + IList primes = priv.SmallPrimesList; + // Get Chinese Remainders of CipherText + for (int i = 0; i < primes.Count; i++) + { + BigInteger exp = input.ModPow(priv.PhiN.Divide((BigInteger)primes[i]), priv.Modulus); + IList al = lookup[i]; + if (lookup[i].Count != ((BigInteger)primes[i]).IntValue) + { + if (debug) + { + Console.WriteLine("Prime is " + primes[i] + ", lookup table has size " + al.Count); + } + throw new InvalidCipherTextException("Error in lookup Array for " + + ((BigInteger)primes[i]).IntValue + + ": Size mismatch. Expected ArrayList with length " + + ((BigInteger)primes[i]).IntValue + " but found ArrayList of length " + + lookup[i].Count); + } + int lookedup = al.IndexOf(exp); + + if (lookedup == -1) + { + if (debug) + { + Console.WriteLine("Actual prime is " + primes[i]); + Console.WriteLine("Decrypted value is " + exp); + + Console.WriteLine("LookupList for " + primes[i] + " with size " + lookup[i].Count + + " is: "); + for (int j = 0; j < lookup[i].Count; j++) + { + Console.WriteLine(lookup[i][j]); + } + } + throw new InvalidCipherTextException("Lookup failed"); + } + plain.Add(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) { + // Console.WriteLine("Decryption is " + test); + // } + // if ((key.G.ModPow(test, key.Modulus)).Equals(input)) { + // output = test.ToByteArray(); + // } else { + // if(debug){ + // Console.WriteLine("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.Modulus.ToByteArray(); +// Array.Clear(output, 0, output.Length); + byte[] output = new byte[key.Modulus.BitLength / 8 + 1]; + + byte[] tmp = key.G.ModPow(plain, key.Modulus).ToByteArray(); + Array.Copy(tmp, 0, output, output.Length - tmp.Length, tmp.Length); + if (debug) + { + Console.WriteLine("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) + { + // 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.Modulus); + if (debug) + { + Console.WriteLine("c(m1) as BigInteger:....... " + m1Crypt); + Console.WriteLine("c(m2) as BigInteger:....... " + m2Crypt); + Console.WriteLine("c(m1)*c(m2)%n = c(m1+m2)%n: " + m1m2Crypt); + } + + //byte[] output = key.Modulus.ToByteArray(); + //Array.Clear(output, 0, output.Length); + byte[] output = new byte[key.Modulus.BitLength / 8 + 1]; + + byte[] m1m2CryptBytes = m1m2Crypt.ToByteArray(); + Array.Copy(m1m2CryptBytes, 0, output, + output.Length - m1m2CryptBytes.Length, m1m2CryptBytes.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) + { + if (debug) + { + Console.WriteLine(); + } + if (data.Length > GetInputBlockSize()) + { + int inBlocksize = GetInputBlockSize(); + int outBlocksize = GetOutputBlockSize(); + if (debug) + { + Console.WriteLine("Input blocksize is: " + inBlocksize + " bytes"); + Console.WriteLine("Output blocksize is: " + outBlocksize + " bytes"); + Console.WriteLine("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) + { + Console.WriteLine("new datapos is " + datapos); + } + if (tmp != null) + { + tmp.CopyTo(retval, retpos); + retpos += tmp.Length; + } + else + { + if (debug) + { + Console.WriteLine("cipher returned null"); + } + throw new InvalidCipherTextException("cipher returned null"); + } + } + byte[] ret = new byte[retpos]; + Array.Copy(retval, 0, ret, 0, retpos); + if (debug) + { + Console.WriteLine("returning " + ret.Length + " bytes"); + } + return ret; + } + else + { + if (debug) + { + Console.WriteLine("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(IList congruences, IList primes) + { + BigInteger retval = BigInteger.Zero; + BigInteger all = BigInteger.One; + for (int i = 0; i < primes.Count; i++) + { + all = all.Multiply((BigInteger)primes[i]); + } + for (int i = 0; i < primes.Count; i++) + { + BigInteger a = (BigInteger)primes[i]; + BigInteger b = all.Divide(a); + BigInteger b2 = b.ModInverse(a); + BigInteger tmp = b.Multiply(b2); + tmp = tmp.Multiply((BigInteger)congruences[i]); + retval = retval.Add(tmp); + } + + return retval.Mod(all); + } + } +} diff --git a/crypto/src/crypto/engines/NoekeonEngine.cs b/crypto/src/crypto/engines/NoekeonEngine.cs new file mode 100644 index 000000000..b73e696a9 --- /dev/null +++ b/crypto/src/crypto/engines/NoekeonEngine.cs @@ -0,0 +1,240 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * A Noekeon engine, using direct-key mode. + */ + public class NoekeonEngine + : IBlockCipher + { + private const int GenericSize = 16; // Block and key size, as well as the amount of rounds. + + private static readonly uint[] nullVector = + { + 0x00, 0x00, 0x00, 0x00 // Used in decryption + }; + + private static readonly uint[] roundConstants = + { + 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, + 0xd4 + }; + + private uint[] state = new uint[4], // a + subKeys = new uint[4], // k + decryptKeys = new uint[4]; + + private bool _initialised, _forEncryption; + + /** + * Create an instance of the Noekeon encryption algorithm + * and set some defaults + */ + public NoekeonEngine() + { + _initialised = false; + } + + public string AlgorithmName + { + get { return "Noekeon"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + 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 ArgumentException if the params argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("Invalid parameters passed to Noekeon init - " + parameters.GetType().Name, "parameters"); + + _forEncryption = forEncryption; + _initialised = true; + + KeyParameter p = (KeyParameter) parameters; + + setKey(p.GetKey()); + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (!_initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + if ((inOff + GenericSize) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + GenericSize) > output.Length) + throw new DataLengthException("output buffer too short"); + + return _forEncryption + ? encryptBlock(input, inOff, output, outOff) + : decryptBlock(input, inOff, output, outOff); + } + + public void Reset() + { + // TODO This should do something in case the encryption is aborted + } + + /** + * Re-key the cipher. + * + * @param key the key to be used + */ + private void setKey(byte[] key) + { + subKeys[0] = Pack.BE_To_UInt32(key, 0); + subKeys[1] = Pack.BE_To_UInt32(key, 4); + subKeys[2] = Pack.BE_To_UInt32(key, 8); + subKeys[3] = Pack.BE_To_UInt32(key, 12); + } + + private int encryptBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + state[0] = Pack.BE_To_UInt32(input, inOff); + state[1] = Pack.BE_To_UInt32(input, inOff+4); + state[2] = Pack.BE_To_UInt32(input, inOff+8); + state[3] = Pack.BE_To_UInt32(input, 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); + + Pack.UInt32_To_BE(state[0], output, outOff); + Pack.UInt32_To_BE(state[1], output, outOff+4); + Pack.UInt32_To_BE(state[2], output, outOff+8); + Pack.UInt32_To_BE(state[3], output, outOff+12); + + return GenericSize; + } + + private int decryptBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + state[0] = Pack.BE_To_UInt32(input, inOff); + state[1] = Pack.BE_To_UInt32(input, inOff+4); + state[2] = Pack.BE_To_UInt32(input, inOff+8); + state[3] = Pack.BE_To_UInt32(input, inOff+12); + + Array.Copy(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]; + + Pack.UInt32_To_BE(state[0], output, outOff); + Pack.UInt32_To_BE(state[1], output, outOff+4); + Pack.UInt32_To_BE(state[2], output, outOff+8); + Pack.UInt32_To_BE(state[3], output, outOff+12); + + return GenericSize; + } + + private void gamma(uint[] a) + { + a[1] ^= ~a[3] & ~a[2]; + a[0] ^= a[2] & a[1]; + + uint 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(uint[] a, uint[] k) + { + uint 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(uint[] a) + { + a[1] = rotl(a[1], 1); + a[2] = rotl(a[2], 5); + a[3] = rotl(a[3], 2); + } + + private void pi2(uint[] a) + { + a[1] = rotl(a[1], 31); + a[2] = rotl(a[2], 27); + a[3] = rotl(a[3], 30); + } + + // Helpers + + private uint rotl(uint x, int y) + { + return (x << y) | (x >> (32-y)); + } + } +} diff --git a/crypto/src/crypto/engines/NullEngine.cs b/crypto/src/crypto/engines/NullEngine.cs new file mode 100644 index 000000000..407b8ccc6 --- /dev/null +++ b/crypto/src/crypto/engines/NullEngine.cs @@ -0,0 +1,70 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting. + * Provided for the sake of completeness. + */ + public class NullEngine + : IBlockCipher + { + private bool initialised; + private const int BlockSize = 1; + + public NullEngine() + { + } + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + // we don't mind any parameters that may come in + initialised = true; + } + + public string AlgorithmName + { + get { return "Null"; } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + public int GetBlockSize() + { + return BlockSize; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (!initialised) + throw new InvalidOperationException("Null engine not initialised"); + if ((inOff + BlockSize) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BlockSize) > output.Length) + throw new DataLengthException("output buffer too short"); + + for (int i = 0; i < BlockSize; ++i) + { + output[outOff + i] = input[inOff + i]; + } + + return BlockSize; + } + + public void Reset() + { + // nothing needs to be done + } + } +} diff --git a/crypto/src/crypto/engines/RC2Engine.cs b/crypto/src/crypto/engines/RC2Engine.cs new file mode 100644 index 000000000..aaf8c714c --- /dev/null +++ b/crypto/src/crypto/engines/RC2Engine.cs @@ -0,0 +1,312 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of RC2 as described in RFC 2268 + * "A Description of the RC2(r) Encryption Algorithm" R. Rivest. + */ + public class RC2Engine + : IBlockCipher + { + // + // the values we use for key expansion (based on the digits of PI) + // + private static readonly 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 const int BLOCK_SIZE = 8; + + private int[] workingKey; + private bool 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 forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.encrypting = forEncryption; + + if (parameters is RC2Parameters) + { + RC2Parameters param = (RC2Parameters) parameters; + + workingKey = GenerateWorkingKey(param.GetKey(), param.EffectiveKeyBits); + } + else if (parameters is KeyParameter) + { + KeyParameter param = (KeyParameter) parameters; + byte[] key = param.GetKey(); + + workingKey = GenerateWorkingKey(key, key.Length * 8); + } + else + { + throw new ArgumentException("invalid parameter passed to RC2 init - " + parameters.GetType().Name); + } + } + + public void Reset() + { + } + + public string AlgorithmName + { + get { return "RC2"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + throw new InvalidOperationException("RC2 engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, 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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int x76, x54, x32, x10; + + x76 = ((input[inOff + 7] & 0xff) << 8) + (input[inOff + 6] & 0xff); + x54 = ((input[inOff + 5] & 0xff) << 8) + (input[inOff + 4] & 0xff); + x32 = ((input[inOff + 3] & 0xff) << 8) + (input[inOff + 2] & 0xff); + x10 = ((input[inOff + 1] & 0xff) << 8) + (input[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); + } + + outBytes[outOff + 0] = (byte)x10; + outBytes[outOff + 1] = (byte)(x10 >> 8); + outBytes[outOff + 2] = (byte)x32; + outBytes[outOff + 3] = (byte)(x32 >> 8); + outBytes[outOff + 4] = (byte)x54; + outBytes[outOff + 5] = (byte)(x54 >> 8); + outBytes[outOff + 6] = (byte)x76; + outBytes[outOff + 7] = (byte)(x76 >> 8); + } + + private void DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int x76, x54, x32, x10; + + x76 = ((input[inOff + 7] & 0xff) << 8) + (input[inOff + 6] & 0xff); + x54 = ((input[inOff + 5] & 0xff) << 8) + (input[inOff + 4] & 0xff); + x32 = ((input[inOff + 3] & 0xff) << 8) + (input[inOff + 2] & 0xff); + x10 = ((input[inOff + 1] & 0xff) << 8) + (input[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 ]); + } + + outBytes[outOff + 0] = (byte)x10; + outBytes[outOff + 1] = (byte)(x10 >> 8); + outBytes[outOff + 2] = (byte)x32; + outBytes[outOff + 3] = (byte)(x32 >> 8); + outBytes[outOff + 4] = (byte)x54; + outBytes[outOff + 5] = (byte)(x54 >> 8); + outBytes[outOff + 6] = (byte)x76; + outBytes[outOff + 7] = (byte)(x76 >> 8); + } + } + +} diff --git a/crypto/src/crypto/engines/RC2WrapEngine.cs b/crypto/src/crypto/engines/RC2WrapEngine.cs new file mode 100644 index 000000000..238c9f76a --- /dev/null +++ b/crypto/src/crypto/engines/RC2WrapEngine.cs @@ -0,0 +1,370 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Wrap keys according to RFC 3217 - RC2 mechanism + */ + public class RC2WrapEngine + : IWrapper + { + /** Field engine */ + private CbcBlockCipher engine; + + /** Field param */ + private ICipherParameters parameters; + + /** Field paramPlusIV */ + private ParametersWithIV paramPlusIV; + + /** Field iv */ + private byte[] iv; + + /** Field forWrapping */ + private bool forWrapping; + + private SecureRandom sr; + + /** Field IV2 */ + private static readonly byte[] IV2 = + { + (byte) 0x4a, (byte) 0xdd, (byte) 0xa2, + (byte) 0x2c, (byte) 0x79, (byte) 0xe8, + (byte) 0x21, (byte) 0x05 + }; + + // + // checksum digest + // + IDigest sha1 = new Sha1Digest(); + byte[] digest = new byte[20]; + + /** + * Method init + * + * @param forWrapping + * @param param + */ + public void Init( + bool forWrapping, + ICipherParameters parameters) + { + this.forWrapping = forWrapping; + this.engine = new CbcBlockCipher(new RC2Engine()); + + if (parameters is ParametersWithRandom) + { + ParametersWithRandom pWithR = (ParametersWithRandom)parameters; + sr = pWithR.Random; + parameters = pWithR.Parameters; + } + else + { + sr = new SecureRandom(); + } + + if (parameters is ParametersWithIV) + { + if (!forWrapping) + throw new ArgumentException("You should not supply an IV for unwrapping"); + + this.paramPlusIV = (ParametersWithIV)parameters; + this.iv = this.paramPlusIV.GetIV(); + this.parameters = this.paramPlusIV.Parameters; + + if (this.iv.Length != 8) + throw new ArgumentException("IV is not 8 octets"); + } + else + { + this.parameters = parameters; + + 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.parameters, this.iv); + } + } + } + + /** + * Method GetAlgorithmName + * + * @return + */ + public string AlgorithmName + { + get { return "RC2"; } + } + + /** + * Method wrap + * + * @param in + * @param inOff + * @param inLen + * @return + */ + public byte[] Wrap( + byte[] input, + int inOff, + int length) + { + if (!forWrapping) + { + throw new InvalidOperationException("Not initialized for wrapping"); + } + + int len = length + 1; + if ((len % 8) != 0) + { + len += 8 - (len % 8); + } + + byte [] keyToBeWrapped = new byte[len]; + + keyToBeWrapped[0] = (byte)length; + Array.Copy(input, inOff, keyToBeWrapped, 1, length); + + byte[] pad = new byte[keyToBeWrapped.Length - length - 1]; + + if (pad.Length > 0) + { + sr.NextBytes(pad); + Array.Copy(pad, 0, keyToBeWrapped, length + 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]; + + Array.Copy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.Length); + Array.Copy(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]; + + Array.Copy(WKCKS, 0, TEMP1, 0, WKCKS.Length); + + int noOfBlocks = WKCKS.Length / engine.GetBlockSize(); + int extraBytes = WKCKS.Length % engine.GetBlockSize(); + + if (extraBytes != 0) + { + throw new InvalidOperationException("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]; + + Array.Copy(this.iv, 0, TEMP2, 0, this.iv.Length); + Array.Copy(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.parameters, 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 + * @throws InvalidCipherTextException + */ + public byte[] Unwrap( + byte[] input, + int inOff, + int length) + { + if (forWrapping) + { + throw new InvalidOperationException("Not set for unwrapping"); + } + + if (input == null) + { + throw new InvalidCipherTextException("Null pointer as ciphertext"); + } + + if (length % 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.parameters, IV2); + + this.engine.Init(false, param2); + + byte [] TEMP3 = new byte[length]; + + Array.Copy(input, inOff, TEMP3, 0, length); + + 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]; + + Array.Copy(TEMP2, 0, this.iv, 0, 8); + Array.Copy(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.parameters, this.iv); + + this.engine.Init(false, this.paramPlusIV); + + byte[] LCEKPADICV = new byte[TEMP1.Length]; + + Array.Copy(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]; + + Array.Copy(LCEKPADICV, 0, result, 0, LCEKPADICV.Length - 8); + Array.Copy(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]]; + Array.Copy(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. + * + * @param key + * @return + * @throws Exception + * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + */ + private byte[] CalculateCmsKeyChecksum( + byte[] key) + { + sha1.BlockUpdate(key, 0, key.Length); + sha1.DoFinal(digest, 0); + + byte[] result = new byte[8]; + Array.Copy(digest, 0, result, 0, 8); + return result; + } + + /** + * @param key + * @param checksum + * @return + * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + */ + private bool CheckCmsKeyChecksum( + byte[] key, + byte[] checksum) + { + return Arrays.ConstantTimeAreEqual(CalculateCmsKeyChecksum(key), checksum); + } + } +} diff --git a/crypto/src/crypto/engines/RC4Engine.cs b/crypto/src/crypto/engines/RC4Engine.cs new file mode 100644 index 000000000..c65468d93 --- /dev/null +++ b/crypto/src/crypto/engines/RC4Engine.cs @@ -0,0 +1,147 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + public class RC4Engine + : IStreamCipher + { + private readonly static int STATE_LENGTH = 256; + + /* + * variables to hold the state of the RC4 engine + * during encryption and decryption + */ + + private byte[] engineState; + private int x; + private int y; + private byte[] workingKey; + + /** + * initialise a RC4 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is KeyParameter) + { + /* + * RC4 encryption and decryption is completely + * symmetrical, so the 'forEncryption' is + * irrelevant. + */ + workingKey = ((KeyParameter)parameters).GetKey(); + SetKey(workingKey); + + return; + } + + throw new ArgumentException("invalid parameter passed to RC4 init - " + parameters.GetType().ToString()); + } + + public string AlgorithmName + { + get { return "RC4"; } + } + + public byte ReturnByte( + byte input) + { + x = (x + 1) & 0xff; + y = (engineState[x] + y) & 0xff; + + // swap + byte tmp = engineState[x]; + engineState[x] = engineState[y]; + engineState[y] = tmp; + + // xor + return (byte)(input ^ engineState[(engineState[x] + engineState[y]) & 0xff]); + } + + public void ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff + ) + { + if ((inOff + length) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + length) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + for (int i = 0; i < length ; i++) + { + x = (x + 1) & 0xff; + y = (engineState[x] + y) & 0xff; + + // swap + byte tmp = engineState[x]; + engineState[x] = engineState[y]; + engineState[y] = tmp; + + // xor + output[i+outOff] = (byte)(input[i + inOff] + ^ engineState[(engineState[x] + engineState[y]) & 0xff]); + } + } + + 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/crypto/src/crypto/engines/RC532Engine.cs b/crypto/src/crypto/engines/RC532Engine.cs new file mode 100644 index 000000000..1661707ef --- /dev/null +++ b/crypto/src/crypto/engines/RC532Engine.cs @@ -0,0 +1,294 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * The specification for RC5 came from the RC5 Encryption Algorithm + * publication in RSA CryptoBytes, Spring of 1995. + * http://www.rsasecurity.com/rsalabs/cryptobytes. + *

+ * This implementation has a word size of 32 bits.

+ */ + public class RC532Engine + : IBlockCipher + { + /* + * 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 readonly int P32 = unchecked((int) 0xb7e15163); + private static readonly int Q32 = unchecked((int) 0x9e3779b9); + + private bool forEncryption; + + /** + * Create an instance of the RC5 encryption algorithm + * and set some defaults + */ + public RC532Engine() + { + _noRounds = 12; // the default +// _S = null; + } + + public string AlgorithmName + { + get { return "RC5-32"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return 2 * 4; + } + + /** + * initialise a RC5-32 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (typeof(RC5Parameters).IsInstanceOfType(parameters)) + { + RC5Parameters p = (RC5Parameters)parameters; + + _noRounds = p.Rounds; + + SetKey(p.GetKey()); + } + else if (typeof(KeyParameter).IsInstanceOfType(parameters)) + { + KeyParameter p = (KeyParameter)parameters; + + SetKey(p.GetKey()); + } + else + { + throw new ArgumentException("invalid parameter passed to RC532 init - " + parameters.GetType().ToString()); + } + + this.forEncryption = forEncryption; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + return (forEncryption) + ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); + } + + public void Reset() + { + } + + /** + * Re-key the cipher. + * + * @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 ii = 0, jj = 0; + + for (int k = 0; k < iter; k++) + { + A = _S[ii] = RotateLeft(_S[ii] + A + B, 3); + B = L[jj] = RotateLeft( L[jj] + A + B, A+B); + ii = (ii+1) % _S.Length; + jj = (jj+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. + * + * @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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int A = BytesToWord(input, inOff) + _S[0]; + int B = BytesToWord(input, 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, outBytes, outOff); + WordToBytes(B, outBytes, outOff + 4); + + return 2 * 4; + } + + private int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int A = BytesToWord(input, inOff); + int B = BytesToWord(input, 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], outBytes, outOff); + WordToBytes(B - _S[1], outBytes, outOff + 4); + + return 2 * 4; + } + + + ////////////////////////////////////////////////////////////// + // + // PRIVATE Helper Methods + // + ////////////////////////////////////////////////////////////// + + /** + * Perform a left "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(32) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % 32 + */ + private int RotateLeft(int x, int y) { + return ((int) ( (uint) (x << (y & (32-1))) | + ((uint) x >> (32 - (y & (32-1)))) ) + ); + } + + /** + * Perform a right "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(32) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % 32 + */ + private int RotateRight(int x, int y) { + return ((int) ( ((uint) x >> (y & (32-1))) | + (uint) (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/crypto/src/crypto/engines/RC564Engine.cs b/crypto/src/crypto/engines/RC564Engine.cs new file mode 100644 index 000000000..5c69d40ff --- /dev/null +++ b/crypto/src/crypto/engines/RC564Engine.cs @@ -0,0 +1,295 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * The specification for RC5 came from the RC5 Encryption Algorithm + * publication in RSA CryptoBytes, Spring of 1995. + * http://www.rsasecurity.com/rsalabs/cryptobytes. + *

+ * This implementation is set to work with a 64 bit word size.

+ */ + public class RC564Engine + : IBlockCipher + { + private static readonly int wordSize = 64; + private static readonly 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 readonly long P64 = unchecked( (long) 0xb7e151628aed2a6bL); + private static readonly long Q64 = unchecked( (long) 0x9e3779b97f4a7c15L); + + private bool forEncryption; + + /** + * Create an instance of the RC5 encryption algorithm + * and set some defaults + */ + public RC564Engine() + { + _noRounds = 12; +// _S = null; + } + + public string AlgorithmName + { + get { return "RC5-64"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return 2 * bytesPerWord; + } + + /** + * initialise a RC5-64 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(typeof(RC5Parameters).IsInstanceOfType(parameters))) + { + throw new ArgumentException("invalid parameter passed to RC564 init - " + parameters.GetType().ToString()); + } + + RC5Parameters p = (RC5Parameters)parameters; + + this.forEncryption = forEncryption; + + _noRounds = p.Rounds; + + SetKey(p.GetKey()); + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + return (forEncryption) ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); + } + + public void Reset() + { + } + + /** + * Re-key the cipher. + * + * @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 ii = 0, jj = 0; + + for (int k = 0; k < iter; k++) + { + A = _S[ii] = RotateLeft(_S[ii] + A + B, 3); + B = L[jj] = RotateLeft( L[jj] + A + B, A+B); + ii = (ii+1) % _S.Length; + jj = (jj+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. + * + * @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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + long A = BytesToWord(input, inOff) + _S[0]; + long B = BytesToWord(input, 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, outBytes, outOff); + WordToBytes(B, outBytes, outOff + bytesPerWord); + + return 2 * bytesPerWord; + } + + private int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + long A = BytesToWord(input, inOff); + long B = BytesToWord(input, 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], outBytes, outOff); + WordToBytes(B - _S[1], outBytes, outOff + bytesPerWord); + + return 2 * bytesPerWord; + } + + + ////////////////////////////////////////////////////////////// + // + // PRIVATE Helper Methods + // + ////////////////////////////////////////////////////////////// + + /** + * Perform a left "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(wordSize) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % wordSize + */ + private long RotateLeft(long x, long y) { + return ((long) ( (ulong) (x << (int) (y & (wordSize-1))) | + ((ulong) x >> (int) (wordSize - (y & (wordSize-1))))) + ); + } + + /** + * Perform a right "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(wordSize) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % wordSize + */ + private long RotateRight(long x, long y) { + return ((long) ( ((ulong) x >> (int) (y & (wordSize-1))) | + (ulong) (x << (int) (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 = (long) ((ulong) word >> 8); + } + } + } + +} diff --git a/crypto/src/crypto/engines/RC6Engine.cs b/crypto/src/crypto/engines/RC6Engine.cs new file mode 100644 index 000000000..d72cc2f7b --- /dev/null +++ b/crypto/src/crypto/engines/RC6Engine.cs @@ -0,0 +1,362 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * An RC6 engine. + */ + public class RC6Engine + : IBlockCipher + { + private static readonly int wordSize = 32; + private static readonly int bytesPerWord = wordSize / 8; + + /* + * the number of rounds to perform + */ + private static readonly 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 readonly int P32 = unchecked((int) 0xb7e15163); + private static readonly int Q32 = unchecked((int) 0x9e3779b9); + + private static readonly int LGW = 5; // log2(32) + + private bool forEncryption; + + /** + * Create an instance of the RC6 encryption algorithm + * and set some defaults + */ + public RC6Engine() + { +// _S = null; + } + + public string AlgorithmName + { + get { return "RC6"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return 4 * bytesPerWord; + } + + /** + * initialise a RC5-32 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to RC6 init - " + parameters.GetType().ToString()); + + this.forEncryption = forEncryption; + + KeyParameter p = (KeyParameter)parameters; + SetKey(p.GetKey()); + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + int blockSize = GetBlockSize(); + if (_S == null) + throw new InvalidOperationException("RC6 engine not initialised"); + if ((inOff + blockSize) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + blockSize) > output.Length) + throw new DataLengthException("output buffer too short"); + + return (forEncryption) + ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); + } + + public void Reset() + { + } + + /** + * Re-key the cipher. + * + * @param inKey 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 ii = 0, jj = 0; + + for (int k = 0; k < iter; k++) + { + A = _S[ii] = RotateLeft(_S[ii] + A + B, 3); + B = L[jj] = RotateLeft( L[jj] + A + B, A+B); + ii = (ii+1) % _S.Length; + jj = (jj+1) % L.Length; + } + } + + private int EncryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + // load A,B,C and D registers from in. + int A = BytesToWord(input, inOff); + int B = BytesToWord(input, inOff + bytesPerWord); + int C = BytesToWord(input, inOff + bytesPerWord*2); + int D = BytesToWord(input, 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, outBytes, outOff); + WordToBytes(B, outBytes, outOff + bytesPerWord); + WordToBytes(C, outBytes, outOff + bytesPerWord*2); + WordToBytes(D, outBytes, outOff + bytesPerWord*3); + + return 4 * bytesPerWord; + } + + private int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + // load A,B,C and D registers from out. + int A = BytesToWord(input, inOff); + int B = BytesToWord(input, inOff + bytesPerWord); + int C = BytesToWord(input, inOff + bytesPerWord*2); + int D = BytesToWord(input, 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, outBytes, outOff); + WordToBytes(B, outBytes, outOff + bytesPerWord); + WordToBytes(C, outBytes, outOff + bytesPerWord*2); + WordToBytes(D, outBytes, outOff + bytesPerWord*3); + + return 4 * bytesPerWord; + } + + + ////////////////////////////////////////////////////////////// + // + // PRIVATE Helper Methods + // + ////////////////////////////////////////////////////////////// + + /** + * Perform a left "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(wordSize) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % wordSize + */ + private int RotateLeft(int x, int y) + { + return ((int)((uint)(x << (y & (wordSize-1))) + | ((uint) x >> (wordSize - (y & (wordSize-1)))))); + } + + /** + * Perform a right "spin" of the word. The rotation of the given + * word x is rotated left by y bits. + * Only the lg(wordSize) low-order bits of y + * are used to determine the rotation amount. Here it is + * assumed that the wordsize used is a power of 2. + * + * @param x word to rotate + * @param y number of bits to rotate % wordSize + */ + private int RotateRight(int x, int y) + { + return ((int)(((uint) x >> (y & (wordSize-1))) + | (uint)(x << (wordSize - (y & (wordSize-1)))))); + } + + 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 = (int) ((uint) word >> 8); + } + } + } + +} diff --git a/crypto/src/crypto/engines/RFC3211WrapEngine.cs b/crypto/src/crypto/engines/RFC3211WrapEngine.cs new file mode 100644 index 000000000..e520075f9 --- /dev/null +++ b/crypto/src/crypto/engines/RFC3211WrapEngine.cs @@ -0,0 +1,168 @@ +using System; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of the RFC 3211 Key Wrap + * Specification. + */ + public class Rfc3211WrapEngine + : IWrapper + { + private CbcBlockCipher engine; + private ParametersWithIV param; + private bool forWrapping; + private SecureRandom rand; + + public Rfc3211WrapEngine( + IBlockCipher engine) + { + this.engine = new CbcBlockCipher(engine); + } + + public void Init( + bool forWrapping, + ICipherParameters param) + { + this.forWrapping = forWrapping; + + if (param is ParametersWithRandom) + { + ParametersWithRandom p = (ParametersWithRandom) param; + + this.rand = p.Random; + this.param = (ParametersWithIV) p.Parameters; + } + else + { + if (forWrapping) + { + rand = new SecureRandom(); + } + + this.param = (ParametersWithIV) param; + } + } + + public string AlgorithmName + { + get { return engine.GetUnderlyingCipher().AlgorithmName + "/RFC3211Wrap"; } + } + + public byte[] Wrap( + byte[] inBytes, + int inOff, + int inLen) + { + if (!forWrapping) + { + throw new InvalidOperationException("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)~inBytes[inOff]; + cekBlock[2] = (byte)~inBytes[inOff + 1]; + cekBlock[3] = (byte)~inBytes[inOff + 2]; + + Array.Copy(inBytes, inOff, cekBlock, 4, inLen); + + rand.NextBytes(cekBlock, inLen + 4, cekBlock.Length - inLen - 4); + + 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[] inBytes, + int inOff, + int inLen) + { + if (forWrapping) + { + throw new InvalidOperationException("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]; + + Array.Copy(inBytes, inOff, cekBlock, 0, inLen); + Array.Copy(inBytes, inOff, iv, 0, iv.Length); + + engine.Init(false, new ParametersWithIV(param.Parameters, iv)); + + for (int i = blockSize; i < cekBlock.Length; i += blockSize) + { + engine.ProcessBlock(cekBlock, i, cekBlock, i); + } + + Array.Copy(cekBlock, cekBlock.Length - iv.Length, iv, 0, iv.Length); + + engine.Init(false, new ParametersWithIV(param.Parameters, 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]; + + Array.Copy(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/crypto/src/crypto/engines/RFC3394WrapEngine.cs b/crypto/src/crypto/engines/RFC3394WrapEngine.cs new file mode 100644 index 000000000..7596e7218 --- /dev/null +++ b/crypto/src/crypto/engines/RFC3394WrapEngine.cs @@ -0,0 +1,178 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /// + /// An implementation of the AES Key Wrapper from the NIST Key Wrap + /// Specification as described in RFC 3394. + ///

+ /// For further details see: http://www.ietf.org/rfc/rfc3394.txt + /// and http://csrc.nist.gov/encryption/kms/key-wrap.pdf. + /// + public class Rfc3394WrapEngine + : IWrapper + { + private readonly IBlockCipher engine; + + private KeyParameter param; + private bool forWrapping; + + private byte[] iv = + { + 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6 + }; + + public Rfc3394WrapEngine( + IBlockCipher engine) + { + this.engine = engine; + } + + public void Init( + bool forWrapping, + ICipherParameters parameters) + { + this.forWrapping = forWrapping; + + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + if (parameters is KeyParameter) + { + this.param = (KeyParameter) parameters; + } + else if (parameters is ParametersWithIV) + { + ParametersWithIV pIV = (ParametersWithIV) parameters; + byte[] iv = pIV.GetIV(); + + if (iv.Length != 8) + throw new ArgumentException("IV length not equal to 8", "parameters"); + + this.iv = iv; + this.param = (KeyParameter) pIV.Parameters; + } + else + { + // TODO Throw an exception for bad parameters? + } + } + + public string AlgorithmName + { + get { return engine.AlgorithmName; } + } + + public byte[] Wrap( + byte[] input, + int inOff, + int inLen) + { + if (!forWrapping) + { + throw new InvalidOperationException("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]; + + Array.Copy(iv, 0, block, 0, iv.Length); + Array.Copy(input, 0, block, iv.Length, inLen); + + engine.Init(true, param); + + for (int j = 0; j != 6; j++) + { + for (int i = 1; i <= n; i++) + { + Array.Copy(block, 0, buf, 0, iv.Length); + Array.Copy(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 = (int) ((uint)t >> 8); + } + + Array.Copy(buf, 0, block, 0, 8); + Array.Copy(buf, 8, block, 8 * i, 8); + } + } + + return block; + } + + public byte[] Unwrap( + byte[] input, + int inOff, + int inLen) + { + if (forWrapping) + { + throw new InvalidOperationException("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]; + + Array.Copy(input, 0, a, 0, iv.Length); + Array.Copy(input, 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--) + { + Array.Copy(a, 0, buf, 0, iv.Length); + Array.Copy(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 = (int) ((uint)t >> 8); + } + + engine.ProcessBlock(buf, 0, buf, 0); + Array.Copy(buf, 0, a, 0, 8); + Array.Copy(buf, 8, block, 8 * (i - 1), 8); + } + } + + if (!Arrays.ConstantTimeAreEqual(a, iv)) + throw new InvalidCipherTextException("checksum failed"); + + return block; + } + } +} diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs new file mode 100644 index 000000000..cdf69ddda --- /dev/null +++ b/crypto/src/crypto/engines/RSABlindedEngine.cs @@ -0,0 +1,124 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * this does your basic RSA algorithm with blinding + */ + public class RsaBlindedEngine + : IAsymmetricBlockCipher + { + private readonly RsaCoreEngine core = new RsaCoreEngine(); + private RsaKeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "RSA"; } + } + + /** + * initialise the RSA engine. + * + * @param forEncryption true if we are encrypting, false otherwise. + * @param param the necessary RSA key parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters param) + { + core.Init(forEncryption, param); + + if (param is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + key = (RsaKeyParameters)rParam.Parameters; + random = rParam.Random; + } + 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 inBuf 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[] inBuf, + int inOff, + int inLen) + { + if (key == null) + throw new InvalidOperationException("RSA engine not initialised"); + + BigInteger input = core.ConvertInput(inBuf, inOff, inLen); + + BigInteger result; + if (key is RsaPrivateCrtKeyParameters) + { + RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key; + BigInteger e = k.PublicExponent; + if (e != null) // can't do blinding without a public exponent + { + BigInteger m = k.Modulus; + BigInteger r = BigIntegers.CreateRandomInRange( + BigInteger.One, m.Subtract(BigInteger.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/crypto/src/crypto/engines/RSABlindingEngine.cs b/crypto/src/crypto/engines/RSABlindingEngine.cs new file mode 100644 index 000000000..76b57a3f7 --- /dev/null +++ b/crypto/src/crypto/engines/RSABlindingEngine.cs @@ -0,0 +1,139 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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 + : IAsymmetricBlockCipher + { + private readonly RsaCoreEngine core = new RsaCoreEngine(); + + private RsaKeyParameters key; + private BigInteger blindingFactor; + + private bool forEncryption; + + public string AlgorithmName + { + get { return "RSA"; } + } + + /** + * Initialise the blinding engine. + * + * @param forEncryption true if we are encrypting (blinding), false otherwise. + * @param param the necessary RSA key parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters param) + { + RsaBlindingParameters p; + + if (param is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + p = (RsaBlindingParameters)rParam.Parameters; + } + else + { + p = (RsaBlindingParameters)param; + } + + core.Init(forEncryption, p.PublicKey); + + this.forEncryption = forEncryption; + this.key = p.PublicKey; + this.blindingFactor = p.BlindingFactor; + } + + /** + * 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[] inBuf, + int inOff, + int inLen) + { + BigInteger msg = core.ConvertInput(inBuf, 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.Exponent, key.Modulus)); + blindMsg = blindMsg.Mod(key.Modulus); + + return blindMsg; + } + + /* + * Unblind the message blinded with the blind factor. + */ + private BigInteger UnblindMessage( + BigInteger blindedMsg) + { + BigInteger m = key.Modulus; + BigInteger msg = blindedMsg; + BigInteger blindFactorInverse = blindingFactor.ModInverse(m); + msg = msg.Multiply(blindFactorInverse); + msg = msg.Mod(m); + + return msg; + } + } +} diff --git a/crypto/src/crypto/engines/RSACoreEngine.cs b/crypto/src/crypto/engines/RSACoreEngine.cs new file mode 100644 index 000000000..4e64d25d6 --- /dev/null +++ b/crypto/src/crypto/engines/RSACoreEngine.cs @@ -0,0 +1,156 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * this does your basic RSA algorithm. + */ + class RsaCoreEngine + { + private RsaKeyParameters key; + private bool forEncryption; + private int bitSize; + + /** + * initialise the RSA engine. + * + * @param forEncryption true if we are encrypting, false otherwise. + * @param param the necessary RSA key parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + parameters = ((ParametersWithRandom) parameters).Parameters; + } + + if (!(parameters is RsaKeyParameters)) + throw new InvalidKeyException("Not an RSA key"); + + this.key = (RsaKeyParameters) parameters; + this.forEncryption = forEncryption; + this.bitSize = key.Modulus.BitLength; + } + + /** + * 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() + { + if (forEncryption) + { + return (bitSize - 1) / 8; + } + + 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() + { + if (forEncryption) + { + return (bitSize + 7) / 8; + } + + return (bitSize - 1) / 8; + } + + public BigInteger ConvertInput( + byte[] inBuf, + int inOff, + int inLen) + { + int maxLength = (bitSize + 7) / 8; + + if (inLen > maxLength) + throw new DataLengthException("input too large for RSA cipher."); + + BigInteger input = new BigInteger(1, inBuf, inOff, inLen); + + if (input.CompareTo(key.Modulus) >= 0) + throw new DataLengthException("input too large for RSA cipher."); + + return input; + } + + public byte[] ConvertOutput( + BigInteger result) + { + byte[] output = result.ToByteArrayUnsigned(); + + if (forEncryption) + { + int outSize = GetOutputBlockSize(); + + // TODO To avoid this, create version of BigInteger.ToByteArray that + // writes to an existing array + if (output.Length < outSize) // have ended up with less bytes than normal, lengthen + { + byte[] tmp = new byte[outSize]; + output.CopyTo(tmp, tmp.Length - output.Length); + output = tmp; + } + } + + return output; + } + + public BigInteger ProcessBlock( + BigInteger input) + { + if (key is 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.P;; + BigInteger q = crtKey.Q; + BigInteger dP = crtKey.DP; + BigInteger dQ = crtKey.DQ; + BigInteger qInv = crtKey.QInv; + + 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; + } + + return input.ModPow(key.Exponent, key.Modulus); + } + } +} diff --git a/crypto/src/crypto/engines/RijndaelEngine.cs b/crypto/src/crypto/engines/RijndaelEngine.cs new file mode 100644 index 000000000..df2e5baea --- /dev/null +++ b/crypto/src/crypto/engines/RijndaelEngine.cs @@ -0,0 +1,747 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * an implementation of Rijndael, based on the documentation and reference implementation + * by Paulo Barreto, Vincent Rijmen, for v2.0 August '99. + *

+ * Note: this implementation is based on information prior to readonly NIST publication. + *

+ */ + public class RijndaelEngine + : IBlockCipher + { + private static readonly int MAXROUNDS = 14; + + private static readonly int MAXKC = (256/4); + + private static readonly byte[] Logtable = + { + 0, 0, 25, 1, 50, 2, 26, 198, + 75, 199, 27, 104, 51, 238, 223, 3, + 100, 4, 224, 14, 52, 141, 129, 239, + 76, 113, 8, 200, 248, 105, 28, 193, + 125, 194, 29, 181, 249, 185, 39, 106, + 77, 228, 166, 114, 154, 201, 9, 120, + 101, 47, 138, 5, 33, 15, 225, 36, + 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, + 19, 92, 210, 241, 64, 70, 131, 56, + 102, 221, 253, 48, 191, 6, 139, 98, + 179, 37, 226, 152, 34, 136, 145, 16, + 126, 110, 72, 195, 163, 182, 30, 66, + 58, 107, 40, 84, 250, 133, 61, 186, + 43, 121, 10, 21, 155, 159, 94, 202, + 78, 212, 172, 229, 243, 115, 167, 87, + 175, 88, 168, 80, 244, 234, 214, 116, + 79, 174, 233, 213, 231, 230, 173, 232, + 44, 215, 117, 122, 235, 22, 11, 245, + 89, 203, 95, 176, 156, 169, 81, 160, + 127, 12, 246, 111, 23, 196, 73, 236, + 216, 67, 31, 45, 164, 118, 123, 183, + 204, 187, 62, 90, 251, 96, 177, 134, + 59, 82, 161, 108, 170, 85, 41, 157, + 151, 178, 135, 144, 97, 190, 220, 252, + 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, + 20, 42, 158, 93, 86, 242, 211, 171, + 68, 17, 146, 217, 35, 32, 46, 137, + 180, 124, 184, 38, 119, 153, 227, 165, + 103, 74, 237, 222, 197, 49, 254, 24, + 13, 99, 140, 128, 192, 247, 112, 7 + }; + + private static readonly byte[] Alogtable = + { + 0, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, + 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, + 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, + 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, + 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, + 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, + 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, + 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, + 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, + 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, + 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, + 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, + 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, + 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, + 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, + 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, + 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, + 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, + 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, + 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, + }; + + private static readonly byte[] S = + { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22, + }; + + private static readonly byte[] Si = + { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, + }; + + private static readonly byte[] 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 readonly byte[][] shifts0 = new byte [][] + { + new byte[]{ 0, 8, 16, 24 }, + new byte[]{ 0, 8, 16, 24 }, + new byte[]{ 0, 8, 16, 24 }, + new byte[]{ 0, 8, 16, 32 }, + new byte[]{ 0, 8, 24, 32 } + }; + + static readonly byte[][] shifts1 = + { + new byte[]{ 0, 24, 16, 8 }, + new byte[]{ 0, 32, 24, 16 }, + new byte[]{ 0, 40, 32, 24 }, + new byte[]{ 0, 48, 40, 24 }, + new byte[]{ 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 (((long)((ulong) r >> shift) | (r << (BC - shift)))) & BC_MASK; + + ulong temp = (ulong) r >> shift; + + // NB: This corrects for Mono Bug #79087 (fixed in 1.1.17) + if (shift > 31) + { + temp &= 0xFFFFFFFFUL; + } + + return ((long) temp | (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]; + long[][] W = new long[MAXROUNDS+1][]; + + for (int i = 0; i < MAXROUNDS+1; i++) W[i] = new long[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 ArgumentException("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] ^= (byte) 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 bool 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 blocksize 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 = unchecked( (long)0xffffffffffffffffL); + shifts0SC = shifts0[4]; + shifts1SC = shifts1[4]; + break; + default: + throw new ArgumentException("unknown blocksize to Rijndael"); + } + + this.blockBits = blockBits; + } + + /** + * initialise a Rijndael cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (typeof(KeyParameter).IsInstanceOfType(parameters)) + { + workingKey = GenerateWorkingKey(((KeyParameter)parameters).GetKey()); + this.forEncryption = forEncryption; + return; + } + + throw new ArgumentException("invalid parameter passed to Rijndael init - " + parameters.GetType().ToString()); + } + + public string AlgorithmName + { + get { return "Rijndael"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BC / 2; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + { + throw new InvalidOperationException("Rijndael engine not initialised"); + } + + if ((inOff + (BC / 2)) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + (BC / 2)) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + UnPackBlock(input, inOff); + + if (forEncryption) + { + EncryptBlock(workingKey); + } + else + { + DecryptBlock(workingKey); + } + + PackBlock(output, outOff); + + return BC / 2; + } + + public void Reset() + { + } + + private void UnPackBlock( + byte[] bytes, + int off) + { + int index = off; + + A0 = (long)(bytes[index++] & 0xff); + A1 = (long)(bytes[index++] & 0xff); + A2 = (long)(bytes[index++] & 0xff); + A3 = (long)(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/crypto/src/crypto/engines/RsaEngine.cs b/crypto/src/crypto/engines/RsaEngine.cs new file mode 100644 index 000000000..7e6dfb163 --- /dev/null +++ b/crypto/src/crypto/engines/RsaEngine.cs @@ -0,0 +1,78 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * this does your basic RSA algorithm. + */ + public class RsaEngine + : IAsymmetricBlockCipher + { + private RsaCoreEngine core; + + public string AlgorithmName + { + get { return "RSA"; } + } + + /** + * initialise the RSA engine. + * + * @param forEncryption true if we are encrypting, false otherwise. + * @param param the necessary RSA key parameters. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (core == null) + core = new RsaCoreEngine(); + + core.Init(forEncryption, parameters); + } + + /** + * 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 inBuf 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[] inBuf, + int inOff, + int inLen) + { + if (core == null) + throw new InvalidOperationException("RSA engine not initialised"); + + return core.ConvertOutput(core.ProcessBlock(core.ConvertInput(inBuf, inOff, inLen))); + } + } +} diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs new file mode 100644 index 000000000..efea0f1fe --- /dev/null +++ b/crypto/src/crypto/engines/SEEDEngine.cs @@ -0,0 +1,361 @@ +using System; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Implementation of the SEED algorithm as described in RFC 4009 + */ + public class SeedEngine + : IBlockCipher + { + private const int BlockSize = 16; + + private static readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] 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 readonly uint[] KC = + { + 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, + 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, + 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, + 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b + }; + + private int[] wKey; + private bool forEncryption; + + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + wKey = createWorkingKey(((KeyParameter)parameters).GetKey()); + } + + public string AlgorithmName + { + get { return "SEED"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BlockSize; + } + + public int ProcessBlock( + byte[] inBuf, + int inOff, + byte[] outBuf, + int outOff) + { + if (wKey == null) + throw new InvalidOperationException("SEED engine not initialised"); + if (inOff + BlockSize > inBuf.Length) + throw new DataLengthException("input buffer too short"); + if (outOff + BlockSize > outBuf.Length) + throw new DataLengthException("output buffer too short"); + + long l = bytesToLong(inBuf, inOff + 0); + long r = bytesToLong(inBuf, 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(outBuf, outOff + 0, r); + longToBytes(outBuf, outOff + 8, l); + + return BlockSize; + } + + 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 - (int)KC[i]); + key[2 * i + 1] = G(key1 - key3 + (int)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) | ((long)((ulong) x >> 56)); + } + + private long rotateRight8( + long x) + { + return ((long)((ulong) 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 (int)(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/crypto/src/crypto/engines/SEEDWrapEngine.cs b/crypto/src/crypto/engines/SEEDWrapEngine.cs new file mode 100644 index 000000000..6b71f940b --- /dev/null +++ b/crypto/src/crypto/engines/SEEDWrapEngine.cs @@ -0,0 +1,16 @@ +namespace Org.BouncyCastle.Crypto.Engines +{ + /// + /// An implementation of the SEED key wrapper based on RFC 4010/RFC 3394. + ///

+ /// For further details see: http://www.ietf.org/rfc/rfc4010.txt. + /// + public class SeedWrapEngine + : Rfc3394WrapEngine + { + public SeedWrapEngine() + : base(new SeedEngine()) + { + } + } +} diff --git a/crypto/src/crypto/engines/Salsa20Engine.cs b/crypto/src/crypto/engines/Salsa20Engine.cs new file mode 100644 index 000000000..7d68deab1 --- /dev/null +++ b/crypto/src/crypto/engines/Salsa20Engine.cs @@ -0,0 +1,299 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005 + */ + public class Salsa20Engine + : IStreamCipher + { + /** Constants */ + private const int StateSize = 16; // 16, 32 bit ints = 64 bytes + + private readonly static byte[] + sigma = Strings.ToAsciiByteArray("expand 32-byte k"), + tau = Strings.ToAsciiByteArray("expand 16-byte k"); + + /* + * variables to hold the state of the engine + * during encryption and decryption + */ + private int index = 0; + private uint[] engineState = new uint[StateSize]; // state + private uint[] x = new uint[StateSize]; // internal buffer + private byte[] keyStream = new byte[StateSize * 4], // expanded state, 64 bytes + workingKey = null, + workingIV = null; + private bool initialised = false; + + /* + * internal counter + */ + private uint cW0, cW1, cW2; + + /** + * initialise a Salsa20 cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param params the parameters required to set up the cipher. + * @exception ArgumentException if the params argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + /* + * Salsa20 encryption and decryption is completely + * symmetrical, so the 'forEncryption' is + * irrelevant. (Like 90% of stream ciphers) + */ + + ParametersWithIV ivParams = parameters as ParametersWithIV; + + if (ivParams == null) + throw new ArgumentException("Salsa20 Init requires an IV", "parameters"); + + byte[] iv = ivParams.GetIV(); + + if (iv == null || iv.Length != 8) + throw new ArgumentException("Salsa20 requires exactly 8 bytes of IV"); + + KeyParameter key = ivParams.Parameters as KeyParameter; + + if (key == null) + throw new ArgumentException("Salsa20 Init requires a key", "parameters"); + + workingKey = key.GetKey(); + workingIV = iv; + + SetKey(workingKey, workingIV); + } + + public string AlgorithmName + { + get { return "Salsa20"; } + } + + public byte ReturnByte( + byte input) + { + if (LimitExceeded()) + { + throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV"); + } + + if (index == 0) + { + GenerateKeyStream(keyStream); + + if (++engineState[8] == 0) + { + ++engineState[9]; + } + } + + byte output = (byte)(keyStream[index] ^ input); + index = (index + 1) & 63; + + return output; + } + + public void ProcessBytes( + byte[] inBytes, + int inOff, + int len, + byte[] outBytes, + int outOff) + { + if (!initialised) + { + throw new InvalidOperationException(AlgorithmName + " not initialised"); + } + + if ((inOff + len) > inBytes.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + len) > outBytes.Length) + { + throw new DataLengthException("output buffer too short"); + } + + if (LimitExceeded((uint)len)) + { + throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV"); + } + + for (int i = 0; i < len; i++) + { + if (index == 0) + { + GenerateKeyStream(keyStream); + + if (++engineState[8] == 0) + { + ++engineState[9]; + } + } + outBytes[i+outOff] = (byte)(keyStream[index]^inBytes[i+inOff]); + index = (index + 1) & 63; + } + } + + public void Reset() + { + SetKey(workingKey, workingIV); + } + + // Private implementation + + private void SetKey(byte[] keyBytes, byte[] ivBytes) + { + workingKey = keyBytes; + workingIV = ivBytes; + + index = 0; + ResetCounter(); + int offset = 0; + byte[] constants; + + // Key + engineState[1] = Pack.LE_To_UInt32(workingKey, 0); + engineState[2] = Pack.LE_To_UInt32(workingKey, 4); + engineState[3] = Pack.LE_To_UInt32(workingKey, 8); + engineState[4] = Pack.LE_To_UInt32(workingKey, 12); + + if (workingKey.Length == 32) + { + constants = sigma; + offset = 16; + } + else + { + constants = tau; + } + + engineState[11] = Pack.LE_To_UInt32(workingKey, offset); + engineState[12] = Pack.LE_To_UInt32(workingKey, offset + 4); + engineState[13] = Pack.LE_To_UInt32(workingKey, offset + 8); + engineState[14] = Pack.LE_To_UInt32(workingKey, offset + 12); + engineState[0] = Pack.LE_To_UInt32(constants, 0); + engineState[5] = Pack.LE_To_UInt32(constants, 4); + engineState[10] = Pack.LE_To_UInt32(constants, 8); + engineState[15] = Pack.LE_To_UInt32(constants, 12); + + // IV + engineState[6] = Pack.LE_To_UInt32(workingIV, 0); + engineState[7] = Pack.LE_To_UInt32(workingIV, 4); + engineState[8] = engineState[9] = 0; + + initialised = true; + } + + private void GenerateKeyStream(byte[] output) + { + SalsaCore(20, engineState, x); + Pack.UInt32_To_LE(x, output, 0); + } + + internal static void SalsaCore(int rounds, uint[] state, uint[] x) + { + // TODO Exception if rounds odd? + + Array.Copy(state, 0, x, 0, state.Length); + + for (int i = rounds; i > 0; i -= 2) + { + x[ 4] ^= R((x[ 0]+x[12]), 7); + x[ 8] ^= R((x[ 4]+x[ 0]), 9); + x[12] ^= R((x[ 8]+x[ 4]),13); + x[ 0] ^= R((x[12]+x[ 8]),18); + x[ 9] ^= R((x[ 5]+x[ 1]), 7); + x[13] ^= R((x[ 9]+x[ 5]), 9); + x[ 1] ^= R((x[13]+x[ 9]),13); + x[ 5] ^= R((x[ 1]+x[13]),18); + x[14] ^= R((x[10]+x[ 6]), 7); + x[ 2] ^= R((x[14]+x[10]), 9); + x[ 6] ^= R((x[ 2]+x[14]),13); + x[10] ^= R((x[ 6]+x[ 2]),18); + x[ 3] ^= R((x[15]+x[11]), 7); + x[ 7] ^= R((x[ 3]+x[15]), 9); + x[11] ^= R((x[ 7]+x[ 3]),13); + x[15] ^= R((x[11]+x[ 7]),18); + x[ 1] ^= R((x[ 0]+x[ 3]), 7); + x[ 2] ^= R((x[ 1]+x[ 0]), 9); + x[ 3] ^= R((x[ 2]+x[ 1]),13); + x[ 0] ^= R((x[ 3]+x[ 2]),18); + x[ 6] ^= R((x[ 5]+x[ 4]), 7); + x[ 7] ^= R((x[ 6]+x[ 5]), 9); + x[ 4] ^= R((x[ 7]+x[ 6]),13); + x[ 5] ^= R((x[ 4]+x[ 7]),18); + x[11] ^= R((x[10]+x[ 9]), 7); + x[ 8] ^= R((x[11]+x[10]), 9); + x[ 9] ^= R((x[ 8]+x[11]),13); + x[10] ^= R((x[ 9]+x[ 8]),18); + x[12] ^= R((x[15]+x[14]), 7); + x[13] ^= R((x[12]+x[15]), 9); + x[14] ^= R((x[13]+x[12]),13); + x[15] ^= R((x[14]+x[13]),18); + } + + for (int i = 0; i < StateSize; ++i) + { + x[i] += state[i]; + } + } + + private static uint R(uint x, int y) + { + return (x << y) | (x >> (32 - y)); + } + + private void ResetCounter() + { + cW0 = 0; + cW1 = 0; + cW2 = 0; + } + + private bool 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 bool LimitExceeded( + uint len) + { + uint old = cW0; + cW0 += len; + if (cW0 < old) + { + if (++cW1 == 0) + { + return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6) + } + } + + return false; + } + } +} diff --git a/crypto/src/crypto/engines/SerpentEngine.cs b/crypto/src/crypto/engines/SerpentEngine.cs new file mode 100644 index 000000000..92b25acc6 --- /dev/null +++ b/crypto/src/crypto/engines/SerpentEngine.cs @@ -0,0 +1,779 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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. + *

+ * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a + * candidate algorithm for the NIST AES Quest.> + *

+ *

+ * For full details see the The Serpent home page + *

+ */ + public class SerpentEngine + : IBlockCipher + { + private const int BLOCK_SIZE = 16; + + static readonly int ROUNDS = 32; + static readonly int PHI = unchecked((int)0x9E3779B9); // (Sqrt(5) - 1) * 2**31 + + private bool encrypting; + private int[] wKey; + + private int X0, X1, X2, X3; // registers + + /** + * initialise a Serpent cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to Serpent init - " + parameters.GetType().ToString()); + + this.encrypting = forEncryption; + this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey()); + } + + public string AlgorithmName + { + get { return "Serpent"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (wKey == null) + throw new InvalidOperationException("Serpent not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, 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 ArgumentException + */ + private int[] MakeWorkingKey( + byte[] key) + { + // + // 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 ArgumentException("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); + } + + Array.Copy(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) | (int) ((uint)x >> (32 - bits))); + } + + private int RotateRight( + int x, + int bits) + { + return ( (int)((uint)x >> bits) | (x << (32 - 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)((uint)word >> 8); + dst[dstOff + 1] = (byte)((uint)word >> 16); + dst[dstOff] = (byte)((uint)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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + X3 = BytesToWord(input, inOff); + X2 = BytesToWord(input, inOff + 4); + X1 = BytesToWord(input, inOff + 8); + X0 = BytesToWord(input, 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, outBytes, outOff); + WordToBytes(wKey[130] ^ X2, outBytes, outOff + 4); + WordToBytes(wKey[129] ^ X1, outBytes, outOff + 8); + WordToBytes(wKey[128] ^ X0, outBytes, 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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + X3 = wKey[131] ^ BytesToWord(input, inOff); + X2 = wKey[130] ^ BytesToWord(input, inOff + 4); + X1 = wKey[129] ^ BytesToWord(input, inOff + 8); + X0 = wKey[128] ^ BytesToWord(input, 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], outBytes, outOff); + WordToBytes(X2 ^ wKey[2], outBytes, outOff + 4); + WordToBytes(X1 ^ wKey[1], outBytes, outOff + 8); + WordToBytes(X0 ^ wKey[0], outBytes, outOff + 12); + } + + /* + * The sboxes below are based on the work of Brian Gladman and + * Sam Simpson, whose original notice appears below. + *

+ * For further details see: + * http://fp.gladman.plus.com/cryptography_technology/serpent/ + *

+ */ + + /* Partially optimised Serpent S Box bool 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/crypto/src/crypto/engines/SkipjackEngine.cs b/crypto/src/crypto/engines/SkipjackEngine.cs new file mode 100644 index 000000000..3d2a781e6 --- /dev/null +++ b/crypto/src/crypto/engines/SkipjackEngine.cs @@ -0,0 +1,255 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * a class that provides a basic SKIPJACK engine. + */ + public class SkipjackEngine + : IBlockCipher + { + const int BLOCK_SIZE = 8; + + static readonly 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 bool encrypting; + + /** + * initialise a SKIPJACK cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to SKIPJACK init - " + parameters.GetType().ToString()); + + byte[] keyBytes = ((KeyParameter)parameters).GetKey(); + + this.encrypting = forEncryption; + 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 AlgorithmName + { + get { return "SKIPJACK"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int GetBlockSize() + { + return BLOCK_SIZE; + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (key1 == null) + throw new InvalidOperationException("SKIPJACK engine not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, 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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int w1 = (input[inOff + 0] << 8) + (input[inOff + 1] & 0xff); + int w2 = (input[inOff + 2] << 8) + (input[inOff + 3] & 0xff); + int w3 = (input[inOff + 4] << 8) + (input[inOff + 5] & 0xff); + int w4 = (input[inOff + 6] << 8) + (input[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++; + } + } + + outBytes[outOff + 0] = (byte)((w1 >> 8)); + outBytes[outOff + 1] = (byte)(w1); + outBytes[outOff + 2] = (byte)((w2 >> 8)); + outBytes[outOff + 3] = (byte)(w2); + outBytes[outOff + 4] = (byte)((w3 >> 8)); + outBytes[outOff + 5] = (byte)(w3); + outBytes[outOff + 6] = (byte)((w4 >> 8)); + outBytes[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[] input, + int inOff, + byte[] outBytes, + int outOff) + { + int w2 = (input[inOff + 0] << 8) + (input[inOff + 1] & 0xff); + int w1 = (input[inOff + 2] << 8) + (input[inOff + 3] & 0xff); + int w4 = (input[inOff + 4] << 8) + (input[inOff + 5] & 0xff); + int w3 = (input[inOff + 6] << 8) + (input[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--; + } + } + + outBytes[outOff + 0] = (byte)((w2 >> 8)); + outBytes[outOff + 1] = (byte)(w2); + outBytes[outOff + 2] = (byte)((w1 >> 8)); + outBytes[outOff + 3] = (byte)(w1); + outBytes[outOff + 4] = (byte)((w4 >> 8)); + outBytes[outOff + 5] = (byte)(w4); + outBytes[outOff + 6] = (byte)((w3 >> 8)); + outBytes[outOff + 7] = (byte)(w3); + + return BLOCK_SIZE; + } + } + +} diff --git a/crypto/src/crypto/engines/TEAEngine.cs b/crypto/src/crypto/engines/TEAEngine.cs new file mode 100644 index 000000000..582dd0f73 --- /dev/null +++ b/crypto/src/crypto/engines/TEAEngine.cs @@ -0,0 +1,168 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * An TEA engine. + */ + public class TeaEngine + : IBlockCipher + { + private const int + rounds = 32, + block_size = 8; +// key_size = 16, + + private const uint + delta = 0x9E3779B9, + d_sum = 0xC6EF3720; // sum on decrypt + + /* + * the expanded key array of 4 subkeys + */ + private uint _a, _b, _c, _d; + private bool _initialised; + private bool _forEncryption; + + /** + * Create an instance of the TEA encryption algorithm + * and set some defaults + */ + public TeaEngine() + { + _initialised = false; + } + + public string AlgorithmName + { + get { return "TEA"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + 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 ArgumentException if the params argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + { + throw new ArgumentException("invalid parameter passed to TEA init - " + + parameters.GetType().FullName); + } + + _forEncryption = forEncryption; + _initialised = true; + + KeyParameter p = (KeyParameter) parameters; + + setKey(p.GetKey()); + } + + public int ProcessBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + if (!_initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + if ((inOff + block_size) > inBytes.Length) + throw new DataLengthException("input buffer too short"); + + if ((outOff + block_size) > outBytes.Length) + throw new DataLengthException("output buffer too short"); + + return _forEncryption + ? encryptBlock(inBytes, inOff, outBytes, outOff) + : decryptBlock(inBytes, inOff, outBytes, outOff); + } + + public void Reset() + { + } + + /** + * Re-key the cipher. + * + * @param key the key to be used + */ + private void setKey( + byte[] key) + { + _a = Pack.BE_To_UInt32(key, 0); + _b = Pack.BE_To_UInt32(key, 4); + _c = Pack.BE_To_UInt32(key, 8); + _d = Pack.BE_To_UInt32(key, 12); + } + + private int encryptBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + // Pack bytes into integers + uint v0 = Pack.BE_To_UInt32(inBytes, inOff); + uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4); + + uint 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); + } + + Pack.UInt32_To_BE(v0, outBytes, outOff); + Pack.UInt32_To_BE(v1, outBytes, outOff + 4); + + return block_size; + } + + private int decryptBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + // Pack bytes into integers + uint v0 = Pack.BE_To_UInt32(inBytes, inOff); + uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4); + + uint 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; + } + + Pack.UInt32_To_BE(v0, outBytes, outOff); + Pack.UInt32_To_BE(v1, outBytes, outOff + 4); + + return block_size; + } + } +} diff --git a/crypto/src/crypto/engines/TwofishEngine.cs b/crypto/src/crypto/engines/TwofishEngine.cs new file mode 100644 index 000000000..b983d9d31 --- /dev/null +++ b/crypto/src/crypto/engines/TwofishEngine.cs @@ -0,0 +1,675 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * 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 sealed class TwofishEngine + : IBlockCipher + { + private static readonly 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 const int P_00 = 1; + private const int P_01 = 0; + private const int P_02 = 0; + private const int P_03 = P_01 ^ 1; + private const int P_04 = 1; + + private const int P_10 = 0; + private const int P_11 = 0; + private const int P_12 = 1; + private const int P_13 = P_11 ^ 1; + private const int P_14 = 0; + + private const int P_20 = 1; + private const int P_21 = 1; + private const int P_22 = 0; + private const int P_23 = P_21 ^ 1; + private const int P_24 = 0; + + private const int P_30 = 0; + private const int P_31 = 1; + private const int P_32 = 1; + private const int P_33 = P_31 ^ 1; + private const int P_34 = 1; + + /* Primitive polynomial for GF(256) */ + private const int GF256_FDBK = 0x169; + private const int GF256_FDBK_2 = GF256_FDBK / 2; + private const int GF256_FDBK_4 = GF256_FDBK / 4; + + private const int RS_GF_FDBK = 0x14D; // field generator + + //==================================== + // Useful constants + //==================================== + + private const int ROUNDS = 16; + private const int MAX_ROUNDS = 16; // bytes = 128 bits + private const int BLOCK_SIZE = 16; // bytes = 128 bits + private const int MAX_KEY_BITS = 256; + + private const int INPUT_WHITEN=0; + private const int OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4 + private const int ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8 + + private const int TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40 + + private const int SK_STEP = 0x02020202; + private const int SK_BUMP = 0x01010101; + private const int SK_ROTL = 9; + + private bool encrypting; + + 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; + + private byte[] workingKey; + + 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 forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to Twofish init - " + parameters.GetType().ToString()); + + this.encrypting = forEncryption; + this.workingKey = ((KeyParameter)parameters).GetKey(); + this.k64Cnt = (this.workingKey.Length / 8); // pre-padded ? + SetKey(this.workingKey); + } + + public string AlgorithmName + { + get { return "Twofish"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if (workingKey == null) + throw new InvalidOperationException("Twofish not initialised"); + if ((inOff + BLOCK_SIZE) > input.Length) + throw new DataLengthException("input buffer too short"); + if ((outOff + BLOCK_SIZE) > output.Length) + throw new DataLengthException("output buffer too short"); + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, 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 ArgumentException("Key size less than 64 bits"); + } + + if (k64Cnt > 4) + { + throw new ArgumentException("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,p=0; i> 24); + A += B; + gSubKeys[i*2] = A; + A += B; + gSubKeys[i*2 + 1] = A << SK_ROTL | (int)((uint)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>1) | x2 << 31; + x3 = (x3 << 1 | (int) ((uint)x3 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]); + + t0 = Fe32_0(x2); + t1 = Fe32_3(x3); + x0 ^= t0 + t1 + gSubKeys[k++]; + x0 = (int) ((uint)x0 >>1) | x0 << 31; + x1 = (x1 << 1 | (int)((uint)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 | (int)((uint) x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]); + x1 = (int) ((uint)x1 >>1) | x1 << 31; + + t0 = Fe32_0(x0); + t1 = Fe32_3(x1); + x3 ^= t0 + 2*t1 + gSubKeys[k--]; + x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]); + x3 = (int)((uint)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 = M_b0(x); + int b1 = M_b1(x); + int b2 = M_b2(x); + int b3 = M_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) ^ M_b0(k0)] ^ + gMDS1[(P[P_11,b1] & 0xff) ^ M_b1(k0)] ^ + gMDS2[(P[P_21,b2] & 0xff) ^ M_b2(k0)] ^ + gMDS3[(P[P_31,b3] & 0xff) ^ M_b3(k0)]; + break; + case 0: /* 256 bits of key */ + b0 = (P[P_04,b0] & 0xff) ^ M_b0(k3); + b1 = (P[P_14,b1] & 0xff) ^ M_b1(k3); + b2 = (P[P_24,b2] & 0xff) ^ M_b2(k3); + b3 = (P[P_34,b3] & 0xff) ^ M_b3(k3); + goto case 3; + case 3: + b0 = (P[P_03,b0] & 0xff) ^ M_b0(k2); + b1 = (P[P_13,b1] & 0xff) ^ M_b1(k2); + b2 = (P[P_23,b2] & 0xff) ^ M_b2(k2); + b3 = (P[P_33,b3] & 0xff) ^ M_b3(k2); + goto case 2; + case 2: + result = + gMDS0[(P[P_01,(P[P_02,b0]&0xff)^M_b0(k1)]&0xff)^M_b0(k0)] ^ + gMDS1[(P[P_11,(P[P_12,b1]&0xff)^M_b1(k1)]&0xff)^M_b1(k0)] ^ + gMDS2[(P[P_21,(P[P_22,b2]&0xff)^M_b2(k1)]&0xff)^M_b2(k0)] ^ + gMDS3[(P[P_31,(P[P_32,b3]&0xff)^M_b3(k1)]&0xff)^M_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: + *

+ *

+        * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+        * 
+ * where a = primitive root of field generator 0x14D + *

+ */ + private int RS_rem(int x) + { + int b = (int) (((uint)x >> 24) & 0xff); + int g2 = ((b << 1) ^ + ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff; + int g3 = ( (int)((uint)b >> 1) ^ + ((b & 0x01) != 0 ? (int)((uint)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 M_b0(int x) + { + return x & 0xff; + } + + private int M_b1(int x) + { + return (int)((uint)x >> 8) & 0xff; + } + + private int M_b2(int x) + { + return (int)((uint)x >> 16) & 0xff; + } + + private int M_b3(int x) + { + return (int)((uint)x >> 24) & 0xff; + } + + private int Fe32_0(int x) + { + return gSBox[ 0x000 + 2*(x & 0xff) ] ^ + gSBox[ 0x001 + 2*((int)((uint)x >> 8) & 0xff) ] ^ + gSBox[ 0x200 + 2*((int)((uint)x >> 16) & 0xff) ] ^ + gSBox[ 0x201 + 2*((int)((uint)x >> 24) & 0xff) ]; + } + + private int Fe32_3(int x) + { + return gSBox[ 0x000 + 2*((int)((uint)x >> 24) & 0xff) ] ^ + gSBox[ 0x001 + 2*(x & 0xff) ] ^ + gSBox[ 0x200 + 2*((int)((uint)x >> 8) & 0xff) ] ^ + gSBox[ 0x201 + 2*((int)((uint)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 inData, byte[] b, int offset) + { + b[offset] = (byte)inData; + b[offset + 1] = (byte)(inData >> 8); + b[offset + 2] = (byte)(inData >> 16); + b[offset + 3] = (byte)(inData >> 24); + } + } + +} diff --git a/crypto/src/crypto/engines/VMPCEngine.cs b/crypto/src/crypto/engines/VMPCEngine.cs new file mode 100644 index 000000000..1c2802a80 --- /dev/null +++ b/crypto/src/crypto/engines/VMPCEngine.cs @@ -0,0 +1,140 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + public class VmpcEngine + : IStreamCipher + { + /* + * 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 virtual string AlgorithmName + { + get { 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 ArgumentException + * if the params argument is inappropriate. + */ + public virtual void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is ParametersWithIV)) + throw new ArgumentException("VMPC Init parameters must include an IV"); + + ParametersWithIV ivParams = (ParametersWithIV) parameters; + + if (!(ivParams.Parameters is KeyParameter)) + throw new ArgumentException("VMPC Init parameters must include a key"); + + KeyParameter key = (KeyParameter)ivParams.Parameters; + + this.workingIV = ivParams.GetIV(); + + if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768) + throw new ArgumentException("VMPC requires 1 to 768 bytes of IV"); + + this.workingKey = key.GetKey(); + + InitKey(this.workingKey, this.workingIV); + } + + protected virtual 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 virtual void ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] output, + int outOff) + { + if ((inOff + len) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + len) > output.Length) + { + throw new DataLengthException("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 + output[i + outOff] = (byte) (input[i + inOff] ^ z); + } + } + + public virtual void Reset() + { + InitKey(this.workingKey, this.workingIV); + } + + public virtual byte ReturnByte( + byte input) + { + 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) (input ^ z); + } + } +} diff --git a/crypto/src/crypto/engines/VMPCKSA3Engine.cs b/crypto/src/crypto/engines/VMPCKSA3Engine.cs new file mode 100644 index 000000000..95b6813b7 --- /dev/null +++ b/crypto/src/crypto/engines/VMPCKSA3Engine.cs @@ -0,0 +1,51 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Engines +{ + public class VmpcKsa3Engine + : VmpcEngine + { + public override string AlgorithmName + { + get { return "VMPC-KSA3"; } + } + + protected override 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/crypto/src/crypto/engines/XTEAEngine.cs b/crypto/src/crypto/engines/XTEAEngine.cs new file mode 100644 index 000000000..eb9291775 --- /dev/null +++ b/crypto/src/crypto/engines/XTEAEngine.cs @@ -0,0 +1,168 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * An XTEA engine. + */ + public class XteaEngine + : IBlockCipher + { + private const int + rounds = 32, + block_size = 8, +// key_size = 16, + delta = unchecked((int) 0x9E3779B9); + + /* + * the expanded key array of 4 subkeys + */ + private uint[] _S = new uint[4], + _sum0 = new uint[32], + _sum1 = new uint[32]; + private bool _initialised, _forEncryption; + + /** + * Create an instance of the TEA encryption algorithm + * and set some defaults + */ + public XteaEngine() + { + _initialised = false; + } + + public string AlgorithmName + { + get { return "XTEA"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + 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 ArgumentException if the params argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + { + throw new ArgumentException("invalid parameter passed to TEA init - " + + parameters.GetType().FullName); + } + + _forEncryption = forEncryption; + _initialised = true; + + KeyParameter p = (KeyParameter) parameters; + + setKey(p.GetKey()); + } + + public int ProcessBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + if (!_initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + if ((inOff + block_size) > inBytes.Length) + throw new DataLengthException("input buffer too short"); + + if ((outOff + block_size) > outBytes.Length) + throw new DataLengthException("output buffer too short"); + + return _forEncryption + ? encryptBlock(inBytes, inOff, outBytes, outOff) + : decryptBlock(inBytes, inOff, outBytes, outOff); + } + + public void Reset() + { + } + + /** + * Re-key the cipher. + * + * @param key the key to be used + */ + private void setKey( + byte[] key) + { + int i, j; + for (i = j = 0; i < 4; i++,j+=4) + { + _S[i] = Pack.BE_To_UInt32(key, j); + } + + for (i = j = 0; i < rounds; i++) + { + _sum0[i] = ((uint)j + _S[j & 3]); + j += delta; + _sum1[i] = ((uint)j + _S[j >> 11 & 3]); + } + } + + private int encryptBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + // Pack bytes into integers + uint v0 = Pack.BE_To_UInt32(inBytes, inOff); + uint v1 = Pack.BE_To_UInt32(inBytes, 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]; + } + + Pack.UInt32_To_BE(v0, outBytes, outOff); + Pack.UInt32_To_BE(v1, outBytes, outOff + 4); + + return block_size; + } + + private int decryptBlock( + byte[] inBytes, + int inOff, + byte[] outBytes, + int outOff) + { + // Pack bytes into integers + uint v0 = Pack.BE_To_UInt32(inBytes, inOff); + uint v1 = Pack.BE_To_UInt32(inBytes, 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]; + } + + Pack.UInt32_To_BE(v0, outBytes, outOff); + Pack.UInt32_To_BE(v1, outBytes, outOff + 4); + + return block_size; + } + } +} diff --git a/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs new file mode 100644 index 000000000..bca420711 --- /dev/null +++ b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs @@ -0,0 +1,132 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 + *
+ * This implementation is based on ISO 18033/P1363a. + */ + public class BaseKdfBytesGenerator + : IDerivationFunction + { + private int counterStart; + private IDigest digest; + private byte[] shared; + private byte[] iv; + + /** + * Construct a KDF Parameters generator. + * + * @param counterStart value of counter. + * @param digest the digest to be used as the source of derived keys. + */ + public BaseKdfBytesGenerator(int counterStart, IDigest digest) + { + this.counterStart = counterStart; + this.digest = digest; + } + + public virtual void Init(IDerivationParameters parameters) + { + if (parameters is KdfParameters) + { + KdfParameters p = (KdfParameters)parameters; + + shared = p.GetSharedSecret(); + iv = p.GetIV(); + } + else if (parameters is Iso18033KdfParameters) + { + Iso18033KdfParameters p = (Iso18033KdfParameters)parameters; + + shared = p.GetSeed(); + iv = null; + } + else + { + throw new ArgumentException("KDF parameters required for KDF Generator"); + } + } + + /** + * return the underlying digest. + */ + public virtual IDigest Digest + { + get { return digest; } + } + + /** + * fill len bytes of the output buffer with bytes generated from + * the derivation function. + * + * @throws ArgumentException if the size of the request will cause an overflow. + * @throws DataLengthException if the out buffer is too small. + */ + public virtual int GenerateBytes(byte[] output, int outOff, int length) + { + if ((output.Length - length) < outOff) + throw new DataLengthException("output buffer too small"); + + long oBytes = length; + 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 ArgumentException("Output length too large"); + + int cThreshold = (int)((oBytes + outLen - 1) / outLen); + + byte[] dig = new byte[digest.GetDigestSize()]; + + byte[] C = new byte[4]; + Pack.UInt32_To_BE((uint)counterStart, C, 0); + + uint counterBase = (uint)(counterStart & ~0xFF); + + for (int i = 0; i < cThreshold; i++) + { + digest.BlockUpdate(shared, 0, shared.Length); + digest.BlockUpdate(C, 0, 4); + + if (iv != null) + { + digest.BlockUpdate(iv, 0, iv.Length); + } + + digest.DoFinal(dig, 0); + + if (length > outLen) + { + Array.Copy(dig, 0, output, outOff, outLen); + outOff += outLen; + length -= outLen; + } + else + { + Array.Copy(dig, 0, output, outOff, length); + } + + if (++C[3] == 0) + { + counterBase += 0x100; + Pack.UInt32_To_BE(counterBase, C, 0); + } + } + + digest.Reset(); + + return (int)oBytes; + } + } +} \ No newline at end of file diff --git a/crypto/src/crypto/generators/DHBasicKeyPairGenerator.cs b/crypto/src/crypto/generators/DHBasicKeyPairGenerator.cs new file mode 100644 index 000000000..51b3af687 --- /dev/null +++ b/crypto/src/crypto/generators/DHBasicKeyPairGenerator.cs @@ -0,0 +1,38 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * a basic Diffie-Hellman key pair generator. + * + * This generates keys consistent for use with the basic algorithm for + * Diffie-Hellman. + */ + public class DHBasicKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private DHKeyGenerationParameters param; + + public virtual void Init( + KeyGenerationParameters parameters) + { + this.param = (DHKeyGenerationParameters)parameters; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance; + DHParameters dhp = param.Parameters; + + BigInteger x = helper.CalculatePrivate(dhp, param.Random); + BigInteger y = helper.CalculatePublic(dhp, x); + + return new AsymmetricCipherKeyPair( + new DHPublicKeyParameters(y, dhp), + new DHPrivateKeyParameters(x, dhp)); + } + } +} diff --git a/crypto/src/crypto/generators/DHKeyGeneratorHelper.cs b/crypto/src/crypto/generators/DHKeyGeneratorHelper.cs new file mode 100644 index 000000000..756e8482a --- /dev/null +++ b/crypto/src/crypto/generators/DHKeyGeneratorHelper.cs @@ -0,0 +1,53 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + class DHKeyGeneratorHelper + { + internal static readonly DHKeyGeneratorHelper Instance = new DHKeyGeneratorHelper(); + + private DHKeyGeneratorHelper() + { + } + + internal BigInteger CalculatePrivate( + DHParameters dhParams, + SecureRandom random) + { + int limit = dhParams.L; + + if (limit != 0) + { + return new BigInteger(limit, random).SetBit(limit - 1); + } + + BigInteger min = BigInteger.Two; + int m = dhParams.M; + if (m != 0) + { + min = BigInteger.One.ShiftLeft(m - 1); + } + + BigInteger max = dhParams.P.Subtract(BigInteger.Two); + BigInteger q = dhParams.Q; + if (q != null) + { + max = q.Subtract(BigInteger.Two); + } + + return BigIntegers.CreateRandomInRange(min, max, random); + } + + internal BigInteger CalculatePublic( + DHParameters dhParams, + BigInteger x) + { + return dhParams.G.ModPow(x, dhParams.P); + } + } +} diff --git a/crypto/src/crypto/generators/DHKeyPairGenerator.cs b/crypto/src/crypto/generators/DHKeyPairGenerator.cs new file mode 100644 index 000000000..3bf58ba1b --- /dev/null +++ b/crypto/src/crypto/generators/DHKeyPairGenerator.cs @@ -0,0 +1,38 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * 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 + : IAsymmetricCipherKeyPairGenerator + { + private DHKeyGenerationParameters param; + + public virtual void Init( + KeyGenerationParameters parameters) + { + this.param = (DHKeyGenerationParameters)parameters; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance; + DHParameters dhp = param.Parameters; + + BigInteger x = helper.CalculatePrivate(dhp, param.Random); + BigInteger y = helper.CalculatePublic(dhp, x); + + return new AsymmetricCipherKeyPair( + new DHPublicKeyParameters(y, dhp), + new DHPrivateKeyParameters(x, dhp)); + } + } +} diff --git a/crypto/src/crypto/generators/DHParametersGenerator.cs b/crypto/src/crypto/generators/DHParametersGenerator.cs new file mode 100644 index 000000000..e752c8456 --- /dev/null +++ b/crypto/src/crypto/generators/DHParametersGenerator.cs @@ -0,0 +1,45 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class DHParametersGenerator + { + private int size; + private int certainty; + private SecureRandom random; + + public virtual 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. + *

+ * Note: can take a while...

+ */ + public virtual 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, BigInteger.Two, null); + } + } +} diff --git a/crypto/src/crypto/generators/DHParametersHelper.cs b/crypto/src/crypto/generators/DHParametersHelper.cs new file mode 100644 index 000000000..a61b0817e --- /dev/null +++ b/crypto/src/crypto/generators/DHParametersHelper.cs @@ -0,0 +1,138 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + internal class DHParametersHelper + { + private static readonly BigInteger Six = BigInteger.ValueOf(6); + + private static readonly int[][] primeLists = BigInteger.primeLists; + private static readonly int[] primeProducts = BigInteger.primeProducts; + private static readonly BigInteger[] BigPrimeProducts = ConstructBigPrimeProducts(primeProducts); + + private static BigInteger[] ConstructBigPrimeProducts(int[] primeProducts) + { + BigInteger[] bpp = new BigInteger[primeProducts.Length]; + for (int i = 0; i < bpp.Length; ++i) + { + bpp[i] = BigInteger.ValueOf(primeProducts[i]); + } + return bpp; + } + + /* + * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} + * + * (see: Handbook of Applied Cryptography 4.86) + */ + internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random) + { + BigInteger p, q; + int qLength = size - 1; + + if (size <= 32) + { + for (;;) + { + q = new BigInteger(qLength, 2, random); + + p = q.ShiftLeft(1).Add(BigInteger.One); + + if (p.IsProbablePrime(certainty) + && (certainty <= 2 || q.IsProbablePrime(certainty))) + break; + } + } + else + { + // Note: Modified from Java version for speed + for (;;) + { + q = new BigInteger(qLength, 0, random); + + retry: + for (int i = 0; i < primeLists.Length; ++i) + { + int test = q.Remainder(BigPrimeProducts[i]).IntValue; + + if (i == 0) + { + int rem3 = test % 3; + if (rem3 != 2) + { + int diff = 2 * rem3 + 2; + q = q.Add(BigInteger.ValueOf(diff)); + test = (test + diff) % primeProducts[i]; + } + } + + int[] primeList = primeLists[i]; + for (int j = 0; j < primeList.Length; ++j) + { + int prime = primeList[j]; + int qRem = test % prime; + if (qRem == 0 || qRem == (prime >> 1)) + { + q = q.Add(Six); + goto retry; + } + } + } + + + if (q.BitLength != qLength) + continue; + + if (!q.RabinMillerTest(2, random)) + continue; + + p = q.ShiftLeft(1).Add(BigInteger.One); + + if (p.RabinMillerTest(certainty, random) + && (certainty <= 2 || q.RabinMillerTest(certainty - 2, random))) + 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) + */ + internal static BigInteger SelectGenerator(BigInteger p, BigInteger q, SecureRandom random) + { + BigInteger pMinusTwo = p.Subtract(BigInteger.Two); + BigInteger g; + + /* + * (see: Handbook of Applied Cryptography 4.80) + */ +// do +// { +// g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random); +// } +// while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One) +// || g.ModPow(q, p).Equals(BigInteger.One)); + + /* + * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81) + */ + do + { + BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random); + + g = h.ModPow(BigInteger.Two, p); + } + while (g.Equals(BigInteger.One)); + + return g; + } + } +} diff --git a/crypto/src/crypto/generators/DesEdeKeyGenerator.cs b/crypto/src/crypto/generators/DesEdeKeyGenerator.cs new file mode 100644 index 000000000..5902643fd --- /dev/null +++ b/crypto/src/crypto/generators/DesEdeKeyGenerator.cs @@ -0,0 +1,67 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class DesEdeKeyGenerator + : DesKeyGenerator + { + public DesEdeKeyGenerator() + { + } + + internal DesEdeKeyGenerator( + int defaultStrength) + : base(defaultStrength) + { + } + + /** + * 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 + */ + protected override void engineInit( + KeyGenerationParameters parameters) + { + this.random = parameters.Random; + this.strength = (parameters.Strength + 7) / 8; + + if (strength == 0 || strength == (168 / 8)) + { + strength = DesEdeParameters.DesEdeKeyLength; + } + else if (strength == (112 / 8)) + { + strength = 2 * DesEdeParameters.DesKeyLength; + } + else if (strength != DesEdeParameters.DesEdeKeyLength + && strength != (2 * DesEdeParameters.DesKeyLength)) + { + throw new ArgumentException("DESede key must be " + + (DesEdeParameters.DesEdeKeyLength * 8) + " or " + + (2 * 8 * DesEdeParameters.DesKeyLength) + + " bits long."); + } + } + + protected override byte[] engineGenerateKey() + { + byte[] newKey; + + do + { + newKey = random.GenerateSeed(strength); + DesEdeParameters.SetOddParity(newKey); + } + while (DesEdeParameters.IsWeakKey(newKey, 0, newKey.Length)); + + return newKey; + } + } +} diff --git a/crypto/src/crypto/generators/DesKeyGenerator.cs b/crypto/src/crypto/generators/DesKeyGenerator.cs new file mode 100644 index 000000000..154e3471a --- /dev/null +++ b/crypto/src/crypto/generators/DesKeyGenerator.cs @@ -0,0 +1,57 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class DesKeyGenerator + : CipherKeyGenerator + { + public DesKeyGenerator() + { + } + + internal DesKeyGenerator( + int defaultStrength) + : base(defaultStrength) + { + } + + /** + * 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 + */ + protected override void engineInit( + KeyGenerationParameters parameters) + { + base.engineInit(parameters); + + if (strength == 0 || strength == (56 / 8)) + { + strength = DesParameters.DesKeyLength; + } + else if (strength != DesParameters.DesKeyLength) + { + throw new ArgumentException( + "DES key must be " + (DesParameters.DesKeyLength * 8) + " bits long."); + } + } + + protected override byte[] engineGenerateKey() + { + byte[] newKey; + + do + { + newKey = random.GenerateSeed(DesParameters.DesKeyLength); + DesParameters.SetOddParity(newKey); + } + while (DesParameters.IsWeakKey(newKey, 0)); + + return newKey; + } + } +} diff --git a/crypto/src/crypto/generators/DsaKeyPairGenerator.cs b/crypto/src/crypto/generators/DsaKeyPairGenerator.cs new file mode 100644 index 000000000..bb8ec591b --- /dev/null +++ b/crypto/src/crypto/generators/DsaKeyPairGenerator.cs @@ -0,0 +1,61 @@ +using System; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * a DSA key pair generator. + * + * This Generates DSA keys in line with the method described + * in FIPS 186-3 B.1 FFC Key Pair Generation. + */ + public class DsaKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private DsaKeyGenerationParameters param; + + public void Init( + KeyGenerationParameters parameters) + { + if (parameters == null) + throw new ArgumentNullException("parameters"); + + // Note: If we start accepting instances of KeyGenerationParameters, + // must apply constraint checking on strength (see DsaParametersGenerator.Init) + + this.param = (DsaKeyGenerationParameters) parameters; + } + + public AsymmetricCipherKeyPair GenerateKeyPair() + { + DsaParameters dsaParams = param.Parameters; + + BigInteger x = GeneratePrivateKey(dsaParams.Q, param.Random); + BigInteger y = CalculatePublicKey(dsaParams.P, dsaParams.G, x); + + return new AsymmetricCipherKeyPair( + new DsaPublicKeyParameters(y, dsaParams), + new DsaPrivateKeyParameters(x, dsaParams)); + } + + private static BigInteger GeneratePrivateKey(BigInteger q, SecureRandom random) + { + // TODO Prefer this method? (change test cases that used fixed random) + // B.1.1 Key Pair Generation Using Extra Random Bits +// BigInteger c = new BigInteger(q.BitLength + 64, random); +// return c.Mod(q.Subtract(BigInteger.One)).Add(BigInteger.One); + + // B.1.2 Key Pair Generation by Testing Candidates + return BigIntegers.CreateRandomInRange(BigInteger.One, q.Subtract(BigInteger.One), random); + } + + private static BigInteger CalculatePublicKey(BigInteger p, BigInteger g, BigInteger x) + { + return g.ModPow(x, p); + } + } +} diff --git a/crypto/src/crypto/generators/DsaParametersGenerator.cs b/crypto/src/crypto/generators/DsaParametersGenerator.cs new file mode 100644 index 000000000..cf6343a16 --- /dev/null +++ b/crypto/src/crypto/generators/DsaParametersGenerator.cs @@ -0,0 +1,390 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3. + */ + public class DsaParametersGenerator + { + private IDigest digest; + private int L, N; + private int certainty; + private SecureRandom random; + private bool use186_3; + private int usageIndex; + + public DsaParametersGenerator() + : this(new Sha1Digest()) + { + } + + public DsaParametersGenerator(IDigest digest) + { + this.digest = digest; + } + + /** + * initialise the key generator. + * + * @param size size of the key (range 2^512 -> 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 virtual void Init( + int size, + int certainty, + SecureRandom random) + { + if (!IsValidDsaStrength(size)) + throw new ArgumentException("size must be from 512 - 1024 and a multiple of 64", "size"); + + this.use186_3 = false; + this.L = size; + this.N = GetDefaultN(size); + this.certainty = certainty; + this.random = random; + } + + /** + * Initialise the key generator for DSA 2. + *

+ * Use this init method if you need to generate parameters for DSA 2 keys. + *

+ * + * @param params DSA 2 key generation parameters. + */ + public virtual void Init(DsaParameterGenerationParameters parameters) + { + // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1? + this.use186_3 = true; + this.L = parameters.L; + this.N = parameters.N; + this.certainty = parameters.Certainty; + this.random = parameters.Random; + this.usageIndex = parameters.UsageIndex; + + if ((L < 1024 || L > 3072) || L % 1024 != 0) + throw new ArgumentException("Values must be between 1024 and 3072 and a multiple of 1024", "L"); + if (L == 1024 && N != 160) + throw new ArgumentException("N must be 160 for L = 1024"); + if (L == 2048 && (N != 224 && N != 256)) + throw new ArgumentException("N must be 224 or 256 for L = 2048"); + if (L == 3072 && N != 256) + throw new ArgumentException("N must be 256 for L = 3072"); + + if (digest.GetDigestSize() * 8 < N) + throw new InvalidOperationException("Digest output size too small for value of N"); + } + +// /** +// * add value to b, returning the result in a. The a value is treated +// * as a BigInteger of length (a.Length * 8) bits. The result is +// * modulo 2^a.Length in case of overflow. +// */ +// private static void Add( +// byte[] a, +// byte[] b, +// int value) +// { +// int x = (b[b.Length - 1] & 0xff) + value; +// +// a[b.Length - 1] = (byte)x; +// x = (int) ((uint) x >>8); +// +// for (int i = b.Length - 2; i >= 0; i--) +// { +// x += (b[i] & 0xff); +// a[i] = (byte)x; +// x = (int) ((uint) x >>8); +// } +// } + + /** + * which Generates the p and g values from the given parameters, + * returning the DsaParameters object. + *

+ * Note: can take a while...

+ */ + public virtual DsaParameters GenerateParameters() + { + return use186_3 + ? GenerateParameters_FIPS186_3() + : GenerateParameters_FIPS186_2(); + } + + protected virtual 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 is Sha1Digest)) + throw new InvalidOperationException("can only use SHA-1 for generating FIPS 186-2 parameters"); + + for (;;) + { + random.NextBytes(seed); + + Hash(digest, seed, part1); + Array.Copy(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); + Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length); + } + + Inc(offset); + Hash(digest, offset, part1); + Array.Copy(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(BigInteger.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)); + } + } + } + } + + protected virtual BigInteger CalculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r) + { + BigInteger e = p.Subtract(BigInteger.One).Divide(q); + BigInteger pSub2 = p.Subtract(BigInteger.Two); + + for (;;) + { + BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pSub2, r); + BigInteger g = h.ModPow(e, p); + + if (g.BitLength > 1) + return g; + } + } + + /** + * generate suitable parameters for DSA, in line with + * FIPS 186-3 A.1 Generation of the FFC Primes p and q. + */ + protected virtual DsaParameters GenerateParameters_FIPS186_3() + { +// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function + IDigest 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(BigInteger.One.ShiftLeft(N - 1)); + +// 7. q = 2^(N–1) + U + 1 – ( U mod 2). + BigInteger q = BigInteger.One.ShiftLeft(N - 1).Add(U).Add(BigInteger.One).Subtract( + U.Mod(BigInteger.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 = BigInteger.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(BigInteger.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(BigInteger.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(BigInteger.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. + // TODO Make configurable (8-bit unsigned)? + + 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. + } + } + + protected virtual BigInteger CalculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q, + SecureRandom r) + { + return CalculateGenerator_FIPS186_2(p, q, r); + } + + protected virtual BigInteger CalculateGenerator_FIPS186_3_Verifiable(IDigest d, BigInteger p, BigInteger q, + byte[] seed, int index) + { + // A.2.3 Verifiable Canonical Generation of the Generator g + BigInteger e = p.Subtract(BigInteger.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]; + Array.Copy(seed, 0, U, 0, seed.Length); + Array.Copy(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(BigInteger.Two) >= 0) + return g; + } + + return null; + } + + private static bool IsValidDsaStrength( + int strength) + { + return strength >= 512 && strength <= 1024 && strength % 64 == 0; + } + + protected static void Hash(IDigest d, byte[] input, byte[] output) + { + d.BlockUpdate(input, 0, input.Length); + d.DoFinal(output, 0); + } + + private static int GetDefaultN(int L) + { + return L > 1024 ? 256 : 160; + } + + protected static void Inc(byte[] buf) + { + for (int i = buf.Length - 1; i >= 0; --i) + { + byte b = (byte)(buf[i] + 1); + buf[i] = b; + + if (b != 0) + break; + } + } + } +} diff --git a/crypto/src/crypto/generators/ECKeyPairGenerator.cs b/crypto/src/crypto/generators/ECKeyPairGenerator.cs new file mode 100644 index 000000000..8f2b1c2b5 --- /dev/null +++ b/crypto/src/crypto/generators/ECKeyPairGenerator.cs @@ -0,0 +1,153 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class ECKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private readonly string algorithm; + + private ECDomainParameters parameters; + private DerObjectIdentifier publicKeyParamSet; + private SecureRandom random; + + public ECKeyPairGenerator() + : this("EC") + { + } + + public ECKeyPairGenerator( + string algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + this.algorithm = ECKeyParameters.VerifyAlgorithmName(algorithm); + } + + public void Init( + KeyGenerationParameters parameters) + { + if (parameters is ECKeyGenerationParameters) + { + ECKeyGenerationParameters ecP = (ECKeyGenerationParameters) parameters; + + this.publicKeyParamSet = ecP.PublicKeyParamSet; + this.parameters = ecP.DomainParameters; + } + else + { + DerObjectIdentifier oid; + switch (parameters.Strength) + { + case 192: + oid = X9ObjectIdentifiers.Prime192v1; + break; + case 224: + oid = SecObjectIdentifiers.SecP224r1; + break; + case 239: + oid = X9ObjectIdentifiers.Prime239v1; + break; + case 256: + oid = X9ObjectIdentifiers.Prime256v1; + break; + case 384: + oid = SecObjectIdentifiers.SecP384r1; + break; + case 521: + oid = SecObjectIdentifiers.SecP521r1; + break; + default: + throw new InvalidParameterException("unknown key size."); + } + + X9ECParameters ecps = FindECCurveByOid(oid); + + this.parameters = new ECDomainParameters( + ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed()); + } + + this.random = parameters.Random; + } + + /** + * 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 = parameters.N; + BigInteger d; + + do + { + d = new BigInteger(n.BitLength, random); + } + while (d.SignValue == 0 || (d.CompareTo(n) >= 0)); + + ECPoint q = parameters.G.Multiply(d); + + if (publicKeyParamSet != null) + { + return new AsymmetricCipherKeyPair( + new ECPublicKeyParameters(algorithm, q, publicKeyParamSet), + new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet)); + } + + return new AsymmetricCipherKeyPair( + new ECPublicKeyParameters(algorithm, q, parameters), + new ECPrivateKeyParameters(algorithm, d, parameters)); + } + + internal static X9ECParameters FindECCurveByOid(DerObjectIdentifier oid) + { + // TODO ECGost3410NamedCurves support (returns ECDomainParameters though) + + X9ECParameters ecP = X962NamedCurves.GetByOid(oid); + + if (ecP == null) + { + ecP = SecNamedCurves.GetByOid(oid); + + if (ecP == null) + { + ecP = NistNamedCurves.GetByOid(oid); + + if (ecP == null) + { + ecP = TeleTrusTNamedCurves.GetByOid(oid); + } + } + } + + return ecP; + } + + internal static ECPublicKeyParameters GetCorrespondingPublicKey( + ECPrivateKeyParameters privKey) + { + ECDomainParameters parameters = privKey.Parameters; + ECPoint q = parameters.G.Multiply(privKey.D); + + if (privKey.PublicKeyParamSet != null) + { + return new ECPublicKeyParameters(privKey.AlgorithmName, q, privKey.PublicKeyParamSet); + } + + return new ECPublicKeyParameters(privKey.AlgorithmName, q, parameters); + } + } +} diff --git a/crypto/src/crypto/generators/ElGamalKeyPairGenerator.cs b/crypto/src/crypto/generators/ElGamalKeyPairGenerator.cs new file mode 100644 index 000000000..227e7fe94 --- /dev/null +++ b/crypto/src/crypto/generators/ElGamalKeyPairGenerator.cs @@ -0,0 +1,40 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * a ElGamal key pair generator. + *

+ * This Generates keys consistent for use with ElGamal as described in + * page 164 of "Handbook of Applied Cryptography".

+ */ + public class ElGamalKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private ElGamalKeyGenerationParameters param; + + public void Init( + KeyGenerationParameters parameters) + { + this.param = (ElGamalKeyGenerationParameters) parameters; + } + + public AsymmetricCipherKeyPair GenerateKeyPair() + { + DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance; + ElGamalParameters egp = param.Parameters; + DHParameters dhp = new DHParameters(egp.P, egp.G, null, 0, egp.L); + + BigInteger x = helper.CalculatePrivate(dhp, param.Random); + BigInteger y = helper.CalculatePublic(dhp, x); + + return new AsymmetricCipherKeyPair( + new ElGamalPublicKeyParameters(y, egp), + new ElGamalPrivateKeyParameters(x, egp)); + } + } + +} diff --git a/crypto/src/crypto/generators/ElGamalParametersGenerator.cs b/crypto/src/crypto/generators/ElGamalParametersGenerator.cs new file mode 100644 index 000000000..8443bb00e --- /dev/null +++ b/crypto/src/crypto/generators/ElGamalParametersGenerator.cs @@ -0,0 +1,46 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + 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. + *

+ * 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/crypto/src/crypto/generators/GOST3410KeyPairGenerator.cs b/crypto/src/crypto/generators/GOST3410KeyPairGenerator.cs new file mode 100644 index 000000000..5878da64b --- /dev/null +++ b/crypto/src/crypto/generators/GOST3410KeyPairGenerator.cs @@ -0,0 +1,73 @@ +using System; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * a GOST3410 key pair generator. + * This generates GOST3410 keys in line with the method described + * in GOST R 34.10-94. + */ + public class Gost3410KeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private Gost3410KeyGenerationParameters param; + + public void Init( + KeyGenerationParameters parameters) + { + if (parameters is Gost3410KeyGenerationParameters) + { + this.param = (Gost3410KeyGenerationParameters) parameters; + } + else + { + Gost3410KeyGenerationParameters kgp = new Gost3410KeyGenerationParameters( + parameters.Random, + CryptoProObjectIdentifiers.GostR3410x94CryptoProA); + + if (parameters.Strength != kgp.Parameters.P.BitLength - 1) + { + // TODO Should we complain? + } + + this.param = kgp; + } + } + + public AsymmetricCipherKeyPair GenerateKeyPair() + { + SecureRandom random = param.Random; + Gost3410Parameters gost3410Params = param.Parameters; + + BigInteger q = gost3410Params.Q; + BigInteger x; + do + { + x = new BigInteger(256, random); + } + while (x.SignValue < 1 || x.CompareTo(q) >= 0); + + BigInteger p = gost3410Params.P; + BigInteger a = gost3410Params.A; + + // calculate the public key. + BigInteger y = a.ModPow(x, p); + + if (param.PublicKeyParamSet != null) + { + return new AsymmetricCipherKeyPair( + new Gost3410PublicKeyParameters(y, param.PublicKeyParamSet), + new Gost3410PrivateKeyParameters(x, param.PublicKeyParamSet)); + } + + return new AsymmetricCipherKeyPair( + new Gost3410PublicKeyParameters(y, gost3410Params), + new Gost3410PrivateKeyParameters(x, gost3410Params)); + } + } +} diff --git a/crypto/src/crypto/generators/GOST3410ParametersGenerator.cs b/crypto/src/crypto/generators/GOST3410ParametersGenerator.cs new file mode 100644 index 000000000..52a9f5a82 --- /dev/null +++ b/crypto/src/crypto/generators/GOST3410ParametersGenerator.cs @@ -0,0 +1,530 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * generate suitable parameters for GOST3410. + */ + public class Gost3410ParametersGenerator + { + private int size; + private int typeproc; + private SecureRandom init_random; + + /** + * initialise the key generator. + * + * @param size size of the key + * @param typeProcedure type procedure A,B = 1; A',B' - else + * @param random random byte source. + */ + public void Init( + int size, + int typeProcedure, + SecureRandom random) + { + this.size = size; + this.typeproc = typeProcedure; + this.init_random = random; + } + + //Procedure A + private int procedure_A(int x0, int c, BigInteger[] pq, int size) + { + //Verify and perform condition: 065536) + { + x0 = init_random.NextInt()/32768; + } + + while((c<0 || c>65536) || (c/2==0)) + { + c = init_random.NextInt()/32768 + 1; + } + + BigInteger C = BigInteger.ValueOf(c); + BigInteger constA16 = BigInteger.ValueOf(19381); + + //step1 + BigInteger[] y = new BigInteger[1]; // begin length = 1 + y[0] = BigInteger.ValueOf(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]; /////////////// + Array.Copy(t,0,tmp_t,0,t.Length); // extension + t = new int[tmp_t.Length]; // array t + Array.Copy(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 t[m]) + { + goto step6; //step 12 + } + + p[m] = NByLastP.Add(BigInteger.One); + + //step13 + if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0 + && BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0) + { + break; + } + + N = N.Add(BigInteger.Two); + } + + if (--m < 0) + { + pq[0] = p[0]; + pq[1] = p[1]; + return y[0].IntValue; //return for procedure B step 2 + } + + break; //step 14 + } + } + return y[0].IntValue; + } + + //Procedure A' + private long procedure_Aa(long x0, long c, BigInteger[] pq, int size) + { + //Verify and perform condition: 04294967296L) + { + x0 = init_random.NextInt()*2; + } + + while((c<0 || c>4294967296L) || (c/2==0)) + { + c = init_random.NextInt()*2+1; + } + + BigInteger C = BigInteger.ValueOf(c); + BigInteger constA32 = BigInteger.ValueOf(97781173); + + //step1 + BigInteger[] y = new BigInteger[1]; // begin length = 1 + y[0] = BigInteger.ValueOf(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]; /////////////// + Array.Copy(t,0,tmp_t,0,t.Length); // extension + t = new int[tmp_t.Length]; // array t + Array.Copy(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 t[m]) + { + goto step6; //step 12 + } + + p[m] = NByLastP.Add(BigInteger.One); + + //step13 + if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0 + && BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0) + { + break; + } + + N = N.Add(BigInteger.Two); + } + + if (--m < 0) + { + pq[0] = p[0]; + pq[1] = p[1]; + return y[0].LongValue; //return for procedure B' step 2 + } + + break; //step 14 + } + } + return y[0].LongValue; + } + + //Procedure B + private void procedure_B(int x0, int c, BigInteger[] pq) + { + //Verify and perform condition: 065536) + { + 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 = BigInteger.ValueOf(c); + BigInteger constA16 = BigInteger.ValueOf(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] = BigInteger.ValueOf(x0); + + const int tp = 1024; + + BigInteger qQ = q.Multiply(Q); + +step3: + for(;;) + { + //step 3 + for (int j=0; j<64; j++) + { + y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16)); + } + + //step 4 + BigInteger Y = BigInteger.Zero; + + for (int j=0; j<64; j++) + { + Y = Y.Add(y[j].ShiftLeft(16*j)); + } + + y[0] = y[64]; //step 5 + + //step 6 + BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add( + Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024))); + + if (N.TestBit(0)) + { + N = N.Add(BigInteger.One); + } + + //step 7 + + for(;;) + { + //step 11 + BigInteger qQN = qQ.Multiply(N); + + if (qQN.BitLength > tp) + { + goto step3; //step 9 + } + + p = qQN.Add(BigInteger.One); + + //step10 + if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0 + && BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0) + { + pq[0] = p; + pq[1] = q; + return; + } + + N = N.Add(BigInteger.Two); + } + } + } + + //Procedure B' + private void procedure_Bb(long x0, long c, BigInteger[] pq) + { + //Verify and perform condition: 04294967296L) + { + 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 = BigInteger.ValueOf(c); + BigInteger constA32 = BigInteger.ValueOf(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] = BigInteger.ValueOf(x0); + + const int tp = 1024; + + BigInteger qQ = q.Multiply(Q); + +step3: + for(;;) + { + //step 3 + for (int j=0; j<32; j++) + { + y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32)); + } + + //step 4 + BigInteger Y = BigInteger.Zero; + for (int j=0; j<32; j++) + { + Y = Y.Add(y[j].ShiftLeft(32*j)); + } + + y[0] = y[32]; //step 5 + + //step 6 + BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add( + Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024))); + + if (N.TestBit(0)) + { + N = N.Add(BigInteger.One); + } + + //step 7 + + for(;;) + { + //step 11 + BigInteger qQN = qQ.Multiply(N); + + if (qQN.BitLength > tp) + { + goto step3; //step 9 + } + + p = qQN.Add(BigInteger.One); + + //step10 + if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0 + && BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0) + { + pq[0] = p; + pq[1] = q; + return; + } + + N = N.Add(BigInteger.Two); + } + } + } + + + /** + * 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(BigInteger.One); + BigInteger pSub1Divq = pSub1.Divide(q); + + for(;;) + { + BigInteger d = new BigInteger(p.BitLength, init_random); + + // 1 < d < p-1 + if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0) + { + BigInteger a = d.ModPow(pSub1Divq, p); + + if (a.CompareTo(BigInteger.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 ArgumentException("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 InvalidOperationException("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/crypto/src/crypto/generators/Kdf1BytesGenerator.cs b/crypto/src/crypto/generators/Kdf1BytesGenerator.cs new file mode 100644 index 000000000..0ddf6c166 --- /dev/null +++ b/crypto/src/crypto/generators/Kdf1BytesGenerator.cs @@ -0,0 +1,26 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 + *
+ * This implementation is based on IEEE P1363/ISO 18033. + */ + public class Kdf1BytesGenerator + : BaseKdfBytesGenerator + { + /** + * Construct a KDF1 byte generator. + * + * @param digest the digest to be used as the source of derived keys. + */ + public Kdf1BytesGenerator(IDigest digest) + : base(0, digest) + { + } + } +} diff --git a/crypto/src/crypto/generators/Kdf2BytesGenerator.cs b/crypto/src/crypto/generators/Kdf2BytesGenerator.cs new file mode 100644 index 000000000..8a6821980 --- /dev/null +++ b/crypto/src/crypto/generators/Kdf2BytesGenerator.cs @@ -0,0 +1,27 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 + *
+ * This implementation is based on IEEE P1363/ISO 18033. + */ + public class Kdf2BytesGenerator + : BaseKdfBytesGenerator + { + /** + * Construct a KDF2 bytes generator. Generates key material + * according to IEEE P1363 or ISO 18033 depending on the initialisation. + * + * @param digest the digest to be used as the source of derived keys. + */ + public Kdf2BytesGenerator(IDigest digest) + : base(1, digest) + { + } + } +} diff --git a/crypto/src/crypto/generators/Mgf1BytesGenerator.cs b/crypto/src/crypto/generators/Mgf1BytesGenerator.cs new file mode 100644 index 000000000..23a3aca25 --- /dev/null +++ b/crypto/src/crypto/generators/Mgf1BytesGenerator.cs @@ -0,0 +1,117 @@ +using System; +//using Org.BouncyCastle.Math; +//using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * Generator for MGF1 as defined in Pkcs 1v2 + */ + public class Mgf1BytesGenerator : IDerivationFunction + { + private IDigest digest; + private byte[] seed; + private int hLen; + + /** + * @param digest the digest to be used as the source of Generated bytes + */ + public Mgf1BytesGenerator( + IDigest digest) + { + this.digest = digest; + this.hLen = digest.GetDigestSize(); + } + + public void Init( + IDerivationParameters parameters) + { + if (!(typeof(MgfParameters).IsInstanceOfType(parameters))) + { + throw new ArgumentException("MGF parameters required for MGF1Generator"); + } + + MgfParameters p = (MgfParameters)parameters; + + seed = p.GetSeed(); + } + + /** + * return the underlying digest. + */ + public IDigest Digest + { + get + { + return digest; + } + } + + /** + * int to octet string. + */ + private void ItoOSP( + int i, + byte[] sp) + { + sp[0] = (byte)((uint) i >> 24); + sp[1] = (byte)((uint) i >> 16); + sp[2] = (byte)((uint) i >> 8); + sp[3] = (byte)((uint) 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[] output, + int outOff, + int length) + { + if ((output.Length - length) < outOff) + { + throw new DataLengthException("output buffer too small"); + } + + byte[] hashBuf = new byte[hLen]; + byte[] C = new byte[4]; + int counter = 0; + + digest.Reset(); + + if (length > hLen) + { + do + { + ItoOSP(counter, C); + + digest.BlockUpdate(seed, 0, seed.Length); + digest.BlockUpdate(C, 0, C.Length); + digest.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, output, outOff + counter * hLen, hLen); + } + while (++counter < (length / hLen)); + } + + if ((counter * hLen) < length) + { + ItoOSP(counter, C); + + digest.BlockUpdate(seed, 0, seed.Length); + digest.BlockUpdate(C, 0, C.Length); + digest.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, output, outOff + counter * hLen, length - (counter * hLen)); + } + + return length; + } + } + +} diff --git a/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs b/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs new file mode 100644 index 000000000..7011cf253 --- /dev/null +++ b/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs @@ -0,0 +1,333 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * 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 + : IAsymmetricCipherKeyPairGenerator + { + private static readonly 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; + + /* + * (non-Javadoc) + * + * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.bouncycastle.crypto.KeyGenerationParameters) + */ + public void Init(KeyGenerationParameters parameters) + { + this.param = (NaccacheSternKeyGenerationParameters)parameters; + } + + /* + * (non-Javadoc) + * + * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair() + */ + public AsymmetricCipherKeyPair GenerateKeyPair() + { + int strength = param.Strength; + SecureRandom rand = param.Random; + int certainty = param.Certainty; + bool debug = param.IsDebug; + + if (debug) + { + Console.WriteLine("Fetching first " + param.CountSmallPrimes + " primes."); + } + + IList smallPrimes = findFirstPrimes(param.CountSmallPrimes); + + smallPrimes = permuteList(smallPrimes, rand); + + BigInteger u = BigInteger.One; + BigInteger v = BigInteger.One; + + for (int i = 0; i < smallPrimes.Count / 2; i++) + { + u = u.Multiply((BigInteger)smallPrimes[i]); + } + for (int i = smallPrimes.Count / 2; i < smallPrimes.Count; i++) + { + v = v.Multiply((BigInteger)smallPrimes[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) + { + Console.WriteLine("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(BigInteger.One); + + if (!p.IsProbablePrime(certainty)) + continue; + + for (;;) + { + _q = generatePrime(24, certainty, rand); + + if (_p.Equals(_q)) + continue; + + q = _q.Multiply(_2bv).Add(BigInteger.One); + + if (q.IsProbablePrime(certainty)) + break; + } + + if (!sigma.Gcd(_p.Multiply(_q)).Equals(BigInteger.One)) + { + Console.WriteLine("sigma.gcd(_p.mult(_q)) != 1!\n _p: " + _p +"\n _q: "+ _q ); + continue; + } + + if (p.Multiply(q).BitLength < strength) + { + if (debug) + { + Console.WriteLine("key size too small. Should be " + strength + " but is actually " + + p.Multiply(q).BitLength); + } + continue; + } + break; + } + + if (debug) + { + Console.WriteLine("needed " + tries + " tries to generate p and q."); + } + + BigInteger n = p.Multiply(q); + BigInteger phi_n = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One)); + BigInteger g; + tries = 0; + if (debug) + { + Console.WriteLine("generating g"); + } + for (;;) + { + // TODO After the first loop, just regenerate one randomly-selected gPart each time? + IList gParts = Platform.CreateArrayList(); + for (int ind = 0; ind != smallPrimes.Count; ind++) + { + BigInteger i = (BigInteger)smallPrimes[ind]; + BigInteger e = phi_n.Divide(i); + + for (;;) + { + tries++; + + g = generatePrime(strength, certainty, rand); + + if (!g.ModPow(e, n).Equals(BigInteger.One)) + { + gParts.Add(g); + break; + } + } + } + g = BigInteger.One; + for (int i = 0; i < smallPrimes.Count; i++) + { + BigInteger gPart = (BigInteger) gParts[i]; + BigInteger smallPrime = (BigInteger) smallPrimes[i]; + g = g.Multiply(gPart.ModPow(sigma.Divide(smallPrime), n)).Mod(n); + } + + // make sure that g is not divisible by p_i or q_i + bool divisible = false; + for (int i = 0; i < smallPrimes.Count; i++) + { + if (g.ModPow(phi_n.Divide((BigInteger)smallPrimes[i]), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/" + smallPrimes[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(BigInteger.One)) + if (g.ModPow(phi_n.ShiftRight(2), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/4\n g:" + g); + } + continue; + } + + if (g.ModPow(phi_n.Divide(_p), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/p'\n g: " + g); + } + continue; + } + if (g.ModPow(phi_n.Divide(_q), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/q'\n g: " + g); + } + continue; + } + if (g.ModPow(phi_n.Divide(a), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/a\n g: " + g); + } + continue; + } + if (g.ModPow(phi_n.Divide(b), n).Equals(BigInteger.One)) + { + if (debug) + { + Console.WriteLine("g has order phi(n)/b\n g: " + g); + } + continue; + } + break; + } + if (debug) + { + Console.WriteLine("needed " + tries + " tries to generate g"); + Console.WriteLine(); + Console.WriteLine("found new NaccacheStern cipher variables:"); + Console.WriteLine("smallPrimes: " + CollectionUtilities.ToString(smallPrimes)); + Console.WriteLine("sigma:...... " + sigma + " (" + sigma.BitLength + " bits)"); + Console.WriteLine("a:.......... " + a); + Console.WriteLine("b:.......... " + b); + Console.WriteLine("p':......... " + _p); + Console.WriteLine("q':......... " + _q); + Console.WriteLine("p:.......... " + p); + Console.WriteLine("q:.......... " + q); + Console.WriteLine("n:.......... " + n); + Console.WriteLine("phi(n):..... " + phi_n); + Console.WriteLine("g:.......... " + g); + Console.WriteLine(); + } + + 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) + { + return new BigInteger(bitLength, certainty, rand); + } + + /** + * 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 IList with the permuted elements. + */ + private static IList permuteList( + IList arr, + SecureRandom rand) + { + // TODO Create a utility method for generating permutation of first 'n' integers + + IList retval = Platform.CreateArrayList(arr.Count); + + foreach (object element in arr) + { + int index = rand.Next(retval.Count + 1); + retval.Insert(index, element); + } + + return retval; + } + + /** + * 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 IList findFirstPrimes( + int count) + { + IList primes = Platform.CreateArrayList(count); + + for (int i = 0; i != count; i++) + { + primes.Add(BigInteger.ValueOf(smallPrimes[i])); + } + + return primes; + } + + } +} diff --git a/crypto/src/crypto/generators/OpenSSLPBEParametersGenerator.cs b/crypto/src/crypto/generators/OpenSSLPBEParametersGenerator.cs new file mode 100644 index 000000000..8da5d3ad1 --- /dev/null +++ b/crypto/src/crypto/generators/OpenSSLPBEParametersGenerator.cs @@ -0,0 +1,167 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * Generator for PBE derived keys and ivs as usd by OpenSSL. + *

+ * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an + * iteration count of 1. + *

+ */ + public class OpenSslPbeParametersGenerator + : PbeParametersGenerator + { + private readonly IDigest digest = new MD5Digest(); + + /** + * Construct a OpenSSL Parameters generator. + */ + public OpenSslPbeParametersGenerator() + { + } + + public override void Init( + byte[] password, + byte[] salt, + int iterationCount) + { + // Ignore the provided iterationCount + base.Init(password, salt, 1); + } + + /** + * Initialise - note the iteration count for this algorithm is fixed at 1. + * + * @param password password to use. + * @param salt salt to use. + */ + public virtual void Init( + byte[] password, + byte[] salt) + { + base.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.BlockUpdate(mPassword, 0, mPassword.Length); + digest.BlockUpdate(mSalt, 0, mSalt.Length); + + digest.DoFinal(buf, 0); + + int len = (bytesNeeded > buf.Length) ? buf.Length : bytesNeeded; + Array.Copy(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.BlockUpdate(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 ArgumentException if the key length larger than the base hash size. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize) + { + return GenerateDerivedMacParameters(keySize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize); + + return ParameterUtilities.CreateKeyParameter(algorithm, 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 ArgumentException if keySize + ivSize is larger than the base hash size. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters 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); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize + ivSize); + KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize); + + return new ParametersWithIV(key, 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 ArgumentException if the key length larger than the base hash size. + */ + public override ICipherParameters GenerateDerivedMacParameters( + int keySize) + { + keySize = keySize / 8; + + byte[] dKey = GenerateDerivedKey(keySize); + + return new KeyParameter(dKey, 0, keySize); + } + } +} diff --git a/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs new file mode 100644 index 000000000..cbbfd1b3b --- /dev/null +++ b/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs @@ -0,0 +1,245 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * Generator for Pbe derived keys and ivs as defined by Pkcs 12 V1.0. + *

+ * The document this implementation is based on can be found at + * + * RSA's Pkcs12 Page + *

+ */ + public class Pkcs12ParametersGenerator + : PbeParametersGenerator + { + public const int KeyMaterial = 1; + public const int IVMaterial = 2; + public const int MacMaterial = 3; + + private readonly IDigest digest; + + private readonly int u; + private readonly int v; + + /** + * Construct a Pkcs 12 Parameters generator. + * + * @param digest the digest to be used as the source of derived keys. + * @exception ArgumentException if an unknown digest is passed in. + */ + public Pkcs12ParametersGenerator( + IDigest digest) + { + this.digest = digest; + + u = digest.GetDigestSize(); + v = digest.GetByteLength(); + } + + /** + * 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 = (int) ((uint) 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 = (int) ((uint) 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 ((mSalt != null) && (mSalt.Length != 0)) + { + S = new byte[v * ((mSalt.Length + v - 1) / v)]; + + for (int i = 0; i != S.Length; i++) + { + S[i] = mSalt[i % mSalt.Length]; + } + } + else + { + S = new byte[0]; + } + + byte[] P; + + if ((mPassword != null) && (mPassword.Length != 0)) + { + P = new byte[v * ((mPassword.Length + v - 1) / v)]; + + for (int i = 0; i != P.Length; i++) + { + P[i] = mPassword[i % mPassword.Length]; + } + } + else + { + P = new byte[0]; + } + + byte[] I = new byte[S.Length + P.Length]; + + Array.Copy(S, 0, I, 0, S.Length); + Array.Copy(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.BlockUpdate(D, 0, D.Length); + digest.BlockUpdate(I, 0, I.Length); + digest.DoFinal(A, 0); + + for (int j = 1; j != mIterationCount; j++) + { + digest.BlockUpdate(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) + { + Array.Copy(A, 0, dKey, (i - 1) * u, dKey.Length - ((i - 1) * u)); + } + else + { + Array.Copy(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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize); + + return new KeyParameter(dKey, 0, keySize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize); + + return ParameterUtilities.CreateKeyParameter(algorithm, 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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize); + + byte[] iv = GenerateDerivedKey(IVMaterial, ivSize); + + return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize); + KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize); + + byte[] iv = GenerateDerivedKey(IVMaterial, ivSize); + + return new ParametersWithIV(key, 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 override ICipherParameters GenerateDerivedMacParameters( + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(MacMaterial, keySize); + + return new KeyParameter(dKey, 0, keySize); + } + } +} diff --git a/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs new file mode 100644 index 000000000..8586e1ca9 --- /dev/null +++ b/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs @@ -0,0 +1,162 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * 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. + *

+ * The document this implementation is based on can be found at + * + * RSA's Pkcs5 Page + *

+ */ + public class Pkcs5S1ParametersGenerator + : PbeParametersGenerator + { + private readonly IDigest digest; + + /** + * Construct a Pkcs 5 Scheme 1 Parameters generator. + * + * @param digest the digest to be used as the source of derived keys. + */ + public Pkcs5S1ParametersGenerator( + IDigest digest) + { + this.digest = digest; + } + + /** + * the derived key function, the ith hash of the mPassword and the mSalt. + */ + private byte[] GenerateDerivedKey() + { + byte[] digestBytes = new byte[digest.GetDigestSize()]; + + digest.BlockUpdate(mPassword, 0, mPassword.Length); + digest.BlockUpdate(mSalt, 0, mSalt.Length); + + digest.DoFinal(digestBytes, 0); + for (int i = 1; i < mIterationCount; i++) + { + digest.BlockUpdate(digestBytes, 0, digestBytes.Length); + digest.DoFinal(digestBytes, 0); + } + + return digestBytes; + } + + /** + * Generate a key parameter derived from the mPassword, mSalt, and iteration + * count we are currently initialised with. + * + * @param keySize the size of the key we want (in bits) + * @return a KeyParameter object. + * @exception ArgumentException if the key length larger than the base hash size. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize) + { + return GenerateDerivedMacParameters(keySize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize) + { + keySize /= 8; + + if (keySize > digest.GetDigestSize()) + { + throw new ArgumentException( + "Can't Generate a derived key " + keySize + " bytes long."); + } + + byte[] dKey = GenerateDerivedKey(); + + return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize); + } + + /** + * Generate a key with initialisation vector parameter derived from + * the mPassword, mSalt, 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 ArgumentException if keySize + ivSize is larger than the base hash size. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + if ((keySize + ivSize) > digest.GetDigestSize()) + { + throw new ArgumentException( + "Can't Generate a derived key " + (keySize + ivSize) + " bytes long."); + } + + byte[] dKey = GenerateDerivedKey(); + + return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + if ((keySize + ivSize) > digest.GetDigestSize()) + { + throw new ArgumentException( + "Can't Generate a derived key " + (keySize + ivSize) + " bytes long."); + } + + byte[] dKey = GenerateDerivedKey(); + KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize); + + return new ParametersWithIV(key, dKey, keySize, ivSize); + } + + /** + * Generate a key parameter for use with a MAC derived from the mPassword, + * mSalt, and iteration count we are currently initialised with. + * + * @param keySize the size of the key we want (in bits) + * @return a KeyParameter object. + * @exception ArgumentException if the key length larger than the base hash size. + */ + public override ICipherParameters GenerateDerivedMacParameters( + int keySize) + { + keySize /= 8; + + if (keySize > digest.GetDigestSize()) + { + throw new ArgumentException( + "Can't Generate a derived key " + keySize + " bytes long."); + } + + byte[] dKey = GenerateDerivedKey(); + + return new KeyParameter(dKey, 0, keySize); + } + } +} diff --git a/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs new file mode 100644 index 000000000..10352abbc --- /dev/null +++ b/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs @@ -0,0 +1,180 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * 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. + *

+ * The document this implementation is based on can be found at + * + * RSA's Pkcs5 Page

+ */ + public class Pkcs5S2ParametersGenerator + : PbeParametersGenerator + { + private readonly IMac hMac; + private readonly byte[] state; + + /** + * construct a Pkcs5 Scheme 2 Parameters generator. + */ + public Pkcs5S2ParametersGenerator() + : this(new Sha1Digest()) + { + } + + public Pkcs5S2ParametersGenerator(IDigest digest) + { + this.hMac = new HMac(digest); + this.state = new byte[hMac.GetMacSize()]; + } + + private void F( + byte[] S, + int c, + byte[] iBuf, + byte[] outBytes, + int outOff) + { + if (c == 0) + throw new ArgumentException("iteration count must be at least 1."); + + if (S != null) + { + hMac.BlockUpdate(S, 0, S.Length); + } + + hMac.BlockUpdate(iBuf, 0, iBuf.Length); + hMac.DoFinal(state, 0); + + Array.Copy(state, 0, outBytes, outOff, state.Length); + + for (int count = 1; count < c; ++count) + { + hMac.BlockUpdate(state, 0, state.Length); + hMac.DoFinal(state, 0); + + for (int j = 0; j < state.Length; ++j) + { + outBytes[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; + + ICipherParameters param = new KeyParameter(mPassword); + + hMac.Init(param); + + for (int i = 1; i <= l; i++) + { + // Increment the value in 'iBuf' + int pos = 3; + while (++iBuf[pos] == 0) + { + --pos; + } + + F(mSalt, mIterationCount, 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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize) + { + return GenerateDerivedMacParameters(keySize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize); + + return ParameterUtilities.CreateKeyParameter(algorithm, 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. + */ + [Obsolete("Use version with 'algorithm' parameter")] + public override ICipherParameters GenerateDerivedParameters( + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize + ivSize); + + return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); + } + + public override ICipherParameters GenerateDerivedParameters( + string algorithm, + int keySize, + int ivSize) + { + keySize /= 8; + ivSize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize + ivSize); + KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize); + + return new ParametersWithIV(key, 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 override ICipherParameters GenerateDerivedMacParameters( + int keySize) + { + keySize /= 8; + + byte[] dKey = GenerateDerivedKey(keySize); + + return new KeyParameter(dKey, 0, keySize); + } + } +} diff --git a/crypto/src/crypto/generators/RSABlindingFactorGenerator.cs b/crypto/src/crypto/generators/RSABlindingFactorGenerator.cs new file mode 100644 index 000000000..e2f63face --- /dev/null +++ b/crypto/src/crypto/generators/RSABlindingFactorGenerator.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * 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 RsaKeyParameters key; + private SecureRandom random; + + /** + * Initialise the factor generator + * + * @param param the necessary RSA key parameters. + */ + public void Init( + ICipherParameters param) + { + if (param is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + key = (RsaKeyParameters)rParam.Parameters; + random = rParam.Random; + } + else + { + key = (RsaKeyParameters)param; + random = new SecureRandom(); + } + + if (key.IsPrivate) + throw new ArgumentException("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 InvalidOperationException("generator not initialised"); + + BigInteger m = key.Modulus; + 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.SignValue == 0 || factor.Equals(BigInteger.One) || !gcd.Equals(BigInteger.One)); + + return factor; + } + } +} diff --git a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs new file mode 100644 index 000000000..3074aed04 --- /dev/null +++ b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs @@ -0,0 +1,139 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Generators +{ + /** + * an RSA key pair generator. + */ + public class RsaKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); + private const int DefaultTests = 12; + + private RsaKeyGenerationParameters param; + + public void Init( + KeyGenerationParameters parameters) + { + if (parameters is RsaKeyGenerationParameters) + { + this.param = (RsaKeyGenerationParameters)parameters; + } + else + { + this.param = new RsaKeyGenerationParameters( + DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests); + } + } + + 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.Strength; + int pbitlength = (strength + 1) / 2; + int qbitlength = (strength - pbitlength); + int mindiffbits = strength / 3; + + e = param.PublicExponent; + + // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) + // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") + + // + // Generate p, prime and (p-1) relatively prime to e + // + for (;;) + { + p = new BigInteger(pbitlength, 1, param.Random); + + if (p.Mod(e).Equals(BigInteger.One)) + continue; + + if (!p.IsProbablePrime(param.Certainty)) + continue; + + if (e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One)) + break; + } + + // + // Generate a modulus of the required length + // + for (;;) + { + // Generate q, prime and (q-1) relatively prime to e, + // and not equal to p + // + for (;;) + { + q = new BigInteger(qbitlength, 1, param.Random); + + if (q.Subtract(p).Abs().BitLength < mindiffbits) + continue; + + if (q.Mod(e).Equals(BigInteger.One)) + continue; + + if (!q.IsProbablePrime(param.Certainty)) + continue; + + if (e.Gcd(q.Subtract(BigInteger.One)).Equals(BigInteger.One)) + break; + } + + // + // calculate the modulus + // + n = p.Multiply(q); + + if (n.BitLength == param.Strength) + break; + + // + // if we Get here our primes aren't big enough, make the largest + // of the two p and try again + // + p = p.Max(q); + } + + if (p.CompareTo(q) < 0) + { + phi = p; + p = q; + q = phi; + } + + pSub1 = p.Subtract(BigInteger.One); + qSub1 = q.Subtract(BigInteger.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)); + } + } + +} diff --git a/crypto/src/crypto/generators/SCrypt.cs b/crypto/src/crypto/generators/SCrypt.cs new file mode 100644 index 000000000..efa74d735 --- /dev/null +++ b/crypto/src/crypto/generators/SCrypt.cs @@ -0,0 +1,140 @@ +using System; +using System.Threading; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class SCrypt + { + // TODO Validate arguments + public static byte[] Generate(byte[] P, byte[] S, int N, int r, int p, int dkLen) + { + 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); + + uint[] B = null; + + try + { + int BLen = bytes.Length >> 2; + B = new uint[BLen]; + + Pack.LE_To_UInt32(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.UInt32_To_LE(B, bytes, 0); + + return SingleIterationPBKDF2(P, bytes, dkLen); + } + finally + { + ClearAll(bytes, 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(uint[] B, int BOff, int N, int r) + { + int BCount = r * 32; + + uint[] blockX1 = new uint[16]; + uint[] blockX2 = new uint[16]; + uint[] blockY = new uint[BCount]; + + uint[] X = new uint[BCount]; + uint[][] V = new uint[N][]; + + try + { + Array.Copy(B, BOff, X, 0, BCount); + + for (int i = 0; i < N; ++i) + { + V[i] = (uint[])X.Clone(); + BlockMix(X, blockX1, blockX2, blockY, r); + } + + uint mask = (uint)N - 1; + for (int i = 0; i < N; ++i) + { + uint j = X[BCount - 16] & mask; + Xor(X, V[j], 0, X); + BlockMix(X, blockX1, blockX2, blockY, r); + } + + Array.Copy(X, 0, B, BOff, BCount); + } + finally + { + ClearAll(V); + ClearAll(X, blockX1, blockX2, blockY); + } + } + + private static void BlockMix(uint[] B, uint[] X1, uint[] X2, uint[] Y, int r) + { + Array.Copy(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); + Array.Copy(X1, 0, Y, YOff, 16); + + YOff = halfLen + BOff - YOff; + BOff += 16; + } + + Array.Copy(Y, 0, B, 0, Y.Length); + } + + private static void Xor(uint[] a, uint[] b, int bOff, uint[] output) + { + for (int i = output.Length - 1; i >= 0; --i) + { + output[i] = a[i] ^ b[bOff + i]; + } + } + + private static void Clear(Array array) + { + if (array != null) + { + Array.Clear(array, 0, array.Length); + } + } + + private static void ClearAll(params Array[] arrays) + { + foreach (Array array in arrays) + { + Clear(array); + } + } + } +} diff --git a/crypto/src/crypto/io/CipherStream.cs b/crypto/src/crypto/io/CipherStream.cs new file mode 100644 index 000000000..b6920854d --- /dev/null +++ b/crypto/src/crypto/io/CipherStream.cs @@ -0,0 +1,234 @@ +using System; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class CipherStream + : Stream + { + internal Stream stream; + internal IBufferedCipher inCipher, outCipher; + private byte[] mInBuf; + private int mInPos; + private bool inStreamEnded; + + public CipherStream( + Stream stream, + IBufferedCipher readCipher, + IBufferedCipher writeCipher) + { + this.stream = stream; + + if (readCipher != null) + { + this.inCipher = readCipher; + mInBuf = null; + } + + if (writeCipher != null) + { + this.outCipher = writeCipher; + } + } + + public IBufferedCipher ReadCipher + { + get { return inCipher; } + } + + public IBufferedCipher WriteCipher + { + get { return outCipher; } + } + + public override int ReadByte() + { + if (inCipher == null) + return stream.ReadByte(); + + if (mInBuf == null || mInPos >= mInBuf.Length) + { + if (!FillInBuf()) + return -1; + } + + return mInBuf[mInPos++]; + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + if (inCipher == null) + return stream.Read(buffer, offset, count); + + int num = 0; + while (num < count) + { + if (mInBuf == null || mInPos >= mInBuf.Length) + { + if (!FillInBuf()) + break; + } + + int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos); + Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy); + mInPos += numToCopy; + num += numToCopy; + } + + return num; + } + + private bool FillInBuf() + { + if (inStreamEnded) + return false; + + mInPos = 0; + + do + { + mInBuf = ReadAndProcessBlock(); + } + while (!inStreamEnded && mInBuf == null); + + return mInBuf != null; + } + + private byte[] ReadAndProcessBlock() + { + int blockSize = inCipher.GetBlockSize(); + int readSize = (blockSize == 0) ? 256 : blockSize; + + byte[] block = new byte[readSize]; + int numRead = 0; + do + { + int count = stream.Read(block, numRead, block.Length - numRead); + if (count < 1) + { + inStreamEnded = true; + break; + } + numRead += count; + } + while (numRead < block.Length); + + Debug.Assert(inStreamEnded || numRead == block.Length); + + byte[] bytes = inStreamEnded + ? inCipher.DoFinal(block, 0, numRead) + : inCipher.ProcessBytes(block); + + if (bytes != null && bytes.Length == 0) + { + bytes = null; + } + + return bytes; + } + + public override void Write( + byte[] buffer, + int offset, + int count) + { + Debug.Assert(buffer != null); + Debug.Assert(0 <= offset && offset <= buffer.Length); + Debug.Assert(count >= 0); + + int end = offset + count; + + Debug.Assert(0 <= end && end <= buffer.Length); + + if (outCipher == null) + { + stream.Write(buffer, offset, count); + return; + } + + byte[] data = outCipher.ProcessBytes(buffer, offset, count); + if (data != null) + { + stream.Write(data, 0, data.Length); + } + } + + public override void WriteByte( + byte b) + { + if (outCipher == null) + { + stream.WriteByte(b); + return; + } + + byte[] data = outCipher.ProcessByte(b); + if (data != null) + { + stream.Write(data, 0, data.Length); + } + } + + public override bool CanRead + { + get { return stream.CanRead && (inCipher != null); } + } + + public override bool CanWrite + { + get { return stream.CanWrite && (outCipher != null); } + } + + public override bool CanSeek + { + get { return false; } + } + + public sealed override long Length + { + get { throw new NotSupportedException(); } + } + + public sealed override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + public override void Close() + { + if (outCipher != null) + { + byte[] data = outCipher.DoFinal(); + stream.Write(data, 0, data.Length); + stream.Flush(); + } + stream.Close(); + } + + public override void Flush() + { + // Note: outCipher.DoFinal is only called during Close() + stream.Flush(); + } + + public sealed override long Seek( + long offset, + SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public sealed override void SetLength( + long length) + { + throw new NotSupportedException(); + } + } +} diff --git a/crypto/src/crypto/io/DigestStream.cs b/crypto/src/crypto/io/DigestStream.cs new file mode 100644 index 000000000..c819a409a --- /dev/null +++ b/crypto/src/crypto/io/DigestStream.cs @@ -0,0 +1,137 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class DigestStream + : Stream + { + protected readonly Stream stream; + protected readonly IDigest inDigest; + protected readonly IDigest outDigest; + + public DigestStream( + Stream stream, + IDigest readDigest, + IDigest writeDigest) + { + this.stream = stream; + this.inDigest = readDigest; + this.outDigest = writeDigest; + } + + public virtual IDigest ReadDigest() + { + return inDigest; + } + + public virtual IDigest WriteDigest() + { + return outDigest; + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + int n = stream.Read(buffer, offset, count); + if (inDigest != null) + { + if (n > 0) + { + inDigest.BlockUpdate(buffer, offset, n); + } + } + return n; + } + + public override int ReadByte() + { + int b = stream.ReadByte(); + if (inDigest != null) + { + if (b >= 0) + { + inDigest.Update((byte)b); + } + } + return b; + } + + public override void Write( + byte[] buffer, + int offset, + int count) + { + if (outDigest != null) + { + if (count > 0) + { + outDigest.BlockUpdate(buffer, offset, count); + } + } + stream.Write(buffer, offset, count); + } + + public override void WriteByte( + byte b) + { + if (outDigest != null) + { + outDigest.Update(b); + } + stream.WriteByte(b); + } + + public override bool CanRead + { + get { return stream.CanRead; } + } + + public override bool CanWrite + { + get { return stream.CanWrite; } + } + + public override bool CanSeek + { + get { return stream.CanSeek; } + } + + public override long Length + { + get { return stream.Length; } + } + + public override long Position + { + get { return stream.Position; } + set { stream.Position = value; } + } + + public override void Close() + { + stream.Close(); + } + + public override void Flush() + { + stream.Flush(); + } + + public override long Seek( + long offset, + SeekOrigin origin) + { + return stream.Seek(offset, origin); + } + + public override void SetLength( + long length) + { + stream.SetLength(length); + } + } +} + diff --git a/crypto/src/crypto/io/MacStream.cs b/crypto/src/crypto/io/MacStream.cs new file mode 100644 index 000000000..51cf1832e --- /dev/null +++ b/crypto/src/crypto/io/MacStream.cs @@ -0,0 +1,136 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class MacStream + : Stream + { + protected readonly Stream stream; + protected readonly IMac inMac; + protected readonly IMac outMac; + + public MacStream( + Stream stream, + IMac readMac, + IMac writeMac) + { + this.stream = stream; + this.inMac = readMac; + this.outMac = writeMac; + } + + public virtual IMac ReadMac() + { + return inMac; + } + + public virtual IMac WriteMac() + { + return outMac; + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + int n = stream.Read(buffer, offset, count); + if (inMac != null) + { + if (n > 0) + { + inMac.BlockUpdate(buffer, offset, n); + } + } + return n; + } + + public override int ReadByte() + { + int b = stream.ReadByte(); + if (inMac != null) + { + if (b >= 0) + { + inMac.Update((byte)b); + } + } + return b; + } + + public override void Write( + byte[] buffer, + int offset, + int count) + { + if (outMac != null) + { + if (count > 0) + { + outMac.BlockUpdate(buffer, offset, count); + } + } + stream.Write(buffer, offset, count); + } + + public override void WriteByte(byte b) + { + if (outMac != null) + { + outMac.Update(b); + } + stream.WriteByte(b); + } + + public override bool CanRead + { + get { return stream.CanRead; } + } + + public override bool CanWrite + { + get { return stream.CanWrite; } + } + + public override bool CanSeek + { + get { return stream.CanSeek; } + } + + public override long Length + { + get { return stream.Length; } + } + + public override long Position + { + get { return stream.Position; } + set { stream.Position = value; } + } + + public override void Close() + { + stream.Close(); + } + + public override void Flush() + { + stream.Flush(); + } + + public override long Seek( + long offset, + SeekOrigin origin) + { + return stream.Seek(offset,origin); + } + + public override void SetLength( + long length) + { + stream.SetLength(length); + } + } +} + diff --git a/crypto/src/crypto/io/SignerStream.cs b/crypto/src/crypto/io/SignerStream.cs new file mode 100644 index 000000000..49dfb38c6 --- /dev/null +++ b/crypto/src/crypto/io/SignerStream.cs @@ -0,0 +1,137 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class SignerStream + : Stream + { + protected readonly Stream stream; + protected readonly ISigner inSigner; + protected readonly ISigner outSigner; + + public SignerStream( + Stream stream, + ISigner readSigner, + ISigner writeSigner) + { + this.stream = stream; + this.inSigner = readSigner; + this.outSigner = writeSigner; + } + + public virtual ISigner ReadSigner() + { + return inSigner; + } + + public virtual ISigner WriteSigner() + { + return outSigner; + } + + public override int Read( + byte[] buffer, + int offset, + int count) + { + int n = stream.Read(buffer, offset, count); + if (inSigner != null) + { + if (n > 0) + { + inSigner.BlockUpdate(buffer, offset, n); + } + } + return n; + } + + public override int ReadByte() + { + int b = stream.ReadByte(); + if (inSigner != null) + { + if (b >= 0) + { + inSigner.Update((byte)b); + } + } + return b; + } + + public override void Write( + byte[] buffer, + int offset, + int count) + { + if (outSigner != null) + { + if (count > 0) + { + outSigner.BlockUpdate(buffer, offset, count); + } + } + stream.Write(buffer, offset, count); + } + + public override void WriteByte( + byte b) + { + if (outSigner != null) + { + outSigner.Update(b); + } + stream.WriteByte(b); + } + + public override bool CanRead + { + get { return stream.CanRead; } + } + + public override bool CanWrite + { + get { return stream.CanWrite; } + } + + public override bool CanSeek + { + get { return stream.CanSeek; } + } + + public override long Length + { + get { return stream.Length; } + } + + public override long Position + { + get { return stream.Position; } + set { stream.Position = value; } + } + + public override void Close() + { + stream.Close(); + } + + public override void Flush() + { + stream.Flush(); + } + + public override long Seek( + long offset, + SeekOrigin origin) + { + return stream.Seek(offset, origin); + } + + public override void SetLength( + long length) + { + stream.SetLength(length); + } + } +} + diff --git a/crypto/src/crypto/macs/CMac.cs b/crypto/src/crypto/macs/CMac.cs new file mode 100644 index 000000000..c51a550c9 --- /dev/null +++ b/crypto/src/crypto/macs/CMac.cs @@ -0,0 +1,241 @@ +using System; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html + *

+ * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC + *

+ * CMAC is a NIST recomendation - see + * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf + *

+ * CMAC/OMAC1 is a blockcipher-based message authentication code designed and + * analyzed by Tetsu Iwata and Kaoru Kurosawa. + *

+ * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message + * Authentication Code). OMAC stands for One-Key CBC MAC. + *

+ * 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. + *

+ */ + public class CMac + : IMac + { + private const byte CONSTANT_128 = (byte)0x87; + private const byte CONSTANT_64 = (byte)0x1b; + + private byte[] ZEROES; + + private byte[] mac; + + private byte[] buf; + private int bufOff; + private IBlockCipher 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( + IBlockCipher 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. + *

+ * 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( + IBlockCipher cipher, + int macSizeInBits) + { + if ((macSizeInBits % 8) != 0) + throw new ArgumentException("MAC size must be multiple of 8"); + + if (macSizeInBits > (cipher.GetBlockSize() * 8)) + { + throw new ArgumentException( + "MAC size must be less or equal to " + + (cipher.GetBlockSize() * 8)); + } + + if (cipher.GetBlockSize() != 8 && cipher.GetBlockSize() != 16) + { + throw new ArgumentException( + "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 AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + private static byte[] doubleLu( + byte[] inBytes) + { + int FirstBit = (inBytes[0] & 0xFF) >> 7; + byte[] ret = new byte[inBytes.Length]; + for (int i = 0; i < inBytes.Length - 1; i++) + { + ret[i] = (byte)((inBytes[i] << 1) + ((inBytes[i + 1] & 0xFF) >> 7)); + } + ret[inBytes.Length - 1] = (byte)(inBytes[inBytes.Length - 1] << 1); + if (FirstBit == 1) + { + ret[inBytes.Length - 1] ^= inBytes.Length == 16 ? CONSTANT_128 : CONSTANT_64; + } + return ret; + } + + public void Init( + ICipherParameters parameters) + { + if (parameters != null) + { + cipher.Init(true, parameters); + + //initializes the L, Lu, Lu2 numbers + L = new byte[ZEROES.Length]; + cipher.ProcessBlock(ZEROES, 0, L, 0); + Lu = doubleLu(L); + Lu2 = doubleLu(Lu); + } + + Reset(); + } + + public int GetMacSize() + { + return macSize; + } + + public void Update( + byte input) + { + if (bufOff == buf.Length) + { + cipher.ProcessBlock(buf, 0, mac, 0); + bufOff = 0; + } + + buf[bufOff++] = input; + } + + public void BlockUpdate( + byte[] inBytes, + int inOff, + int len) + { + if (len < 0) + throw new ArgumentException("Can't have a negative input length!"); + + int blockSize = cipher.GetBlockSize(); + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(inBytes, inOff, buf, bufOff, gapLen); + + cipher.ProcessBlock(buf, 0, mac, 0); + + bufOff = 0; + len -= gapLen; + inOff += gapLen; + + while (len > blockSize) + { + cipher.ProcessBlock(inBytes, inOff, mac, 0); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(inBytes, inOff, buf, bufOff, len); + + bufOff += len; + } + + public int DoFinal( + byte[] outBytes, + 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); + + Array.Copy(mac, 0, outBytes, outOff, macSize); + + Reset(); + + return macSize; + } + + /** + * Reset the mac generator. + */ + public void Reset() + { + /* + * clean the buffer. + */ + Array.Clear(buf, 0, buf.Length); + bufOff = 0; + + /* + * Reset the underlying cipher. + */ + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/macs/CbcBlockCipherMac.cs b/crypto/src/crypto/macs/CbcBlockCipherMac.cs new file mode 100644 index 000000000..146e16aa8 --- /dev/null +++ b/crypto/src/crypto/macs/CbcBlockCipherMac.cs @@ -0,0 +1,209 @@ +using System; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * standard CBC Block Cipher MAC - if no padding is specified the default of + * pad of zeroes is used. + */ + public class CbcBlockCipherMac + : IMac + { + private byte[] buf; + private int bufOff; + private IBlockCipher cipher; + private IBlockCipherPadding 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( + IBlockCipher 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( + IBlockCipher cipher, + IBlockCipherPadding 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. + *

+ * 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( + IBlockCipher 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. + *

+ * 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( + IBlockCipher cipher, + int macSizeInBits, + IBlockCipherPadding padding) + { + if ((macSizeInBits % 8) != 0) + throw new ArgumentException("MAC size must be multiple of 8"); + + this.cipher = new CbcBlockCipher(cipher); + this.padding = padding; + this.macSize = macSizeInBits / 8; + + buf = new byte[cipher.GetBlockSize()]; + bufOff = 0; + } + + public string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + public void Init( + ICipherParameters parameters) + { + Reset(); + + cipher.Init(true, parameters); + } + + public int GetMacSize() + { + return macSize; + } + + public void Update( + byte input) + { + if (bufOff == buf.Length) + { + cipher.ProcessBlock(buf, 0, buf, 0); + bufOff = 0; + } + + buf[bufOff++] = input; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int len) + { + if (len < 0) + throw new ArgumentException("Can't have a negative input length!"); + + int blockSize = cipher.GetBlockSize(); + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + cipher.ProcessBlock(buf, 0, buf, 0); + + bufOff = 0; + len -= gapLen; + inOff += gapLen; + + while (len > blockSize) + { + cipher.ProcessBlock(input, inOff, buf, 0); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, len); + + bufOff += len; + } + + public int DoFinal( + byte[] output, + int outOff) + { + int blockSize = cipher.GetBlockSize(); + + if (padding == null) + { + // pad with zeroes + while (bufOff < blockSize) + { + buf[bufOff++] = 0; + } + } + else + { + if (bufOff == blockSize) + { + cipher.ProcessBlock(buf, 0, buf, 0); + bufOff = 0; + } + + padding.AddPadding(buf, bufOff); + } + + cipher.ProcessBlock(buf, 0, buf, 0); + + Array.Copy(buf, 0, output, outOff, macSize); + + Reset(); + + return macSize; + } + + /** + * Reset the mac generator. + */ + public void Reset() + { + // Clear the buffer. + Array.Clear(buf, 0, buf.Length); + bufOff = 0; + + // Reset the underlying cipher. + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/macs/CfbBlockCipherMac.cs b/crypto/src/crypto/macs/CfbBlockCipherMac.cs new file mode 100644 index 000000000..364cf8499 --- /dev/null +++ b/crypto/src/crypto/macs/CfbBlockCipherMac.cs @@ -0,0 +1,368 @@ +using System; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher. + */ + class MacCFBBlockCipher + : IBlockCipher + { + private byte[] IV; + private byte[] cfbV; + private byte[] cfbOutV; + + private readonly int blockSize; + private readonly IBlockCipher 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 MacCFBBlockCipher( + IBlockCipher 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 ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + + if (iv.Length < IV.Length) + { + Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length); + } + else + { + Array.Copy(iv, 0, IV, 0, IV.Length); + } + + parameters = ivParam.Parameters; + } + + Reset(); + + cipher.Init(true, parameters); + } + + /** + * return the algorithm name and mode. + * + * @return the name of the underlying algorithm followed by "/CFB" + * and the block size in bits. + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/CFB" + (blockSize * 8); } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + throw new DataLengthException("input buffer too short"); + + if ((outOff + blockSize) > outBytes.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++) + { + outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]); + } + + // + // change over the input block. + // + Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize); + Array.Copy(outBytes, outOff, cfbV, cfbV.Length - blockSize, blockSize); + + return blockSize; + } + + /** + * reset the chaining vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + IV.CopyTo(cfbV, 0); + + cipher.Reset(); + } + + public void GetMacBlock( + byte[] mac) + { + cipher.ProcessBlock(cfbV, 0, mac, 0); + } + } + + public class CfbBlockCipherMac + : IMac + { + private byte[] mac; + private byte[] Buffer; + private int bufOff; + private MacCFBBlockCipher cipher; + private IBlockCipherPadding padding; + 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( + IBlockCipher 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( + IBlockCipher cipher, + IBlockCipherPadding 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. + *

+ * 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( + IBlockCipher 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. + *

+ * 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( + IBlockCipher cipher, + int cfbBitSize, + int macSizeInBits, + IBlockCipherPadding padding) + { + if ((macSizeInBits % 8) != 0) + throw new ArgumentException("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; + + Buffer = new byte[this.cipher.GetBlockSize()]; + bufOff = 0; + } + + public string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + public void Init( + ICipherParameters parameters) + { + Reset(); + + cipher.Init(true, parameters); + } + + public int GetMacSize() + { + return macSize; + } + + public void Update( + byte input) + { + if (bufOff == Buffer.Length) + { + cipher.ProcessBlock(Buffer, 0, mac, 0); + bufOff = 0; + } + + Buffer[bufOff++] = input; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int len) + { + if (len < 0) + throw new ArgumentException("Can't have a negative input length!"); + + int blockSize = cipher.GetBlockSize(); + int resultLen = 0; + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, Buffer, bufOff, gapLen); + + resultLen += cipher.ProcessBlock(Buffer, 0, mac, 0); + + bufOff = 0; + len -= gapLen; + inOff += gapLen; + + while (len > blockSize) + { + resultLen += cipher.ProcessBlock(input, inOff, mac, 0); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, Buffer, bufOff, len); + + bufOff += len; + } + + public int DoFinal( + byte[] output, + int outOff) + { + int blockSize = cipher.GetBlockSize(); + + // pad with zeroes + if (this.padding == null) + { + while (bufOff < blockSize) + { + Buffer[bufOff++] = 0; + } + } + else + { + padding.AddPadding(Buffer, bufOff); + } + + cipher.ProcessBlock(Buffer, 0, mac, 0); + + cipher.GetMacBlock(mac); + + Array.Copy(mac, 0, output, outOff, macSize); + + Reset(); + + return macSize; + } + + /** + * Reset the mac generator. + */ + public void Reset() + { + // Clear the buffer. + Array.Clear(Buffer, 0, Buffer.Length); + bufOff = 0; + + // Reset the underlying cipher. + cipher.Reset(); + } + } + +} diff --git a/crypto/src/crypto/macs/GOST28147Mac.cs b/crypto/src/crypto/macs/GOST28147Mac.cs new file mode 100644 index 000000000..9a8f1b730 --- /dev/null +++ b/crypto/src/crypto/macs/GOST28147Mac.cs @@ -0,0 +1,296 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * implementation of GOST 28147-89 MAC + */ + public class Gost28147Mac : IMac + { + private const int blockSize = 8; + private const int macSize = 4; + private int bufOff; + private byte[] buf; + private byte[] mac; + private bool firstStep = true; + private int[] workingKey; + + // + // 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 static int[] generateWorkingKey( + byte[] userKey) + { + if (userKey.Length != 32) + throw new ArgumentException("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( + ICipherParameters parameters) + { + Reset(); + buf = new byte[blockSize]; + if (parameters is ParametersWithSBox) + { + ParametersWithSBox param = (ParametersWithSBox)parameters; + + // + // Set the S-Box + // + param.GetSBox().CopyTo(this.S, 0); + + // + // set key if there is one + // + if (param.Parameters != null) + { + workingKey = generateWorkingKey(((KeyParameter)param.Parameters).GetKey()); + } + } + else if (parameters is KeyParameter) + { + workingKey = generateWorkingKey(((KeyParameter)parameters).GetKey()); + } + else + { + throw new ArgumentException("invalid parameter passed to Gost28147 init - " + + parameters.GetType().Name); + } + } + + public string AlgorithmName + { + get { 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 + int omLeft = om << 11; + int omRight = (int)(((uint) om) >> (32 - 11)); // Note: Casts required to get unsigned bit rotation + + return omLeft | omRight; + } + + private void gost28147MacFunc( + int[] workingKey, + byte[] input, + int inOff, + byte[] output, + int outOff) + { + int N1, N2, tmp; //tmp -> for saving N1 + N1 = bytesToint(input, inOff); + N2 = bytesToint(input, 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, output, outOff); + intTobytes(N2, output, outOff + 4); + } + + //array of bytes to type int + private static int bytesToint( + byte[] input, + int inOff) + { + return (int)((input[inOff + 3] << 24) & 0xff000000) + ((input[inOff + 2] << 16) & 0xff0000) + + ((input[inOff + 1] << 8) & 0xff00) + (input[inOff] & 0xff); + } + + //int to array of bytes + private static void intTobytes( + int num, + byte[] output, + int outOff) + { + output[outOff + 3] = (byte)(num >> 24); + output[outOff + 2] = (byte)(num >> 16); + output[outOff + 1] = (byte)(num >> 8); + output[outOff] = (byte)num; + } + + private static byte[] CM5func( + byte[] buf, + int bufOff, + byte[] mac) + { + byte[] sum = new byte[buf.Length - bufOff]; + + Array.Copy(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 input) + { + if (bufOff == buf.Length) + { + byte[] sumbuf = new byte[buf.Length]; + Array.Copy(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++] = input; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int len) + { + if (len < 0) + throw new ArgumentException("Can't have a negative input length!"); + + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + byte[] sumbuf = new byte[buf.Length]; + Array.Copy(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(input, inOff, mac); + gost28147MacFunc(workingKey, sumbuf, 0, mac, 0); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, len); + + bufOff += len; + } + + public int DoFinal( + byte[] output, + int outOff) + { + //padding with zero + while (bufOff < blockSize) + { + buf[bufOff++] = 0; + } + + byte[] sumbuf = new byte[buf.Length]; + Array.Copy(buf, 0, sumbuf, 0, mac.Length); + + if (firstStep) + { + firstStep = false; + } + else + { + sumbuf = CM5func(buf, 0, mac); + } + + gost28147MacFunc(workingKey, sumbuf, 0, mac, 0); + + Array.Copy(mac, (mac.Length/2)-macSize, output, outOff, macSize); + + Reset(); + + return macSize; + } + + public void Reset() + { + // Clear the buffer. + Array.Clear(buf, 0, buf.Length); + bufOff = 0; + + firstStep = true; + } + } +} diff --git a/crypto/src/crypto/macs/HMac.cs b/crypto/src/crypto/macs/HMac.cs new file mode 100644 index 000000000..7ae1e02b9 --- /dev/null +++ b/crypto/src/crypto/macs/HMac.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * HMAC implementation based on RFC2104 + * + * H(K XOR opad, H(K XOR ipad, text)) + */ + public class HMac + : IMac + { + private const byte IPAD = (byte)0x36; + private const byte OPAD = (byte)0x5C; + + private readonly IDigest digest; + private readonly int digestSize; + private readonly int blockLength; + + private readonly byte[] inputPad; + private readonly byte[] outputBuf; + + public HMac(IDigest digest) + { + this.digest = digest; + this.digestSize = digest.GetDigestSize(); + this.blockLength = digest.GetByteLength(); + this.inputPad = new byte[blockLength]; + this.outputBuf = new byte[blockLength + digestSize]; + } + + public virtual string AlgorithmName + { + get { return digest.AlgorithmName + "/HMAC"; } + } + + public virtual IDigest GetUnderlyingDigest() + { + return digest; + } + + public virtual void Init(ICipherParameters parameters) + { + digest.Reset(); + + byte[] key = ((KeyParameter)parameters).GetKey(); + int keyLength = key.Length; + + if (keyLength > blockLength) + { + digest.BlockUpdate(key, 0, keyLength); + digest.DoFinal(inputPad, 0); + + keyLength = digestSize; + } + else + { + Array.Copy(key, 0, inputPad, 0, keyLength); + } + + Array.Clear(inputPad, keyLength, blockLength - keyLength); + Array.Copy(inputPad, 0, outputBuf, 0, blockLength); + + XorPad(inputPad, blockLength, IPAD); + XorPad(outputBuf, blockLength, OPAD); + + // Initialise the digest + digest.BlockUpdate(inputPad, 0, inputPad.Length); + } + + public virtual int GetMacSize() + { + return digestSize; + } + + public virtual void Update(byte input) + { + digest.Update(input); + } + + public virtual void BlockUpdate(byte[] input, int inOff, int len) + { + digest.BlockUpdate(input, inOff, len); + } + + public virtual int DoFinal(byte[] output, int outOff) + { + digest.DoFinal(outputBuf, blockLength); + digest.BlockUpdate(outputBuf, 0, outputBuf.Length); + int len = digest.DoFinal(output, outOff); + + Array.Clear(outputBuf, blockLength, digestSize); + + // Initialise the digest + digest.BlockUpdate(inputPad, 0, inputPad.Length); + + return len; + } + + /** + * Reset the mac generator. + */ + public virtual void Reset() + { + // Reset underlying digest + digest.Reset(); + + // Initialise the digest + digest.BlockUpdate(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/crypto/src/crypto/macs/ISO9797Alg3Mac.cs b/crypto/src/crypto/macs/ISO9797Alg3Mac.cs new file mode 100644 index 000000000..6fee619c1 --- /dev/null +++ b/crypto/src/crypto/macs/ISO9797Alg3Mac.cs @@ -0,0 +1,275 @@ +using System; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * 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 : IMac + { + private byte[] mac; + private byte[] buf; + private int bufOff; + private IBlockCipher cipher; + private IBlockCipherPadding 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( + IBlockCipher 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( + IBlockCipher cipher, + IBlockCipherPadding 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. + *

+ * 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( + IBlockCipher 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. + *

+ * 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( + IBlockCipher cipher, + int macSizeInBits, + IBlockCipherPadding padding) + { + if ((macSizeInBits % 8) != 0) + throw new ArgumentException("MAC size must be multiple of 8"); + + if (!(cipher is DesEngine)) + throw new ArgumentException("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 AlgorithmName + { + get { return "ISO9797Alg3"; } + } + + public void Init( + ICipherParameters parameters) + { + Reset(); + + if (!(parameters is KeyParameter || parameters is ParametersWithIV)) + throw new ArgumentException("parameters 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 (parameters is KeyParameter) + { + kp = (KeyParameter)parameters; + } + else + { + kp = (KeyParameter)((ParametersWithIV)parameters).Parameters; + } + + 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 ArgumentException("Key must be either 112 or 168 bit long"); + } + + if (parameters is ParametersWithIV) + { + cipher.Init(true, new ParametersWithIV(key1, ((ParametersWithIV)parameters).GetIV())); + } + else + { + cipher.Init(true, key1); + } + } + + public int GetMacSize() + { + return macSize; + } + + public void Update( + byte input) + { + if (bufOff == buf.Length) + { + cipher.ProcessBlock(buf, 0, mac, 0); + bufOff = 0; + } + + buf[bufOff++] = input; + } + + public void BlockUpdate( + byte[] input, + int inOff, + int len) + { + if (len < 0) + throw new ArgumentException("Can't have a negative input length!"); + + int blockSize = cipher.GetBlockSize(); + int resultLen = 0; + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + resultLen += cipher.ProcessBlock(buf, 0, mac, 0); + + bufOff = 0; + len -= gapLen; + inOff += gapLen; + + while (len > blockSize) + { + resultLen += cipher.ProcessBlock(input, inOff, mac, 0); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, len); + + bufOff += len; + } + + public int DoFinal( + byte[] output, + int outOff) + { + int blockSize = cipher.GetBlockSize(); + + if (padding == null) + { + // pad with zeroes + while (bufOff < blockSize) + { + buf[bufOff++] = 0; + } + } + 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); + // **** + + Array.Copy(mac, 0, output, outOff, macSize); + + Reset(); + + return macSize; + } + + /** + * Reset the mac generator. + */ + public void Reset() + { + Array.Clear(buf, 0, buf.Length); + bufOff = 0; + + // reset the underlying cipher. + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/macs/SipHash.cs b/crypto/src/crypto/macs/SipHash.cs new file mode 100644 index 000000000..ab8b1b06b --- /dev/null +++ b/crypto/src/crypto/macs/SipHash.cs @@ -0,0 +1,170 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /// + /// 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). + /// + /// + /// "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 + : IMac + { + protected readonly int c, d; + + protected long k0, k1; + protected long v0, v1, v2, v3, v4; + + protected byte[] buf = new byte[8]; + protected int bufPos = 0; + protected int wordCount = 0; + + /// SipHash-2-4 + public SipHash() + : this(2, 4) + { + } + + /// SipHash-c-d + /// the number of compression rounds + /// the number of finalization rounds + public SipHash(int c, int d) + { + this.c = c; + this.d = d; + } + + public virtual string AlgorithmName + { + get { return "SipHash-" + c + "-" + d; } + } + + public virtual int GetMacSize() + { + return 8; + } + + public virtual void Init(ICipherParameters parameters) + { + KeyParameter keyParameter = parameters as KeyParameter; + if (keyParameter == null) + throw new ArgumentException("must be an instance of KeyParameter", "parameters"); + byte[] key = keyParameter.GetKey(); + if (key.Length != 16) + throw new ArgumentException("must be a 128-bit key", "parameters"); + + this.k0 = (long)Pack.LE_To_UInt64(key, 0); + this.k1 = (long)Pack.LE_To_UInt64(key, 8); + + Reset(); + } + + public virtual void Update(byte input) + { + buf[bufPos] = input; + if (++bufPos == buf.Length) + { + ProcessMessageWord(); + bufPos = 0; + } + } + + public virtual void BlockUpdate(byte[] input, int offset, int length) + { + for (int i = 0; i < length; ++i) + { + buf[bufPos] = input[offset + i]; + if (++bufPos == buf.Length) + { + ProcessMessageWord(); + bufPos = 0; + } + } + } + + public virtual long DoFinal() + { + buf[7] = (byte)((wordCount << 3) + bufPos); + while (bufPos < 7) + { + buf[bufPos++] = 0; + } + + ProcessMessageWord(); + + v2 ^= 0xffL; + + ApplySipRounds(d); + + long result = v0 ^ v1 ^ v2 ^ v3; + + Reset(); + + return result; + } + + public virtual int DoFinal(byte[] output, int outOff) + { + long result = DoFinal(); + Pack.UInt64_To_LE((ulong)result, output, outOff); + return 8; + } + + public virtual void Reset() + { + v0 = k0 ^ 0x736f6d6570736575L; + v1 = k1 ^ 0x646f72616e646f6dL; + v2 = k0 ^ 0x6c7967656e657261L; + v3 = k1 ^ 0x7465646279746573L; + + Array.Clear(buf, 0, buf.Length); + bufPos = 0; + wordCount = 0; + } + + protected virtual void ProcessMessageWord() + { + ++wordCount; + long m = (long)Pack.LE_To_UInt64(buf, 0); + v3 ^= m; + ApplySipRounds(c); + v0 ^= m; + } + + protected virtual void ApplySipRounds(int n) + { + for (int r = 0; r < n; ++r) + { + v0 += v1; + v2 += v3; + v1 = RotateLeft(v1, 13); + v3 = RotateLeft(v3, 16); + v1 ^= v0; + v3 ^= v2; + v0 = RotateLeft(v0, 32); + v2 += v1; + v0 += v3; + v1 = RotateLeft(v1, 17); + v3 = RotateLeft(v3, 21); + v1 ^= v2; + v3 ^= v0; + v2 = RotateLeft(v2, 32); + } + } + + protected static long RotateLeft(long x, int n) + { + ulong ux = (ulong)x; + ux = (ux << n) | (ux >> (64 - n)); + return (long)ux; + } + } +} diff --git a/crypto/src/crypto/macs/VMPCMac.cs b/crypto/src/crypto/macs/VMPCMac.cs new file mode 100644 index 000000000..89916355c --- /dev/null +++ b/crypto/src/crypto/macs/VMPCMac.cs @@ -0,0 +1,173 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Macs +{ + public class VmpcMac + : IMac + { + 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 virtual int DoFinal(byte[] output, int outOff) + { + // 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 input 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; + } + + Array.Copy(M, 0, output, outOff, M.Length); + Reset(); + + return M.Length; + } + + public virtual string AlgorithmName + { + get { return "VMPC-MAC"; } + } + + public virtual int GetMacSize() + { + return 20; + } + + public virtual void Init(ICipherParameters parameters) + { + if (!(parameters is ParametersWithIV)) + throw new ArgumentException("VMPC-MAC Init parameters must include an IV", "parameters"); + + ParametersWithIV ivParams = (ParametersWithIV) parameters; + KeyParameter key = (KeyParameter) ivParams.Parameters; + + if (!(ivParams.Parameters is KeyParameter)) + throw new ArgumentException("VMPC-MAC Init parameters must include a key", "parameters"); + + this.workingIV = ivParams.GetIV(); + + if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768) + throw new ArgumentException("VMPC-MAC requires 1 to 768 bytes of IV", "parameters"); + + 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 virtual 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 virtual void Update(byte input) + { + s = P[(s + P[n & 0xff]) & 0xff]; + byte c = (byte) (input ^ 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 virtual void BlockUpdate(byte[] input, int inOff, int len) + { + if ((inOff + len) > input.Length) + throw new DataLengthException("input buffer too short"); + + for (int i = 0; i < len; i++) + { + Update(input[i]); + } + } + } +} diff --git a/crypto/src/crypto/modes/CbcBlockCipher.cs b/crypto/src/crypto/modes/CbcBlockCipher.cs new file mode 100644 index 000000000..9345fd8c2 --- /dev/null +++ b/crypto/src/crypto/modes/CbcBlockCipher.cs @@ -0,0 +1,241 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher. + */ + public class CbcBlockCipher + : IBlockCipher + { + private byte[] IV, cbcV, cbcNextV; + private int blockSize; + private IBlockCipher cipher; + private bool encrypting; + + /** + * Basic constructor. + * + * @param cipher the block cipher to be used as the basis of chaining. + */ + public CbcBlockCipher( + IBlockCipher 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 IBlockCipher 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 forEncryption if true the cipher is initialised for + * encryption, if false for decryption. + * @param param the key and other data required by the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + bool oldEncrypting = this.encrypting; + + this.encrypting = forEncryption; + + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + + if (iv.Length != blockSize) + { + throw new ArgumentException("initialisation vector must be the same length as block size"); + } + + Array.Copy(iv, 0, IV, 0, iv.Length); + + parameters = ivParam.Parameters; + } + + Reset(); + + // if null it's an IV changed only. + if (parameters != null) + { + cipher.Init(encrypting, parameters); + } + else if (oldEncrypting != encrypting) + { + throw new ArgumentException("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 AlgorithmName + { + get { return cipher.AlgorithmName + "/CBC"; } + } + + public bool IsPartialBlockOkay + { + get { return false; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + return (encrypting) + ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); + } + + /** + * reset the chaining vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + Array.Copy(IV, 0, cbcV, 0, IV.Length); + Array.Clear(cbcNextV, 0, cbcNextV.Length); + + 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + private int EncryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.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] ^= input[inOff + i]; + } + + int length = cipher.ProcessBlock(cbcV, 0, outBytes, outOff); + + /* + * copy ciphertext to cbcV + */ + Array.Copy(outBytes, 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + private int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + Array.Copy(input, inOff, cbcNextV, 0, blockSize); + + int length = cipher.ProcessBlock(input, inOff, outBytes, outOff); + + /* + * XOR the cbcV and the output + */ + for (int i = 0; i < blockSize; i++) + { + outBytes[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/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs new file mode 100644 index 000000000..653d75cb9 --- /dev/null +++ b/crypto/src/crypto/modes/CcmBlockCipher.cs @@ -0,0 +1,383 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in + * NIST Special Publication 800-38C. + *

+ * Note: this mode is a packet mode - it needs all the data up front. + *

+ */ + public class CcmBlockCipher + : IAeadBlockCipher + { + private static readonly int BlockSize = 16; + + private readonly IBlockCipher cipher; + private readonly byte[] macBlock; + private bool forEncryption; + private byte[] nonce; + private byte[] initialAssociatedText; + private int macSize; + private ICipherParameters keyParam; + private readonly MemoryStream associatedText = new MemoryStream(); + private readonly MemoryStream data = new MemoryStream(); + + /** + * Basic constructor. + * + * @param cipher the block cipher to be used. + */ + public CcmBlockCipher( + IBlockCipher cipher) + { + this.cipher = cipher; + this.macBlock = new byte[BlockSize]; + + if (cipher.GetBlockSize() != BlockSize) + throw new ArgumentException("cipher required with a block size of " + BlockSize + "."); + } + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public virtual IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + + public virtual void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + if (parameters is AeadParameters) + { + AeadParameters param = (AeadParameters) parameters; + + nonce = param.GetNonce(); + initialAssociatedText = param.GetAssociatedText(); + macSize = param.MacSize / 8; + keyParam = param.Key; + } + else if (parameters is ParametersWithIV) + { + ParametersWithIV param = (ParametersWithIV) parameters; + + nonce = param.GetIV(); + initialAssociatedText = null; + macSize = macBlock.Length / 2; + keyParam = param.Parameters; + } + else + { + throw new ArgumentException("invalid parameters passed to CCM"); + } + + if (nonce == null || nonce.Length < 7 || nonce.Length > 13) + { + throw new ArgumentException("nonce must have length from 7 to 13 octets"); + } + } + + public virtual string AlgorithmName + { + get { return cipher.AlgorithmName + "/CCM"; } + } + + public virtual int GetBlockSize() + { + return cipher.GetBlockSize(); + } + + public virtual void ProcessAadByte(byte input) + { + associatedText.WriteByte(input); + } + + public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) + { + // TODO: Process AAD online + associatedText.Write(inBytes, inOff, len); + } + + public virtual int ProcessByte( + byte input, + byte[] outBytes, + int outOff) + { + data.WriteByte(input); + + return 0; + } + + public virtual int ProcessBytes( + byte[] inBytes, + int inOff, + int inLen, + byte[] outBytes, + int outOff) + { + data.Write(inBytes, inOff, inLen); + + return 0; + } + + public virtual int DoFinal( + byte[] outBytes, + int outOff) + { + byte[] enc = ProcessPacket(data.GetBuffer(), 0, (int)data.Position); + + Array.Copy(enc, 0, outBytes, outOff, enc.Length); + + Reset(); + + return enc.Length; + } + + public virtual void Reset() + { + cipher.Reset(); + associatedText.SetLength(0); + data.SetLength(0); + } + + /** + * Returns a byte array containing the mac calculated as part of the + * last encrypt or decrypt operation. + * + * @return the last mac calculated. + */ + public virtual byte[] GetMac() + { + byte[] mac = new byte[macSize]; + + Array.Copy(macBlock, 0, mac, 0, mac.Length); + + return mac; + } + + public virtual int GetUpdateOutputSize( + int len) + { + return 0; + } + + public int GetOutputSize( + int len) + { + int totalData = (int)data.Length + len; + + if (forEncryption) + { + return totalData + macSize; + } + + return totalData < macSize ? 0 : totalData - macSize; + } + + public byte[] ProcessPacket( + byte[] input, + int inOff, + int inLen) + { + // 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 InvalidOperationException("CCM cipher unitialized."); + + int n = nonce.Length; + int q = 15 - n; + if (q < 4) + { + int limitLen = 1 << (8 * q); + if (inLen >= limitLen) + throw new InvalidOperationException("CCM packet too large for choice of q."); + } + + byte[] iv = new byte[BlockSize]; + iv[0] = (byte)((q - 1) & 0x7); + nonce.CopyTo(iv, 1); + + IBlockCipher ctrCipher = new SicBlockCipher(cipher); + ctrCipher.Init(forEncryption, new ParametersWithIV(keyParam, iv)); + + int index = inOff; + int outOff = 0; + byte[] output; + + if (forEncryption) + { + output = new byte[inLen + macSize]; + + calculateMac(input, inOff, inLen, macBlock); + + ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); // S0 + + while (index < inLen - BlockSize) // S1... + { + ctrCipher.ProcessBlock(input, index, output, outOff); + outOff += BlockSize; + index += BlockSize; + } + + byte[] block = new byte[BlockSize]; + + Array.Copy(input, index, block, 0, inLen - index); + + ctrCipher.ProcessBlock(block, 0, block, 0); + + Array.Copy(block, 0, output, outOff, inLen - index); + + outOff += inLen - index; + + Array.Copy(macBlock, 0, output, outOff, output.Length - outOff); + } + else + { + output = new byte[inLen - macSize]; + + Array.Copy(input, inOff + inLen - macSize, macBlock, 0, macSize); + + ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); + + for (int i = macSize; i != macBlock.Length; i++) + { + macBlock[i] = 0; + } + + while (outOff < output.Length - BlockSize) + { + ctrCipher.ProcessBlock(input, index, output, outOff); + outOff += BlockSize; + index += BlockSize; + } + + byte[] block = new byte[BlockSize]; + + Array.Copy(input, index, block, 0, output.Length - outOff); + + ctrCipher.ProcessBlock(block, 0, block, 0); + + Array.Copy(block, 0, output, outOff, output.Length - outOff); + + byte[] calculatedMacBlock = new byte[BlockSize]; + + calculateMac(output, 0, output.Length, calculatedMacBlock); + + if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock)) + throw new InvalidCipherTextException("mac check in CCM failed"); + } + + return output; + } + + private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock) + { + IMac cMac = new CbcBlockCipherMac(cipher, macSize * 8); + + cMac.Init(keyParam); + + // + // build b0 + // + byte[] b0 = new byte[16]; + + if (HasAssociatedText()) + { + b0[0] |= 0x40; + } + + b0[0] |= (byte)((((cMac.GetMacSize() - 2) / 2) & 0x7) << 3); + + b0[0] |= (byte)(((15 - nonce.Length) - 1) & 0x7); + + Array.Copy(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.BlockUpdate(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.BlockUpdate(initialAssociatedText, 0, initialAssociatedText.Length); + } + if (associatedText.Position > 0) + { + cMac.BlockUpdate(associatedText.GetBuffer(), 0, (int)associatedText.Position); + } + + extra = (extra + textLength) % 16; + if (extra != 0) + { + for (int i = extra; i < 16; ++i) + { + cMac.Update((byte)0x00); + } + } + } + + // + // add the text + // + cMac.BlockUpdate(data, dataOff, dataLen); + + return cMac.DoFinal(macBlock, 0); + } + + private int GetAssociatedTextLength() + { + return (int)associatedText.Length + ((initialAssociatedText == null) ? 0 : initialAssociatedText.Length); + } + + private bool HasAssociatedText() + { + return GetAssociatedTextLength() > 0; + } + } +} diff --git a/crypto/src/crypto/modes/CfbBlockCipher.cs b/crypto/src/crypto/modes/CfbBlockCipher.cs new file mode 100644 index 000000000..433716535 --- /dev/null +++ b/crypto/src/crypto/modes/CfbBlockCipher.cs @@ -0,0 +1,224 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher. + */ + public class CfbBlockCipher + : IBlockCipher + { + private byte[] IV; + private byte[] cfbV; + private byte[] cfbOutV; + private bool encrypting; + + private readonly int blockSize; + private readonly IBlockCipher 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 CfbBlockCipher( + IBlockCipher 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()]; + } + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + /** + * Initialise the cipher and, possibly, the initialisation vector (IV). + * If an IV isn't passed as part of the parameter, the IV will be all zeros. + * An IV which is too short is handled in FIPS compliant fashion. + * + * @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. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.encrypting = forEncryption; + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV) parameters; + byte[] iv = ivParam.GetIV(); + int diff = IV.Length - iv.Length; + Array.Copy(iv, 0, IV, diff, iv.Length); + Array.Clear(IV, 0, diff); + + parameters = ivParam.Parameters; + } + Reset(); + + // if it's null, key is to be reused. + if (parameters != null) + { + cipher.Init(true, parameters); + } + } + + /** + * return the algorithm name and mode. + * + * @return the name of the underlying algorithm followed by "/CFB" + * and the block size in bits. + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/CFB" + (blockSize * 8); } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + return (encrypting) + ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int EncryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + if ((outOff + blockSize) > outBytes.Length) + { + throw new DataLengthException("output buffer too short"); + } + cipher.ProcessBlock(cfbV, 0, cfbOutV, 0); + // + // XOR the cfbV with the plaintext producing the ciphertext + // + for (int i = 0; i < blockSize; i++) + { + outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]); + } + // + // change over the input block. + // + Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize); + Array.Copy(outBytes, outOff, cfbV, cfbV.Length - blockSize, blockSize); + 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + if ((outOff + blockSize) > outBytes.Length) + { + throw new DataLengthException("output buffer too short"); + } + cipher.ProcessBlock(cfbV, 0, cfbOutV, 0); + // + // change over the input block. + // + Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize); + Array.Copy(input, inOff, cfbV, cfbV.Length - blockSize, blockSize); + // + // XOR the cfbV with the ciphertext producing the plaintext + // + for (int i = 0; i < blockSize; i++) + { + outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]); + } + return blockSize; + } + /** + * reset the chaining vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + Array.Copy(IV, 0, cfbV, 0, IV.Length); + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/modes/CtsBlockCipher.cs b/crypto/src/crypto/modes/CtsBlockCipher.cs new file mode 100644 index 000000000..a32b49675 --- /dev/null +++ b/crypto/src/crypto/modes/CtsBlockCipher.cs @@ -0,0 +1,253 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to + * be used to produce cipher text which is the same outLength as the plain text. + */ + public class CtsBlockCipher + : BufferedBlockCipher + { + private readonly int blockSize; + + /** + * Create a buffered block cipher that uses Cipher Text Stealing + * + * @param cipher the underlying block cipher this buffering object wraps. + */ + public CtsBlockCipher( + IBlockCipher cipher) + { + // TODO Should this test for acceptable ones instead? + if (cipher is OfbBlockCipher || cipher is CfbBlockCipher) + throw new ArgumentException("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 of 'length' bytes. + * + * @param length the outLength of the input. + * @return the space required to accommodate a call to update + * with length bytes of input. + */ + public override int GetUpdateOutputSize( + int length) + { + int total = length + 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 length bytes. + * + * @param length the outLength of the input. + * @return the space required to accommodate a call to update and doFinal + * with length bytes of input. + */ + public override int GetOutputSize( + int length) + { + 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessByte( + byte input, + byte[] output, + int outOff) + { + int resultLen = 0; + + if (bufOff == buf.Length) + { + resultLen = cipher.ProcessBlock(buf, 0, output, outOff); + Debug.Assert(resultLen == blockSize); + + Array.Copy(buf, blockSize, buf, 0, blockSize); + bufOff = blockSize; + } + + buf[bufOff++] = input; + + 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 length 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + if (length < 0) + { + throw new ArgumentException("Can't have a negative input outLength!"); + } + + int blockSize = GetBlockSize(); + int outLength = GetUpdateOutputSize(length); + + if (outLength > 0) + { + if ((outOff + outLength) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + } + + int resultLen = 0; + int gapLen = buf.Length - bufOff; + + if (length > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + resultLen += cipher.ProcessBlock(buf, 0, output, outOff); + Array.Copy(buf, blockSize, buf, 0, blockSize); + + bufOff = blockSize; + + length -= gapLen; + inOff += gapLen; + + while (length > blockSize) + { + Array.Copy(input, inOff, buf, bufOff, blockSize); + resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen); + Array.Copy(buf, blockSize, buf, 0, blockSize); + + length -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, length); + + bufOff += length; + + 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 InvalidOperationException if the underlying cipher is not + * initialised. + * @exception InvalidCipherTextException if cipher text decrypts wrongly (in + * case the exception will never Get thrown). + */ + public override int DoFinal( + byte[] output, + int outOff) + { + if (bufOff + outOff > output.Length) + { + throw new DataLengthException("output buffer too small in doFinal"); + } + + int blockSize = cipher.GetBlockSize(); + int length = 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]; + } + + IBlockCipher c = (cipher is CbcBlockCipher) + ? ((CbcBlockCipher)cipher).GetUnderlyingCipher() + : cipher; + + c.ProcessBlock(buf, blockSize, output, outOff); + + Array.Copy(block, 0, output, outOff + blockSize, length); + } + else + { + byte[] lastBlock = new byte[blockSize]; + + IBlockCipher c = (cipher is CbcBlockCipher) + ? ((CbcBlockCipher)cipher).GetUnderlyingCipher() + : cipher; + + c.ProcessBlock(buf, 0, block, 0); + + for (int i = blockSize; i != bufOff; i++) + { + lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]); + } + + Array.Copy(buf, blockSize, block, 0, length); + + cipher.ProcessBlock(block, 0, output, outOff); + Array.Copy(lastBlock, 0, output, outOff + blockSize, length); + } + + int offset = bufOff; + + Reset(); + + return offset; + } + } +} diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs new file mode 100644 index 000000000..bb027b597 --- /dev/null +++ b/crypto/src/crypto/modes/EAXBlockCipher.cs @@ -0,0 +1,365 @@ +using System; + +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * 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 + : IAeadBlockCipher + { + private enum Tag : byte { N, H, C }; + + private SicBlockCipher cipher; + + private bool forEncryption; + + private int blockSize; + + private IMac mac; + + private byte[] nonceMac; + private byte[] associatedTextMac; + private byte[] macBlock; + + private int macSize; + private byte[] bufBlock; + private int bufOff; + + private bool cipherInitialized; + private byte[] initialAssociatedText; + + /** + * Constructor that accepts an instance of a block cipher engine. + * + * @param cipher the engine to use + */ + public EaxBlockCipher( + IBlockCipher cipher) + { + blockSize = cipher.GetBlockSize(); + mac = new CMac(cipher); + macBlock = new byte[blockSize]; + bufBlock = new byte[blockSize * 2]; + associatedTextMac = new byte[mac.GetMacSize()]; + nonceMac = new byte[mac.GetMacSize()]; + this.cipher = new SicBlockCipher(cipher); + } + + public virtual string AlgorithmName + { + get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; } + } + + public virtual int GetBlockSize() + { + return cipher.GetBlockSize(); + } + + public virtual void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + byte[] nonce; + ICipherParameters keyParam; + + if (parameters is AeadParameters) + { + AeadParameters param = (AeadParameters) parameters; + + nonce = param.GetNonce(); + initialAssociatedText = param.GetAssociatedText(); + macSize = param.MacSize / 8; + keyParam = param.Key; + } + else if (parameters is ParametersWithIV) + { + ParametersWithIV param = (ParametersWithIV) parameters; + + nonce = param.GetIV(); + initialAssociatedText = null; + macSize = mac.GetMacSize() / 2; + keyParam = param.Parameters; + } + else + { + throw new ArgumentException("invalid parameters passed to EAX"); + } + + byte[] tag = new byte[blockSize]; + + // Key reuse implemented in CBC mode of underlying CMac + mac.Init(keyParam); + + tag[blockSize - 1] = (byte)Tag.N; + mac.BlockUpdate(tag, 0, blockSize); + mac.BlockUpdate(nonce, 0, nonce.Length); + mac.DoFinal(nonceMac, 0); + + tag[blockSize - 1] = (byte)Tag.H; + mac.BlockUpdate(tag, 0, blockSize); + + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } + + // Same BlockCipher underlies this and the mac, so reuse last key on cipher + cipher.Init(true, new ParametersWithIV(null, nonceMac)); + } + + private void InitCipher() + { + if (cipherInitialized) + { + return; + } + + cipherInitialized = true; + + mac.DoFinal(associatedTextMac, 0); + + byte[] tag = new byte[blockSize]; + tag[blockSize - 1] = (byte)Tag.C; + mac.BlockUpdate(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 virtual void Reset() + { + Reset(true); + } + + private void Reset( + bool clearMac) + { + cipher.Reset(); // TODO Redundant since the mac will reset it? + mac.Reset(); + + bufOff = 0; + Array.Clear(bufBlock, 0, bufBlock.Length); + + if (clearMac) + { + Array.Clear(macBlock, 0, macBlock.Length); + } + + byte[] tag = new byte[blockSize]; + tag[blockSize - 1] = (byte)Tag.H; + mac.BlockUpdate(tag, 0, blockSize); + + cipherInitialized = false; + + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } + } + + public virtual void ProcessAadByte(byte input) + { + if (cipherInitialized) + { + throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + } + mac.Update(input); + } + + public void ProcessAadBytes(byte[] inBytes, int inOff, int len) + { + if (cipherInitialized) + { + throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + } + mac.BlockUpdate(inBytes, inOff, len); + } + + public virtual int ProcessByte( + byte input, + byte[] outBytes, + int outOff) + { + InitCipher(); + + return Process(input, outBytes, outOff); + } + + public virtual int ProcessBytes( + byte[] inBytes, + int inOff, + int len, + byte[] outBytes, + int outOff) + { + InitCipher(); + + int resultLen = 0; + + for (int i = 0; i != len; i++) + { + resultLen += Process(inBytes[inOff + i], outBytes, outOff + resultLen); + } + + return resultLen; + } + + public virtual int DoFinal( + byte[] outBytes, + int outOff) + { + InitCipher(); + + int extra = bufOff; + byte[] tmp = new byte[bufBlock.Length]; + + bufOff = 0; + + if (forEncryption) + { + cipher.ProcessBlock(bufBlock, 0, tmp, 0); + cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); + + Array.Copy(tmp, 0, outBytes, outOff, extra); + + mac.BlockUpdate(tmp, 0, extra); + + CalculateMac(); + + Array.Copy(macBlock, 0, outBytes, outOff + extra, macSize); + + Reset(false); + + return extra + macSize; + } + else + { + if (extra > macSize) + { + mac.BlockUpdate(bufBlock, 0, extra - macSize); + + cipher.ProcessBlock(bufBlock, 0, tmp, 0); + cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); + + Array.Copy(tmp, 0, outBytes, outOff, extra - macSize); + } + + CalculateMac(); + + if (!VerifyMac(bufBlock, extra - macSize)) + throw new InvalidCipherTextException("mac check in EAX failed"); + + Reset(false); + + return extra - macSize; + } + } + + public virtual byte[] GetMac() + { + byte[] mac = new byte[macSize]; + + Array.Copy(macBlock, 0, mac, 0, macSize); + + return mac; + } + + public virtual int GetUpdateOutputSize( + int len) + { + int totalData = len + bufOff; + if (!forEncryption) + { + if (totalData < macSize) + { + return 0; + } + totalData -= macSize; + } + return totalData - totalData % blockSize; + } + + public virtual 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[] outBytes, + int outOff) + { + bufBlock[bufOff++] = b; + + if (bufOff == bufBlock.Length) + { + int size; + + if (forEncryption) + { + size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff); + + mac.BlockUpdate(outBytes, outOff, blockSize); + } + else + { + mac.BlockUpdate(bufBlock, 0, blockSize); + + size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff); + } + + bufOff = blockSize; + Array.Copy(bufBlock, blockSize, bufBlock, 0, blockSize); + + return size; + } + + return 0; + } + + private bool 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/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs new file mode 100644 index 000000000..95fe6f7ec --- /dev/null +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -0,0 +1,506 @@ +using System; + +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Modes.Gcm; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /// + /// Implements the Galois/Counter mode (GCM) detailed in + /// NIST Special Publication 800-38D. + /// + public class GcmBlockCipher + : IAeadBlockCipher + { + private const int BlockSize = 16; + + private readonly IBlockCipher cipher; + private readonly IGcmMultiplier multiplier; + private IGcmExponentiator exp; + + // These fields are set by Init and not modified by processing + private bool 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 ulong totalLength; + private byte[] atBlock; + private int atBlockPos; + private ulong atLength; + private ulong atLengthPre; + + public GcmBlockCipher( + IBlockCipher c) + : this(c, null) + { + } + + public GcmBlockCipher( + IBlockCipher c, + IGcmMultiplier m) + { + if (c.GetBlockSize() != BlockSize) + throw new ArgumentException("cipher required with a block size of " + BlockSize + "."); + + if (m == null) + { + // TODO Consider a static property specifying default multiplier + m = new Tables8kGcmMultiplier(); + } + + this.cipher = c; + this.multiplier = m; + } + + public virtual string AlgorithmName + { + get { return cipher.AlgorithmName + "/GCM"; } + } + + public virtual int GetBlockSize() + { + return BlockSize; + } + + public virtual void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + this.macBlock = null; + + KeyParameter keyParam; + + if (parameters is AeadParameters) + { + AeadParameters param = (AeadParameters)parameters; + + nonce = param.GetNonce(); + initialAssociatedText = param.GetAssociatedText(); + + int macSizeBits = param.MacSize; + if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0) + { + throw new ArgumentException("Invalid value for MAC size: " + macSizeBits); + } + + macSize = macSizeBits / 8; + keyParam = param.Key; + } + else if (parameters is ParametersWithIV) + { + ParametersWithIV param = (ParametersWithIV)parameters; + + nonce = param.GetIV(); + initialAssociatedText = null; + macSize = 16; + keyParam = (KeyParameter)param.Parameters; + } + else + { + throw new ArgumentException("invalid parameters passed to GCM"); + } + + int bufLength = forEncryption ? BlockSize : (BlockSize + macSize); + this.bufBlock = new byte[bufLength]; + + if (nonce == null || nonce.Length < 1) + { + throw new ArgumentException("IV must be at least 1 byte"); + } + + // TODO This should be configurable by Init parameters + // (but must be 16 if nonce length not 12) (BlockSize?) +// this.tagLength = 16; + + // 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[BlockSize]; + cipher.ProcessBlock(H, 0, H, 0); + + // if keyParam is null we're reusing the last key and the multiplier doesn't need re-init + multiplier.Init(H); + exp = null; + } + + this.J0 = new byte[BlockSize]; + + if (nonce.Length == 12) + { + Array.Copy(nonce, 0, J0, 0, nonce.Length); + this.J0[BlockSize - 1] = 0x01; + } + else + { + gHASH(J0, nonce, nonce.Length); + byte[] X = new byte[BlockSize]; + Pack.UInt64_To_BE((ulong)nonce.Length * 8UL, X, 8); + gHASHBlock(J0, X); + } + + this.S = new byte[BlockSize]; + this.S_at = new byte[BlockSize]; + this.S_atPre = new byte[BlockSize]; + this.atBlock = new byte[BlockSize]; + 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 virtual byte[] GetMac() + { + return Arrays.Clone(macBlock); + } + + public virtual int GetOutputSize( + int len) + { + int totalData = len + bufOff; + + if (forEncryption) + { + return totalData + macSize; + } + + return totalData < macSize ? 0 : totalData - macSize; + } + + public virtual int GetUpdateOutputSize( + int len) + { + int totalData = len + bufOff; + if (!forEncryption) + { + if (totalData < macSize) + { + return 0; + } + totalData -= macSize; + } + return totalData - totalData % BlockSize; + } + + public virtual void ProcessAadByte(byte input) + { + atBlock[atBlockPos] = input; + if (++atBlockPos == BlockSize) + { + // Hash each block as it fills + gHASHBlock(S_at, atBlock); + atBlockPos = 0; + atLength += BlockSize; + } + } + + public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) + { + for (int i = 0; i < len; ++i) + { + atBlock[atBlockPos] = inBytes[inOff + i]; + if (++atBlockPos == BlockSize) + { + // Hash each block as it fills + gHASHBlock(S_at, atBlock); + atBlockPos = 0; + atLength += BlockSize; + } + } + } + + private void InitCipher() + { + if (atLength > 0) + { + Array.Copy(S_at, 0, S_atPre, 0, BlockSize); + atLengthPre = atLength; + } + + // Finish hash for partial AAD block + if (atBlockPos > 0) + { + gHASHPartial(S_atPre, atBlock, 0, atBlockPos); + atLengthPre += (uint)atBlockPos; + } + + if (atLengthPre > 0) + { + Array.Copy(S_atPre, 0, S, 0, BlockSize); + } + } + + public virtual int ProcessByte( + byte input, + byte[] output, + int outOff) + { + bufBlock[bufOff] = input; + if (++bufOff == bufBlock.Length) + { + OutputBlock(output, outOff); + return BlockSize; + } + return 0; + } + + public virtual int ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] output, + int outOff) + { + int resultLen = 0; + + for (int i = 0; i < len; ++i) + { + bufBlock[bufOff] = input[inOff + i]; + if (++bufOff == bufBlock.Length) + { + OutputBlock(output, outOff + resultLen); + resultLen += BlockSize; + } + } + + return resultLen; + } + + private void OutputBlock(byte[] output, int offset) + { + if (totalLength == 0) + { + InitCipher(); + } + gCTRBlock(bufBlock, output, offset); + if (forEncryption) + { + bufOff = 0; + } + else + { + Array.Copy(bufBlock, BlockSize, bufBlock, 0, macSize); + bufOff = macSize; + } + } + + public int DoFinal(byte[] output, int outOff) + { + if (totalLength == 0) + { + InitCipher(); + } + + int extra = bufOff; + if (!forEncryption) + { + if (extra < macSize) + throw new InvalidCipherTextException("data too short"); + + extra -= macSize; + } + + if (extra > 0) + { + gCTRPartial(bufBlock, 0, extra, output, outOff); + } + + atLength += (uint)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) + { + GcmUtilities.Xor(S_at, S_atPre); + } + + // Number of cipher-text blocks produced + long c = (long)(((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 + GcmUtilities.Multiply(S_at, H_c); + + // Adjust the current hash + GcmUtilities.Xor(S, S_at); + } + + // Final gHASH + byte[] X = new byte[BlockSize]; + Pack.UInt64_To_BE(atLength * 8UL, X, 0); + Pack.UInt64_To_BE(totalLength * 8UL, X, 8); + + gHASHBlock(S, X); + + // TODO Fix this if tagLength becomes configurable + // T = MSBt(GCTRk(J0,S)) + byte[] tag = new byte[BlockSize]; + cipher.ProcessBlock(J0, 0, tag, 0); + GcmUtilities.Xor(tag, S); + + int resultLen = extra; + + // We place into macBlock our calculated value for T + this.macBlock = new byte[macSize]; + Array.Copy(tag, 0, macBlock, 0, macSize); + + if (forEncryption) + { + // Append T to the message + Array.Copy(macBlock, 0, output, outOff + bufOff, macSize); + resultLen += macSize; + } + else + { + // Retrieve the T value from the message and compare to calculated one + byte[] msgMac = new byte[macSize]; + Array.Copy(bufBlock, extra, msgMac, 0, macSize); + if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac)) + throw new InvalidCipherTextException("mac check in GCM failed"); + } + + Reset(false); + + return resultLen; + } + + public virtual void Reset() + { + Reset(true); + } + + private void Reset( + bool clearMac) + { + cipher.Reset(); + + S = new byte[BlockSize]; + S_at = new byte[BlockSize]; + S_atPre = new byte[BlockSize]; + atBlock = new byte[BlockSize]; + atBlockPos = 0; + atLength = 0; + atLengthPre = 0; + counter = Arrays.Clone(J0); + bufOff = 0; + totalLength = 0; + + if (bufBlock != null) + { + Arrays.Fill(bufBlock, 0); + } + + if (clearMac) + { + macBlock = null; + } + + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } + } + + private void gCTRBlock(byte[] block, byte[] output, int outOff) + { + byte[] tmp = GetNextCounterBlock(); + + GcmUtilities.Xor(tmp, block); + Array.Copy(tmp, 0, output, outOff, BlockSize); + + gHASHBlock(S, forEncryption ? tmp : block); + + totalLength += BlockSize; + } + + private void gCTRPartial(byte[] buf, int off, int len, byte[] output, int outOff) + { + byte[] tmp = GetNextCounterBlock(); + + GcmUtilities.Xor(tmp, buf, off, len); + Array.Copy(tmp, 0, output, outOff, len); + + gHASHPartial(S, forEncryption ? tmp : buf, 0, len); + + totalLength += (uint)len; + } + + private void gHASH(byte[] Y, byte[] b, int len) + { + for (int pos = 0; pos < len; pos += BlockSize) + { + int num = System.Math.Min(len - pos, BlockSize); + gHASHPartial(Y, b, pos, num); + } + } + + private void gHASHBlock(byte[] Y, byte[] b) + { + GcmUtilities.Xor(Y, b); + multiplier.MultiplyH(Y); + } + + private void gHASHPartial(byte[] Y, byte[] b, int off, int len) + { + GcmUtilities.Xor(Y, b, off, len); + multiplier.MultiplyH(Y); + } + + private byte[] GetNextCounterBlock() + { + for (int i = 15; i >= 12; --i) + { + if (++counter[i] != 0) break; + } + + byte[] tmp = new byte[BlockSize]; + // TODO Sure would be nice if ciphers could operate on int[] + cipher.ProcessBlock(counter, 0, tmp, 0); + return tmp; + } + } +} diff --git a/crypto/src/crypto/modes/GOFBBlockCipher.cs b/crypto/src/crypto/modes/GOFBBlockCipher.cs new file mode 100644 index 000000000..a91562549 --- /dev/null +++ b/crypto/src/crypto/modes/GOFBBlockCipher.cs @@ -0,0 +1,227 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * implements the GOST 28147 OFB counter mode (GCTR). + */ + public class GOfbBlockCipher + : IBlockCipher + { + private byte[] IV; + private byte[] ofbV; + private byte[] ofbOutV; + + private readonly int blockSize; + private readonly IBlockCipher cipher; + + bool firstStep = true; + int N3; + int N4; + const int C1 = 16843012; //00000001000000010000000100000100 + const 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( + IBlockCipher cipher) + { + this.cipher = cipher; + this.blockSize = cipher.GetBlockSize(); + + if (blockSize != 8) + { + throw new ArgumentException("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()]; + } + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + + /** + * Initialise the cipher and, possibly, the initialisation vector (IV). + * If an IV isn't passed as part of the parameter, the IV will be all zeros. + * An IV which is too short is handled in FIPS compliant fashion. + * + * @param encrypting if true the cipher is initialised for + * encryption, if false for decryption. + * @param parameters the key and other data required by the cipher. + * @exception ArgumentException if the parameters argument is inappropriate. + */ + public void Init( + bool forEncryption, //ignored by this CTR mode + ICipherParameters parameters) + { + firstStep = true; + N3 = 0; + N4 = 0; + + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + + if (iv.Length < IV.Length) + { + // prepend the supplied IV with zeros (per FIPS PUB 81) + Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length); + for (int i = 0; i < IV.Length - iv.Length; i++) + { + IV[i] = 0; + } + } + else + { + Array.Copy(iv, 0, IV, 0, IV.Length); + } + + parameters = ivParam.Parameters; + } + + Reset(); + + // if it's null, key is to be reused. + if (parameters != null) + { + cipher.Init(true, parameters); + } + } + + /** + * return the algorithm name and mode. + * + * @return the name of the underlying algorithm followed by "/GCTR" + * and the block size in bits + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/GCTR"; } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + blockSize) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + 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); + + // + // XOR the ofbV with the plaintext producing the cipher text (and + // the next input block). + // + for (int i = 0; i < blockSize; i++) + { + output[outOff + i] = (byte)(ofbOutV[i] ^ input[inOff + i]); + } + + // + // change over the input block. + // + Array.Copy(ofbV, blockSize, ofbV, 0, ofbV.Length - blockSize); + Array.Copy(ofbOutV, 0, ofbV, ofbV.Length - blockSize, blockSize); + + return blockSize; + } + + /** + * reset the feedback vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + Array.Copy(IV, 0, ofbV, 0, IV.Length); + + cipher.Reset(); + } + + //array of bytes to type int + private int bytesToint( + byte[] inBytes, + int inOff) + { + return (int)((inBytes[inOff + 3] << 24) & 0xff000000) + ((inBytes[inOff + 2] << 16) & 0xff0000) + + ((inBytes[inOff + 1] << 8) & 0xff00) + (inBytes[inOff] & 0xff); + } + + //int to array of bytes + private void intTobytes( + int num, + byte[] outBytes, + int outOff) + { + outBytes[outOff + 3] = (byte)(num >> 24); + outBytes[outOff + 2] = (byte)(num >> 16); + outBytes[outOff + 1] = (byte)(num >> 8); + outBytes[outOff] = (byte)num; + } + } +} diff --git a/crypto/src/crypto/modes/IAeadBlockCipher.cs b/crypto/src/crypto/modes/IAeadBlockCipher.cs new file mode 100644 index 000000000..06bc50488 --- /dev/null +++ b/crypto/src/crypto/modes/IAeadBlockCipher.cs @@ -0,0 +1,102 @@ +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /// + /// A block cipher mode that includes authenticated encryption with a streaming mode + /// and optional associated data. + /// + public interface IAeadBlockCipher + { + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// Parameter can either be an AeadParameters or a ParametersWithIV object. + /// Initialise for encryption if true, for decryption if false. + /// The key or other data required by the cipher. + void Init(bool forEncryption, ICipherParameters parameters); + + /// The block size for this cipher, in bytes. + int GetBlockSize(); + + /// Add a single byte to the associated data check. + /// If the implementation supports it, this will be an online operation and will not retain the associated data. + /// The byte to be processed. + void ProcessAadByte(byte input); + + /// Add a sequence of bytes to the associated data check. + /// If the implementation supports it, this will be an online operation and will not retain the associated data. + /// The input byte array. + /// The offset into the input array where the data to be processed starts. + /// The number of bytes to be processed. + void ProcessAadBytes(byte[] inBytes, int inOff, int len); + + /** + * Encrypt/decrypt a single byte. + * + * @param input the byte to be processed. + * @param outBytes 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. + */ + int ProcessByte(byte input, byte[] outBytes, int outOff); + + /** + * Process a block of bytes from in putting the result into out. + * + * @param inBytes 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 outBytes 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. + */ + int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff); + + /** + * Finish the operation either appending or verifying the MAC at the end of the data. + * + * @param outBytes 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 InvalidOperationException if the cipher is in an inappropriate state. + * @throws InvalidCipherTextException if the MAC fails to match. + */ + int DoFinal(byte[] outBytes, int outOff); + + /** + * Return the value of the MAC associated with the last stream processed. + * + * @return MAC for plaintext data. + */ + byte[] GetMac(); + + /** + * Return the size of the output buffer required for a ProcessBytes + * an input of len bytes. + * + * @param len the length of the input. + * @return the space required to accommodate a call to ProcessBytes + * with len bytes of input. + */ + int GetUpdateOutputSize(int len); + + /** + * Return the size of the output buffer required for a ProcessBytes 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 ProcessBytes and DoFinal + * with len bytes of input. + */ + int GetOutputSize(int len); + + /// + /// Reset the cipher to the same state as it was after the last init (if there was one). + /// + void Reset(); + } +} diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs new file mode 100644 index 000000000..3ee06b805 --- /dev/null +++ b/crypto/src/crypto/modes/OCBBlockCipher.cs @@ -0,0 +1,543 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * An implementation of the "work in progress" Internet-Draft The OCB Authenticated-Encryption + * Algorithm, licensed per: + * + *

License for + * Open-Source Software Implementations of OCB (Jan 9, 2013) - 'License 1'
+ * 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. + *

+ * 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.

+ */ + public class OcbBlockCipher + : IAeadBlockCipher + { + private const int BLOCK_SIZE = 16; + + private readonly IBlockCipher hashCipher; + private readonly IBlockCipher mainCipher; + + /* + * CONFIGURATION + */ + private bool forEncryption; + private int macSize; + private byte[] initialAssociatedText; + + /* + * KEY-DEPENDENT + */ + // NOTE: elements are lazily calculated + private IList L; + private byte[] L_Asterisk, L_Dollar; + + /* + * NONCE-DEPENDENT + */ + private byte[] OffsetMAIN_0; + + /* + * PER-ENCRYPTION/DECRYPTION + */ + private byte[] hashBlock, mainBlock; + private int hashBlockPos, mainBlockPos; + private long hashBlockCount, mainBlockCount; + private byte[] OffsetHASH; + private byte[] Sum; + private byte[] OffsetMAIN; + private byte[] Checksum; + + // NOTE: The MAC value is preserved after doFinal + private byte[] macBlock; + + public OcbBlockCipher(IBlockCipher hashCipher, IBlockCipher mainCipher) + { + if (hashCipher == null) + throw new ArgumentNullException("hashCipher"); + if (hashCipher.GetBlockSize() != BLOCK_SIZE) + throw new ArgumentException("must have a block size of " + BLOCK_SIZE, "hashCipher"); + if (mainCipher == null) + throw new ArgumentNullException("mainCipher"); + if (mainCipher.GetBlockSize() != BLOCK_SIZE) { + throw new ArgumentException("must have a block size of " + BLOCK_SIZE, "mainCipher"); + } + + if (!hashCipher.AlgorithmName.Equals(mainCipher.AlgorithmName)) + throw new ArgumentException("'hashCipher' and 'mainCipher' must be the same algorithm"); + + this.hashCipher = hashCipher; + this.mainCipher = mainCipher; + } + + public virtual IBlockCipher GetUnderlyingCipher() + { + return mainCipher; + } + + public virtual string AlgorithmName + { + get { return mainCipher.AlgorithmName + "/OCB"; } + } + + public virtual void Init(bool forEncryption, ICipherParameters parameters) + { + this.forEncryption = forEncryption; + this.macBlock = null; + + KeyParameter keyParameter; + + byte[] N; + if (parameters is AeadParameters) + { + AeadParameters aeadParameters = (AeadParameters) parameters; + + N = aeadParameters.GetNonce(); + initialAssociatedText = aeadParameters.GetAssociatedText(); + + int macSizeBits = aeadParameters.MacSize; + if (macSizeBits < 64 || macSizeBits > 128 || macSizeBits % 8 != 0) + throw new ArgumentException("Invalid value for MAC size: " + macSizeBits); + + macSize = macSizeBits / 8; + keyParameter = aeadParameters.Key; + } + else if (parameters is ParametersWithIV) + { + ParametersWithIV parametersWithIV = (ParametersWithIV) parameters; + + N = parametersWithIV.GetIV(); + initialAssociatedText = null; + macSize = 16; + keyParameter = (KeyParameter) parametersWithIV.Parameters; + } + else + { + throw new ArgumentException("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 ArgumentException("IV must be no more than 15 bytes"); + } + + /* + * KEY-DEPENDENT INITIALISATION + */ + + // if keyParam is null we're reusing the last key. + if (keyParameter != null) + { + // TODO + } + + // hashCipher always used in forward mode + hashCipher.Init(true, keyParameter); + mainCipher.Init(forEncryption, keyParameter); + + this.L_Asterisk = new byte[16]; + hashCipher.ProcessBlock(L_Asterisk, 0, L_Asterisk, 0); + + this.L_Dollar = OCB_double(L_Asterisk); + + this.L = Platform.CreateArrayList(); + this.L.Add(OCB_double(L_Dollar)); + + /* + * NONCE-DEPENDENT AND PER-ENCRYPTION/DECRYPTION INITIALISATION + */ + + byte[] nonce = new byte[16]; + Array.Copy(N, 0, nonce, nonce.Length - N.Length, N.Length); + nonce[0] = (byte)(macSize << 4); + nonce[15 - N.Length] |= 1; + + int bottom = nonce[15] & 0x3F; + + byte[] Ktop = new byte[16]; + nonce[15] &= 0xC0; + hashCipher.ProcessBlock(nonce, 0, Ktop, 0); + + byte[] Stretch = new byte[24]; + Array.Copy(Ktop, 0, Stretch, 0, 16); + for (int i = 0; i < 8; ++i) + { + Stretch[16 + i] = (byte) (Ktop[i] ^ Ktop[i + 1]); + } + + this.OffsetMAIN_0 = new byte[16]; + int bits = bottom % 8, bytes = bottom / 8; + if (bits == 0) + { + Array.Copy(Stretch, bytes, OffsetMAIN_0, 0, 16); + } + else + { + for (int i = 0; i < 16; ++i) + { + uint b1 = Stretch[bytes]; + uint b2 = Stretch[++bytes]; + 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]; + this.OffsetMAIN = Arrays.Clone(this.OffsetMAIN_0); + this.Checksum = new byte[16]; + + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } + } + + public virtual int GetBlockSize() + { + return BLOCK_SIZE; + } + + public virtual byte[] GetMac() + { + return Arrays.Clone(macBlock); + } + + public virtual int GetOutputSize(int len) + { + int totalData = len + mainBlockPos; + if (forEncryption) + { + return totalData + macSize; + } + return totalData < macSize ? 0 : totalData - macSize; + } + + public virtual int GetUpdateOutputSize(int len) + { + int totalData = len + mainBlockPos; + if (!forEncryption) + { + if (totalData < macSize) + { + return 0; + } + totalData -= macSize; + } + return totalData - totalData % BLOCK_SIZE; + } + + public virtual void ProcessAadByte(byte input) + { + hashBlock[hashBlockPos] = input; + if (++hashBlockPos == hashBlock.Length) + { + ProcessHashBlock(); + } + } + + public virtual 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 virtual int ProcessByte(byte input, byte[] output, int outOff) + { + mainBlock[mainBlockPos] = input; + if (++mainBlockPos == mainBlock.Length) + { + ProcessMainBlock(output, outOff); + return BLOCK_SIZE; + } + return 0; + } + + public virtual int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) + { + 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 virtual int DoFinal(byte[] output, int outOff) + { + /* + * 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]; + Array.Copy(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); + + Array.Copy(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]; + Array.Copy(Checksum, 0, macBlock, 0, macSize); + + /* + * Validate or append tag and reset this cipher for the next run + */ + int resultLen = mainBlockPos; + + if (forEncryption) + { + // Append tag to the message + Array.Copy(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 virtual void Reset() + { + Reset(true); + } + + protected virtual void Clear(byte[] bs) + { + if (bs != null) + { + Array.Clear(bs, 0, bs.Length); + } + } + + protected virtual byte[] GetLSub(int n) + { + while (n >= L.Count) + { + L.Add(OCB_double((byte[]) L[L.Count - 1])); + } + return (byte[])L[n]; + } + + protected virtual void ProcessHashBlock() + { + /* + * HASH: Process any whole blocks + */ + UpdateHASH(GetLSub(OCB_ntz(++hashBlockCount))); + hashBlockPos = 0; + } + + protected virtual void ProcessMainBlock(byte[] output, int outOff) + { + /* + * 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); + + Array.Copy(mainBlock, 0, output, outOff, 16); + + if (!forEncryption) + { + Xor(Checksum, mainBlock); + Array.Copy(mainBlock, BLOCK_SIZE, mainBlock, 0, macSize); + mainBlockPos = macSize; + } + } + + protected virtual void Reset(bool clearMac) + { + hashCipher.Reset(); + mainCipher.Reset(); + + Clear(hashBlock); + Clear(mainBlock); + + hashBlockPos = 0; + mainBlockPos = 0; + + hashBlockCount = 0; + mainBlockCount = 0; + + Clear(OffsetHASH); + Clear(Sum); + Array.Copy(OffsetMAIN_0, 0, OffsetMAIN, 0, 16); + Clear(Checksum); + + if (clearMac) + { + macBlock = null; + } + + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } + } + + protected virtual 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] ^= (byte)(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; + uint bit = 0; + while (--i >= 0) + { + uint b = block[i]; + output[i] = (byte) ((b << 1) | bit); + bit = (b >> 7) & 1; + } + return (int)bit; + } + + protected static void Xor(byte[] block, byte[] val) + { + for (int i = 15; i >= 0; --i) + { + block[i] ^= val[i]; + } + } + } +} diff --git a/crypto/src/crypto/modes/OfbBlockCipher.cs b/crypto/src/crypto/modes/OfbBlockCipher.cs new file mode 100644 index 000000000..a99f8c5d7 --- /dev/null +++ b/crypto/src/crypto/modes/OfbBlockCipher.cs @@ -0,0 +1,182 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * implements a Output-FeedBack (OFB) mode on top of a simple cipher. + */ + public class OfbBlockCipher + : IBlockCipher + { + private byte[] IV; + private byte[] ofbV; + private byte[] ofbOutV; + + private readonly int blockSize; + private readonly IBlockCipher 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( + IBlockCipher cipher, + int blockSize) + { + 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()]; + } + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + + /** + * Initialise the cipher and, possibly, the initialisation vector (IV). + * If an IV isn't passed as part of the parameter, the IV will be all zeros. + * An IV which is too short is handled in FIPS compliant fashion. + * + * @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. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, //ignored by this OFB mode + ICipherParameters parameters) + { + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + + if (iv.Length < IV.Length) + { + // prepend the supplied IV with zeros (per FIPS PUB 81) + Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length); + for (int i = 0; i < IV.Length - iv.Length; i++) + { + IV[i] = 0; + } + } + else + { + Array.Copy(iv, 0, IV, 0, IV.Length); + } + + parameters = ivParam.Parameters; + } + + Reset(); + + // if it's null, key is to be reused. + if (parameters != null) + { + cipher.Init(true, parameters); + } + } + + /** + * return the algorithm name and mode. + * + * @return the name of the underlying algorithm followed by "/OFB" + * and the block size in bits + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/OFB" + (blockSize * 8); } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + blockSize) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + cipher.ProcessBlock(ofbV, 0, ofbOutV, 0); + + // + // XOR the ofbV with the plaintext producing the cipher text (and + // the next input block). + // + for (int i = 0; i < blockSize; i++) + { + output[outOff + i] = (byte)(ofbOutV[i] ^ input[inOff + i]); + } + + // + // change over the input block. + // + Array.Copy(ofbV, blockSize, ofbV, 0, ofbV.Length - blockSize); + Array.Copy(ofbOutV, 0, ofbV, ofbV.Length - blockSize, blockSize); + + return blockSize; + } + + /** + * reset the feedback vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + Array.Copy(IV, 0, ofbV, 0, IV.Length); + + cipher.Reset(); + } + } + +} diff --git a/crypto/src/crypto/modes/OpenPgpCfbBlockCipher.cs b/crypto/src/crypto/modes/OpenPgpCfbBlockCipher.cs new file mode 100644 index 000000000..038ca783d --- /dev/null +++ b/crypto/src/crypto/modes/OpenPgpCfbBlockCipher.cs @@ -0,0 +1,337 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * 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. + *

+ * For further info see RFC 2440. + *

+ */ + public class OpenPgpCfbBlockCipher + : IBlockCipher + { + private byte[] IV; + private byte[] FR; + private byte[] FRE; + + private readonly IBlockCipher cipher; + private readonly int blockSize; + + private int count; + private bool forEncryption; + + /** + * Basic constructor. + * + * @param cipher the block cipher to be used as the basis of the + * feedback mode. + */ + public OpenPgpCfbBlockCipher( + IBlockCipher 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 IBlockCipher 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 AlgorithmName + { + get { return cipher.AlgorithmName + "/OpenPGPCFB"; } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + return (forEncryption) ? EncryptBlock(input, inOff, output, outOff) : DecryptBlock(input, inOff, output, outOff); + } + + /** + * reset the chaining vector back to the IV and reset the underlying + * cipher. + */ + public void Reset() + { + count = 0; + + Array.Copy(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 parameters the key and other data required by the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + + if (iv.Length < IV.Length) + { + // prepend the supplied IV with zeros (per FIPS PUB 81) + Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length); + for (int i = 0; i < IV.Length - iv.Length; i++) + { + IV[i] = 0; + } + } + else + { + Array.Copy(iv, 0, IV, 0, IV.Length); + } + + parameters = ivParam.Parameters; + } + + Reset(); + + cipher.Init(true, parameters); + } + + /** + * Encrypt one byte of data according to CFB mode. + * @param data the byte to encrypt + * @param blockOff offset in the current 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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + private int EncryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + blockSize) > outBytes.Length) + { + throw new DataLengthException("output buffer too short"); + } + + if (count > blockSize) + { + FR[blockSize - 2] = outBytes[outOff] = EncryptByte(input[inOff], blockSize - 2); + FR[blockSize - 1] = outBytes[outOff + 1] = EncryptByte(input[inOff + 1], blockSize - 1); + + cipher.ProcessBlock(FR, 0, FRE, 0); + + for (int n = 2; n < blockSize; n++) + { + FR[n - 2] = outBytes[outOff + n] = EncryptByte(input[inOff + n], n - 2); + } + } + else if (count == 0) + { + cipher.ProcessBlock(FR, 0, FRE, 0); + + for (int n = 0; n < blockSize; n++) + { + FR[n] = outBytes[outOff + n] = EncryptByte(input[inOff + n], n); + } + + count += blockSize; + } + else if (count == blockSize) + { + cipher.ProcessBlock(FR, 0, FRE, 0); + + outBytes[outOff] = EncryptByte(input[inOff], 0); + outBytes[outOff + 1] = EncryptByte(input[inOff + 1], 1); + + // + // do reset + // + Array.Copy(FR, 2, FR, 0, blockSize - 2); + Array.Copy(outBytes, outOff, FR, blockSize - 2, 2); + + cipher.ProcessBlock(FR, 0, FRE, 0); + + for (int n = 2; n < blockSize; n++) + { + FR[n - 2] = outBytes[outOff + n] = EncryptByte(input[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 InvalidOperationException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + private int DecryptBlock( + byte[] input, + int inOff, + byte[] outBytes, + int outOff) + { + if ((inOff + blockSize) > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + blockSize) > outBytes.Length) + { + throw new DataLengthException("output buffer too short"); + } + + if (count > blockSize) + { + byte inVal = input[inOff]; + FR[blockSize - 2] = inVal; + outBytes[outOff] = EncryptByte(inVal, blockSize - 2); + + inVal = input[inOff + 1]; + FR[blockSize - 1] = inVal; + outBytes[outOff + 1] = EncryptByte(inVal, blockSize - 1); + + cipher.ProcessBlock(FR, 0, FRE, 0); + + for (int n = 2; n < blockSize; n++) + { + inVal = input[inOff + n]; + FR[n - 2] = inVal; + outBytes[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] = input[inOff + n]; + outBytes[n] = EncryptByte(input[inOff + n], n); + } + + count += blockSize; + } + else if (count == blockSize) + { + cipher.ProcessBlock(FR, 0, FRE, 0); + + byte inVal1 = input[inOff]; + byte inVal2 = input[inOff + 1]; + outBytes[outOff ] = EncryptByte(inVal1, 0); + outBytes[outOff + 1] = EncryptByte(inVal2, 1); + + Array.Copy(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 = input[inOff + n]; + FR[n - 2] = inVal; + outBytes[outOff + n] = EncryptByte(inVal, n - 2); + } + + count += blockSize; + } + + return blockSize; + } + } +} diff --git a/crypto/src/crypto/modes/SicBlockCipher.cs b/crypto/src/crypto/modes/SicBlockCipher.cs new file mode 100644 index 000000000..07c5d1978 --- /dev/null +++ b/crypto/src/crypto/modes/SicBlockCipher.cs @@ -0,0 +1,115 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * Implements the Segmented Integer Counter (SIC) mode on top of a simple + * block cipher. + */ + public class SicBlockCipher + : IBlockCipher + { + private readonly IBlockCipher cipher; + private readonly int blockSize; + private readonly byte[] IV; + private readonly byte[] counter; + private readonly byte[] counterOut; + + /** + * Basic constructor. + * + * @param c the block cipher to be used. + */ + public SicBlockCipher(IBlockCipher cipher) + { + this.cipher = cipher; + this.blockSize = cipher.GetBlockSize(); + this.IV = new byte[blockSize]; + this.counter = new byte[blockSize]; + this.counterOut = new byte[blockSize]; + } + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + + public void Init( + bool forEncryption, //ignored by this CTR mode + ICipherParameters parameters) + { + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV) parameters; + byte[] iv = ivParam.GetIV(); + Array.Copy(iv, 0, IV, 0, IV.Length); + + Reset(); + + // if null it's an IV changed only. + if (ivParam.Parameters != null) + { + cipher.Init(true, ivParam.Parameters); + } + } + else + { + throw new ArgumentException("SIC mode requires ParametersWithIV", "parameters"); + } + } + + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/SIC"; } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + public int GetBlockSize() + { + return cipher.GetBlockSize(); + } + + public int ProcessBlock( + byte[] input, + int inOff, + byte[] output, + int outOff) + { + cipher.ProcessBlock(counter, 0, counterOut, 0); + + // + // XOR the counterOut with the plaintext producing the cipher text + // + for (int i = 0; i < counterOut.Length; i++) + { + output[outOff + i] = (byte)(counterOut[i] ^ input[inOff + i]); + } + + // Increment the counter + int j = counter.Length; + while (--j >= 0 && ++counter[j] == 0) + { + } + + return counter.Length; + } + + public void Reset() + { + Array.Copy(IV, 0, counter, 0, counter.Length); + cipher.Reset(); + } + } +} diff --git a/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs b/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs new file mode 100644 index 000000000..98049e1db --- /dev/null +++ b/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs @@ -0,0 +1,40 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class BasicGcmExponentiator + : IGcmExponentiator + { + private byte[] x; + + public void Init(byte[] x) + { + this.x = Arrays.Clone(x); + } + + public void ExponentiateX(long pow, byte[] output) + { + // Initial value is little-endian 1 + byte[] y = GcmUtilities.OneAsBytes(); + + if (pow > 0) + { + byte[] powX = Arrays.Clone(x); + do + { + if ((pow & 1L) != 0) + { + GcmUtilities.Multiply(y, powX); + } + GcmUtilities.Multiply(powX, powX); + pow >>= 1; + } + while (pow > 0); + } + + Array.Copy(y, 0, output, 0, 16); + } + } +} diff --git a/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs b/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs new file mode 100644 index 000000000..85e3ac9b1 --- /dev/null +++ b/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs @@ -0,0 +1,22 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class BasicGcmMultiplier + : IGcmMultiplier + { + private byte[] H; + + public void Init(byte[] H) + { + this.H = Arrays.Clone(H); + } + + public void MultiplyH(byte[] x) + { + GcmUtilities.Multiply(x, H); + } + } +} diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs new file mode 100644 index 000000000..71e63c8fd --- /dev/null +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -0,0 +1,237 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + internal abstract class GcmUtilities + { + internal static byte[] OneAsBytes() + { + byte[] tmp = new byte[16]; + tmp[0] = 0x80; + return tmp; + } + + internal static uint[] OneAsUints() + { + uint[] tmp = new uint[4]; + tmp[0] = 0x80000000; + return tmp; + } + + internal static uint[] AsUints(byte[] bs) + { + uint[] output = new uint[4]; + Pack.BE_To_UInt32(bs, 0, output); + return output; + } + + internal static void AsUints(byte[] bs, uint[] output) + { + Pack.BE_To_UInt32(bs, 0, output); + } + + internal 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); + } + + bool lsb = (tmp[15] & 1) != 0; + ShiftRight(tmp); + if (lsb) + { + // R = new byte[]{ 0xe1, ... }; + //GCMUtilities.Xor(tmp, R); + tmp[0] ^= (byte)0xe1; + } + } + } + + Array.Copy(c, 0, block, 0, 16); + } + + // P is the value with only bit i=1 set + internal static void MultiplyP(uint[] x) + { + bool lsb = (x[3] & 1) != 0; + ShiftRight(x); + if (lsb) + { + // R = new uint[]{ 0xe1000000, 0, 0, 0 }; + //Xor(v, R); + x[0] ^= 0xe1000000; + } + } + + internal static void MultiplyP(uint[] x, uint[] output) + { + bool lsb = (x[3] & 1) != 0; + ShiftRight(x, output); + if (lsb) + { + output[0] ^= 0xe1000000; + } + } + + internal static void MultiplyP8(uint[] x) + { +// for (int i = 8; i != 0; --i) +// { +// MultiplyP(x); +// } + + uint lsw = x[3]; + ShiftRightN(x, 8); + for (int i = 7; i >= 0; --i) + { + if ((lsw & (1 << i)) != 0) + { + x[0] ^= (0xe1000000 >> (7 - i)); + } + } + } + + internal static void MultiplyP8(uint[] x, uint[] output) + { + uint lsw = x[3]; + ShiftRightN(x, 8, output); + for (int i = 7; i >= 0; --i) + { + if ((lsw & (1 << i)) != 0) + { + output[0] ^= (0xe1000000 >> (7 - i)); + } + } + } + + internal static void ShiftRight(byte[] block) + { + int i = 0; + byte bit = 0; + for (; ; ) + { + byte b = block[i]; + block[i] = (byte)((b >> 1) | bit); + if (++i == 16) break; + bit = (byte)(b << 7); + } + } + + static void ShiftRight(byte[] block, byte[] output) + { + int i = 0; + byte bit = 0; + for (;;) + { + byte b = block[i]; + output[i] = (byte)((b >> 1) | bit); + if (++i == 16) break; + bit = (byte)(b << 7); + } + } + + internal static void ShiftRight(uint[] block) + { + int i = 0; + uint bit = 0; + for (; ; ) + { + uint b = block[i]; + block[i] = (b >> 1) | bit; + if (++i == 4) break; + bit = b << 31; + } + } + + internal static void ShiftRight(uint[] block, uint[] output) + { + int i = 0; + uint bit = 0; + for (; ; ) + { + uint b = block[i]; + output[i] = (b >> 1) | bit; + if (++i == 4) break; + bit = b << 31; + } + } + + internal static void ShiftRightN(uint[] block, int n) + { + int i = 0; + uint bit = 0; + for (; ; ) + { + uint b = block[i]; + block[i] = (b >> n) | bit; + if (++i == 4) break; + bit = b << (32 - n); + } + } + + internal static void ShiftRightN(uint[] block, int n, uint[] output) + { + int i = 0; + uint bit = 0; + for (; ; ) + { + uint b = block[i]; + output[i] = (b >> n) | bit; + if (++i == 4) break; + bit = b << (32 - n); + } + } + + internal static void Xor(byte[] block, byte[] val) + { + for (int i = 15; i >= 0; --i) + { + block[i] ^= val[i]; + } + } + + internal static void Xor(byte[] block, byte[] val, int off, int len) + { + while (--len >= 0) + { + block[len] ^= val[off + len]; + } + } + + internal static void Xor(byte[] block, byte[] val, byte[] output) + { + for (int i = 15; i >= 0; --i) + { + output[i] = (byte)(block[i] ^ val[i]); + } + } + + internal static void Xor(uint[] block, uint[] val) + { + for (int i = 3; i >= 0; --i) + { + block[i] ^= val[i]; + } + } + + internal static void Xor(uint[] block, uint[] val, uint[] output) + { + for (int i = 3; i >= 0; --i) + { + output[i] = block[i] ^ val[i]; + } + } + } +} diff --git a/crypto/src/crypto/modes/gcm/IGcmExponentiator.cs b/crypto/src/crypto/modes/gcm/IGcmExponentiator.cs new file mode 100644 index 000000000..5b4ce9d7a --- /dev/null +++ b/crypto/src/crypto/modes/gcm/IGcmExponentiator.cs @@ -0,0 +1,10 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public interface IGcmExponentiator + { + void Init(byte[] x); + void ExponentiateX(long pow, byte[] output); + } +} diff --git a/crypto/src/crypto/modes/gcm/IGcmMultiplier.cs b/crypto/src/crypto/modes/gcm/IGcmMultiplier.cs new file mode 100644 index 000000000..ec7b906ee --- /dev/null +++ b/crypto/src/crypto/modes/gcm/IGcmMultiplier.cs @@ -0,0 +1,10 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public interface IGcmMultiplier + { + void Init(byte[] H); + void MultiplyH(byte[] x); + } +} diff --git a/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs b/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs new file mode 100644 index 000000000..44933bba7 --- /dev/null +++ b/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables1kGcmExponentiator + : IGcmExponentiator + { + // A lookup table of the power-of-two powers of 'x' + // - lookupPowX2[i] = x^(2^i) + private IList lookupPowX2; + + public void Init(byte[] x) + { + if (lookupPowX2 != null && Arrays.AreEqual(x, (byte[])lookupPowX2[0])) + { + return; + } + + lookupPowX2 = Platform.CreateArrayList(8); + lookupPowX2.Add(Arrays.Clone(x)); + } + + public void ExponentiateX(long pow, byte[] output) + { + byte[] y = GcmUtilities.OneAsBytes(); + int bit = 0; + while (pow > 0) + { + if ((pow & 1L) != 0) + { + EnsureAvailable(bit); + GcmUtilities.Multiply(y, (byte[])lookupPowX2[bit]); + } + ++bit; + pow >>= 1; + } + + Array.Copy(y, 0, output, 0, 16); + } + + private void EnsureAvailable(int bit) + { + int count = lookupPowX2.Count; + if (count <= bit) + { + byte[] tmp = (byte[])lookupPowX2[count - 1]; + do + { + tmp = Arrays.Clone(tmp); + GcmUtilities.Multiply(tmp, tmp); + lookupPowX2.Add(tmp); + } + while (++count <= bit); + } + } + } +} diff --git a/crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs b/crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs new file mode 100644 index 000000000..707b0be2e --- /dev/null +++ b/crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs @@ -0,0 +1,77 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables64kGcmMultiplier + : IGcmMultiplier + { + private byte[] H; + private uint[][][] M; + + public void Init(byte[] H) + { + if (M == null) + { + M = new uint[16][][]; + } + else if (Arrays.AreEqual(this.H, H)) + { + return; + } + + this.H = Arrays.Clone(H); + + M[0] = new uint[256][]; + M[0][0] = new uint[4]; + M[0][128] = GcmUtilities.AsUints(H); + for (int j = 64; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[0][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][j] = tmp; + } + for (int i = 0; ; ) + { + for (int j = 2; j < 256; j += j) + { + for (int k = 1; k < j; ++k) + { + uint[] tmp = (uint[])M[i][j].Clone(); + GcmUtilities.Xor(tmp, M[i][k]); + M[i][j + k] = tmp; + } + } + + if (++i == 16) return; + + M[i] = new uint[256][]; + M[i][0] = new uint[4]; + for (int j = 128; j > 0; j >>= 1) + { + uint[] tmp = (uint[])M[i - 1][j].Clone(); + GcmUtilities.MultiplyP8(tmp); + M[i][j] = tmp; + } + } + } + + public void MultiplyH(byte[] x) + { + uint[] z = new uint[4]; + for (int i = 0; i != 16; ++i) + { + //GcmUtilities.Xor(z, M[i][x[i]]); + uint[] m = M[i][x[i]]; + z[0] ^= m[0]; + z[1] ^= m[1]; + z[2] ^= m[2]; + z[3] ^= m[3]; + } + + Pack.UInt32_To_BE(z, x, 0); + } + } +} diff --git a/crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs b/crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs new file mode 100644 index 000000000..5f3d6c86c --- /dev/null +++ b/crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs @@ -0,0 +1,103 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables8kGcmMultiplier + : IGcmMultiplier + { + private byte[] H; + private uint[][][] M; + + public void Init(byte[] H) + { + if (M == null) + { + M = new uint[32][][]; + } + else if (Arrays.AreEqual(this.H, H)) + { + return; + } + + this.H = Arrays.Clone(H); + + M[0] = new uint[16][]; + M[1] = new uint[16][]; + M[0][0] = new uint[4]; + M[1][0] = new uint[4]; + M[1][8] = GcmUtilities.AsUints(H); + + for (int j = 4; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[1][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[1][j] = tmp; + } + + { + uint[] tmp = (uint[])M[1][1].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][8] = tmp; + } + + for (int j = 4; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[0][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][j] = tmp; + } + + for (int i = 0; ; ) + { + for (int j = 2; j < 16; j += j) + { + for (int k = 1; k < j; ++k) + { + uint[] tmp = (uint[])M[i][j].Clone(); + GcmUtilities.Xor(tmp, M[i][k]); + M[i][j + k] = tmp; + } + } + + if (++i == 32) return; + + if (i > 1) + { + M[i] = new uint[16][]; + M[i][0] = new uint[4]; + for (int j = 8; j > 0; j >>= 1) + { + uint[] tmp = (uint[])M[i - 2][j].Clone(); + GcmUtilities.MultiplyP8(tmp); + M[i][j] = tmp; + } + } + } + } + + public void MultiplyH(byte[] x) + { + uint[] z = new uint[4]; + for (int i = 15; i >= 0; --i) + { + //GcmUtilities.Xor(z, M[i + i][x[i] & 0x0f]); + uint[] m = M[i + i][x[i] & 0x0f]; + z[0] ^= m[0]; + z[1] ^= m[1]; + z[2] ^= m[2]; + z[3] ^= m[3]; + //GcmUtilities.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.UInt32_To_BE(z, x, 0); + } + } +} diff --git a/crypto/src/crypto/paddings/BlockCipherPadding.cs b/crypto/src/crypto/paddings/BlockCipherPadding.cs new file mode 100644 index 000000000..33a5f9f0f --- /dev/null +++ b/crypto/src/crypto/paddings/BlockCipherPadding.cs @@ -0,0 +1,43 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + + +namespace Org.BouncyCastle.Crypto.Paddings +{ + /** + * Block cipher padders are expected to conform to this interface + */ + public interface IBlockCipherPadding + { + /** + * Initialise the padder. + * + * @param param parameters, if any required. + */ + void Init(SecureRandom random); + //throws ArgumentException; + + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + string PaddingName { get; } + + /** + * add the pad bytes to the passed in block, returning the + * number of bytes added. + */ + int AddPadding(byte[] input, int inOff); + + /** + * return the number of pad bytes present in the block. + * @exception InvalidCipherTextException if the padding is badly formed + * or invalid. + */ + int PadCount(byte[] input); + //throws InvalidCipherTextException; + } + +} diff --git a/crypto/src/crypto/paddings/ISO10126d2Padding.cs b/crypto/src/crypto/paddings/ISO10126d2Padding.cs new file mode 100644 index 000000000..e132a62dd --- /dev/null +++ b/crypto/src/crypto/paddings/ISO10126d2Padding.cs @@ -0,0 +1,76 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + + +namespace Org.BouncyCastle.Crypto.Paddings +{ + + /** + * A padder that adds ISO10126-2 padding to a block. + */ + public class ISO10126d2Padding: IBlockCipherPadding + { + private SecureRandom random; + + /** + * Initialise the padder. + * + * @param random a SecureRandom if available. + */ + public void Init( + SecureRandom random) + //throws ArgumentException + { + this.random = (random != null) ? random : new SecureRandom(); + } + + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + public string PaddingName + { + get { return "ISO10126-2"; } + } + + /** + * add the pad bytes to the passed in block, returning the + * number of bytes added. + */ + public int AddPadding( + byte[] input, + int inOff) + { + byte code = (byte)(input.Length - inOff); + + while (inOff < (input.Length - 1)) + { + input[inOff] = (byte)random.NextInt(); + inOff++; + } + + input[inOff] = code; + + return code; + } + + /** + * return the number of pad bytes present in the block. + */ + public int PadCount(byte[] input) + //throws InvalidCipherTextException + { + int count = input[input.Length - 1] & 0xff; + + if (count > input.Length) + { + throw new InvalidCipherTextException("pad block corrupted"); + } + + return count; + } + } + +} diff --git a/crypto/src/crypto/paddings/ISO7816d4Padding.cs b/crypto/src/crypto/paddings/ISO7816d4Padding.cs new file mode 100644 index 000000000..016b25a81 --- /dev/null +++ b/crypto/src/crypto/paddings/ISO7816d4Padding.cs @@ -0,0 +1,79 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + /** + * 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 + : IBlockCipherPadding + { + /** + * Initialise the padder. + * + * @param random - a SecureRandom if available. + */ + public void Init( + SecureRandom random) + { + // nothing to do. + } + + /** + * Return the name of the algorithm the padder implements. + * + * @return the name of the algorithm the padder implements. + */ + public string PaddingName + { + get { return "ISO7816-4"; } + } + + /** + * add the pad bytes to the passed in block, returning the + * number of bytes added. + */ + public int AddPadding( + byte[] input, + int inOff) + { + int added = (input.Length - inOff); + + input[inOff]= (byte) 0x80; + inOff ++; + + while (inOff < input.Length) + { + input[inOff] = (byte) 0; + inOff++; + } + + return added; + } + + /** + * return the number of pad bytes present in the block. + */ + public int PadCount( + byte[] input) + { + int count = input.Length - 1; + + while (count > 0 && input[count] == 0) + { + count--; + } + + if (input[count] != (byte)0x80) + { + throw new InvalidCipherTextException("pad block corrupted"); + } + + return input.Length - count; + } + } +} diff --git a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs new file mode 100644 index 000000000..fb8a92ba3 --- /dev/null +++ b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs @@ -0,0 +1,288 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + /** + * 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 + : BufferedBlockCipher + { + private readonly IBlockCipherPadding 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( + IBlockCipher cipher, + IBlockCipherPadding 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( + IBlockCipher cipher) + : this(cipher, new Pkcs7Padding()) { } + + /** + * 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. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public override void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.forEncryption = forEncryption; + + SecureRandom initRandom = null; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom p = (ParametersWithRandom)parameters; + initRandom = p.Random; + parameters = p.Parameters; + } + + Reset(); + padding.Init(initRandom); + cipher.Init(forEncryption, parameters); + } + + /** + * 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 override int GetOutputSize( + int length) + { + int total = length + 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 override int GetUpdateOutputSize( + int length) + { + int total = length + 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. + * @return the number of output bytes copied to out. + * @exception DataLengthException if there isn't enough space in out. + * @exception InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessByte( + byte input, + byte[] output, + int outOff) + { + int resultLen = 0; + + if (bufOff == buf.Length) + { + resultLen = cipher.ProcessBlock(buf, 0, output, outOff); + bufOff = 0; + } + + buf[bufOff++] = input; + + 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 InvalidOperationException if the cipher isn't initialised. + */ + public override int ProcessBytes( + byte[] input, + int inOff, + int length, + byte[] output, + int outOff) + { + if (length < 0) + { + throw new ArgumentException("Can't have a negative input length!"); + } + + int blockSize = GetBlockSize(); + int outLength = GetUpdateOutputSize(length); + + if (outLength > 0) + { + if ((outOff + outLength) > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + } + + int resultLen = 0; + int gapLen = buf.Length - bufOff; + + if (length > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + resultLen += cipher.ProcessBlock(buf, 0, output, outOff); + + bufOff = 0; + length -= gapLen; + inOff += gapLen; + + while (length > buf.Length) + { + resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen); + + length -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, length); + + bufOff += length; + + 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 InvalidOperationException if the underlying cipher is not + * initialised. + * @exception InvalidCipherTextException if padding is expected and not found. + */ + public override int DoFinal( + byte[] output, + int outOff) + { + int blockSize = cipher.GetBlockSize(); + int resultLen = 0; + + if (forEncryption) + { + if (bufOff == blockSize) + { + if ((outOff + 2 * blockSize) > output.Length) + { + Reset(); + + throw new DataLengthException("output buffer too short"); + } + + resultLen = cipher.ProcessBlock(buf, 0, output, outOff); + bufOff = 0; + } + + padding.AddPadding(buf, bufOff); + + resultLen += cipher.ProcessBlock(buf, 0, output, 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); + + Array.Copy(buf, 0, output, outOff, resultLen); + } + finally + { + Reset(); + } + } + + return resultLen; + } + } + +} diff --git a/crypto/src/crypto/paddings/Pkcs7Padding.cs b/crypto/src/crypto/paddings/Pkcs7Padding.cs new file mode 100644 index 000000000..f3166fd96 --- /dev/null +++ b/crypto/src/crypto/paddings/Pkcs7Padding.cs @@ -0,0 +1,79 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + /** + * A padder that adds Pkcs7/Pkcs5 padding to a block. + */ + public class Pkcs7Padding + : IBlockCipherPadding + { + /** + * Initialise the padder. + * + * @param random - a SecureRandom if available. + */ + public void Init( + SecureRandom random) + { + // nothing to do. + } + + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + public string PaddingName + { + get { return "PKCS7"; } + } + + /** + * add the pad bytes to the passed in block, returning the + * number of bytes added. + */ + public int AddPadding( + byte[] input, + int inOff) + { + byte code = (byte)(input.Length - inOff); + + while (inOff < input.Length) + { + input[inOff] = code; + inOff++; + } + + return code; + } + + /** + * return the number of pad bytes present in the block. + */ + public int PadCount( + byte[] input) + { + int count = (int) input[input.Length - 1]; + + if (count < 1 || count > input.Length) + { + throw new InvalidCipherTextException("pad block corrupted"); + } + + for (int i = 1; i <= count; i++) + { + if (input[input.Length - i] != count) + { + throw new InvalidCipherTextException("pad block corrupted"); + } + } + + return count; + } + } + +} diff --git a/crypto/src/crypto/paddings/TbcPadding.cs b/crypto/src/crypto/paddings/TbcPadding.cs new file mode 100644 index 000000000..74b64e8e1 --- /dev/null +++ b/crypto/src/crypto/paddings/TbcPadding.cs @@ -0,0 +1,79 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + + /// A padder that adds Trailing-Bit-Compliment padding to a block. + ///

+ /// This padding pads the block out compliment of the last bit + /// of the plain text. + ///

+ ///
+ public class TbcPadding + : IBlockCipherPadding + { + /// Return the name of the algorithm the cipher implements. + /// the name of the algorithm the cipher implements. + /// + public string PaddingName + { + get { return "TBC"; } + } + + /// Initialise the padder. + /// - a SecureRandom if available. + /// + public virtual void Init(SecureRandom random) + { + // nothing to do. + } + + /// add the pad bytes to the passed in block, returning the + /// number of bytes added. + ///

+ /// 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. + ///

+ ///
+ public virtual int AddPadding(byte[] input, int inOff) + { + int count = input.Length - inOff; + byte code; + + if (inOff > 0) + { + code = (byte)((input[inOff - 1] & 0x01) == 0?0xff:0x00); + } + else + { + code = (byte)((input[input.Length - 1] & 0x01) == 0?0xff:0x00); + } + + while (inOff < input.Length) + { + input[inOff] = code; + inOff++; + } + + return count; + } + + /// return the number of pad bytes present in the block. + public virtual int PadCount(byte[] input) + { + byte code = input[input.Length - 1]; + + int index = input.Length - 1; + while (index > 0 && input[index - 1] == code) + { + index--; + } + + return input.Length - index; + } + } +} diff --git a/crypto/src/crypto/paddings/X923Padding.cs b/crypto/src/crypto/paddings/X923Padding.cs new file mode 100644 index 000000000..cc1b52b3e --- /dev/null +++ b/crypto/src/crypto/paddings/X923Padding.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + /** + * 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 + : IBlockCipherPadding + { + private SecureRandom random; + + /** + * Initialise the padder. + * + * @param random a SecureRandom if one is available. + */ + public void Init( + SecureRandom random) + { + this.random = random; + } + + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + public string PaddingName + { + get { return "X9.23"; } + } + + /** + * add the pad bytes to the passed in block, returning the + * number of bytes added. + */ + public int AddPadding( + byte[] input, + int inOff) + { + byte code = (byte)(input.Length - inOff); + + while (inOff < input.Length - 1) + { + if (random == null) + { + input[inOff] = 0; + } + else + { + input[inOff] = (byte)random.NextInt(); + } + inOff++; + } + + input[inOff] = code; + + return code; + } + + /** + * return the number of pad bytes present in the block. + */ + public int PadCount( + byte[] input) + { + int count = input[input.Length - 1] & 0xff; + + if (count > input.Length) + { + throw new InvalidCipherTextException("pad block corrupted"); + } + + return count; + } + } +} diff --git a/crypto/src/crypto/paddings/ZeroBytePadding.cs b/crypto/src/crypto/paddings/ZeroBytePadding.cs new file mode 100644 index 000000000..0d55ca4c2 --- /dev/null +++ b/crypto/src/crypto/paddings/ZeroBytePadding.cs @@ -0,0 +1,68 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Paddings +{ + + /// A padder that adds Null byte padding to a block. + public class ZeroBytePadding : IBlockCipherPadding + { + /// Return the name of the algorithm the cipher implements. + /// + /// + /// the name of the algorithm the cipher implements. + /// + public string PaddingName + { + get { return "ZeroBytePadding"; } + } + + /// Initialise the padder. + /// + /// + /// - a SecureRandom if available. + /// + public void Init(SecureRandom random) + { + // nothing to do. + } + + /// add the pad bytes to the passed in block, returning the + /// number of bytes added. + /// + public int AddPadding( + byte[] input, + int inOff) + { + int added = (input.Length - inOff); + + while (inOff < input.Length) + { + input[inOff] = (byte) 0; + inOff++; + } + + return added; + } + + /// return the number of pad bytes present in the block. + public int PadCount( + byte[] input) + { + int count = input.Length; + + while (count > 0) + { + if (input[count - 1] != 0) + { + break; + } + + count--; + } + + return input.Length - count; + } + } +} diff --git a/crypto/src/crypto/parameters/AEADParameters.cs b/crypto/src/crypto/parameters/AEADParameters.cs new file mode 100644 index 000000000..825d6b7f2 --- /dev/null +++ b/crypto/src/crypto/parameters/AEADParameters.cs @@ -0,0 +1,65 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class AeadParameters + : ICipherParameters + { + private readonly byte[] associatedText; + private readonly byte[] nonce; + private readonly KeyParameter key; + private readonly 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 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 virtual KeyParameter Key + { + get { return key; } + } + + public virtual int MacSize + { + get { return macSize; } + } + + public virtual byte[] GetAssociatedText() + { + return associatedText; + } + + public virtual byte[] GetNonce() + { + return nonce; + } + } +} diff --git a/crypto/src/crypto/parameters/CcmParameters.cs b/crypto/src/crypto/parameters/CcmParameters.cs new file mode 100644 index 000000000..d4459081c --- /dev/null +++ b/crypto/src/crypto/parameters/CcmParameters.cs @@ -0,0 +1,26 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + [Obsolete("Use AeadParameters")] + public class CcmParameters + : 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) + : base(key, macSize, nonce, associatedText) + { + } + } +} diff --git a/crypto/src/crypto/parameters/DHKeyGenerationParameters.cs b/crypto/src/crypto/parameters/DHKeyGenerationParameters.cs new file mode 100644 index 000000000..ab3e18f09 --- /dev/null +++ b/crypto/src/crypto/parameters/DHKeyGenerationParameters.cs @@ -0,0 +1,31 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHKeyGenerationParameters + : KeyGenerationParameters + { + private readonly DHParameters parameters; + + public DHKeyGenerationParameters( + SecureRandom random, + DHParameters parameters) + : base(random, GetStrength(parameters)) + { + this.parameters = parameters; + } + + public DHParameters Parameters + { + get { return parameters; } + } + + internal static int GetStrength( + DHParameters parameters) + { + return parameters.L != 0 ? parameters.L : parameters.P.BitLength; + } + } +} diff --git a/crypto/src/crypto/parameters/DHKeyParameters.cs b/crypto/src/crypto/parameters/DHKeyParameters.cs new file mode 100644 index 000000000..1a5c1386f --- /dev/null +++ b/crypto/src/crypto/parameters/DHKeyParameters.cs @@ -0,0 +1,76 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHKeyParameters + : AsymmetricKeyParameter + { + private readonly DHParameters parameters; + private readonly DerObjectIdentifier algorithmOid; + + protected DHKeyParameters( + bool isPrivate, + DHParameters parameters) + : this(isPrivate, parameters, PkcsObjectIdentifiers.DhKeyAgreement) + { + } + + protected DHKeyParameters( + bool isPrivate, + DHParameters parameters, + DerObjectIdentifier algorithmOid) + : base(isPrivate) + { + // TODO Should we allow parameters to be null? + this.parameters = parameters; + this.algorithmOid = algorithmOid; + } + + public DHParameters Parameters + { + get { return parameters; } + } + + public DerObjectIdentifier AlgorithmOid + { + get { return algorithmOid; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DHKeyParameters other = obj as DHKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DHKeyParameters other) + { + return Platform.Equals(parameters, other.parameters) + && base.Equals(other); + } + + public override int GetHashCode() + { + int hc = base.GetHashCode(); + + if (parameters != null) + { + hc ^= parameters.GetHashCode(); + } + + return hc; + } + } +} diff --git a/crypto/src/crypto/parameters/DHParameters.cs b/crypto/src/crypto/parameters/DHParameters.cs new file mode 100644 index 000000000..a0544e73b --- /dev/null +++ b/crypto/src/crypto/parameters/DHParameters.cs @@ -0,0 +1,184 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHParameters + : ICipherParameters + { + private const int DefaultMinimumLength = 160; + + private readonly BigInteger p, g, q, j; + private readonly int m, l; + private readonly DHValidationParameters validation; + + private static int GetDefaultMParam( + int lParam) + { + if (lParam == 0) + return DefaultMinimumLength; + + return System.Math.Min(lParam, DefaultMinimumLength); + } + + 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, DefaultMinimumLength, 0, j, validation) + { + } + + public DHParameters( + BigInteger p, + BigInteger g, + BigInteger q, + int m, + int l, + BigInteger j, + DHValidationParameters validation) + { + if (p == null) + throw new ArgumentNullException("p"); + if (g == null) + throw new ArgumentNullException("g"); + if (!p.TestBit(0)) + throw new ArgumentException("field must be an odd prime", "p"); + if (g.CompareTo(BigInteger.Two) < 0 + || g.CompareTo(p.Subtract(BigInteger.Two)) > 0) + throw new ArgumentException("generator must in the range [2, p - 2]", "g"); + if (q != null && q.BitLength >= p.BitLength) + throw new ArgumentException("q too big to be a factor of (p-1)", "q"); + if (m >= p.BitLength) + throw new ArgumentException("m value must be < bitlength of p", "m"); + if (l != 0) + { + if (l >= p.BitLength) + throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l"); + if (l < m) + throw new ArgumentException("when l value specified, it may not be less than m value", "l"); + } + if (j != null && j.CompareTo(BigInteger.Two) < 0) + throw new ArgumentException("subgroup factor must be >= 2", "j"); + + // TODO If q, j both provided, validate p = jq + 1 ? + + this.p = p; + this.g = g; + this.q = q; + this.m = m; + this.l = l; + this.j = j; + this.validation = validation; + } + + public BigInteger P + { + get { return p; } + } + + public BigInteger G + { + get { return g; } + } + + public BigInteger Q + { + get { return q; } + } + + public BigInteger J + { + get { return j; } + } + + /// The minimum bitlength of the private value. + public int M + { + get { return m; } + } + + /// The bitlength of the private value. + public int L + { + get { return l; } + } + + public DHValidationParameters ValidationParameters + { + get { return validation; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DHParameters other = obj as DHParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DHParameters other) + { + return p.Equals(other.p) + && g.Equals(other.g) + && Platform.Equals(q, other.q); + } + + public override int GetHashCode() + { + int hc = p.GetHashCode() ^ g.GetHashCode(); + + if (q != null) + { + hc ^= q.GetHashCode(); + } + + return hc; + } + } +} diff --git a/crypto/src/crypto/parameters/DHPrivateKeyParameters.cs b/crypto/src/crypto/parameters/DHPrivateKeyParameters.cs new file mode 100644 index 000000000..fc724df81 --- /dev/null +++ b/crypto/src/crypto/parameters/DHPrivateKeyParameters.cs @@ -0,0 +1,60 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHPrivateKeyParameters + : DHKeyParameters + { + private readonly BigInteger x; + + public DHPrivateKeyParameters( + BigInteger x, + DHParameters parameters) + : base(true, parameters) + { + this.x = x; + } + + public DHPrivateKeyParameters( + BigInteger x, + DHParameters parameters, + DerObjectIdentifier algorithmOid) + : base(true, parameters, algorithmOid) + { + this.x = x; + } + + public BigInteger X + { + get { return x; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DHPrivateKeyParameters other = obj as DHPrivateKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DHPrivateKeyParameters other) + { + return x.Equals(other.x) && base.Equals(other); + } + + public override int GetHashCode() + { + return x.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs new file mode 100644 index 000000000..e79375f71 --- /dev/null +++ b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs @@ -0,0 +1,66 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHPublicKeyParameters + : DHKeyParameters + { + private readonly BigInteger y; + + public DHPublicKeyParameters( + BigInteger y, + DHParameters parameters) + : base(false, parameters) + { + if (y == null) + throw new ArgumentNullException("y"); + + this.y = y; + } + + public DHPublicKeyParameters( + BigInteger y, + DHParameters parameters, + DerObjectIdentifier algorithmOid) + : base(false, parameters, algorithmOid) + { + if (y == null) + throw new ArgumentNullException("y"); + + this.y = y; + } + + public BigInteger Y + { + get { return y; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DHPublicKeyParameters other = obj as DHPublicKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DHPublicKeyParameters other) + { + return y.Equals(other.y) && base.Equals(other); + } + + public override int GetHashCode() + { + return y.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/DHValidationParameters.cs b/crypto/src/crypto/parameters/DHValidationParameters.cs new file mode 100644 index 000000000..50c0739fa --- /dev/null +++ b/crypto/src/crypto/parameters/DHValidationParameters.cs @@ -0,0 +1,59 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DHValidationParameters + { + private readonly byte[] seed; + private readonly int counter; + + public DHValidationParameters( + byte[] seed, + int counter) + { + if (seed == null) + throw new ArgumentNullException("seed"); + + this.seed = (byte[]) seed.Clone(); + this.counter = counter; + } + + public byte[] GetSeed() + { + return (byte[]) seed.Clone(); + } + + public int Counter + { + get { return counter; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DHValidationParameters other = obj as DHValidationParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DHValidationParameters other) + { + return counter == other.counter + && Arrays.AreEqual(this.seed, other.seed); + } + + public override int GetHashCode() + { + return counter.GetHashCode() ^ Arrays.GetHashCode(seed); + } + } +} diff --git a/crypto/src/crypto/parameters/DSAParameterGenerationParameters.cs b/crypto/src/crypto/parameters/DSAParameterGenerationParameters.cs new file mode 100644 index 000000000..7427574c8 --- /dev/null +++ b/crypto/src/crypto/parameters/DSAParameterGenerationParameters.cs @@ -0,0 +1,74 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaParameterGenerationParameters + { + public const int DigitalSignatureUsage = 1; + public const int KeyEstablishmentUsage = 2; + + private readonly int l; + private readonly int n; + private readonly int certainty; + private readonly SecureRandom random; + private readonly int usageIndex; + + /** + * 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.random = random; + this.usageIndex = usageIndex; + } + + public virtual int L + { + get { return l; } + } + + public virtual int N + { + get { return n; } + } + + public virtual int UsageIndex + { + get { return usageIndex; } + } + + public virtual int Certainty + { + get { return certainty; } + } + + public virtual SecureRandom Random + { + get { return random; } + } + } +} diff --git a/crypto/src/crypto/parameters/DesEdeParameters.cs b/crypto/src/crypto/parameters/DesEdeParameters.cs new file mode 100644 index 000000000..420aaecea --- /dev/null +++ b/crypto/src/crypto/parameters/DesEdeParameters.cs @@ -0,0 +1,95 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DesEdeParameters + : DesParameters + { + /* + * DES-EDE Key length in bytes. + */ + public const int DesEdeKeyLength = 24; + + private static byte[] FixKey( + byte[] key, + int keyOff, + int keyLen) + { + byte[] tmp = new byte[24]; + + switch (keyLen) + { + case 16: + Array.Copy(key, keyOff, tmp, 0, 16); + Array.Copy(key, keyOff, tmp, 16, 8); + break; + case 24: + Array.Copy(key, keyOff, tmp, 0, 24); + break; + default: + throw new ArgumentException("Bad length for DESede key: " + keyLen, "keyLen"); + } + + if (IsWeakKey(tmp)) + throw new ArgumentException("attempt to create weak DESede key"); + + return tmp; + } + + public DesEdeParameters( + byte[] key) + : base(FixKey(key, 0, key.Length)) + { + } + + public DesEdeParameters( + byte[] key, + int keyOff, + int keyLen) + : base(FixKey(key, keyOff, keyLen)) + { + } + + /** + * 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 bool IsWeakKey( + byte[] key, + int offset, + int length) + { + for (int i = offset; i < length; i += DesKeyLength) + { + 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 new bool IsWeakKey( + byte[] key, + int offset) + { + return IsWeakKey(key, offset, key.Length - offset); + } + + public static new bool IsWeakKey( + byte[] key) + { + return IsWeakKey(key, 0, key.Length); + } + } +} diff --git a/crypto/src/crypto/parameters/DesParameters.cs b/crypto/src/crypto/parameters/DesParameters.cs new file mode 100644 index 000000000..ee37cd861 --- /dev/null +++ b/crypto/src/crypto/parameters/DesParameters.cs @@ -0,0 +1,130 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DesParameters + : KeyParameter + { + public DesParameters( + byte[] key) + : base(key) + { + if (IsWeakKey(key)) + throw new ArgumentException("attempt to create weak DES key"); + } + + public DesParameters( + byte[] key, + int keyOff, + int keyLen) + : base(key, keyOff, keyLen) + { + if (IsWeakKey(key, keyOff)) + throw new ArgumentException("attempt to create weak DES key"); + } + + /* + * DES Key Length in bytes. + */ + public const int DesKeyLength = 8; + + /* + * Table of weak and semi-weak keys taken from Schneier pp281 + */ + private const int N_DES_WEAK_KEYS = 16; + + private static readonly 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. + *

+ * See "Applied + * Cryptography" by Bruce Schneier for more information. + *

+ * @return true if the given DES key material is weak or semi-weak, + * false otherwise. + */ + public static bool IsWeakKey( + byte[] key, + int offset) + { + if (key.Length - offset < DesKeyLength) + throw new ArgumentException("key material too short."); + + //nextkey: + for (int i = 0; i < N_DES_WEAK_KEYS; i++) + { + bool unmatch = false; + for (int j = 0; j < DesKeyLength; j++) + { + if (key[j + offset] != DES_weak_keys[i * DesKeyLength + j]) + { + //continue nextkey; + unmatch = true; + break; + } + } + + if (!unmatch) + { + return true; + } + } + + return false; + } + + public static bool IsWeakKey( + byte[] key) + { + return IsWeakKey(key, 0); + } + + /** + * 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/crypto/src/crypto/parameters/DsaKeyGenerationParameters.cs b/crypto/src/crypto/parameters/DsaKeyGenerationParameters.cs new file mode 100644 index 000000000..86d6f5bd4 --- /dev/null +++ b/crypto/src/crypto/parameters/DsaKeyGenerationParameters.cs @@ -0,0 +1,26 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaKeyGenerationParameters + : KeyGenerationParameters + { + private readonly DsaParameters parameters; + + public DsaKeyGenerationParameters( + SecureRandom random, + DsaParameters parameters) + : base(random, parameters.P.BitLength - 1) + { + this.parameters = parameters; + } + + public DsaParameters Parameters + { + get { return parameters; } + } + } + +} diff --git a/crypto/src/crypto/parameters/DsaKeyParameters.cs b/crypto/src/crypto/parameters/DsaKeyParameters.cs new file mode 100644 index 000000000..5fe6d7ab4 --- /dev/null +++ b/crypto/src/crypto/parameters/DsaKeyParameters.cs @@ -0,0 +1,59 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public abstract class DsaKeyParameters + : AsymmetricKeyParameter + { + private readonly DsaParameters parameters; + + protected DsaKeyParameters( + bool isPrivate, + DsaParameters parameters) + : base(isPrivate) + { + // Note: parameters may be null + this.parameters = parameters; + } + + public DsaParameters Parameters + { + get { return parameters; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DsaKeyParameters other = obj as DsaKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DsaKeyParameters other) + { + return Platform.Equals(parameters, other.parameters) + && base.Equals(other); + } + + public override int GetHashCode() + { + int hc = base.GetHashCode(); + + if (parameters != null) + { + hc ^= parameters.GetHashCode(); + } + + return hc; + } + } +} diff --git a/crypto/src/crypto/parameters/DsaParameters.cs b/crypto/src/crypto/parameters/DsaParameters.cs new file mode 100644 index 000000000..50d080ee2 --- /dev/null +++ b/crypto/src/crypto/parameters/DsaParameters.cs @@ -0,0 +1,85 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaParameters + : ICipherParameters + { + private readonly BigInteger p, q , g; + private readonly DsaValidationParameters validation; + + public DsaParameters( + BigInteger p, + BigInteger q, + BigInteger g) + : this(p, q, g, null) + { + } + + public DsaParameters( + BigInteger p, + BigInteger q, + BigInteger g, + DsaValidationParameters parameters) + { + if (p == null) + throw new ArgumentNullException("p"); + if (q == null) + throw new ArgumentNullException("q"); + if (g == null) + throw new ArgumentNullException("g"); + + this.p = p; + this.q = q; + this.g = g; + this.validation = parameters; + } + + public BigInteger P + { + get { return p; } + } + + public BigInteger Q + { + get { return q; } + } + + public BigInteger G + { + get { return g; } + } + + public DsaValidationParameters ValidationParameters + { + get { return validation; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DsaParameters other = obj as DsaParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DsaParameters other) + { + return p.Equals(other.p) && q.Equals(other.q) && g.Equals(other.g); + } + + public override int GetHashCode() + { + return p.GetHashCode() ^ q.GetHashCode() ^ g.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/DsaPrivateKeyParameters.cs b/crypto/src/crypto/parameters/DsaPrivateKeyParameters.cs new file mode 100644 index 000000000..2abdd0e4f --- /dev/null +++ b/crypto/src/crypto/parameters/DsaPrivateKeyParameters.cs @@ -0,0 +1,53 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaPrivateKeyParameters + : DsaKeyParameters + { + private readonly BigInteger x; + + public DsaPrivateKeyParameters( + BigInteger x, + DsaParameters parameters) + : base(true, parameters) + { + if (x == null) + throw new ArgumentNullException("x"); + + this.x = x; + } + + public BigInteger X + { + get { return x; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DsaPrivateKeyParameters other = obj as DsaPrivateKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DsaPrivateKeyParameters other) + { + return x.Equals(other.x) && base.Equals(other); + } + + public override int GetHashCode() + { + return x.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs new file mode 100644 index 000000000..f11f858f3 --- /dev/null +++ b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs @@ -0,0 +1,52 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaPublicKeyParameters + : DsaKeyParameters + { + private readonly BigInteger y; + + public DsaPublicKeyParameters( + BigInteger y, + DsaParameters parameters) + : base(false, parameters) + { + if (y == null) + throw new ArgumentNullException("y"); + + this.y = y; + } + + public BigInteger Y + { + get { return y; } + } + + public override bool Equals(object obj) + { + if (obj == this) + return true; + + DsaPublicKeyParameters other = obj as DsaPublicKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + DsaPublicKeyParameters other) + { + return y.Equals(other.y) && base.Equals(other); + } + + public override int GetHashCode() + { + return y.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/DsaValidationParameters.cs b/crypto/src/crypto/parameters/DsaValidationParameters.cs new file mode 100644 index 000000000..c2f84c785 --- /dev/null +++ b/crypto/src/crypto/parameters/DsaValidationParameters.cs @@ -0,0 +1,72 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class DsaValidationParameters + { + private readonly byte[] seed; + private readonly int counter; + private readonly int usageIndex; + + public DsaValidationParameters(byte[] seed, int counter) + : this(seed, counter, -1) + { + } + + public DsaValidationParameters( + byte[] seed, + int counter, + int usageIndex) + { + if (seed == null) + throw new ArgumentNullException("seed"); + + this.seed = (byte[]) seed.Clone(); + this.counter = counter; + this.usageIndex = usageIndex; + } + + public virtual byte[] GetSeed() + { + return (byte[]) seed.Clone(); + } + + public virtual int Counter + { + get { return counter; } + } + + public virtual int UsageIndex + { + get { return usageIndex; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + DsaValidationParameters other = obj as DsaValidationParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected virtual bool Equals( + DsaValidationParameters other) + { + return counter == other.counter + && Arrays.AreEqual(seed, other.seed); + } + + public override int GetHashCode() + { + return counter.GetHashCode() ^ Arrays.GetHashCode(seed); + } + } +} diff --git a/crypto/src/crypto/parameters/ECDomainParameters.cs b/crypto/src/crypto/parameters/ECDomainParameters.cs new file mode 100644 index 000000000..c6a3e4e72 --- /dev/null +++ b/crypto/src/crypto/parameters/ECDomainParameters.cs @@ -0,0 +1,116 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ECDomainParameters + { + internal ECCurve curve; + internal byte[] seed; + internal ECPoint g; + internal BigInteger n; + internal BigInteger h; + + public ECDomainParameters( + ECCurve curve, + ECPoint g, + BigInteger n) + : this(curve, g, n, BigInteger.One) + { + } + + 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) + { + if (curve == null) + throw new ArgumentNullException("curve"); + if (g == null) + throw new ArgumentNullException("g"); + if (n == null) + throw new ArgumentNullException("n"); + if (h == null) + throw new ArgumentNullException("h"); + + this.curve = curve; + this.g = g; + this.n = n; + this.h = h; + this.seed = Arrays.Clone(seed); + } + + public ECCurve Curve + { + get { return curve; } + } + + public ECPoint G + { + get { return g; } + } + + public BigInteger N + { + get { return n; } + } + + public BigInteger H + { + get { return h; } + } + + public byte[] GetSeed() + { + return Arrays.Clone(seed); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECDomainParameters other = obj as ECDomainParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECDomainParameters other) + { + return curve.Equals(other.curve) + && g.Equals(other.g) + && n.Equals(other.n) + && h.Equals(other.h) + && Arrays.AreEqual(seed, other.seed); + } + + public override int GetHashCode() + { + return curve.GetHashCode() + ^ g.GetHashCode() + ^ n.GetHashCode() + ^ h.GetHashCode() + ^ Arrays.GetHashCode(seed); + } + } + +} diff --git a/crypto/src/crypto/parameters/ECKeyGenerationParameters.cs b/crypto/src/crypto/parameters/ECKeyGenerationParameters.cs new file mode 100644 index 000000000..9b2b98845 --- /dev/null +++ b/crypto/src/crypto/parameters/ECKeyGenerationParameters.cs @@ -0,0 +1,41 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ECKeyGenerationParameters + : KeyGenerationParameters + { + private readonly ECDomainParameters domainParams; + private readonly DerObjectIdentifier publicKeyParamSet; + + public ECKeyGenerationParameters( + ECDomainParameters domainParameters, + SecureRandom random) + : base(random, domainParameters.N.BitLength) + { + this.domainParams = domainParameters; + } + + public ECKeyGenerationParameters( + DerObjectIdentifier publicKeyParamSet, + SecureRandom random) + : this(ECKeyParameters.LookupParameters(publicKeyParamSet), random) + { + this.publicKeyParamSet = publicKeyParamSet; + } + + public ECDomainParameters DomainParameters + { + get { return domainParams; } + } + + public DerObjectIdentifier PublicKeyParamSet + { + get { return publicKeyParamSet; } + } + } +} diff --git a/crypto/src/crypto/parameters/ECKeyParameters.cs b/crypto/src/crypto/parameters/ECKeyParameters.cs new file mode 100644 index 000000000..70b3543da --- /dev/null +++ b/crypto/src/crypto/parameters/ECKeyParameters.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public abstract class ECKeyParameters + : AsymmetricKeyParameter + { + private static readonly string[] algorithms = { "EC", "ECDSA", "ECDH", "ECDHC", "ECGOST3410", "ECMQV" }; + + private readonly string algorithm; + private readonly ECDomainParameters parameters; + private readonly DerObjectIdentifier publicKeyParamSet; + + protected ECKeyParameters( + string algorithm, + bool isPrivate, + ECDomainParameters parameters) + : base(isPrivate) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (parameters == null) + throw new ArgumentNullException("parameters"); + + this.algorithm = VerifyAlgorithmName(algorithm); + this.parameters = parameters; + } + + protected ECKeyParameters( + string algorithm, + bool isPrivate, + DerObjectIdentifier publicKeyParamSet) + : base(isPrivate) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (publicKeyParamSet == null) + throw new ArgumentNullException("publicKeyParamSet"); + + this.algorithm = VerifyAlgorithmName(algorithm); + this.parameters = LookupParameters(publicKeyParamSet); + this.publicKeyParamSet = publicKeyParamSet; + } + + public string AlgorithmName + { + get { return algorithm; } + } + + public ECDomainParameters Parameters + { + get { return parameters; } + } + + public DerObjectIdentifier PublicKeyParamSet + { + get { return publicKeyParamSet; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECDomainParameters other = obj as ECDomainParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECKeyParameters other) + { + return parameters.Equals(other.parameters) && base.Equals(other); + } + + public override int GetHashCode() + { + return parameters.GetHashCode() ^ base.GetHashCode(); + } + + internal ECKeyGenerationParameters CreateKeyGenerationParameters( + SecureRandom random) + { + if (publicKeyParamSet != null) + { + return new ECKeyGenerationParameters(publicKeyParamSet, random); + } + + return new ECKeyGenerationParameters(parameters, random); + } + + internal static string VerifyAlgorithmName(string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + if (Array.IndexOf(algorithms, algorithm, 0, algorithms.Length) < 0) + throw new ArgumentException("unrecognised algorithm: " + algorithm, "algorithm"); + return upper; + } + + internal static ECDomainParameters LookupParameters( + DerObjectIdentifier publicKeyParamSet) + { + if (publicKeyParamSet == null) + throw new ArgumentNullException("publicKeyParamSet"); + + ECDomainParameters p = ECGost3410NamedCurves.GetByOid(publicKeyParamSet); + + if (p == null) + { + X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(publicKeyParamSet); + + if (x9 == null) + { + throw new ArgumentException("OID is not a valid public key parameter set", "publicKeyParamSet"); + } + + p = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + } + + return p; + } + } +} diff --git a/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs b/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs new file mode 100644 index 000000000..e6352d5d1 --- /dev/null +++ b/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs @@ -0,0 +1,87 @@ +using System; +using System.Globalization; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ECPrivateKeyParameters + : ECKeyParameters + { + private readonly BigInteger d; + + public ECPrivateKeyParameters( + BigInteger d, + ECDomainParameters parameters) + : this("EC", d, parameters) + { + } + + [Obsolete("Use version with explicit 'algorithm' parameter")] + public ECPrivateKeyParameters( + BigInteger d, + DerObjectIdentifier publicKeyParamSet) + : base("ECGOST3410", true, publicKeyParamSet) + { + if (d == null) + throw new ArgumentNullException("d"); + + this.d = d; + } + + public ECPrivateKeyParameters( + string algorithm, + BigInteger d, + ECDomainParameters parameters) + : base(algorithm, true, parameters) + { + if (d == null) + throw new ArgumentNullException("d"); + + this.d = d; + } + + public ECPrivateKeyParameters( + string algorithm, + BigInteger d, + DerObjectIdentifier publicKeyParamSet) + : base(algorithm, true, publicKeyParamSet) + { + if (d == null) + throw new ArgumentNullException("d"); + + this.d = d; + } + + public BigInteger D + { + get { return d; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECPrivateKeyParameters other = obj as ECPrivateKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECPrivateKeyParameters other) + { + return d.Equals(other.d) && base.Equals(other); + } + + public override int GetHashCode() + { + return d.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs new file mode 100644 index 000000000..9e71c2a25 --- /dev/null +++ b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs @@ -0,0 +1,86 @@ +using System; +using System.Globalization; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ECPublicKeyParameters + : ECKeyParameters + { + private readonly ECPoint q; + + public ECPublicKeyParameters( + ECPoint q, + ECDomainParameters parameters) + : this("EC", q, parameters) + { + } + + [Obsolete("Use version with explicit 'algorithm' parameter")] + public ECPublicKeyParameters( + ECPoint q, + DerObjectIdentifier publicKeyParamSet) + : base("ECGOST3410", false, publicKeyParamSet) + { + if (q == null) + throw new ArgumentNullException("q"); + + this.q = q; + } + + public ECPublicKeyParameters( + string algorithm, + ECPoint q, + ECDomainParameters parameters) + : base(algorithm, false, parameters) + { + if (q == null) + throw new ArgumentNullException("q"); + + this.q = q; + } + + public ECPublicKeyParameters( + string algorithm, + ECPoint q, + DerObjectIdentifier publicKeyParamSet) + : base(algorithm, false, publicKeyParamSet) + { + if (q == null) + throw new ArgumentNullException("q"); + + this.q = q; + } + + public ECPoint Q + { + get { return q; } + } + + public override bool Equals(object obj) + { + if (obj == this) + return true; + + ECPublicKeyParameters other = obj as ECPublicKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECPublicKeyParameters other) + { + return q.Equals(other.q) && base.Equals(other); + } + + public override int GetHashCode() + { + return q.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/ElGamalKeyGenerationParameters.cs b/crypto/src/crypto/parameters/ElGamalKeyGenerationParameters.cs new file mode 100644 index 000000000..40ca70df4 --- /dev/null +++ b/crypto/src/crypto/parameters/ElGamalKeyGenerationParameters.cs @@ -0,0 +1,31 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ElGamalKeyGenerationParameters + : KeyGenerationParameters + { + private readonly ElGamalParameters parameters; + + public ElGamalKeyGenerationParameters( + SecureRandom random, + ElGamalParameters parameters) + : base(random, GetStrength(parameters)) + { + this.parameters = parameters; + } + + public ElGamalParameters Parameters + { + get { return parameters; } + } + + internal static int GetStrength( + ElGamalParameters parameters) + { + return parameters.L != 0 ? parameters.L : parameters.P.BitLength; + } + } +} diff --git a/crypto/src/crypto/parameters/ElGamalKeyParameters.cs b/crypto/src/crypto/parameters/ElGamalKeyParameters.cs new file mode 100644 index 000000000..8b6e27957 --- /dev/null +++ b/crypto/src/crypto/parameters/ElGamalKeyParameters.cs @@ -0,0 +1,59 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ElGamalKeyParameters + : AsymmetricKeyParameter + { + private readonly ElGamalParameters parameters; + + protected ElGamalKeyParameters( + bool isPrivate, + ElGamalParameters parameters) + : base(isPrivate) + { + // TODO Should we allow 'parameters' to be null? + this.parameters = parameters; + } + + public ElGamalParameters Parameters + { + get { return parameters; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ElGamalKeyParameters other = obj as ElGamalKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ElGamalKeyParameters other) + { + return Platform.Equals(parameters, other.parameters) + && base.Equals(other); + } + + public override int GetHashCode() + { + int hc = base.GetHashCode(); + + if (parameters != null) + { + hc ^= parameters.GetHashCode(); + } + + return hc; + } + } +} diff --git a/crypto/src/crypto/parameters/ElGamalParameters.cs b/crypto/src/crypto/parameters/ElGamalParameters.cs new file mode 100644 index 000000000..ab6d3e710 --- /dev/null +++ b/crypto/src/crypto/parameters/ElGamalParameters.cs @@ -0,0 +1,81 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ElGamalParameters + : ICipherParameters + { + private readonly BigInteger p, g; + private readonly int l; + + public ElGamalParameters( + BigInteger p, + BigInteger g) + : this(p, g, 0) + { + } + + public ElGamalParameters( + BigInteger p, + BigInteger g, + int l) + { + if (p == null) + throw new ArgumentNullException("p"); + if (g == null) + throw new ArgumentNullException("g"); + + this.p = p; + this.g = g; + this.l = l; + } + + public BigInteger P + { + get { return p; } + } + + /** + * return the generator - g + */ + public BigInteger G + { + get { return g; } + } + + /** + * return private value limit - l + */ + public int L + { + get { return l; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ElGamalParameters other = obj as ElGamalParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ElGamalParameters other) + { + return p.Equals(other.p) && g.Equals(other.g) && l == other.l; + } + + public override int GetHashCode() + { + return p.GetHashCode() ^ g.GetHashCode() ^ l; + } + } +} diff --git a/crypto/src/crypto/parameters/ElGamalPrivateKeyParameters.cs b/crypto/src/crypto/parameters/ElGamalPrivateKeyParameters.cs new file mode 100644 index 000000000..6363f2bbb --- /dev/null +++ b/crypto/src/crypto/parameters/ElGamalPrivateKeyParameters.cs @@ -0,0 +1,53 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ElGamalPrivateKeyParameters + : ElGamalKeyParameters + { + private readonly BigInteger x; + + public ElGamalPrivateKeyParameters( + BigInteger x, + ElGamalParameters parameters) + : base(true, parameters) + { + if (x == null) + throw new ArgumentNullException("x"); + + this.x = x; + } + + public BigInteger X + { + get { return x; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ElGamalPrivateKeyParameters other = obj as ElGamalPrivateKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ElGamalPrivateKeyParameters other) + { + return other.x.Equals(x) && base.Equals(other); + } + + public override int GetHashCode() + { + return x.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/ElGamalPublicKeyParameters.cs b/crypto/src/crypto/parameters/ElGamalPublicKeyParameters.cs new file mode 100644 index 000000000..25ac625d5 --- /dev/null +++ b/crypto/src/crypto/parameters/ElGamalPublicKeyParameters.cs @@ -0,0 +1,53 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ElGamalPublicKeyParameters + : ElGamalKeyParameters + { + private readonly BigInteger y; + + public ElGamalPublicKeyParameters( + BigInteger y, + ElGamalParameters parameters) + : base(false, parameters) + { + if (y == null) + throw new ArgumentNullException("y"); + + this.y = y; + } + + public BigInteger Y + { + get { return y; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ElGamalPublicKeyParameters other = obj as ElGamalPublicKeyParameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ElGamalPublicKeyParameters other) + { + return y.Equals(other.y) && base.Equals(other); + } + + public override int GetHashCode() + { + return y.GetHashCode() ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410KeyGenerationParameters.cs b/crypto/src/crypto/parameters/GOST3410KeyGenerationParameters.cs new file mode 100644 index 000000000..b06a5d896 --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410KeyGenerationParameters.cs @@ -0,0 +1,55 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Gost3410KeyGenerationParameters + : KeyGenerationParameters + { + private readonly Gost3410Parameters parameters; + private readonly DerObjectIdentifier publicKeyParamSet; + + public Gost3410KeyGenerationParameters( + SecureRandom random, + Gost3410Parameters parameters) + : base(random, parameters.P.BitLength - 1) + { + this.parameters = parameters; + } + + public Gost3410KeyGenerationParameters( + SecureRandom random, + DerObjectIdentifier publicKeyParamSet) + : this(random, LookupParameters(publicKeyParamSet)) + { + this.publicKeyParamSet = publicKeyParamSet; + } + + public Gost3410Parameters Parameters + { + get { return parameters; } + } + + public DerObjectIdentifier PublicKeyParamSet + { + get { return publicKeyParamSet; } + } + + private static Gost3410Parameters LookupParameters( + DerObjectIdentifier publicKeyParamSet) + { + if (publicKeyParamSet == null) + throw new ArgumentNullException("publicKeyParamSet"); + + Gost3410ParamSetParameters p = Gost3410NamedParameters.GetByOid(publicKeyParamSet); + + if (p == null) + throw new ArgumentException("OID is not a valid CryptoPro public key parameter set", "publicKeyParamSet"); + + return new Gost3410Parameters(p.P, p.Q, p.A); + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410KeyParameters.cs b/crypto/src/crypto/parameters/GOST3410KeyParameters.cs new file mode 100644 index 000000000..f771c4d97 --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410KeyParameters.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public abstract class Gost3410KeyParameters + : AsymmetricKeyParameter + { + private readonly Gost3410Parameters parameters; + private readonly DerObjectIdentifier publicKeyParamSet; + + protected Gost3410KeyParameters( + bool isPrivate, + Gost3410Parameters parameters) + : base(isPrivate) + { + this.parameters = parameters; + } + + protected Gost3410KeyParameters( + bool isPrivate, + DerObjectIdentifier publicKeyParamSet) + : base(isPrivate) + { + this.parameters = LookupParameters(publicKeyParamSet); + this.publicKeyParamSet = publicKeyParamSet; + } + + public Gost3410Parameters Parameters + { + get { return parameters; } + } + + public DerObjectIdentifier PublicKeyParamSet + { + get { return publicKeyParamSet; } + } + + // TODO Implement Equals/GetHashCode + + private static Gost3410Parameters LookupParameters( + DerObjectIdentifier publicKeyParamSet) + { + if (publicKeyParamSet == null) + throw new ArgumentNullException("publicKeyParamSet"); + + Gost3410ParamSetParameters p = Gost3410NamedParameters.GetByOid(publicKeyParamSet); + + if (p == null) + throw new ArgumentException("OID is not a valid CryptoPro public key parameter set", "publicKeyParamSet"); + + return new Gost3410Parameters(p.P, p.Q, p.A); + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410Parameters.cs b/crypto/src/crypto/parameters/GOST3410Parameters.cs new file mode 100644 index 000000000..2ec167ef0 --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410Parameters.cs @@ -0,0 +1,86 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Gost3410Parameters + : ICipherParameters + { + private readonly BigInteger p, q, a; + private readonly Gost3410ValidationParameters validation; + + public Gost3410Parameters( + BigInteger p, + BigInteger q, + BigInteger a) + : this(p, q, a, null) + { + } + + public Gost3410Parameters( + BigInteger p, + BigInteger q, + BigInteger a, + Gost3410ValidationParameters validation) + { + if (p == null) + throw new ArgumentNullException("p"); + if (q == null) + throw new ArgumentNullException("q"); + if (a == null) + throw new ArgumentNullException("a"); + + this.p = p; + this.q = q; + this.a = a; + this.validation = validation; + } + + public BigInteger P + { + get { return p; } + } + + public BigInteger Q + { + get { return q; } + } + + public BigInteger A + { + get { return a; } + } + + public Gost3410ValidationParameters ValidationParameters + { + get { return validation; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + Gost3410Parameters other = obj as Gost3410Parameters; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + Gost3410Parameters other) + { + return p.Equals(other.p) && q.Equals(other.q) && a.Equals(other.a); + } + + public override int GetHashCode() + { + return p.GetHashCode() ^ q.GetHashCode() ^ a.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410PrivateKeyParameters.cs b/crypto/src/crypto/parameters/GOST3410PrivateKeyParameters.cs new file mode 100644 index 000000000..e3a613de6 --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410PrivateKeyParameters.cs @@ -0,0 +1,41 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Gost3410PrivateKeyParameters + : Gost3410KeyParameters + { + private readonly BigInteger x; + + public Gost3410PrivateKeyParameters( + BigInteger x, + Gost3410Parameters parameters) + : base(true, parameters) + { + if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0) + throw new ArgumentException("Invalid x for GOST3410 private key", "x"); + + this.x = x; + } + + public Gost3410PrivateKeyParameters( + BigInteger x, + DerObjectIdentifier publicKeyParamSet) + : base(true, publicKeyParamSet) + { + if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0) + throw new ArgumentException("Invalid x for GOST3410 private key", "x"); + + this.x = x; + } + + public BigInteger X + { + get { return x; } + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410PublicKeyParameters.cs b/crypto/src/crypto/parameters/GOST3410PublicKeyParameters.cs new file mode 100644 index 000000000..96b7e91ea --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410PublicKeyParameters.cs @@ -0,0 +1,40 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Gost3410PublicKeyParameters + : Gost3410KeyParameters + { + private readonly BigInteger y; + + public Gost3410PublicKeyParameters( + BigInteger y, + Gost3410Parameters parameters) + : base(false, parameters) + { + if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0) + throw new ArgumentException("Invalid y for GOST3410 public key", "y"); + + this.y = y; + } + + public Gost3410PublicKeyParameters( + BigInteger y, + DerObjectIdentifier publicKeyParamSet) + : base(false, publicKeyParamSet) + { + if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0) + throw new ArgumentException("Invalid y for GOST3410 public key", "y"); + + this.y = y; + } + + public BigInteger Y + { + get { return y; } + } + } +} diff --git a/crypto/src/crypto/parameters/GOST3410ValidationParameters.cs b/crypto/src/crypto/parameters/GOST3410ValidationParameters.cs new file mode 100644 index 000000000..21e5af823 --- /dev/null +++ b/crypto/src/crypto/parameters/GOST3410ValidationParameters.cs @@ -0,0 +1,51 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + 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 C { get { return c; } } + public int X0 { get { return x0; } } + public long CL { get { return cL; } } + public long X0L { get { return x0L; } } + + public override bool Equals( + object obj) + { + Gost3410ValidationParameters other = obj as Gost3410ValidationParameters; + + return other != null + && other.c == this.c + && other.x0 == this.x0 + && other.cL == this.cL + && other.x0L == this.x0L; + } + + public override int GetHashCode() + { + return c.GetHashCode() ^ x0.GetHashCode() ^ cL.GetHashCode() ^ x0L.GetHashCode(); + } + + } +} diff --git a/crypto/src/crypto/parameters/ISO18033KDFParameters.cs b/crypto/src/crypto/parameters/ISO18033KDFParameters.cs new file mode 100644 index 000000000..2d8fff8e3 --- /dev/null +++ b/crypto/src/crypto/parameters/ISO18033KDFParameters.cs @@ -0,0 +1,25 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * parameters for Key derivation functions for ISO-18033 + */ + public class Iso18033KdfParameters + : IDerivationParameters + { + byte[] seed; + + public Iso18033KdfParameters( + byte[] seed) + { + this.seed = seed; + } + + public byte[] GetSeed() + { + return seed; + } + } +} diff --git a/crypto/src/crypto/parameters/IesParameters.cs b/crypto/src/crypto/parameters/IesParameters.cs new file mode 100644 index 000000000..d306b2c33 --- /dev/null +++ b/crypto/src/crypto/parameters/IesParameters.cs @@ -0,0 +1,49 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * parameters for using an integrated cipher in stream mode. + */ + public class IesParameters : ICipherParameters + { + 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 MacKeySize + { + get + { + return macKeySize; + } + } + } + +} diff --git a/crypto/src/crypto/parameters/IesWithCipherParameters.cs b/crypto/src/crypto/parameters/IesWithCipherParameters.cs new file mode 100644 index 000000000..70ef55d54 --- /dev/null +++ b/crypto/src/crypto/parameters/IesWithCipherParameters.cs @@ -0,0 +1,33 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class IesWithCipherParameters : 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) : base(derivation, encoding, macKeySize) + { + this.cipherKeySize = cipherKeySize; + } + + public int CipherKeySize + { + get + { + return cipherKeySize; + } + } + } + +} diff --git a/crypto/src/crypto/parameters/KdfParameters.cs b/crypto/src/crypto/parameters/KdfParameters.cs new file mode 100644 index 000000000..bc5c905d0 --- /dev/null +++ b/crypto/src/crypto/parameters/KdfParameters.cs @@ -0,0 +1,33 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * parameters for Key derivation functions for IEEE P1363a + */ + public class KdfParameters : IDerivationParameters + { + 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/crypto/src/crypto/parameters/KeyParameter.cs b/crypto/src/crypto/parameters/KeyParameter.cs new file mode 100644 index 000000000..33dff96d7 --- /dev/null +++ b/crypto/src/crypto/parameters/KeyParameter.cs @@ -0,0 +1,43 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class KeyParameter + : ICipherParameters + { + private readonly byte[] key; + + public KeyParameter( + byte[] key) + { + if (key == null) + throw new ArgumentNullException("key"); + + this.key = (byte[]) key.Clone(); + } + + public KeyParameter( + byte[] key, + int keyOff, + int keyLen) + { + if (key == null) + throw new ArgumentNullException("key"); + if (keyOff < 0 || keyOff > key.Length) + throw new ArgumentOutOfRangeException("keyOff"); + if (keyLen < 0 || (keyOff + keyLen) > key.Length) + throw new ArgumentOutOfRangeException("keyLen"); + + this.key = new byte[keyLen]; + Array.Copy(key, keyOff, this.key, 0, keyLen); + } + + public byte[] GetKey() + { + return (byte[]) key.Clone(); + } + } + +} diff --git a/crypto/src/crypto/parameters/MgfParameters.cs b/crypto/src/crypto/parameters/MgfParameters.cs new file mode 100644 index 000000000..11983b877 --- /dev/null +++ b/crypto/src/crypto/parameters/MgfParameters.cs @@ -0,0 +1,31 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /// Parameters for mask derivation functions. + public class MgfParameters + : IDerivationParameters + { + private readonly byte[] seed; + + public MgfParameters( + byte[] seed) + : this(seed, 0, seed.Length) + { + } + + public MgfParameters( + byte[] seed, + int off, + int len) + { + this.seed = new byte[len]; + Array.Copy(seed, off, this.seed, 0, len); + } + + public byte[] GetSeed() + { + return (byte[]) seed.Clone(); + } + } +} diff --git a/crypto/src/crypto/parameters/MqvPrivateParameters.cs b/crypto/src/crypto/parameters/MqvPrivateParameters.cs new file mode 100644 index 000000000..4bf33e347 --- /dev/null +++ b/crypto/src/crypto/parameters/MqvPrivateParameters.cs @@ -0,0 +1,44 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class MqvPrivateParameters + : ICipherParameters + { + private readonly ECPrivateKeyParameters staticPrivateKey; + private readonly ECPrivateKeyParameters ephemeralPrivateKey; + private readonly 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 StaticPrivateKey + { + get { return staticPrivateKey; } + } + + public ECPrivateKeyParameters EphemeralPrivateKey + { + get { return ephemeralPrivateKey; } + } + + public ECPublicKeyParameters EphemeralPublicKey + { + get { return ephemeralPublicKey; } + } + } +} diff --git a/crypto/src/crypto/parameters/MqvPublicParameters.cs b/crypto/src/crypto/parameters/MqvPublicParameters.cs new file mode 100644 index 000000000..a0e273ac4 --- /dev/null +++ b/crypto/src/crypto/parameters/MqvPublicParameters.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class MqvPublicParameters + : ICipherParameters + { + private readonly ECPublicKeyParameters staticPublicKey; + private readonly ECPublicKeyParameters ephemeralPublicKey; + + public MqvPublicParameters( + ECPublicKeyParameters staticPublicKey, + ECPublicKeyParameters ephemeralPublicKey) + { + this.staticPublicKey = staticPublicKey; + this.ephemeralPublicKey = ephemeralPublicKey; + } + + public ECPublicKeyParameters StaticPublicKey + { + get { return staticPublicKey; } + } + + public ECPublicKeyParameters EphemeralPublicKey + { + get { return ephemeralPublicKey; } + } + } +} diff --git a/crypto/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs b/crypto/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs new file mode 100644 index 000000000..5b4052505 --- /dev/null +++ b/crypto/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs @@ -0,0 +1,101 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * 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 : KeyGenerationParameters + { + // private BigInteger publicExponent; + private readonly int certainty; + private readonly int countSmallPrimes; + private bool debug; + + /** + * 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 countSmallPrimes + * How many small key factors are desired + */ + public NaccacheSternKeyGenerationParameters( + SecureRandom random, + int strength, + int certainty, + int countSmallPrimes) + : this(random, strength, certainty, countSmallPrimes, 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 countSmallPrimes, + bool debug) + : base(random, strength) + { + if (countSmallPrimes % 2 == 1) + { + throw new ArgumentException("countSmallPrimes must be a multiple of 2"); + } + if (countSmallPrimes < 30) + { + throw new ArgumentException("countSmallPrimes must be >= 30 for security reasons"); + } + this.certainty = certainty; + this.countSmallPrimes = countSmallPrimes; + this.debug = debug; + } + + /** + * @return Returns the certainty. + */ + public int Certainty + { + get { return certainty; } + } + + /** + * @return Returns the countSmallPrimes. + */ + public int CountSmallPrimes + { + get { return countSmallPrimes; } + } + + public bool IsDebug + { + get { return debug; } + } + } +} diff --git a/crypto/src/crypto/parameters/NaccacheSternKeyParameters.cs b/crypto/src/crypto/parameters/NaccacheSternKeyParameters.cs new file mode 100644 index 000000000..8be7ad835 --- /dev/null +++ b/crypto/src/crypto/parameters/NaccacheSternKeyParameters.cs @@ -0,0 +1,44 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * 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 : AsymmetricKeyParameter + { + private readonly BigInteger g, n; + private readonly int lowerSigmaBound; + + /** + * @param privateKey + */ + public NaccacheSternKeyParameters(bool privateKey, BigInteger g, BigInteger n, int lowerSigmaBound) + : base(privateKey) + { + this.g = g; + this.n = n; + this.lowerSigmaBound = lowerSigmaBound; + } + + /** + * @return Returns the g. + */ + public BigInteger G { get { return g; } } + + /** + * @return Returns the lowerSigmaBound. + */ + public int LowerSigmaBound { get { return lowerSigmaBound; } } + + /** + * @return Returns the n. + */ + public BigInteger Modulus { get { return n; } } + } +} diff --git a/crypto/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs b/crypto/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs new file mode 100644 index 000000000..0e1fe14b7 --- /dev/null +++ b/crypto/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + /** + * 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 : NaccacheSternKeyParameters + { + private readonly BigInteger phiN; + private readonly IList smallPrimes; + +#if !SILVERLIGHT + [Obsolete] + public NaccacheSternPrivateKeyParameters( + BigInteger g, + BigInteger n, + int lowerSigmaBound, + ArrayList smallPrimes, + BigInteger phiN) + : base(true, g, n, lowerSigmaBound) + { + this.smallPrimes = smallPrimes; + this.phiN = phiN; + } +#endif + + /** + * 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, + IList smallPrimes, + BigInteger phiN) + : base(true, g, n, lowerSigmaBound) + { + this.smallPrimes = smallPrimes; + this.phiN = phiN; + } + + public BigInteger PhiN + { + get { return phiN; } + } + +#if !SILVERLIGHT + [Obsolete("Use 'SmallPrimesList' instead")] + public ArrayList SmallPrimes + { + get { return new ArrayList(smallPrimes); } + } +#endif + + public IList SmallPrimesList + { + get { return smallPrimes; } + } + } +} diff --git a/crypto/src/crypto/parameters/ParametersWithIV.cs b/crypto/src/crypto/parameters/ParametersWithIV.cs new file mode 100644 index 000000000..11a8b77a0 --- /dev/null +++ b/crypto/src/crypto/parameters/ParametersWithIV.cs @@ -0,0 +1,43 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ParametersWithIV + : ICipherParameters + { + private readonly ICipherParameters parameters; + private readonly byte[] iv; + + public ParametersWithIV( + ICipherParameters parameters, + byte[] iv) + : this(parameters, iv, 0, iv.Length) + { + } + + public ParametersWithIV( + ICipherParameters parameters, + byte[] iv, + int ivOff, + int ivLen) + { + // NOTE: 'parameters' may be null to imply key re-use + if (iv == null) + throw new ArgumentNullException("iv"); + + this.parameters = parameters; + this.iv = new byte[ivLen]; + Array.Copy(iv, ivOff, this.iv, 0, ivLen); + } + + public byte[] GetIV() + { + return (byte[]) iv.Clone(); + } + + public ICipherParameters Parameters + { + get { return parameters; } + } + } +} diff --git a/crypto/src/crypto/parameters/ParametersWithRandom.cs b/crypto/src/crypto/parameters/ParametersWithRandom.cs new file mode 100644 index 000000000..a05e77409 --- /dev/null +++ b/crypto/src/crypto/parameters/ParametersWithRandom.cs @@ -0,0 +1,48 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ParametersWithRandom + : ICipherParameters + { + private readonly ICipherParameters parameters; + private readonly SecureRandom random; + + public ParametersWithRandom( + ICipherParameters parameters, + SecureRandom random) + { + if (parameters == null) + throw new ArgumentNullException("random"); + if (random == null) + throw new ArgumentNullException("random"); + + this.parameters = parameters; + this.random = random; + } + + public ParametersWithRandom( + ICipherParameters parameters) + : this(parameters, new SecureRandom()) + { + } + + [Obsolete("Use Random property instead")] + public SecureRandom GetRandom() + { + return Random; + } + + public SecureRandom Random + { + get { return random; } + } + + public ICipherParameters Parameters + { + get { return parameters; } + } + } +} diff --git a/crypto/src/crypto/parameters/ParametersWithSBox.cs b/crypto/src/crypto/parameters/ParametersWithSBox.cs new file mode 100644 index 000000000..6473796e3 --- /dev/null +++ b/crypto/src/crypto/parameters/ParametersWithSBox.cs @@ -0,0 +1,24 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class ParametersWithSBox : ICipherParameters + { + private ICipherParameters parameters; + private byte[] sBox; + + public ParametersWithSBox( + ICipherParameters parameters, + byte[] sBox) + { + this.parameters = parameters; + this.sBox = sBox; + } + + public byte[] GetSBox() { return sBox; } + + public ICipherParameters Parameters { get { return parameters; } } + } +} diff --git a/crypto/src/crypto/parameters/ParametersWithSalt.cs b/crypto/src/crypto/parameters/ParametersWithSalt.cs new file mode 100644 index 000000000..7f4cd6cd1 --- /dev/null +++ b/crypto/src/crypto/parameters/ParametersWithSalt.cs @@ -0,0 +1,39 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + + /// Cipher parameters with a fixed salt value associated with them. + public class ParametersWithSalt : ICipherParameters + { + private byte[] salt; + private ICipherParameters parameters; + + public ParametersWithSalt(ICipherParameters parameters, byte[] salt):this(parameters, salt, 0, salt.Length) + { + } + + public ParametersWithSalt(ICipherParameters parameters, byte[] salt, int saltOff, int saltLen) + { + this.salt = new byte[saltLen]; + this.parameters = parameters; + + Array.Copy(salt, saltOff, this.salt, 0, saltLen); + } + + public byte[] GetSalt() + { + return salt; + } + + public ICipherParameters Parameters + { + get + { + return parameters; + } + } + } +} diff --git a/crypto/src/crypto/parameters/RC2Parameters.cs b/crypto/src/crypto/parameters/RC2Parameters.cs new file mode 100644 index 000000000..7a6d5bb6e --- /dev/null +++ b/crypto/src/crypto/parameters/RC2Parameters.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RC2Parameters + : KeyParameter + { + private readonly int bits; + + public RC2Parameters( + byte[] key) + : this(key, (key.Length > 128) ? 1024 : (key.Length * 8)) + { + } + + public RC2Parameters( + byte[] key, + int keyOff, + int keyLen) + : this(key, keyOff, keyLen, (keyLen > 128) ? 1024 : (keyLen * 8)) + { + } + + public RC2Parameters( + byte[] key, + int bits) + : base(key) + { + this.bits = bits; + } + + public RC2Parameters( + byte[] key, + int keyOff, + int keyLen, + int bits) + : base(key, keyOff, keyLen) + { + this.bits = bits; + } + + public int EffectiveKeyBits + { + get { return bits; } + } + } +} diff --git a/crypto/src/crypto/parameters/RC5Parameters.cs b/crypto/src/crypto/parameters/RC5Parameters.cs new file mode 100644 index 000000000..88a59e197 --- /dev/null +++ b/crypto/src/crypto/parameters/RC5Parameters.cs @@ -0,0 +1,27 @@ +using System; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RC5Parameters + : KeyParameter + { + private readonly int rounds; + + public RC5Parameters( + byte[] key, + int rounds) + : base(key) + { + if (key.Length > 255) + throw new ArgumentException("RC5 key length can be no greater than 255"); + + this.rounds = rounds; + } + + public int Rounds + { + get { return rounds; } + } + } +} diff --git a/crypto/src/crypto/parameters/RSABlindingParameters.cs b/crypto/src/crypto/parameters/RSABlindingParameters.cs new file mode 100644 index 000000000..49c7bcce6 --- /dev/null +++ b/crypto/src/crypto/parameters/RSABlindingParameters.cs @@ -0,0 +1,34 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RsaBlindingParameters + : ICipherParameters + { + private readonly RsaKeyParameters publicKey; + private readonly BigInteger blindingFactor; + + public RsaBlindingParameters( + RsaKeyParameters publicKey, + BigInteger blindingFactor) + { + if (publicKey.IsPrivate) + throw new ArgumentException("RSA parameters should be for a public key"); + + this.publicKey = publicKey; + this.blindingFactor = blindingFactor; + } + + public RsaKeyParameters PublicKey + { + get { return publicKey; } + } + + public BigInteger BlindingFactor + { + get { return blindingFactor; } + } + } +} diff --git a/crypto/src/crypto/parameters/RsaKeyGenerationParameters.cs b/crypto/src/crypto/parameters/RsaKeyGenerationParameters.cs new file mode 100644 index 000000000..619ab65b4 --- /dev/null +++ b/crypto/src/crypto/parameters/RsaKeyGenerationParameters.cs @@ -0,0 +1,55 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RsaKeyGenerationParameters + : KeyGenerationParameters + { + private readonly BigInteger publicExponent; + private readonly int certainty; + + public RsaKeyGenerationParameters( + BigInteger publicExponent, + SecureRandom random, + int strength, + int certainty) + : base(random, strength) + { + this.publicExponent = publicExponent; + this.certainty = certainty; + } + + public BigInteger PublicExponent + { + get { return publicExponent; } + } + + public int Certainty + { + get { return certainty; } + } + + public override bool Equals( + object obj) + { + RsaKeyGenerationParameters other = obj as RsaKeyGenerationParameters; + + if (other == null) + { + return false; + } + + return certainty == other.certainty + && publicExponent.Equals(other.publicExponent); + } + + public override int GetHashCode() + { + return certainty.GetHashCode() ^ publicExponent.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/RsaKeyParameters.cs b/crypto/src/crypto/parameters/RsaKeyParameters.cs new file mode 100644 index 000000000..72c0d806f --- /dev/null +++ b/crypto/src/crypto/parameters/RsaKeyParameters.cs @@ -0,0 +1,63 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RsaKeyParameters + : AsymmetricKeyParameter + { + private readonly BigInteger modulus; + private readonly BigInteger exponent; + + public RsaKeyParameters( + bool isPrivate, + BigInteger modulus, + BigInteger exponent) + : base(isPrivate) + { + if (modulus == null) + throw new ArgumentNullException("modulus"); + if (exponent == null) + throw new ArgumentNullException("exponent"); + if (modulus.SignValue <= 0) + throw new ArgumentException("Not a valid RSA modulus", "modulus"); + if (exponent.SignValue <= 0) + throw new ArgumentException("Not a valid RSA exponent", "exponent"); + + this.modulus = modulus; + this.exponent = exponent; + } + + public BigInteger Modulus + { + get { return modulus; } + } + + public BigInteger Exponent + { + get { return exponent; } + } + + public override bool Equals( + object obj) + { + RsaKeyParameters kp = obj as RsaKeyParameters; + + if (kp == null) + { + return false; + } + + return kp.IsPrivate == this.IsPrivate + && kp.Modulus.Equals(this.modulus) + && kp.Exponent.Equals(this.exponent); + } + + public override int GetHashCode() + { + return modulus.GetHashCode() ^ exponent.GetHashCode() ^ IsPrivate.GetHashCode(); + } + } +} diff --git a/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs new file mode 100644 index 000000000..7bd8abd76 --- /dev/null +++ b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs @@ -0,0 +1,104 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class RsaPrivateCrtKeyParameters + : RsaKeyParameters + { + private readonly BigInteger e, p, q, dP, dQ, qInv; + + public RsaPrivateCrtKeyParameters( + BigInteger modulus, + BigInteger publicExponent, + BigInteger privateExponent, + BigInteger p, + BigInteger q, + BigInteger dP, + BigInteger dQ, + BigInteger qInv) + : base(true, modulus, privateExponent) + { + ValidateValue(publicExponent, "publicExponent", "exponent"); + ValidateValue(p, "p", "P value"); + ValidateValue(q, "q", "Q value"); + ValidateValue(dP, "dP", "DP value"); + ValidateValue(dQ, "dQ", "DQ value"); + ValidateValue(qInv, "qInv", "InverseQ value"); + + this.e = publicExponent; + this.p = p; + this.q = q; + this.dP = dP; + this.dQ = dQ; + this.qInv = qInv; + } + + public BigInteger PublicExponent + { + get { return e; } + } + + public BigInteger P + { + get { return p; } + } + + public BigInteger Q + { + get { return q; } + } + + public BigInteger DP + { + get { return dP; } + } + + public BigInteger DQ + { + get { return dQ; } + } + + public BigInteger QInv + { + get { return qInv; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters; + + if (kp == null) + return false; + + return kp.DP.Equals(dP) + && kp.DQ.Equals(dQ) + && kp.Exponent.Equals(this.Exponent) + && kp.Modulus.Equals(this.Modulus) + && kp.P.Equals(p) + && kp.Q.Equals(q) + && kp.PublicExponent.Equals(e) + && kp.QInv.Equals(qInv); + } + + public override int GetHashCode() + { + return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode() + ^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode(); + } + + private static void ValidateValue(BigInteger x, string name, string desc) + { + if (x == null) + throw new ArgumentNullException(name); + if (x.SignValue <= 0) + throw new ArgumentException("Not a valid RSA " + desc, name); + } + } +} diff --git a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs new file mode 100644 index 000000000..e1a0d4012 --- /dev/null +++ b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs @@ -0,0 +1,66 @@ +#if !NETCF_1_0 + +using System; +using System.Security.Cryptography; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /// + /// Uses Microsoft's RNGCryptoServiceProvider + /// + public class CryptoApiRandomGenerator + : IRandomGenerator + { + private readonly RandomNumberGenerator rndProv; + + public CryptoApiRandomGenerator() + : this(new RNGCryptoServiceProvider()) + { + } + + public CryptoApiRandomGenerator(RandomNumberGenerator rng) + { + this.rndProv = rng; + } + + #region IRandomGenerator Members + + public virtual void AddSeedMaterial(byte[] seed) + { + // We don't care about the seed + } + + public virtual void AddSeedMaterial(long seed) + { + // We don't care about the seed + } + + public virtual void NextBytes(byte[] bytes) + { + rndProv.GetBytes(bytes); + } + + public virtual void NextBytes(byte[] bytes, int start, int len) + { + if (start < 0) + throw new ArgumentException("Start offset cannot be negative", "start"); + if (bytes.Length < (start + len)) + throw new ArgumentException("Byte array too small for requested offset and length"); + + if (bytes.Length == len && start == 0) + { + NextBytes(bytes); + } + else + { + byte[] tmpBuf = new byte[len]; + rndProv.GetBytes(tmpBuf); + Array.Copy(tmpBuf, 0, bytes, start, len); + } + } + + #endregion + } +} + +#endif diff --git a/crypto/src/crypto/prng/DigestRandomGenerator.cs b/crypto/src/crypto/prng/DigestRandomGenerator.cs new file mode 100644 index 000000000..cbd2ef060 --- /dev/null +++ b/crypto/src/crypto/prng/DigestRandomGenerator.cs @@ -0,0 +1,129 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /** + * Random generation based on the digest with counter. Calling AddSeedMaterial will + * always increase the entropy of the hash. + *

+ * Internal access to the digest is synchronized so a single one of these can be shared. + *

+ */ + public class DigestRandomGenerator + : IRandomGenerator + { + private const long CYCLE_COUNT = 10; + + private long stateCounter; + private long seedCounter; + private IDigest digest; + private byte[] state; + private byte[] seed; + + public DigestRandomGenerator( + IDigest 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) + { + lock (this) + { + DigestUpdate(inSeed); + DigestUpdate(seed); + DigestDoFinal(seed); + } + } + + public void AddSeedMaterial( + long rSeed) + { + lock (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) + { + lock (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 seedVal) + { + ulong seed = (ulong)seedVal; + for (int i = 0; i != 8; i++) + { + digest.Update((byte)seed); + seed >>= 8; + } + } + + private void DigestUpdate(byte[] inSeed) + { + digest.BlockUpdate(inSeed, 0, inSeed.Length); + } + + private void DigestDoFinal(byte[] result) + { + digest.DoFinal(result, 0); + } + } +} diff --git a/crypto/src/crypto/prng/IRandomGenerator.cs b/crypto/src/crypto/prng/IRandomGenerator.cs new file mode 100644 index 000000000..8dbe4068f --- /dev/null +++ b/crypto/src/crypto/prng/IRandomGenerator.cs @@ -0,0 +1,26 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /// Generic interface for objects generating random bytes. + public interface IRandomGenerator + { + /// Add more seed material to the generator. + /// A byte array to be mixed into the generator's state. + void AddSeedMaterial(byte[] seed); + + /// Add more seed material to the generator. + /// A long value to be mixed into the generator's state. + void AddSeedMaterial(long seed); + + /// Fill byte array with random values. + /// Array to be filled. + void NextBytes(byte[] bytes); + + /// Fill byte array with random values. + /// Array to receive bytes. + /// Index to start filling at. + /// Length of segment to fill. + void NextBytes(byte[] bytes, int start, int len); + } +} diff --git a/crypto/src/crypto/prng/ReversedWindowGenerator.cs b/crypto/src/crypto/prng/ReversedWindowGenerator.cs new file mode 100644 index 000000000..dd28c525a --- /dev/null +++ b/crypto/src/crypto/prng/ReversedWindowGenerator.cs @@ -0,0 +1,98 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /// + /// Takes bytes generated by an underling RandomGenerator and reverses the order in + /// each small window (of configurable size). + ///

+ /// Access to internals is synchronized so a single one of these can be shared. + ///

+ ///
+ public class ReversedWindowGenerator + : IRandomGenerator + { + private readonly IRandomGenerator generator; + + private byte[] window; + private int windowCount; + + public ReversedWindowGenerator( + IRandomGenerator generator, + int windowSize) + { + if (generator == null) + throw new ArgumentNullException("generator"); + if (windowSize < 2) + throw new ArgumentException("Window size must be at least 2", "windowSize"); + + this.generator = generator; + this.window = new byte[windowSize]; + } + + /// Add more seed material to the generator. + /// A byte array to be mixed into the generator's state. + public virtual void AddSeedMaterial( + byte[] seed) + { + lock (this) + { + windowCount = 0; + generator.AddSeedMaterial(seed); + } + } + + /// Add more seed material to the generator. + /// A long value to be mixed into the generator's state. + public virtual void AddSeedMaterial( + long seed) + { + lock (this) + { + windowCount = 0; + generator.AddSeedMaterial(seed); + } + } + + /// Fill byte array with random values. + /// Array to be filled. + public virtual void NextBytes( + byte[] bytes) + { + doNextBytes(bytes, 0, bytes.Length); + } + + /// Fill byte array with random values. + /// Array to receive bytes. + /// Index to start filling at. + /// Length of segment to fill. + public virtual void NextBytes( + byte[] bytes, + int start, + int len) + { + doNextBytes(bytes, start, len); + } + + private void doNextBytes( + byte[] bytes, + int start, + int len) + { + lock (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/crypto/src/crypto/prng/ThreadedSeedGenerator.cs b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs new file mode 100644 index 000000000..c29ad2c9a --- /dev/null +++ b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs @@ -0,0 +1,117 @@ +using System; +using System.Threading; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /** + * A thread based seed generator - one source of randomness. + *

+ * Based on an idea from Marcus Lippert. + *

+ */ + public class ThreadedSeedGenerator + { + private class SeedGenerator + { +#if NETCF_1_0 + // No volatile keyword, but all fields implicitly volatile anyway + private int counter = 0; + private bool stop = false; +#else + private volatile int counter = 0; + private volatile bool stop = false; +#endif + + private void Run(object ignored) + { + while (!this.stop) + { + this.counter++; + } + } + + public byte[] GenerateSeed( + int numBytes, + bool fast) + { +#if SILVERLIGHT + return DoGenerateSeed(numBytes, fast); +#else + ThreadPriority originalPriority = Thread.CurrentThread.Priority; + try + { + Thread.CurrentThread.Priority = ThreadPriority.Normal; + return DoGenerateSeed(numBytes, fast); + } + finally + { + Thread.CurrentThread.Priority = originalPriority; + } +#endif + } + + private byte[] DoGenerateSeed( + int numBytes, + bool fast) + { + this.counter = 0; + this.stop = false; + + byte[] result = new byte[numBytes]; + int last = 0; + int end = fast ? numBytes : numBytes * 8; + + ThreadPool.QueueUserWorkItem(new WaitCallback(Run)); + + for (int i = 0; i < end; i++) + { + while (this.counter == last) + { + try + { + Thread.Sleep(1); + } + catch (Exception) + { + // ignore + } + } + + last = this.counter; + + if (fast) + { + result[i] = (byte) last; + } + else + { + int bytepos = i / 8; + result[bytepos] = (byte) ((result[bytepos] << 1) | (last & 1)); + } + } + + this.stop = true; + + return result; + } + } + + /** + * Generate seed bytes. Set fast to false for best quality. + *

+ * 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. + *

+ * @param numBytes the number of bytes to generate + * @param fast true if fast mode should be used + */ + public byte[] GenerateSeed( + int numBytes, + bool fast) + { + return new SeedGenerator().GenerateSeed(numBytes, fast); + } + } +} diff --git a/crypto/src/crypto/prng/VMPCRandomGenerator.cs b/crypto/src/crypto/prng/VMPCRandomGenerator.cs new file mode 100644 index 000000000..64f287d13 --- /dev/null +++ b/crypto/src/crypto/prng/VMPCRandomGenerator.cs @@ -0,0 +1,114 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng +{ + public class VmpcRandomGenerator + : IRandomGenerator + { + private byte n = 0; + + /// + /// Permutation generated by 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; + /// } + /// + 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 P. + private byte s = (byte) 0xbe; + + public VmpcRandomGenerator() + { + } + + public virtual 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 virtual void AddSeedMaterial(long seed) + { + AddSeedMaterial(Pack.UInt64_To_BE((ulong)seed)); + } + + public virtual void NextBytes(byte[] bytes) + { + NextBytes(bytes, 0, bytes.Length); + } + + public virtual void NextBytes(byte[] bytes, int start, int len) + { + lock (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/crypto/src/crypto/signers/DsaDigestSigner.cs b/crypto/src/crypto/signers/DsaDigestSigner.cs new file mode 100644 index 000000000..aee713450 --- /dev/null +++ b/crypto/src/crypto/signers/DsaDigestSigner.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class DsaDigestSigner + : ISigner + { + private readonly IDigest digest; + private readonly IDsa dsaSigner; + private bool forSigning; + + public DsaDigestSigner( + IDsa signer, + IDigest digest) + { + this.digest = digest; + this.dsaSigner = signer; + } + + public string AlgorithmName + { + get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + this.forSigning = forSigning; + + AsymmetricKeyParameter k; + + if (parameters is ParametersWithRandom) + { + k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters; + } + else + { + k = (AsymmetricKeyParameter)parameters; + } + + if (forSigning && !k.IsPrivate) + throw new InvalidKeyException("Signing Requires Private Key."); + + if (!forSigning && k.IsPrivate) + throw new InvalidKeyException("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 BlockUpdate( + byte[] input, + int inOff, + int length) + { + digest.BlockUpdate(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 InvalidOperationException("DSADigestSigner not initialised for signature generation."); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + BigInteger[] sig = dsaSigner.GenerateSignature(hash); + + return DerEncode(sig[0], sig[1]); + } + + /// true if the internal state represents the signature described in the passed in array. + public bool VerifySignature( + byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("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) + { + return false; + } + } + + /// Reset the internal state + public void Reset() + { + digest.Reset(); + } + + private byte[] DerEncode( + BigInteger r, + BigInteger s) + { + return new DerSequence(new DerInteger(r), new DerInteger(s)).GetDerEncoded(); + } + + private BigInteger[] DerDecode( + byte[] encoding) + { + Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + + return new BigInteger[] + { + ((DerInteger) s[0]).Value, + ((DerInteger) s[1]).Value + }; + } + } +} diff --git a/crypto/src/crypto/signers/DsaSigner.cs b/crypto/src/crypto/signers/DsaSigner.cs new file mode 100644 index 000000000..419b1972e --- /dev/null +++ b/crypto/src/crypto/signers/DsaSigner.cs @@ -0,0 +1,136 @@ +using System; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * The Digital Signature Algorithm - as described in "Handbook of Applied + * Cryptography", pages 452 - 453. + */ + public class DsaSigner + : IDsa + { + private DsaKeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "DSA"; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + if (forSigning) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + + this.random = rParam.Random; + parameters = rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + } + + if (!(parameters is DsaPrivateKeyParameters)) + throw new InvalidKeyException("DSA private key required for signing"); + + this.key = (DsaPrivateKeyParameters) parameters; + } + else + { + if (!(parameters is DsaPublicKeyParameters)) + throw new InvalidKeyException("DSA public key required for verification"); + + this.key = (DsaPublicKeyParameters) parameters; + } + } + + /** + * 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 parameters = key.Parameters; + BigInteger q = parameters.Q; + BigInteger m = calculateE(q, message); + BigInteger k; + + do + { + k = new BigInteger(q.BitLength, random); + } + while (k.CompareTo(q) >= 0); + + BigInteger r = parameters.G.ModPow(k, parameters.P).Mod(q); + + k = k.ModInverse(q).Multiply( + m.Add(((DsaPrivateKeyParameters)key).X.Multiply(r))); + + BigInteger s = k.Mod(q); + + return new BigInteger[]{ r, s }; + } + + /** + * 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 bool VerifySignature( + byte[] message, + BigInteger r, + BigInteger s) + { + DsaParameters parameters = key.Parameters; + BigInteger q = parameters.Q; + BigInteger m = calculateE(q, message); + + if (r.SignValue <= 0 || q.CompareTo(r) <= 0) + { + return false; + } + + if (s.SignValue <= 0 || q.CompareTo(s) <= 0) + { + return false; + } + + BigInteger w = s.ModInverse(q); + + BigInteger u1 = m.Multiply(w).Mod(q); + BigInteger u2 = r.Multiply(w).Mod(q); + + BigInteger p = parameters.P; + u1 = parameters.G.ModPow(u1, p); + u2 = ((DsaPublicKeyParameters)key).Y.ModPow(u2, p); + + BigInteger v = u1.Multiply(u2).Mod(p).Mod(q); + + return v.Equals(r); + } + + private BigInteger calculateE( + BigInteger n, + byte[] message) + { + int length = System.Math.Min(message.Length, n.BitLength / 8); + + return new BigInteger(1, message, 0, length); + } + } +} diff --git a/crypto/src/crypto/signers/ECDsaSigner.cs b/crypto/src/crypto/signers/ECDsaSigner.cs new file mode 100644 index 000000000..d602ec3bb --- /dev/null +++ b/crypto/src/crypto/signers/ECDsaSigner.cs @@ -0,0 +1,159 @@ +using System; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * EC-DSA as described in X9.62 + */ + public class ECDsaSigner + : IDsa + { + private ECKeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "ECDSA"; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + if (forSigning) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom) parameters; + + this.random = rParam.Random; + parameters = rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + } + + if (!(parameters is ECPrivateKeyParameters)) + throw new InvalidKeyException("EC private key required for signing"); + + this.key = (ECPrivateKeyParameters) parameters; + } + else + { + if (!(parameters is ECPublicKeyParameters)) + throw new InvalidKeyException("EC public key required for verification"); + + this.key = (ECPublicKeyParameters) parameters; + } + } + + // 5.3 pg 28 + /** + * Generate a signature for the given message using the key we were + * initialised with. For conventional DSA the message should be a SHA-1 + * hash of the message of interest. + * + * @param message the message that will be verified later. + */ + public BigInteger[] GenerateSignature( + byte[] message) + { + BigInteger n = key.Parameters.N; + BigInteger e = calculateE(n, message); + + BigInteger r = null; + BigInteger s = null; + + // 5.3.2 + do // Generate s + { + BigInteger k = null; + + do // Generate r + { + do + { + k = new BigInteger(n.BitLength, random); + } + while (k.SignValue == 0 || k.CompareTo(n) >= 0); + + ECPoint p = key.Parameters.G.Multiply(k); + + // 5.3.3 + BigInteger x = p.X.ToBigInteger(); + + r = x.Mod(n); + } + while (r.SignValue == 0); + + BigInteger d = ((ECPrivateKeyParameters)key).D; + + s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r).Mod(n))).Mod(n); + } + while (s.SignValue == 0); + + 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 bool VerifySignature( + byte[] message, + BigInteger r, + BigInteger s) + { + BigInteger n = key.Parameters.N; + + // r and s should both in the range [1,n-1] + if (r.SignValue < 1 || s.SignValue < 1 + || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0) + { + return false; + } + + BigInteger e = calculateE(n, message); + BigInteger c = s.ModInverse(n); + + BigInteger u1 = e.Multiply(c).Mod(n); + BigInteger u2 = r.Multiply(c).Mod(n); + + ECPoint G = key.Parameters.G; + ECPoint Q = ((ECPublicKeyParameters) key).Q; + + ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2); + + if (point.IsInfinity) + return false; + + BigInteger v = point.X.ToBigInteger().Mod(n); + + return v.Equals(r); + } + + private BigInteger calculateE( + BigInteger n, + byte[] message) + { + int messageBitLength = message.Length * 8; + BigInteger trunc = new BigInteger(1, message); + + if (n.BitLength < messageBitLength) + { + trunc = trunc.ShiftRight(messageBitLength - n.BitLength); + } + + return trunc; + } + } +} diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs new file mode 100644 index 000000000..294d4791a --- /dev/null +++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs @@ -0,0 +1,157 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * GOST R 34.10-2001 Signature Algorithm + */ + public class ECGost3410Signer + : IDsa + { + private ECKeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "ECGOST3410"; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + if (forSigning) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + + this.random = rParam.Random; + parameters = rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + } + + if (!(parameters is ECPrivateKeyParameters)) + throw new InvalidKeyException("EC private key required for signing"); + + this.key = (ECPrivateKeyParameters) parameters; + } + else + { + if (!(parameters is ECPublicKeyParameters)) + throw new InvalidKeyException("EC public key required for verification"); + + this.key = (ECPublicKeyParameters)parameters; + } + } + + /** + * 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); + BigInteger n = key.Parameters.N; + + BigInteger r = null; + BigInteger s = null; + + do // generate s + { + BigInteger k = null; + + do // generate r + { + do + { + k = new BigInteger(n.BitLength, random); + } + while (k.SignValue == 0); + + ECPoint p = key.Parameters.G.Multiply(k); + + BigInteger x = p.X.ToBigInteger(); + + r = x.Mod(n); + } + while (r.SignValue == 0); + + BigInteger d = ((ECPrivateKeyParameters)key).D; + + s = (k.Multiply(e)).Add(d.Multiply(r)).Mod(n); + } + while (s.SignValue == 0); + + 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 bool 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.Parameters.N; + + // r in the range [1,n-1] + if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0) + { + return false; + } + + // s in the range [1,n-1] + if (s.CompareTo(BigInteger.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.Parameters.G; // P + ECPoint Q = ((ECPublicKeyParameters)key).Q; + + ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2); + + if (point.IsInfinity) + return false; + + BigInteger R = point.X.ToBigInteger().Mod(n); + + return R.Equals(r); + } + } +} diff --git a/crypto/src/crypto/signers/ECNRSigner.cs b/crypto/src/crypto/signers/ECNRSigner.cs new file mode 100644 index 000000000..1d9af3d13 --- /dev/null +++ b/crypto/src/crypto/signers/ECNRSigner.cs @@ -0,0 +1,189 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * EC-NR as described in IEEE 1363-2000 + */ + public class ECNRSigner + : IDsa + { + private bool forSigning; + private ECKeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "ECNR"; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom) parameters; + + this.random = rParam.Random; + parameters = rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + } + + if (!(parameters is ECPrivateKeyParameters)) + throw new InvalidKeyException("EC private key required for signing"); + + this.key = (ECPrivateKeyParameters) parameters; + } + else + { + if (!(parameters is ECPublicKeyParameters)) + throw new InvalidKeyException("EC public key required for verification"); + + this.key = (ECPublicKeyParameters) parameters; + } + } + + // 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[] message) + { + if (!this.forSigning) + { + // not properly initilaized... deal with it + throw new InvalidOperationException("not initialised for signing"); + } + + BigInteger n = ((ECPrivateKeyParameters) this.key).Parameters.N; + int nBitLength = n.BitLength; + + BigInteger e = new BigInteger(1, message); + 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.Parameters, this.random)); + + tempPair = keyGen.GenerateKeyPair(); + + // BigInteger Vx = tempPair.getPublic().getW().getAffineX(); + ECPublicKeyParameters V = (ECPublicKeyParameters) tempPair.Public; // get temp's public key + BigInteger Vx = V.Q.X.ToBigInteger(); // get the point's x coordinate + + r = Vx.Add(e).Mod(n); + } + while (r.SignValue == 0); + + // generate s + BigInteger x = privKey.D; // private key value + BigInteger u = ((ECPrivateKeyParameters) tempPair.Private).D; // temp's private key value + s = u.Subtract(r.Multiply(x)).Mod(n); + + return new BigInteger[]{ r, s }; + } + + // 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 bool VerifySignature( + byte[] message, + BigInteger r, + BigInteger s) + { + if (this.forSigning) + { + // not properly initilaized... deal with it + throw new InvalidOperationException("not initialised for verifying"); + } + + ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key; + BigInteger n = pubKey.Parameters.N; + int nBitLength = n.BitLength; + + BigInteger e = new BigInteger(1, message); + 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(BigInteger.One) < 0 || r.CompareTo(n) >= 0) + { + return false; + } + + // TODO So why is this different from the spec? + // s in the range [0,n-1] NB: ECNR spec says 0 + if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0) + { + return false; + } + + // compute P = sG + rW + + ECPoint G = pubKey.Parameters.G; + ECPoint W = pubKey.Q; + // calculate P using Bouncy math + ECPoint P = ECAlgorithms.SumOfTwoMultiplies(G, s, W, r); + + if (P.IsInfinity) + return false; + + BigInteger x = P.X.ToBigInteger(); + BigInteger t = r.Subtract(x).Mod(n); + + return t.Equals(e); + } + } +} diff --git a/crypto/src/crypto/signers/GOST3410DigestSigner.cs b/crypto/src/crypto/signers/GOST3410DigestSigner.cs new file mode 100644 index 000000000..58aefa368 --- /dev/null +++ b/crypto/src/crypto/signers/GOST3410DigestSigner.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Gost3410DigestSigner + : ISigner + { + private readonly IDigest digest; + private readonly IDsa dsaSigner; + private bool forSigning; + + public Gost3410DigestSigner( + IDsa signer, + IDigest digest) + { + this.dsaSigner = signer; + this.digest = digest; + } + + public string AlgorithmName + { + get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + this.forSigning = forSigning; + + AsymmetricKeyParameter k; + if (parameters is ParametersWithRandom) + { + k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters; + } + else + { + k = (AsymmetricKeyParameter)parameters; + } + + if (forSigning && !k.IsPrivate) + { + throw new InvalidKeyException("Signing Requires Private Key."); + } + + if (!forSigning && k.IsPrivate) + { + throw new InvalidKeyException("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 BlockUpdate( + byte[] input, + int inOff, + int length) + { + digest.BlockUpdate(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 InvalidOperationException("GOST3410DigestSigner not initialised for signature generation."); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + try + { + BigInteger[] sig = dsaSigner.GenerateSignature(hash); + byte[] sigBytes = new byte[64]; + + // TODO Add methods to allow writing BigInteger to existing byte array? + byte[] r = sig[0].ToByteArrayUnsigned(); + byte[] s = sig[1].ToByteArrayUnsigned(); + s.CopyTo(sigBytes, 32 - s.Length); + r.CopyTo(sigBytes, 64 - r.Length); + return sigBytes; + } + catch (Exception e) + { + throw new SignatureException(e.Message, e); + } + } + + /// true if the internal state represents the signature described in the passed in array. + public bool VerifySignature( + byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("DSADigestSigner not initialised for verification"); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + BigInteger R, S; + try + { + R = new BigInteger(1, signature, 32, 32); + S = new BigInteger(1, signature, 0, 32); + } + catch (Exception e) + { + throw new SignatureException("error decoding signature bytes.", e); + } + + return dsaSigner.VerifySignature(hash, R, S); + } + + /// Reset the internal state + public void Reset() + { + digest.Reset(); + } + } +} diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs new file mode 100644 index 000000000..375eeb5cc --- /dev/null +++ b/crypto/src/crypto/signers/GOST3410Signer.cs @@ -0,0 +1,132 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * Gost R 34.10-94 Signature Algorithm + */ + public class Gost3410Signer + : IDsa + { + private Gost3410KeyParameters key; + private SecureRandom random; + + public string AlgorithmName + { + get { return "GOST3410"; } + } + + public void Init( + bool forSigning, + ICipherParameters parameters) + { + if (forSigning) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)parameters; + + this.random = rParam.Random; + parameters = rParam.Parameters; + } + else + { + this.random = new SecureRandom(); + } + + if (!(parameters is Gost3410PrivateKeyParameters)) + throw new InvalidKeyException("GOST3410 private key required for signing"); + + this.key = (Gost3410PrivateKeyParameters) parameters; + } + else + { + if (!(parameters is Gost3410PublicKeyParameters)) + throw new InvalidKeyException("GOST3410 public key required for signing"); + + this.key = (Gost3410PublicKeyParameters) parameters; + } + } + + /** + * 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 parameters = key.Parameters; + BigInteger k; + + do + { + k = new BigInteger(parameters.Q.BitLength, random); + } + while (k.CompareTo(parameters.Q) >= 0); + + BigInteger r = parameters.A.ModPow(k, parameters.P).Mod(parameters.Q); + + BigInteger s = k.Multiply(m). + Add(((Gost3410PrivateKeyParameters)key).X.Multiply(r)). + Mod(parameters.Q); + + 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 bool 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 parameters = key.Parameters; + + if (r.SignValue < 0 || parameters.Q.CompareTo(r) <= 0) + { + return false; + } + + if (s.SignValue < 0 || parameters.Q.CompareTo(s) <= 0) + { + return false; + } + + BigInteger v = m.ModPow(parameters.Q.Subtract(BigInteger.Two), parameters.Q); + + BigInteger z1 = s.Multiply(v).Mod(parameters.Q); + BigInteger z2 = (parameters.Q.Subtract(r)).Multiply(v).Mod(parameters.Q); + + z1 = parameters.A.ModPow(z1, parameters.P); + z2 = ((Gost3410PublicKeyParameters)key).Y.ModPow(z2, parameters.P); + + BigInteger u = z1.Multiply(z2).Mod(parameters.P).Mod(parameters.Q); + + return u.Equals(r); + } + } +} diff --git a/crypto/src/crypto/signers/GenericSigner.cs b/crypto/src/crypto/signers/GenericSigner.cs new file mode 100644 index 000000000..1a53eee2b --- /dev/null +++ b/crypto/src/crypto/signers/GenericSigner.cs @@ -0,0 +1,129 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class GenericSigner + : ISigner + { + private readonly IAsymmetricBlockCipher engine; + private readonly IDigest digest; + private bool forSigning; + + public GenericSigner( + IAsymmetricBlockCipher engine, + IDigest digest) + { + this.engine = engine; + this.digest = digest; + } + + public string AlgorithmName + { + get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; } + } + + /** + * initialise the signer for signing or verification. + * + * @param forSigning + * true if for signing, false otherwise + * @param parameters + * necessary parameters. + */ + public void Init( + bool forSigning, + ICipherParameters parameters) + { + this.forSigning = forSigning; + AsymmetricKeyParameter k; + + if (parameters is ParametersWithRandom) + { + k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters; + } + else + { + k = (AsymmetricKeyParameter)parameters; + } + + if (forSigning && !k.IsPrivate) + throw new InvalidKeyException("Signing requires private key."); + + if (!forSigning && k.IsPrivate) + throw new InvalidKeyException("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 BlockUpdate( + byte[] input, + int inOff, + int length) + { + digest.BlockUpdate(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 InvalidOperationException("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 bool VerifySignature( + byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("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) + { + return false; + } + } + + public void Reset() + { + digest.Reset(); + } + } +} diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs new file mode 100644 index 000000000..d4f6c5522 --- /dev/null +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs @@ -0,0 +1,617 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /// ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3). + ///

+ /// Note: the usual length for the salt is the length of the hash + /// function used in bytes.

+ ///
+ public class Iso9796d2PssSigner + : ISignerWithRecovery + { + /// + /// Return a reference to the recoveredMessage message. + /// + /// The full/partial recoveredMessage message. + /// + public byte[] GetRecoveredMessage() + { + return recoveredMessage; + } + + public const int TrailerImplicit = 0xBC; + public const int TrailerRipeMD160 = 0x31CC; + public const int TrailerRipeMD128 = 0x32CC; + public const int TrailerSha1 = 0x33CC; + public const int TrailerSha256 = 0x34CC; + public const int TrailerSha512 = 0x35CC; + public const int TrailerSha384 = 0x36CC; + public const int TrailerWhirlpool = 0x37CC; + + private static readonly IDictionary trailerMap = Platform.CreateHashtable(); + + static Iso9796d2PssSigner() + { + trailerMap.Add("RIPEMD128", TrailerRipeMD128); + trailerMap.Add("RIPEMD160", TrailerRipeMD160); + trailerMap.Add("SHA-1", TrailerSha1); + trailerMap.Add("SHA-256", TrailerSha256); + trailerMap.Add("SHA-384", TrailerSha384); + trailerMap.Add("SHA-512", TrailerSha512); + + trailerMap.Add("Whirlpool", TrailerWhirlpool); + } + + private IDigest digest; + private IAsymmetricBlockCipher 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 readonly int saltLength; + private bool 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. + /// + /// base cipher to use for signature creation/verification + /// digest to use. + /// length of salt in bytes. + /// whether or not the trailer is implicit or gives the hash. + public Iso9796d2PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + int saltLength, + bool isImplicit) + { + this.cipher = cipher; + this.digest = digest; + this.hLen = digest.GetDigestSize(); + this.saltLength = saltLength; + + if (isImplicit) + { + trailer = TrailerImplicit; + } + else + { + string digestAlg = digest.AlgorithmName; + if (!trailerMap.Contains(digestAlg)) + throw new ArgumentException("no valid trailer for digest"); + + trailer = (int)trailerMap[digestAlg]; + } + } + + /// Constructor for a signer with an explicit digest trailer. + /// + /// + /// cipher to use. + /// + /// digest to sign with. + /// + /// length of salt in bytes. + /// + public Iso9796d2PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + int saltLength) + : this(cipher, digest, saltLength, false) + { + } + + public string AlgorithmName + { + get { return digest.AlgorithmName + "with" + "ISO9796-2S2"; } + } + + /// Initialise the signer. + /// true if for signing, false if for verification. + /// 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. + /// + /// if wrong parameter type or a fixed + /// salt is passed in which is the wrong length. + /// + public virtual void Init( + bool forSigning, + ICipherParameters parameters) + { + RsaKeyParameters kParam; + if (parameters is ParametersWithRandom) + { + ParametersWithRandom p = (ParametersWithRandom) parameters; + + kParam = (RsaKeyParameters) p.Parameters; + + if (forSigning) + { + random = p.Random; + } + } + else if (parameters is ParametersWithSalt) + { + if (!forSigning) + throw new ArgumentException("ParametersWithSalt only valid for signing", "parameters"); + + ParametersWithSalt p = (ParametersWithSalt) parameters; + + kParam = (RsaKeyParameters) p.Parameters; + standardSalt = p.GetSalt(); + + if (standardSalt.Length != saltLength) + throw new ArgumentException("Fixed salt is of wrong length"); + } + else + { + kParam = (RsaKeyParameters) parameters; + + if (forSigning) + { + random = new SecureRandom(); + } + } + + cipher.Init(forSigning, kParam); + + keyBits = kParam.Modulus.BitLength; + + block = new byte[(keyBits + 7) / 8]; + + if (trailer == TrailerImplicit) + { + mBuf = new byte[block.Length - digest.GetDigestSize() - saltLength - 1 - 1]; + } + else + { + mBuf = new byte[block.Length - digest.GetDigestSize() - saltLength - 1 - 2]; + } + + Reset(); + } + + /// compare two byte arrays - constant time. + private bool IsSameAs(byte[] a, byte[] b) + { + if (messageLength != b.Length) + { + return false; + } + + bool isOkay = true; + + 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) + { + Array.Clear(block, 0, block.Length); + } + + public virtual void UpdateWithRecoveredMessage( + byte[] signature) + { + 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]; + + Array.Copy(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); + + string digestAlg = digest.AlgorithmName; + if (!trailerMap.Contains(digestAlg)) + throw new ArgumentException("unrecognised hash in signature"); + + if (sigTrail != (int)trailerMap[digestAlg]) + throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); + + 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; + + while (mStart < block.Length) + { + if (block[mStart++] == 0x01) + break; + } + + if (mStart >= block.Length) + { + ClearBlock(block); + } + + fullMessage = (mStart > 1); + + recoveredMessage = new byte[dbMask.Length - mStart - saltLength]; + + Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); + recoveredMessage.CopyTo(mBuf, 0); + + preSig = signature; + preBlock = block; + preMStart = mStart; + preTLength = tLength; + } + + /// update the internal digest with the byte b + public virtual void Update( + byte input) + { + if (preSig == null && messageLength < mBuf.Length) + { + mBuf[messageLength++] = input; + } + else + { + digest.Update(input); + } + } + + /// update the internal digest with the byte array in + public virtual void BlockUpdate( + byte[] input, + int inOff, + int length) + { + if (preSig == null) + { + while (length > 0 && messageLength < mBuf.Length) + { + this.Update(input[inOff]); + inOff++; + length--; + } + } + + if (length > 0) + { + digest.BlockUpdate(input, inOff, length); + } + } + + /// reset the internal state + public virtual 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() + { + int digSize = digest.GetDigestSize(); + byte[] m2Hash = new byte[digSize]; + digest.DoFinal(m2Hash, 0); + + byte[] C = new byte[8]; + LtoOSP(messageLength * 8, C); + + digest.BlockUpdate(C, 0, C.Length); + digest.BlockUpdate(mBuf, 0, messageLength); + digest.BlockUpdate(m2Hash, 0, m2Hash.Length); + + byte[] salt; + if (standardSalt != null) + { + salt = standardSalt; + } + else + { + salt = new byte[saltLength]; + random.NextBytes(salt); + } + + digest.BlockUpdate(salt, 0, salt.Length); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + int tLength = 2; + if (trailer == TrailerImplicit) + { + tLength = 1; + } + + int off = block.Length - messageLength - salt.Length - hLen - tLength - 1; + + block[off] = (byte) (0x01); + + Array.Copy(mBuf, 0, block, off + 1, messageLength); + Array.Copy(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]; + } + + Array.Copy(hash, 0, block, block.Length - hLen - tLength, hLen); + + if (trailer == TrailerImplicit) + { + block[block.Length - 1] = (byte)TrailerImplicit; + } + else + { + block[block.Length - 2] = (byte) ((uint)trailer >> 8); + block[block.Length - 1] = (byte) trailer; + } + + block[0] &= (byte) (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 virtual bool 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) + { + return false; + } + } + else + { + if (!Arrays.AreEqual(preSig, signature)) + { + throw new InvalidOperationException("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.BlockUpdate(C, 0, C.Length); + + if (recoveredMessage.Length != 0) + { + digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length); + } + + digest.BlockUpdate(m2Hash, 0, m2Hash.Length); + + // Update for the salt + digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + int off = block.Length - tLength - hash.Length; + + bool 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. + /// + /// true on full message recovery, false otherwise, or if not sure. + /// + public virtual bool HasFullMessage() + { + return fullMessage; + } + + /// int to octet string. + /// int to octet string. + private void ItoOSP( + int i, + byte[] sp) + { + sp[0] = (byte)((uint)i >> 24); + sp[1] = (byte)((uint)i >> 16); + sp[2] = (byte)((uint)i >> 8); + sp[3] = (byte)((uint)i >> 0); + } + + /// long to octet string. + private void LtoOSP(long l, byte[] sp) + { + sp[0] = (byte)((ulong)l >> 56); + sp[1] = (byte)((ulong)l >> 48); + sp[2] = (byte)((ulong)l >> 40); + sp[3] = (byte)((ulong)l >> 32); + sp[4] = (byte)((ulong)l >> 24); + sp[5] = (byte)((ulong)l >> 16); + sp[6] = (byte)((ulong)l >> 8); + sp[7] = (byte)((ulong)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(); + + do + { + ItoOSP(counter, C); + + digest.BlockUpdate(Z, zOff, zLen); + digest.BlockUpdate(C, 0, C.Length); + digest.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, mask, counter * hLen, hLen); + } + while (++counter < (length / hLen)); + + if ((counter * hLen) < length) + { + ItoOSP(counter, C); + + digest.BlockUpdate(Z, zOff, zLen); + digest.BlockUpdate(C, 0, C.Length); + digest.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, mask, counter * hLen, mask.Length - (counter * hLen)); + } + + return mask; + } + } +} diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs new file mode 100644 index 000000000..cfb8942e6 --- /dev/null +++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs @@ -0,0 +1,563 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /// ISO9796-2 - mechanism using a hash function with recovery (scheme 1) + public class Iso9796d2Signer : ISignerWithRecovery + { + /// + /// Return a reference to the recoveredMessage message. + /// + /// The full/partial recoveredMessage message. + /// + public byte[] GetRecoveredMessage() + { + return recoveredMessage; + } + + public const int TrailerImplicit = 0xBC; + public const int TrailerRipeMD160 = 0x31CC; + public const int TrailerRipeMD128 = 0x32CC; + public const int TrailerSha1 = 0x33CC; + public const int TrailerSha256 = 0x34CC; + public const int TrailerSha512 = 0x35CC; + public const int TrailerSha384 = 0x36CC; + public const int TrailerWhirlpool = 0x37CC; + + private static IDictionary trailerMap = Platform.CreateHashtable(); + + static Iso9796d2Signer() + { + trailerMap.Add("RIPEMD128", TrailerRipeMD128); + trailerMap.Add("RIPEMD160", TrailerRipeMD160); + + trailerMap.Add("SHA-1", TrailerSha1); + trailerMap.Add("SHA-256", TrailerSha256); + trailerMap.Add("SHA-384", TrailerSha384); + trailerMap.Add("SHA-512", TrailerSha512); + + trailerMap.Add("Whirlpool", TrailerWhirlpool); + } + + private IDigest digest; + private IAsymmetricBlockCipher cipher; + + private int trailer; + private int keyBits; + private byte[] block; + private byte[] mBuf; + private int messageLength; + private bool fullMessage; + private byte[] recoveredMessage; + + private byte[] preSig; + private byte[] preBlock; + + /// + /// Generate a signer for the with either implicit or explicit trailers + /// for ISO9796-2. + /// + /// base cipher to use for signature creation/verification + /// digest to use. + /// whether or not the trailer is implicit or gives the hash. + public Iso9796d2Signer( + IAsymmetricBlockCipher cipher, + IDigest digest, + bool isImplicit) + { + this.cipher = cipher; + this.digest = digest; + + if (isImplicit) + { + trailer = TrailerImplicit; + } + else + { + string digestName = digest.AlgorithmName; + + if (trailerMap.Contains(digestName)) + { + trailer = (int)trailerMap[digest.AlgorithmName]; + } + else + { + throw new System.ArgumentException("no valid trailer for digest"); + } + } + } + + /// Constructor for a signer with an explicit digest trailer. + /// + /// + /// cipher to use. + /// + /// digest to sign with. + /// + public Iso9796d2Signer(IAsymmetricBlockCipher cipher, IDigest digest) + : this(cipher, digest, false) + { + } + + public string AlgorithmName + { + get { return digest.AlgorithmName + "with" + "ISO9796-2S1"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + RsaKeyParameters kParam = (RsaKeyParameters) parameters; + + cipher.Init(forSigning, kParam); + + keyBits = kParam.Modulus.BitLength; + + block = new byte[(keyBits + 7) / 8]; + if (trailer == TrailerImplicit) + { + 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 bool IsSameAs(byte[] a, byte[] b) + { + int checkLen; + if (messageLength > mBuf.Length) + { + if (mBuf.Length > b.Length) + { + return false; + } + + checkLen = mBuf.Length; + } + else + { + if (messageLength != b.Length) + { + return false; + } + + checkLen = b.Length; + } + + bool isOkay = true; + + for (int i = 0; i != checkLen; i++) + { + if (a[i] != b[i]) + { + isOkay = false; + } + } + + return isOkay; + } + + /// clear possible sensitive data + private void ClearBlock( + byte[] block) + { + Array.Clear(block, 0, block.Length); + } + + public virtual void UpdateWithRecoveredMessage( + byte[] signature) + { + 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); + + string digestName = digest.AlgorithmName; + if (!trailerMap.Contains(digestName)) + throw new ArgumentException("unrecognised hash in signature"); + if (sigTrail != (int)trailerMap[digestName]) + throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); + + 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]; + Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); + } + else + { + fullMessage = false; + + recoveredMessage = new byte[off - mStart]; + Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); + } + + preSig = signature; + preBlock = block; + + digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length); + messageLength = recoveredMessage.Length; + recoveredMessage.CopyTo(mBuf, 0); + } + + /// update the internal digest with the byte b + public void Update( + byte input) + { + digest.Update(input); + + if (messageLength < mBuf.Length) + { + mBuf[messageLength] = input; + } + + messageLength++; + } + + /// update the internal digest with the byte array in + public void BlockUpdate( + byte[] input, + int inOff, + int length) + { + while (length > 0 && messageLength < mBuf.Length) + { + //for (int i = 0; i < length && (i + messageLength) < mBuf.Length; i++) + //{ + // mBuf[messageLength + i] = input[inOff + i]; + //} + this.Update(input[inOff]); + inOff++; + length--; + } + + digest.BlockUpdate(input, inOff, length); + messageLength += length; + } + + /// reset the internal state + public virtual 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 virtual byte[] GenerateSignature() + { + int digSize = digest.GetDigestSize(); + + int t = 0; + int delta = 0; + + if (trailer == TrailerImplicit) + { + t = 8; + delta = block.Length - digSize - 1; + digest.DoFinal(block, delta); + block[block.Length - 1] = (byte) TrailerImplicit; + } + else + { + t = 16; + delta = block.Length - digSize - 2; + digest.DoFinal(block, delta); + block[block.Length - 2] = (byte) ((uint)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 = (byte) (0x60); + + delta -= mR; + + Array.Copy(mBuf, 0, block, delta, mR); + } + else + { + header = (byte) (0x40); + delta -= messageLength; + + Array.Copy(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 virtual bool VerifySignature(byte[] signature) + { + byte[] block; + + if (preSig == null) + { + try + { + block = cipher.ProcessBlock(signature, 0, signature.Length); + } + catch (Exception) + { + return false; + } + } + else + { + if (!Arrays.AreEqual(preSig, signature)) + throw new InvalidOperationException("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); + + string digestName = digest.AlgorithmName; + if (!trailerMap.Contains(digestName)) + throw new ArgumentException("unrecognised hash in signature"); + if (sigTrail != (int)trailerMap[digestName]) + throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail); + + delta = 2; + } + + // + // find out how much padding we've got + // + int mStart = 0; + for (; 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.BlockUpdate(block, mStart, off - mStart); + digest.DoFinal(hash, 0); + + bool 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]; + Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length); + } + else + { + fullMessage = false; + + digest.DoFinal(hash, 0); + + bool 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]; + Array.Copy(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 bool ReturnFalse(byte[] block) + { + ClearBlock(mBuf); + ClearBlock(block); + + return false; + } + + /// + /// Return true if the full message was recoveredMessage. + /// + /// true on full message recovery, false otherwise. + /// + public virtual bool HasFullMessage() + { + return fullMessage; + } + } +} diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs new file mode 100644 index 000000000..6900224f3 --- /dev/null +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -0,0 +1,345 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /// RSA-PSS as described in Pkcs# 1 v 2.1. + ///

+ /// Note: the usual value for the salt length is the number of + /// bytes in the hash function.

+ ///
+ public class PssSigner + : ISigner + { + public const byte TrailerImplicit = (byte)0xBC; + + private readonly IDigest contentDigest1, contentDigest2; + private readonly IDigest mgfDigest; + private readonly IAsymmetricBlockCipher 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; + + public static PssSigner CreateRawSigner( + IAsymmetricBlockCipher cipher, + IDigest digest) + { + return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), TrailerImplicit); + } + + public static PssSigner CreateRawSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest, + IDigest mgfDigest, + int saltLen, + byte trailer) + { + return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, trailer); + } + + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest) + : this(cipher, digest, digest.GetDigestSize()) + { + } + + /// Basic constructor + /// the asymmetric cipher to use. + /// the digest to use. + /// the length of the salt to use (in bytes). + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + int saltLen) + : this(cipher, digest, saltLen, TrailerImplicit) + { + } + + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest, + IDigest mgfDigest, + int saltLen) + : this(cipher, contentDigest, mgfDigest, saltLen, TrailerImplicit) + { + } + + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + int saltLen, + byte trailer) + : this(cipher, digest, digest, saltLen, TrailerImplicit) + { + } + + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest, + IDigest mgfDigest, + int saltLen, + byte trailer) + : this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, trailer) + { + } + + private PssSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest1, + IDigest contentDigest2, + IDigest mgfDigest, + int saltLen, + byte trailer) + { + this.cipher = cipher; + this.contentDigest1 = contentDigest1; + this.contentDigest2 = contentDigest2; + this.mgfDigest = mgfDigest; + this.hLen = contentDigest2.GetDigestSize(); + this.mgfhLen = mgfDigest.GetDigestSize(); + this.sLen = saltLen; + this.salt = new byte[saltLen]; + this.mDash = new byte[8 + saltLen + hLen]; + this.trailer = trailer; + } + + public string AlgorithmName + { + get { return mgfDigest.AlgorithmName + "withRSAandMGF1"; } + } + + public virtual void Init( + bool forSigning, + ICipherParameters parameters) + { + if (parameters is ParametersWithRandom) + { + ParametersWithRandom p = (ParametersWithRandom) parameters; + + parameters = p.Parameters; + random = p.Random; + } + else + { + if (forSigning) + { + random = new SecureRandom(); + } + } + + cipher.Init(forSigning, parameters); + + RsaKeyParameters kParam; + if (parameters is RsaBlindingParameters) + { + kParam = ((RsaBlindingParameters) parameters).PublicKey; + } + else + { + kParam = (RsaKeyParameters) parameters; + } + + emBits = kParam.Modulus.BitLength - 1; + + if (emBits < (8 * hLen + 8 * sLen + 9)) + throw new ArgumentException("key too small for specified hash and salt lengths"); + + block = new byte[(emBits + 7) / 8]; + } + + /// clear possible sensitive data + private void ClearBlock( + byte[] block) + { + Array.Clear(block, 0, block.Length); + } + + /// update the internal digest with the byte b + public virtual void Update( + byte input) + { + contentDigest1.Update(input); + } + + /// update the internal digest with the byte array in + public virtual void BlockUpdate( + byte[] input, + int inOff, + int length) + { + contentDigest1.BlockUpdate(input, inOff, length); + } + + /// reset the internal state + public virtual void Reset() + { + contentDigest1.Reset(); + } + + /// Generate a signature for the message we've been loaded with using + /// the key we were initialised with. + /// + public virtual byte[] GenerateSignature() + { + contentDigest1.DoFinal(mDash, mDash.Length - hLen - sLen); + + if (sLen != 0) + { + random.NextBytes(salt); + salt.CopyTo(mDash, mDash.Length - sLen); + } + + byte[] h = new byte[hLen]; + + contentDigest2.BlockUpdate(mDash, 0, mDash.Length); + + contentDigest2.DoFinal(h, 0); + + block[block.Length - sLen - 1 - hLen - 1] = (byte) (0x01); + salt.CopyTo(block, block.Length - sLen - hLen - 1); + + 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] &= (byte) ((0xff >> ((block.Length * 8) - emBits))); + + h.CopyTo(block, block.Length - hLen - 1); + + 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 virtual bool VerifySignature( + byte[] signature) + { + contentDigest1.DoFinal(mDash, mDash.Length - hLen - sLen); + + byte[] b = cipher.ProcessBlock(signature, 0, signature.Length); + b.CopyTo(block, block.Length - b.Length); + + 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] &= (byte) ((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; + } + + Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen); + + contentDigest2.BlockUpdate(mDash, 0, mDash.Length); + contentDigest2.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)((uint) i >> 24); + sp[1] = (byte)((uint) i >> 16); + sp[2] = (byte)((uint) i >> 8); + sp[3] = (byte)((uint) 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.BlockUpdate(Z, zOff, zLen); + mgfDigest.BlockUpdate(C, 0, C.Length); + mgfDigest.DoFinal(hashBuf, 0); + + hashBuf.CopyTo(mask, counter * mgfhLen); + ++counter; + } + + if ((counter * mgfhLen) < length) + { + ItoOSP(counter, C); + + mgfDigest.BlockUpdate(Z, zOff, zLen); + mgfDigest.BlockUpdate(C, 0, C.Length); + mgfDigest.DoFinal(hashBuf, 0); + + Array.Copy(hashBuf, 0, mask, counter * mgfhLen, mask.Length - (counter * mgfhLen)); + } + + return mask; + } + } +} diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs new file mode 100644 index 000000000..f57bfc83d --- /dev/null +++ b/crypto/src/crypto/signers/RsaDigestSigner.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class RsaDigestSigner + : ISigner + { + private readonly IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine()); + private readonly AlgorithmIdentifier algId; + private readonly IDigest digest; + private bool forSigning; + + private static readonly IDictionary oidMap = Platform.CreateHashtable(); + + /// + /// Load oid table. + /// + static RsaDigestSigner() + { + oidMap["RIPEMD128"] = TeleTrusTObjectIdentifiers.RipeMD128; + oidMap["RIPEMD160"] = TeleTrusTObjectIdentifiers.RipeMD160; + oidMap["RIPEMD256"] = TeleTrusTObjectIdentifiers.RipeMD256; + + oidMap["SHA-1"] = X509ObjectIdentifiers.IdSha1; + oidMap["SHA-224"] = NistObjectIdentifiers.IdSha224; + oidMap["SHA-256"] = NistObjectIdentifiers.IdSha256; + oidMap["SHA-384"] = NistObjectIdentifiers.IdSha384; + oidMap["SHA-512"] = NistObjectIdentifiers.IdSha512; + + oidMap["MD2"] = PkcsObjectIdentifiers.MD2; + oidMap["MD4"] = PkcsObjectIdentifiers.MD4; + oidMap["MD5"] = PkcsObjectIdentifiers.MD5; + } + + public RsaDigestSigner( + IDigest digest) + { + this.digest = digest; + + string algName = digest.AlgorithmName; + if (algName.Equals("NULL")) + { + this.algId = null; + } + else + { + this.algId = new AlgorithmIdentifier( + (DerObjectIdentifier)oidMap[digest.AlgorithmName], DerNull.Instance); + } + } + + public string AlgorithmName + { + get { return digest.AlgorithmName + "withRSA"; } + } + + /** + * Initialise the signer for signing or verification. + * + * @param forSigning true if for signing, false otherwise + * @param param necessary parameters. + */ + public void Init( + bool forSigning, + ICipherParameters parameters) + { + this.forSigning = forSigning; + AsymmetricKeyParameter k; + + if (parameters is ParametersWithRandom) + { + k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters; + } + else + { + k = (AsymmetricKeyParameter)parameters; + } + + if (forSigning && !k.IsPrivate) + throw new InvalidKeyException("Signing requires private key."); + + if (!forSigning && k.IsPrivate) + throw new InvalidKeyException("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 BlockUpdate( + byte[] input, + int inOff, + int length) + { + digest.BlockUpdate(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 InvalidOperationException("RsaDigestSigner not initialised for signature generation."); + + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + byte[] data = DerEncode(hash); + return rsaEngine.ProcessBlock(data, 0, data.Length); + } + + /** + * return true if the internal state represents the signature described + * in the passed in array. + */ + public bool VerifySignature( + byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("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) + { + return false; + } + + if (sig.Length == expected.Length) + { + for (int i = 0; i < sig.Length; i++) + { + if (sig[i] != expected[i]) + { + return false; + } + } + } + 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; + + for (int i = 0; i < hash.Length; i++) + { + if (sig[sigOffset + i] != expected[expectedOffset + i]) // check hash + { + return false; + } + } + + for (int i = 0; i < sigOffset; i++) + { + if (sig[i] != expected[i]) // check header less NULL + { + return false; + } + } + } + else + { + return false; + } + + return true; + } + + public void Reset() + { + digest.Reset(); + } + + private byte[] DerEncode(byte[] hash) + { + if (algId == null) + { + // For raw RSA, the DigestInfo must be prepared externally + return hash; + } + + DigestInfo dInfo = new DigestInfo(algId, hash); + + return dInfo.GetDerEncoded(); + } + } +} diff --git a/crypto/src/crypto/tls/AlertDescription.cs b/crypto/src/crypto/tls/AlertDescription.cs new file mode 100644 index 000000000..e1229a4a3 --- /dev/null +++ b/crypto/src/crypto/tls/AlertDescription.cs @@ -0,0 +1,47 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 7.2 + /// + public enum AlertDescription : byte + { + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + decryption_failed = 21, + record_overflow = 22, + decompression_failure = 30, + handshake_failure = 40, + /* 41 is not defined, for historical reasons */ + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47, + unknown_ca = 48, + access_denied = 49, + decode_error = 50, + decrypt_error = 51, + export_restriction = 60, + protocol_version = 70, + insufficient_security = 71, + internal_error = 80, + user_canceled = 90, + no_renegotiation = 100, + + /* + * RFC 3546 + */ + unsupported_extension = 110, + certificate_unobtainable = 111, + unrecognized_name = 112, + bad_certificate_status_response = 113, + bad_certificate_hash_value = 114, + + /* + * RFC 4279 + */ + unknown_psk_identity = 115, + } +} diff --git a/crypto/src/crypto/tls/AlertLevel.cs b/crypto/src/crypto/tls/AlertLevel.cs new file mode 100644 index 000000000..afb04308b --- /dev/null +++ b/crypto/src/crypto/tls/AlertLevel.cs @@ -0,0 +1,11 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 7.2 + /// + public enum AlertLevel : byte + { + warning = 1, + fatal = 2, + } +} diff --git a/crypto/src/crypto/tls/AlwaysValidVerifyer.cs b/crypto/src/crypto/tls/AlwaysValidVerifyer.cs new file mode 100644 index 000000000..e26c6fc3f --- /dev/null +++ b/crypto/src/crypto/tls/AlwaysValidVerifyer.cs @@ -0,0 +1,24 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A certificate verifyer, that will always return true. + ///
+	/// DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
+	/// 
+ ///
+ [Obsolete("Perform certificate verification in TlsAuthentication implementation")] + public class AlwaysValidVerifyer + : ICertificateVerifyer + { + /// Return true. + public bool IsValid( + X509CertificateStructure[] certs) + { + return true; + } + } +} diff --git a/crypto/src/crypto/tls/ByteQueue.cs b/crypto/src/crypto/tls/ByteQueue.cs new file mode 100644 index 000000000..c3ce91402 --- /dev/null +++ b/crypto/src/crypto/tls/ByteQueue.cs @@ -0,0 +1,147 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A queue for bytes. + ///

+ /// This file could be more optimized. + ///

+ ///
+ public class ByteQueue + { + /// 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 const int DefaultCapacity = 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(DefaultCapacity) + { + } + + public ByteQueue(int capacity) + { + this.databuf = new byte[capacity]; + } + + /// Read data from the buffer. + /// The buffer where the read data will be copied to. + /// How many bytes to skip at the beginning of buf. + /// How many bytes to read at all. + /// How many bytes from our data to skip. + public void Read( + byte[] buf, + int offset, + int len, + int skip) + { + if ((available - skip) < len) + { + throw new TlsException("Not enough data to read"); + } + if ((buf.Length - offset) < len) + { + throw new TlsException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes"); + } + Array.Copy(databuf, skipped + skip, buf, offset, len); + } + + /// Add some data to our buffer. + /// A byte-array to read data from. + /// How many bytes to skip at the beginning of the array. + /// How many bytes to read from the array. + public void AddData( + byte[] data, + int offset, + int len) + { + if ((skipped + available + len) > databuf.Length) + { + int desiredSize = ByteQueue.NextTwoPow(available + len); + if (desiredSize > databuf.Length) + { + byte[] tmp = new byte[desiredSize]; + Array.Copy(databuf, skipped, tmp, 0, available); + databuf = tmp; + } + else + { + Array.Copy(databuf, skipped, databuf, 0, available); + } + skipped = 0; + } + + Array.Copy(data, offset, databuf, skipped + available, len); + available += len; + } + + /// Remove some bytes from our data from the beginning. + /// How many bytes to remove. + public void RemoveData( + int i) + { + if (i > available) + { + throw new TlsException("Cannot remove " + i + " bytes, only got " + available); + } + + /* + * Skip the data. + */ + available -= i; + skipped += i; + } + + 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; + } + + /// The number of bytes which are available in this buffer. + public int Available + { + get { return available; } + } + } +} diff --git a/crypto/src/crypto/tls/Certificate.cs b/crypto/src/crypto/tls/Certificate.cs new file mode 100644 index 000000000..e4df041e2 --- /dev/null +++ b/crypto/src/crypto/tls/Certificate.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * A representation for a certificate chain. + */ + public class Certificate + { + public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]); + + /** + * The certificates. + */ + internal X509CertificateStructure[] certs; + + /** + * Parse the ServerCertificate message. + * + * @param inStr The stream where to parse from. + * @return A Certificate object with the certs, the server has sended. + * @throws IOException If something goes wrong during parsing. + */ + internal static Certificate Parse( + Stream inStr) + { + int left = TlsUtilities.ReadUint24(inStr); + if (left == 0) + { + return EmptyChain; + } + IList tmp = Platform.CreateArrayList(); + while (left > 0) + { + int size = TlsUtilities.ReadUint24(inStr); + left -= 3 + size; + byte[] buf = new byte[size]; + TlsUtilities.ReadFully(buf, inStr); + MemoryStream bis = new MemoryStream(buf, false); + Asn1Object o = Asn1Object.FromStream(bis); + tmp.Add(X509CertificateStructure.GetInstance(o)); + if (bis.Position < bis.Length) + { + throw new ArgumentException("Sorry, there is garbage data left after the certificate"); + } + } + X509CertificateStructure[] certs = new X509CertificateStructure[tmp.Count]; + for (int i = 0; i < tmp.Count; ++i) + { + certs[i] = (X509CertificateStructure)tmp[i]; + } + return new Certificate(certs); + } + + /** + * Encodes version of the ClientCertificate message + * + * @param outStr stream to write the message to + * @throws IOException If something goes wrong + */ + internal void Encode( + Stream outStr) + { + IList encCerts = Platform.CreateArrayList(); + int totalSize = 0; + foreach (X509CertificateStructure cert in certs) + { + byte[] encCert = cert.GetEncoded(Asn1Encodable.Der); + encCerts.Add(encCert); + totalSize += encCert.Length + 3; + } + + TlsUtilities.WriteUint24(totalSize, outStr); + + foreach (byte[] encCert in encCerts) + { + TlsUtilities.WriteOpaque24(encCert, outStr); + } + } + + /** + * Private constructor from a cert array. + * + * @param certs The certs the chain should contain. + */ + public Certificate(X509CertificateStructure[] certs) + { + if (certs == null) + throw new ArgumentNullException("certs"); + + this.certs = certs; + } + + /// An array which contains the certs, this chain contains. + public X509CertificateStructure[] GetCerts() + { + return (X509CertificateStructure[]) certs.Clone(); + } + + public bool IsEmpty + { + get { return certs.Length == 0; } + } + } +} diff --git a/crypto/src/crypto/tls/CertificateRequest.cs b/crypto/src/crypto/tls/CertificateRequest.cs new file mode 100644 index 000000000..49d8ba6fb --- /dev/null +++ b/crypto/src/crypto/tls/CertificateRequest.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class CertificateRequest + { + private ClientCertificateType[] certificateTypes; + private IList certificateAuthorities; + + public CertificateRequest(ClientCertificateType[] certificateTypes, IList certificateAuthorities) + { + this.certificateTypes = certificateTypes; + this.certificateAuthorities = certificateAuthorities; + } + + public ClientCertificateType[] CertificateTypes + { + get { return certificateTypes; } + } + + /// A of X509Name + public IList CertificateAuthorities + { + get { return certificateAuthorities; } + } + } +} \ No newline at end of file diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs new file mode 100644 index 000000000..6e1f7a545 --- /dev/null +++ b/crypto/src/crypto/tls/CipherSuite.cs @@ -0,0 +1,136 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 A.5 + /// + public enum CipherSuite : int + { + TLS_NULL_WITH_NULL_NULL = 0x0000, + TLS_RSA_WITH_NULL_MD5 = 0x0001, + TLS_RSA_WITH_NULL_SHA = 0x0002, + TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003, + TLS_RSA_WITH_RC4_128_MD5 = 0x0004, + TLS_RSA_WITH_RC4_128_SHA = 0x0005, + TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006, + TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007, + TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008, + TLS_RSA_WITH_DES_CBC_SHA = 0x0009, + TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A, + TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B, + TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C, + TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D, + TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E, + TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F, + TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010, + TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011, + TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012, + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013, + TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014, + TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015, + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016, + TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017, + TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018, + TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019, + TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A, + TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B, + + /* + * RFC 3268 + */ + TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F, + TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030, + TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031, + TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033, + TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034, + TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035, + TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036, + TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039, + TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A, + + /* + * RFC 4279 + */ + TLS_PSK_WITH_RC4_128_SHA = 0x008A, + TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B, + TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, + TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D, + TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E, + TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091, + TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092, + TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094, + TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095, + + /* + * RFC 4492 + */ + TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005, + TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007, + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A, + TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B, + TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F, + TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010, + TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, + TLS_ECDH_anon_WITH_NULL_SHA = 0xC015, + TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016, + TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017, + TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, + TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019, + + /* + * RFC 5054 + */ + TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A, + TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B, + TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C, + TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D, + TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E, + TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F, + TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020, + TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021, + TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022, + + /* + * RFC 5289 + */ + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D, + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030, + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031, + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032, + + /* + * RFC 5746 + */ + TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF, + } +} diff --git a/crypto/src/crypto/tls/ClientCertificateType.cs b/crypto/src/crypto/tls/ClientCertificateType.cs new file mode 100644 index 000000000..58f5d4276 --- /dev/null +++ b/crypto/src/crypto/tls/ClientCertificateType.cs @@ -0,0 +1,20 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 7.4.4 + /// + public enum ClientCertificateType : byte + { + rsa_sign = 1, + dss_sign = 2, + rsa_fixed_dh = 3, + dss_fixed_dh = 4, + + /* + * RFC 4492 5.5 + */ + ecdsa_sign = 64, + rsa_fixed_ecdh = 65, + ecdsa_fixed_ecdh = 66, + } +} \ No newline at end of file diff --git a/crypto/src/crypto/tls/CombinedHash.cs b/crypto/src/crypto/tls/CombinedHash.cs new file mode 100644 index 000000000..59ad87a7b --- /dev/null +++ b/crypto/src/crypto/tls/CombinedHash.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// A combined hash, which implements md5(m) || sha1(m). + internal class CombinedHash + : IDigest + { + private readonly MD5Digest md5; + private readonly Sha1Digest sha1; + + internal CombinedHash() + { + this.md5 = new MD5Digest(); + this.sha1 = new Sha1Digest(); + } + + internal CombinedHash(CombinedHash t) + { + this.md5 = new MD5Digest(t.md5); + this.sha1 = new Sha1Digest(t.sha1); + } + + /// + public string AlgorithmName + { + get + { + return md5.AlgorithmName + " and " + sha1.AlgorithmName + " for TLS 1.0"; + } + } + + /// + public int GetByteLength() + { + return System.Math.Max(md5.GetByteLength(), sha1.GetByteLength()); + } + + /// + public int GetDigestSize() + { + return md5.GetDigestSize() + sha1.GetDigestSize(); + } + + /// + public void Update( + byte input) + { + md5.Update(input); + sha1.Update(input); + } + + /// + public void BlockUpdate( + byte[] input, + int inOff, + int len) + { + md5.BlockUpdate(input, inOff, len); + sha1.BlockUpdate(input, inOff, len); + } + + /// + public int DoFinal( + byte[] output, + int outOff) + { + int i1 = md5.DoFinal(output, outOff); + int i2 = sha1.DoFinal(output, outOff + i1); + return i1 + i2; + } + + /// + public void Reset() + { + md5.Reset(); + sha1.Reset(); + } + } +} diff --git a/crypto/src/crypto/tls/CompressionMethod.cs b/crypto/src/crypto/tls/CompressionMethod.cs new file mode 100644 index 000000000..4a127a63e --- /dev/null +++ b/crypto/src/crypto/tls/CompressionMethod.cs @@ -0,0 +1,20 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 6.1 + /// + public enum CompressionMethod : byte + { + NULL = 0, + + /* + * RFC 3749 2 + */ + DEFLATE = 1 + + /* + * Values from 224 decimal (0xE0) through 255 decimal (0xFF) + * inclusive are reserved for private use. + */ + } +} diff --git a/crypto/src/crypto/tls/ContentType.cs b/crypto/src/crypto/tls/ContentType.cs new file mode 100644 index 000000000..a664e3a38 --- /dev/null +++ b/crypto/src/crypto/tls/ContentType.cs @@ -0,0 +1,13 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 6.2.1 + /// + public enum ContentType : byte + { + change_cipher_spec = 20, + alert = 21, + handshake = 22, + application_data = 23, + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs new file mode 100644 index 000000000..130f4c589 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs @@ -0,0 +1,76 @@ +using System; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class DefaultTlsAgreementCredentials + : TlsAgreementCredentials + { + protected Certificate clientCert; + protected AsymmetricKeyParameter clientPrivateKey; + + protected IBasicAgreement basicAgreement; + protected bool truncateAgreement; + + public DefaultTlsAgreementCredentials(Certificate clientCertificate, AsymmetricKeyParameter clientPrivateKey) + { + if (clientCertificate == null) + { + throw new ArgumentNullException("clientCertificate"); + } + if (clientCertificate.certs.Length == 0) + { + throw new ArgumentException("cannot be empty", "clientCertificate"); + } + if (clientPrivateKey == null) + { + throw new ArgumentNullException("clientPrivateKey"); + } + if (!clientPrivateKey.IsPrivate) + { + throw new ArgumentException("must be private", "clientPrivateKey"); + } + + if (clientPrivateKey is DHPrivateKeyParameters) + { + basicAgreement = new DHBasicAgreement(); + truncateAgreement = true; + } + else if (clientPrivateKey is ECPrivateKeyParameters) + { + basicAgreement = new ECDHBasicAgreement(); + truncateAgreement = false; + } + else + { + throw new ArgumentException("type not supported: " + + clientPrivateKey.GetType().FullName, "clientPrivateKey"); + } + + this.clientCert = clientCertificate; + this.clientPrivateKey = clientPrivateKey; + } + + public virtual Certificate Certificate + { + get { return clientCert; } + } + + public virtual byte[] GenerateAgreement(AsymmetricKeyParameter serverPublicKey) + { + basicAgreement.Init(clientPrivateKey); + BigInteger agreementValue = basicAgreement.CalculateAgreement(serverPublicKey); + + if (truncateAgreement) + { + return BigIntegers.AsUnsignedByteArray(agreementValue); + } + + return BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue); + } + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs new file mode 100644 index 000000000..75ae311e1 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class DefaultTlsCipherFactory + : TlsCipherFactory + { + public virtual TlsCipher CreateCipher(TlsClientContext context, + EncryptionAlgorithm encryptionAlgorithm, DigestAlgorithm digestAlgorithm) + { + switch (encryptionAlgorithm) + { + case EncryptionAlgorithm.cls_3DES_EDE_CBC: + return CreateDesEdeCipher(context, 24, digestAlgorithm); + case EncryptionAlgorithm.AES_128_CBC: + return CreateAesCipher(context, 16, digestAlgorithm); + case EncryptionAlgorithm.AES_256_CBC: + return CreateAesCipher(context, 32, digestAlgorithm); + case EncryptionAlgorithm.RC4_128: + return CreateRC4Cipher(context, 16, digestAlgorithm); + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + /// + protected virtual TlsCipher CreateRC4Cipher(TlsClientContext context, int cipherKeySize, DigestAlgorithm digestAlgorithm) + { + return new TlsStreamCipher(context, CreateRC4StreamCipher(), CreateRC4StreamCipher(), CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize); + } + + /// + protected virtual TlsCipher CreateAesCipher(TlsClientContext context, int cipherKeySize, + DigestAlgorithm digestAlgorithm) + { + return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(), + CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize); + } + + /// + protected virtual TlsCipher CreateDesEdeCipher(TlsClientContext context, int cipherKeySize, + DigestAlgorithm digestAlgorithm) + { + return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(), + CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize); + } + + protected virtual IStreamCipher CreateRC4StreamCipher() + { + return new RC4Engine(); + } + + protected virtual IBlockCipher CreateAesBlockCipher() + { + return new CbcBlockCipher(new AesFastEngine()); + } + + protected virtual IBlockCipher CreateDesEdeBlockCipher() + { + return new CbcBlockCipher(new DesEdeEngine()); + } + + /// + protected virtual IDigest CreateDigest(DigestAlgorithm digestAlgorithm) + { + switch (digestAlgorithm) + { + case DigestAlgorithm.MD5: + return new MD5Digest(); + case DigestAlgorithm.SHA: + return new Sha1Digest(); + case DigestAlgorithm.SHA256: + return new Sha256Digest(); + case DigestAlgorithm.SHA384: + return new Sha384Digest(); + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs new file mode 100644 index 000000000..9f30a33f4 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsClient.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class DefaultTlsClient + : TlsClient + { + protected TlsCipherFactory cipherFactory; + + protected TlsClientContext context; + + protected CompressionMethod selectedCompressionMethod; + protected CipherSuite selectedCipherSuite; + + public DefaultTlsClient() + : this(new DefaultTlsCipherFactory()) + { + } + + public DefaultTlsClient(TlsCipherFactory cipherFactory) + { + this.cipherFactory = cipherFactory; + } + + public virtual void Init(TlsClientContext context) + { + this.context = context; + } + + public virtual CipherSuite[] GetCipherSuites() + { + return new CipherSuite[] { + CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_RSA_WITH_RC4_128_SHA, + }; + } + + public virtual CompressionMethod[] GetCompressionMethods() + { + /* + * To offer DEFLATE compression, override this method: + * return new CompressionMethod[] { CompressionMethod.DEFLATE, CompressionMethod.NULL }; + */ + + return new CompressionMethod[] { CompressionMethod.NULL }; + } + + public virtual IDictionary GetClientExtensions() + { + return null; + } + + public virtual void NotifySessionID(byte[] sessionID) + { + // Currently ignored + } + + public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite) + { + this.selectedCipherSuite = selectedCipherSuite; + } + + public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod) + { + this.selectedCompressionMethod = selectedCompressionMethod; + } + + public virtual void NotifySecureRenegotiation(bool secureRenegotiation) + { + if (!secureRenegotiation) + { + /* + * RFC 5746 3.4. + * If the extension is not present, the server does not support + * secure renegotiation; set secure_renegotiation flag to FALSE. + * In this case, some clients may want to terminate the handshake + * instead of continuing; see Section 4.1 for discussion. + */ +// throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + } + + public virtual void ProcessServerExtensions(IDictionary serverExtensions) + { + } + + public virtual TlsKeyExchange GetKeyExchange() + { + 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_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + return CreateRsaKeyExchange(); + + 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_256_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_256_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_256_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_256_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_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); + + 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_ECDHE_ECDSA_WITH_RC4_128_SHA: + return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_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_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); + + 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_ECDHE_RSA_WITH_RC4_128_SHA: + return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 abstract TlsAuthentication GetAuthentication(); + + public virtual TlsCompression GetCompression() + { + switch (selectedCompressionMethod) + { + case CompressionMethod.NULL: + return new TlsNullCompression(); + + case CompressionMethod.DEFLATE: + return new TlsDeflateCompression(); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsCipher GetCipher() + { + switch (selectedCipherSuite) + { + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + 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_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, DigestAlgorithm.SHA); + + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.RC4_128, DigestAlgorithm.SHA); + + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + 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_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA); + + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + 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_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsKeyExchange CreateDHKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsDHKeyExchange(context, keyExchange); + } + + protected virtual TlsKeyExchange CreateDheKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsDheKeyExchange(context, keyExchange); + } + + protected virtual TlsKeyExchange CreateECDHKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsECDHKeyExchange(context, keyExchange); + } + + protected virtual TlsKeyExchange CreateECDheKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsECDheKeyExchange(context, keyExchange); + } + + protected virtual TlsKeyExchange CreateRsaKeyExchange() + { + return new TlsRsaKeyExchange(context); + } + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs new file mode 100644 index 000000000..86c9d1a18 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs @@ -0,0 +1,76 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class DefaultTlsSignerCredentials + : TlsSignerCredentials + { + protected TlsClientContext context; + protected Certificate clientCert; + protected AsymmetricKeyParameter clientPrivateKey; + + protected TlsSigner clientSigner; + + public DefaultTlsSignerCredentials(TlsClientContext context, + Certificate clientCertificate, AsymmetricKeyParameter clientPrivateKey) + { + if (clientCertificate == null) + { + throw new ArgumentNullException("clientCertificate"); + } + if (clientCertificate.certs.Length == 0) + { + throw new ArgumentException("cannot be empty", "clientCertificate"); + } + if (clientPrivateKey == null) + { + throw new ArgumentNullException("clientPrivateKey"); + } + if (!clientPrivateKey.IsPrivate) + { + throw new ArgumentException("must be private", "clientPrivateKey"); + } + + if (clientPrivateKey is RsaKeyParameters) + { + clientSigner = new TlsRsaSigner(); + } + else if (clientPrivateKey is DsaPrivateKeyParameters) + { + clientSigner = new TlsDssSigner(); + } + else if (clientPrivateKey is ECPrivateKeyParameters) + { + clientSigner = new TlsECDsaSigner(); + } + else + { + throw new ArgumentException("type not supported: " + + clientPrivateKey.GetType().FullName, "clientPrivateKey"); + } + + this.context = context; + this.clientCert = clientCertificate; + this.clientPrivateKey = clientPrivateKey; + } + + public virtual Certificate Certificate + { + get { return clientCert; } + } + + public virtual byte[] GenerateCertificateSignature(byte[] md5andsha1) + { + try + { + return clientSigner.GenerateRawSignature(context.SecureRandom, clientPrivateKey, md5andsha1); + } + catch (CryptoException) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + } +} diff --git a/crypto/src/crypto/tls/DigestAlgorithm.cs b/crypto/src/crypto/tls/DigestAlgorithm.cs new file mode 100644 index 000000000..cede6b7f8 --- /dev/null +++ b/crypto/src/crypto/tls/DigestAlgorithm.cs @@ -0,0 +1,21 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public enum DigestAlgorithm + { + /* + * Note that the values here are implementation-specific and arbitrary. + * It is recommended not to depend on the particular values (e.g. serialization). + */ + NULL, + MD5, + SHA, + + /* + * RFC 5289 + */ + SHA256, + SHA384, + } +} diff --git a/crypto/src/crypto/tls/ECCurveType.cs b/crypto/src/crypto/tls/ECCurveType.cs new file mode 100644 index 000000000..15d5d7b42 --- /dev/null +++ b/crypto/src/crypto/tls/ECCurveType.cs @@ -0,0 +1,29 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 4492 5.4 + /// + public enum ECCurveType : byte + { + /** + * Indicates the elliptic curve domain parameters are conveyed verbosely, and the + * underlying finite field is a prime field. + */ + explicit_prime = 1, + + /** + * Indicates the elliptic curve domain parameters are conveyed verbosely, and the + * underlying finite field is a characteristic-2 field. + */ + explicit_char2 = 2, + + /** + * Indicates that a named curve is used. This option SHOULD be used when applicable. + */ + named_curve = 3, + + /* + * Values 248 through 255 are reserved for private use. + */ + } +} diff --git a/crypto/src/crypto/tls/ECPointFormat.cs b/crypto/src/crypto/tls/ECPointFormat.cs new file mode 100644 index 000000000..4e0dd0067 --- /dev/null +++ b/crypto/src/crypto/tls/ECPointFormat.cs @@ -0,0 +1,16 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 4492 5.1.2 + /// + public enum ECPointFormat : byte + { + uncompressed = 0, + ansiX962_compressed_prime = 1, + ansiX962_compressed_char2 = 2, + + /* + * reserved (248..255) + */ + } +} diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs new file mode 100644 index 000000000..79d3b63b5 --- /dev/null +++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs @@ -0,0 +1,32 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public enum EncryptionAlgorithm + { + /* + * Note that the values here are implementation-specific and arbitrary. + * It is recommended not to depend on the particular values (e.g. serialization). + */ + NULL, + RC4_40, + RC4_128, + RC2_CBC_40, + IDEA_CBC, + DES40_CBC, + DES_CBC, + cls_3DES_EDE_CBC, + + /* + * RFC 3268 + */ + AES_128_CBC, + AES_256_CBC, + + /* + * RFC 5289 + */ + AES_128_GCM, + AES_256_GCM, + } +} diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs new file mode 100644 index 000000000..f00e34e3f --- /dev/null +++ b/crypto/src/crypto/tls/ExtensionType.cs @@ -0,0 +1,31 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 4366 2.3 + /// + public enum ExtensionType : int + { + server_name = 0, + max_fragment_length = 1, + client_certificate_url = 2, + trusted_ca_keys = 3, + truncated_hmac = 4, + status_request = 5, + + /* + * RFC 4492 + */ + elliptic_curves = 10, + ec_point_formats = 11, + + /* + * RFC 5054 2.8.1 + */ + srp = 12, + + /* + * RFC 5746 6 + */ + renegotiation_info = 0xff01, + } +} diff --git a/crypto/src/crypto/tls/HandshakeType.cs b/crypto/src/crypto/tls/HandshakeType.cs new file mode 100644 index 000000000..deedb1f84 --- /dev/null +++ b/crypto/src/crypto/tls/HandshakeType.cs @@ -0,0 +1,19 @@ +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 2246 7.4 + /// + public enum HandshakeType : byte + { + hello_request = 0, + client_hello = 1, + server_hello = 2, + certificate = 11, + server_key_exchange = 12, + certificate_request = 13, + server_hello_done = 14, + certificate_verify = 15, + client_key_exchange = 16, + finished = 20, + } +} diff --git a/crypto/src/crypto/tls/ICertificateVerifyer.cs b/crypto/src/crypto/tls/ICertificateVerifyer.cs new file mode 100644 index 000000000..df5ea51d7 --- /dev/null +++ b/crypto/src/crypto/tls/ICertificateVerifyer.cs @@ -0,0 +1,18 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace 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. + /// + [Obsolete("Perform certificate verification in TlsAuthentication implementation")] + public interface ICertificateVerifyer + { + /// The certs, which are part of the chain. + /// True, if the chain is accepted, false otherwise + bool IsValid(X509CertificateStructure[] certs); + } +} diff --git a/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs b/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs new file mode 100644 index 000000000..3fdbeb2a6 --- /dev/null +++ b/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs @@ -0,0 +1,36 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public enum KeyExchangeAlgorithm + { + /* + * Note that the values here are implementation-specific and arbitrary. + * It is recommended not to depend on the particular values (e.g. serialization). + */ + NULL, + RSA, + RSA_EXPORT, + DHE_DSS, + DHE_DSS_EXPORT, + DHE_RSA, + DHE_RSA_EXPORT, + DH_DSS, + DH_DSS_EXPORT, + DH_RSA, + DH_RSA_EXPORT, + DH_anon, + DH_anon_export, + PSK, + DHE_PSK, + RSA_PSK, + ECDH_ECDSA, + ECDHE_ECDSA, + ECDH_RSA, + ECDHE_RSA, + ECDH_anon, + SRP, + SRP_DSS, + SRP_RSA, + } +} diff --git a/crypto/src/crypto/tls/LegacyTlsAuthentication.cs b/crypto/src/crypto/tls/LegacyTlsAuthentication.cs new file mode 100644 index 000000000..395f94208 --- /dev/null +++ b/crypto/src/crypto/tls/LegacyTlsAuthentication.cs @@ -0,0 +1,30 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication. + /// + [Obsolete] + public class LegacyTlsAuthentication + : TlsAuthentication + { + protected ICertificateVerifyer verifyer; + + public LegacyTlsAuthentication(ICertificateVerifyer verifyer) + { + this.verifyer = verifyer; + } + + public virtual void NotifyServerCertificate(Certificate serverCertificate) + { + if (!this.verifyer.IsValid(serverCertificate.GetCerts())) + throw new TlsFatalAlert(AlertDescription.user_canceled); + } + + public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) + { + return null; + } + } +} diff --git a/crypto/src/crypto/tls/LegacyTlsClient.cs b/crypto/src/crypto/tls/LegacyTlsClient.cs new file mode 100644 index 000000000..fbb9a732e --- /dev/null +++ b/crypto/src/crypto/tls/LegacyTlsClient.cs @@ -0,0 +1,26 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A temporary class to use LegacyTlsAuthentication + /// + [Obsolete] + public class LegacyTlsClient + : DefaultTlsClient + { + [Obsolete] + protected ICertificateVerifyer verifyer; + + [Obsolete] + public LegacyTlsClient(ICertificateVerifyer verifyer) + { + this.verifyer = verifyer; + } + + public override TlsAuthentication GetAuthentication() + { + return new LegacyTlsAuthentication(verifyer); + } + } +} \ No newline at end of file diff --git a/crypto/src/crypto/tls/NamedCurve.cs b/crypto/src/crypto/tls/NamedCurve.cs new file mode 100644 index 000000000..c8ee189aa --- /dev/null +++ b/crypto/src/crypto/tls/NamedCurve.cs @@ -0,0 +1,72 @@ +using System; + +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// RFC 4492 5.1.1 + /// 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 enum NamedCurve : int + { + sect163k1 = 1, + sect163r1 = 2, + sect163r2 = 3, + sect193r1 = 4, + sect193r2 = 5, + sect233k1 = 6, + sect233r1 = 7, + sect239k1 = 8, + sect283k1 = 9, + sect283r1 = 10, + sect409k1 = 11, + sect409r1 = 12, + sect571k1 = 13, + sect571r1 = 14, + secp160k1 = 15, + secp160r1 = 16, + secp160r2 = 17, + secp192k1 = 18, + secp192r1 = 19, + secp224k1 = 20, + secp224r1 = 21, + secp256k1 = 22, + secp256r1 = 23, + secp384r1 = 24, + secp521r1 = 25, + + /* + * reserved (0xFE00..0xFEFF) + */ + + arbitrary_explicit_prime_curves = 0xFF01, + arbitrary_explicit_char2_curves = 0xFF02, + } + + internal class NamedCurveHelper + { + internal static ECDomainParameters GetECParameters(NamedCurve namedCurve) + { + if (!Enum.IsDefined(typeof(NamedCurve), namedCurve)) + return null; + + string curveName = namedCurve.ToString(); + + // Lazily created the first time a particular curve is accessed + X9ECParameters ecP = SecNamedCurves.GetByName(curveName); + + if (ecP == null) + return null; + + // It's a bit inefficient to do this conversion every time + return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed()); + } + } +} diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs new file mode 100644 index 000000000..9db7d7d90 --- /dev/null +++ b/crypto/src/crypto/tls/PskTlsClient.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class PskTlsClient + :TlsClient + { + protected TlsCipherFactory cipherFactory; + protected TlsPskIdentity pskIdentity; + + protected TlsClientContext context; + + protected CompressionMethod selectedCompressionMethod; + protected CipherSuite selectedCipherSuite; + + public PskTlsClient(TlsPskIdentity pskIdentity) + : this(new DefaultTlsCipherFactory(), pskIdentity) + { + } + + public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity) + { + this.cipherFactory = cipherFactory; + this.pskIdentity = pskIdentity; + } + + public virtual void Init(TlsClientContext context) + { + this.context = context; + } + + public virtual CipherSuite[] GetCipherSuites() + { + return new CipherSuite[] { + CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA, + CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA, + CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_PSK_WITH_RC4_128_SHA, + }; + } + + public virtual IDictionary GetClientExtensions() + { + return null; + } + + public virtual CompressionMethod[] GetCompressionMethods() + { + return new CompressionMethod[] { CompressionMethod.NULL }; + } + + public virtual void NotifySessionID(byte[] sessionID) + { + // Currently ignored + } + + public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite) + { + this.selectedCipherSuite = selectedCipherSuite; + } + + public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod) + { + this.selectedCompressionMethod = selectedCompressionMethod; + } + + public virtual void NotifySecureRenegotiation(bool secureRenegotiation) + { + if (!secureRenegotiation) + { + /* + * RFC 5746 3.4. If the extension is not present, the server does not support + * secure renegotiation; set secure_renegotiation flag to FALSE. In this case, + * some clients may want to terminate the handshake instead of continuing; see + * Section 4.1 for discussion. + */ +// throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + } + + public virtual void ProcessServerExtensions(IDictionary serverExtensions) + { + } + + public virtual TlsKeyExchange GetKeyExchange() + { + switch (selectedCipherSuite) + { + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + 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_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); + + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 abstract TlsAuthentication GetAuthentication(); + + public virtual TlsCompression GetCompression() + { + switch (selectedCompressionMethod) + { + case CompressionMethod.NULL: + return new TlsNullCompression(); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsCipher GetCipher() + { + switch (selectedCipherSuite) + { + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, + DigestAlgorithm.SHA); + + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, + DigestAlgorithm.SHA); + + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, + DigestAlgorithm.SHA); + + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + return cipherFactory.CreateCipher(context, EncryptionAlgorithm.RC4_128, + DigestAlgorithm.SHA); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsKeyExchange CreatePskKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsPskKeyExchange(context, keyExchange, pskIdentity); + } + } +} diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs new file mode 100644 index 000000000..4a5cdc1c9 --- /dev/null +++ b/crypto/src/crypto/tls/RecordStream.cs @@ -0,0 +1,166 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// An implementation of the TLS 1.0 record layer. + internal class RecordStream + { + private TlsProtocolHandler handler; + private Stream inStr; + private Stream outStr; + private CombinedHash hash; + private TlsCompression readCompression = null; + private TlsCompression writeCompression = null; + private TlsCipher readCipher = null; + private TlsCipher writeCipher = null; + private MemoryStream buffer = new MemoryStream(); + + internal RecordStream( + TlsProtocolHandler handler, + Stream inStr, + Stream outStr) + { + this.handler = handler; + this.inStr = inStr; + this.outStr = outStr; + this.hash = new CombinedHash(); + this.readCompression = new TlsNullCompression(); + this.writeCompression = this.readCompression; + this.readCipher = new TlsNullCipher(); + this.writeCipher = this.readCipher; + } + + internal void ClientCipherSpecDecided(TlsCompression tlsCompression, TlsCipher tlsCipher) + { + this.writeCompression = tlsCompression; + this.writeCipher = tlsCipher; + } + + internal void ServerClientSpecReceived() + { + this.readCompression = this.writeCompression; + this.readCipher = this.writeCipher; + } + + public void ReadData() + { + ContentType type = (ContentType)TlsUtilities.ReadUint8(inStr); + TlsUtilities.CheckVersion(inStr); + int size = TlsUtilities.ReadUint16(inStr); + byte[] buf = DecodeAndVerify(type, inStr, size); + handler.ProcessData(type, buf, 0, buf.Length); + } + + internal byte[] DecodeAndVerify( + ContentType type, + Stream inStr, + int len) + { + byte[] buf = new byte[len]; + TlsUtilities.ReadFully(buf, inStr); + byte[] decoded = readCipher.DecodeCiphertext(type, buf, 0, buf.Length); + + Stream cOut = readCompression.Decompress(buffer); + + if (cOut == buffer) + { + return decoded; + } + + cOut.Write(decoded, 0, decoded.Length); + cOut.Flush(); + byte[] contents = buffer.ToArray(); + buffer.SetLength(0); + return contents; + } + + internal void WriteMessage( + ContentType type, + byte[] message, + int offset, + int len) + { + if (type == ContentType.handshake) + { + UpdateHandshakeData(message, offset, len); + } + + Stream cOut = writeCompression.Compress(buffer); + + byte[] ciphertext; + if (cOut == buffer) + { + ciphertext = writeCipher.EncodePlaintext(type, message, offset, len); + } + else + { + cOut.Write(message, offset, len); + cOut.Flush(); + ciphertext = writeCipher.EncodePlaintext(type, buffer.GetBuffer(), 0, (int)buffer.Position); + buffer.SetLength(0); + } + + byte[] writeMessage = new byte[ciphertext.Length + 5]; + TlsUtilities.WriteUint8((byte)type, writeMessage, 0); + TlsUtilities.WriteVersion(writeMessage, 1); + TlsUtilities.WriteUint16(ciphertext.Length, writeMessage, 3); + Array.Copy(ciphertext, 0, writeMessage, 5, ciphertext.Length); + outStr.Write(writeMessage, 0, writeMessage.Length); + outStr.Flush(); + } + + internal void UpdateHandshakeData( + byte[] message, + int offset, + int len) + { + hash.BlockUpdate(message, offset, len); + } + + internal byte[] GetCurrentHash() + { + return DoFinal(new CombinedHash(hash)); + } + + internal void Close() + { + IOException e = null; + try + { + inStr.Close(); + } + catch (IOException ex) + { + e = ex; + } + + try + { + // NB: This is harmless if outStr == inStr + outStr.Close(); + } + catch (IOException ex) + { + e = ex; + } + + if (e != null) + { + throw e; + } + } + + internal void Flush() + { + outStr.Flush(); + } + + private static byte[] DoFinal(CombinedHash ch) + { + byte[] bs = new byte[ch.GetDigestSize()]; + ch.DoFinal(bs, 0); + return bs; + } + } +} diff --git a/crypto/src/crypto/tls/SecurityParameters.cs b/crypto/src/crypto/tls/SecurityParameters.cs new file mode 100644 index 000000000..9ed3969eb --- /dev/null +++ b/crypto/src/crypto/tls/SecurityParameters.cs @@ -0,0 +1,26 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class SecurityParameters + { + internal byte[] clientRandom = null; + internal byte[] serverRandom = null; + internal byte[] masterSecret = null; + + public byte[] ClientRandom + { + get { return clientRandom; } + } + + public byte[] ServerRandom + { + get { return serverRandom; } + } + + public byte[] MasterSecret + { + get { return masterSecret; } + } + } +} diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs new file mode 100644 index 000000000..6c2638bb3 --- /dev/null +++ b/crypto/src/crypto/tls/SrpTlsClient.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class SrpTlsClient + : TlsClient + { + protected TlsCipherFactory cipherFactory; + protected byte[] identity; + protected byte[] password; + + protected TlsClientContext context; + + protected CompressionMethod selectedCompressionMethod; + protected CipherSuite selectedCipherSuite; + + public SrpTlsClient(byte[] identity, byte[] password) + : this(new DefaultTlsCipherFactory(), identity, password) + { + } + + public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password) + { + this.cipherFactory = cipherFactory; + this.identity = Arrays.Clone(identity); + this.password = Arrays.Clone(password); + } + + public virtual void Init(TlsClientContext context) + { + this.context = context; + } + + public virtual CipherSuite[] GetCipherSuites() + { + return new CipherSuite[] { + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, + }; + } + + public virtual IDictionary GetClientExtensions() + { + IDictionary clientExtensions = Platform.CreateHashtable(); + + MemoryStream srpData = new MemoryStream(); + TlsUtilities.WriteOpaque8(this.identity, srpData); + clientExtensions[ExtensionType.srp] = srpData.ToArray(); + + return clientExtensions; + } + + public virtual CompressionMethod[] GetCompressionMethods() + { + return new CompressionMethod[] { CompressionMethod.NULL }; + } + + public virtual void NotifySessionID(byte[] sessionID) + { + // Currently ignored + } + + public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite) + { + this.selectedCipherSuite = selectedCipherSuite; + } + + public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod) + { + this.selectedCompressionMethod = selectedCompressionMethod; + } + + public virtual void NotifySecureRenegotiation(bool secureRenegotiation) + { + if (!secureRenegotiation) + { + /* + * RFC 5746 3.4. If the extension is not present, the server does not support + * secure renegotiation; set secure_renegotiation flag to FALSE. In this case, + * some clients may want to terminate the handshake instead of continuing; see + * Section 4.1 for discussion. + */ +// throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + } + + public virtual void ProcessServerExtensions(IDictionary serverExtensions) + { + // There is no server response for the SRP extension + } + + public virtual TlsKeyExchange GetKeyExchange() + { + 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 TlsProtocolHandler 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 abstract TlsAuthentication GetAuthentication(); + + public virtual TlsCompression GetCompression() + { + switch (selectedCompressionMethod) + { + case CompressionMethod.NULL: + return new TlsNullCompression(); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsCipher GetCipher() + { + 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.cls_3DES_EDE_CBC, DigestAlgorithm.SHA); + + 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, DigestAlgorithm.SHA); + + 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, DigestAlgorithm.SHA); + + default: + /* + * Note: internal error here; the TlsProtocolHandler 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 virtual TlsKeyExchange CreateSrpKeyExchange(KeyExchangeAlgorithm keyExchange) + { + return new TlsSrpKeyExchange(context, keyExchange, identity, password); + } + } +} diff --git a/crypto/src/crypto/tls/Ssl3Mac.cs b/crypto/src/crypto/tls/Ssl3Mac.cs new file mode 100644 index 000000000..b2f3f309e --- /dev/null +++ b/crypto/src/crypto/tls/Ssl3Mac.cs @@ -0,0 +1,114 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * HMAC implementation based on original internet draft for HMAC (RFC 2104) + * + * The difference is that padding is concatentated versus XORed with the key + * + * H(K + opad, H(K + ipad, text)) + */ + public class Ssl3Mac + : IMac + { + private const byte IPAD = 0x36; + private const byte OPAD = 0x5C; + + internal static readonly byte[] MD5_IPAD = GenPad(IPAD, 48); + internal static readonly byte[] MD5_OPAD = GenPad(OPAD, 48); + internal static readonly byte[] SHA1_IPAD = GenPad(IPAD, 40); + internal static readonly byte[] SHA1_OPAD = GenPad(OPAD, 40); + + private IDigest digest; + + private byte[] secret; + private byte[] ipad, opad; + + /** + * 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(IDigest digest) + { + this.digest = digest; + + if (digest.GetDigestSize() == 20) + { + this.ipad = SHA1_IPAD; + this.opad = SHA1_OPAD; + } + else + { + this.ipad = MD5_IPAD; + this.opad = MD5_OPAD; + } + } + + public virtual string AlgorithmName + { + get { return digest.AlgorithmName + "/SSL3MAC"; } + } + + public virtual void Init(ICipherParameters parameters) + { + secret = Arrays.Clone(((KeyParameter)parameters).GetKey()); + + Reset(); + } + + public virtual int GetMacSize() + { + return digest.GetDigestSize(); + } + + public virtual void Update(byte input) + { + digest.Update(input); + } + + public virtual void BlockUpdate(byte[] input, int inOff, int len) + { + digest.BlockUpdate(input, inOff, len); + } + + public virtual int DoFinal(byte[] output, int outOff) + { + byte[] tmp = new byte[digest.GetDigestSize()]; + digest.DoFinal(tmp, 0); + + digest.BlockUpdate(secret, 0, secret.Length); + digest.BlockUpdate(opad, 0, opad.Length); + digest.BlockUpdate(tmp, 0, tmp.Length); + + int len = digest.DoFinal(output, outOff); + + Reset(); + + return len; + } + + /** + * Reset the mac generator. + */ + public virtual void Reset() + { + digest.Reset(); + digest.BlockUpdate(secret, 0, secret.Length); + digest.BlockUpdate(ipad, 0, ipad.Length); + } + + private static byte[] GenPad(byte b, int count) + { + byte[] padding = new byte[count]; + Arrays.Fill(padding, b); + return padding; + } + } +} diff --git a/crypto/src/crypto/tls/TlsAgreementCredentials.cs b/crypto/src/crypto/tls/TlsAgreementCredentials.cs new file mode 100644 index 000000000..46ee4f90e --- /dev/null +++ b/crypto/src/crypto/tls/TlsAgreementCredentials.cs @@ -0,0 +1,11 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsAgreementCredentials : TlsCredentials + { + /// + byte[] GenerateAgreement(AsymmetricKeyParameter serverPublicKey); + } +} diff --git a/crypto/src/crypto/tls/TlsAuthentication.cs b/crypto/src/crypto/tls/TlsAuthentication.cs new file mode 100644 index 000000000..9aea5e449 --- /dev/null +++ b/crypto/src/crypto/tls/TlsAuthentication.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsAuthentication + { + /// + /// Called by the protocol handler to report the server certificate. + /// + /// + /// This method is responsible for certificate verification and validation + /// + /// The server received + /// + void NotifyServerCertificate(Certificate serverCertificate); + + /// + /// Return client credentials in response to server's certificate request + /// + /// + /// A containing server certificate request details + /// + /// + /// A to be used for client authentication + /// (or null for no client authentication) + /// + /// + TlsCredentials GetClientCredentials(CertificateRequest certificateRequest); + } +} diff --git a/crypto/src/crypto/tls/TlsBlockCipher.cs b/crypto/src/crypto/tls/TlsBlockCipher.cs new file mode 100644 index 000000000..d77f118f4 --- /dev/null +++ b/crypto/src/crypto/tls/TlsBlockCipher.cs @@ -0,0 +1,251 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A generic TLS 1.0 block cipher. This can be used for AES or 3DES for example. + /// + public class TlsBlockCipher + : TlsCipher + { + protected TlsClientContext context; + protected byte[] randomData; + + protected IBlockCipher encryptCipher; + protected IBlockCipher decryptCipher; + + protected TlsMac wMac; + protected TlsMac rMac; + + public virtual TlsMac WriteMac + { + get { return wMac; } + } + + public virtual TlsMac ReadMac + { + get { return rMac; } + } + + public TlsBlockCipher(TlsClientContext context, IBlockCipher encryptCipher, + IBlockCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize) + { + this.context = context; + + this.randomData = new byte[256]; + context.SecureRandom.NextBytes(randomData); + + this.encryptCipher = encryptCipher; + this.decryptCipher = decryptCipher; + + int prfSize = (2 * cipherKeySize) + writeDigest.GetDigestSize() + + readDigest.GetDigestSize() + encryptCipher.GetBlockSize() + + decryptCipher.GetBlockSize(); + + SecurityParameters securityParameters = context.SecurityParameters; + + byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion", + TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom), + prfSize); + + int offset = 0; + + // Init MACs + wMac = CreateTlsMac(writeDigest, keyBlock, ref offset); + rMac = CreateTlsMac(readDigest, keyBlock, ref offset); + + // Build keys + KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize); + KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize); + + // Add IVs + ParametersWithIV encryptParams = CreateParametersWithIV(encryptKey, + keyBlock, ref offset, encryptCipher.GetBlockSize()); + ParametersWithIV decryptParams = CreateParametersWithIV(decryptKey, + keyBlock, ref offset, decryptCipher.GetBlockSize()); + + if (offset != prfSize) + throw new TlsFatalAlert(AlertDescription.internal_error); + + // Init Ciphers + encryptCipher.Init(true, encryptParams); + decryptCipher.Init(false, decryptParams); + } + + protected virtual TlsMac CreateTlsMac(IDigest digest, byte[] buf, ref int off) + { + int len = digest.GetDigestSize(); + TlsMac mac = new TlsMac(digest, buf, off, len); + off += len; + return mac; + } + + protected virtual KeyParameter CreateKeyParameter(byte[] buf, ref int off, int len) + { + KeyParameter key = new KeyParameter(buf, off, len); + off += len; + return key; + } + + protected virtual ParametersWithIV CreateParametersWithIV(KeyParameter key, + byte[] buf, ref int off, int len) + { + ParametersWithIV ivParams = new ParametersWithIV(key, buf, off, len); + off += len; + return ivParams; + } + + public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len) + { + int blocksize = encryptCipher.GetBlockSize(); + int padding_length = blocksize - 1 - ((len + wMac.Size) % blocksize); + + //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion; + bool isTls = true; + + if (isTls) + { + // Add a random number of extra blocks worth of padding + int maxExtraPadBlocks = (255 - padding_length) / blocksize; + int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks); + padding_length += actualExtraPadBlocks * blocksize; + } + + int totalsize = len + wMac.Size + padding_length + 1; + byte[] outbuf = new byte[totalsize]; + Array.Copy(plaintext, offset, outbuf, 0, len); + byte[] mac = wMac.CalculateMac(type, plaintext, offset, len); + Array.Copy(mac, 0, outbuf, len, mac.Length); + int paddoffset = len + mac.Length; + for (int i = 0; i <= padding_length; i++) + { + outbuf[i + paddoffset] = (byte)padding_length; + } + for (int i = 0; i < totalsize; i += blocksize) + { + encryptCipher.ProcessBlock(outbuf, i, outbuf, i); + } + return outbuf; + } + + public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len) + { + int blockSize = decryptCipher.GetBlockSize(); + int macSize = rMac.Size; + + /* + * TODO[TLS 1.1] Explicit IV implies minLen = blockSize + max(blockSize, macSize + 1), + * and will need further changes to offset and plen variables below. + */ + + int minLen = System.Math.Max(blockSize, macSize + 1); + if (len < minLen) + throw new TlsFatalAlert(AlertDescription.decode_error); + + if (len % blockSize != 0) + throw new TlsFatalAlert(AlertDescription.decryption_failed); + + for (int i = 0; i < len; i += blockSize) + { + decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i); + } + + int plen = len; + + // If there's anything wrong with the padding, this will return zero + int totalPad = CheckPaddingConstantTime(ciphertext, offset, plen, blockSize, macSize); + + int macInputLen = plen - totalPad - macSize; + + byte[] decryptedMac = Arrays.Copy(ciphertext, offset + macInputLen, macSize); + byte[] calculatedMac = rMac.CalculateMacConstantTime(type, ciphertext, offset, macInputLen, plen - macSize, randomData); + + bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, decryptedMac); + + if (badMac || totalPad == 0) + throw new TlsFatalAlert(AlertDescription.bad_record_mac); + + return Arrays.Copy(ciphertext, offset, macInputLen); + } + + protected virtual 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; + + //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion; + bool isTls = true; + + if ((!isTls && totalPad > blockSize) || (macSize + totalPad > len)) + { + totalPad = 0; + } + else + { + int padPos = end - totalPad; + do + { + padDiff |= (byte)(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 |= (byte)(dummyPad[dummyIndex++] ^ lastByte); + } + // Ensure the above loop is not eliminated + dummyPad[0] ^= padDiff; + } + + return totalPad; + } + + protected virtual int ChooseExtraPadBlocks(SecureRandom r, int max) + { +// return r.NextInt(max + 1); + + uint x = (uint)r.NextInt(); + int n = LowestBitSet(x); + return System.Math.Min(n, max); + } + + private int LowestBitSet(uint x) + { + if (x == 0) + { + return 32; + } + + int n = 0; + while ((x & 1) == 0) + { + ++n; + x >>= 1; + } + return n; + } + } +} diff --git a/crypto/src/crypto/tls/TlsCipher.cs b/crypto/src/crypto/tls/TlsCipher.cs new file mode 100644 index 000000000..22c769d82 --- /dev/null +++ b/crypto/src/crypto/tls/TlsCipher.cs @@ -0,0 +1,14 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsCipher + { + /// + byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len); + + /// + byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len); + } +} diff --git a/crypto/src/crypto/tls/TlsCipherFactory.cs b/crypto/src/crypto/tls/TlsCipherFactory.cs new file mode 100644 index 000000000..0756603f4 --- /dev/null +++ b/crypto/src/crypto/tls/TlsCipherFactory.cs @@ -0,0 +1,12 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsCipherFactory + { + /// + TlsCipher CreateCipher(TlsClientContext context, EncryptionAlgorithm encryptionAlgorithm, + DigestAlgorithm digestAlgorithm); + } +} diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs new file mode 100644 index 000000000..eceaa3cd3 --- /dev/null +++ b/crypto/src/crypto/tls/TlsClient.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsClient + { + /// + /// Called at the start of a new TLS session, before any other methods. + /// + /// + /// A + /// + void Init(TlsClientContext context); + + /// + /// Get the list of cipher suites that this client supports. + /// + /// + /// An array of , each specifying a supported cipher suite. + /// + CipherSuite[] GetCipherSuites(); + + /// + /// Get the list of compression methods that this client supports. + /// + /// + /// An array of , each specifying a supported compression method. + /// + CompressionMethod[] GetCompressionMethods(); + + /// + /// Get the (optional) table of client extensions to be included in (extended) client hello. + /// + /// + /// A ( -> byte[]). May be null. + /// + /// + IDictionary GetClientExtensions(); + + /// + /// Reports the session ID once it has been determined. + /// + /// + /// A + /// + void NotifySessionID(byte[] sessionID); + + /// + /// Report the cipher suite that was selected by the server. + /// + /// + /// The protocol handler validates this value against the offered cipher suites + /// + /// + /// + /// A + /// + void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite); + + /// + /// Report the compression method that was selected by the server. + /// + /// + /// The protocol handler validates this value against the offered compression methods + /// + /// + /// + /// A + /// + void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod); + + /// + /// Report whether the server supports secure renegotiation + /// + /// + /// The protocol handler automatically processes the relevant extensions + /// + /// + /// A , true if the server supports secure renegotiation + /// + /// + void NotifySecureRenegotiation(bool secureRenegotiation); + + /// + /// Report the extensions from an extended server hello. + /// + /// + /// Will only be called if we returned a non-null result from . + /// + /// + /// A ( -> byte[]) + /// + void ProcessServerExtensions(IDictionary serverExtensions); + + /// + /// Return an implementation of to negotiate the key exchange + /// part of the protocol. + /// + /// + /// A + /// + /// + TlsKeyExchange GetKeyExchange(); + + /// + /// Return an implementation of to handle authentication + /// part of the protocol. + /// + /// + TlsAuthentication GetAuthentication(); + + /// + /// Return an implementation of to handle record compression. + /// + /// + TlsCompression GetCompression(); + + /// + /// Return an implementation of to use for encryption/decryption. + /// + /// + /// A + /// + /// + TlsCipher GetCipher(); + } +} diff --git a/crypto/src/crypto/tls/TlsClientContext.cs b/crypto/src/crypto/tls/TlsClientContext.cs new file mode 100644 index 000000000..dbb10aa76 --- /dev/null +++ b/crypto/src/crypto/tls/TlsClientContext.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsClientContext + { + SecureRandom SecureRandom { get; } + + SecurityParameters SecurityParameters { get; } + + object UserObject { get; set; } + } +} diff --git a/crypto/src/crypto/tls/TlsClientContextImpl.cs b/crypto/src/crypto/tls/TlsClientContextImpl.cs new file mode 100644 index 000000000..9d5dee232 --- /dev/null +++ b/crypto/src/crypto/tls/TlsClientContextImpl.cs @@ -0,0 +1,37 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsClientContextImpl + : TlsClientContext + { + private readonly SecureRandom secureRandom; + private readonly SecurityParameters securityParameters; + + private object userObject = null; + + internal TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters) + { + this.secureRandom = secureRandom; + this.securityParameters = securityParameters; + } + + public virtual SecureRandom SecureRandom + { + get { return secureRandom; } + } + + public virtual SecurityParameters SecurityParameters + { + get { return securityParameters; } + } + + public virtual object UserObject + { + get { return userObject; } + set { this.userObject = value; } + } + } +} diff --git a/crypto/src/crypto/tls/TlsCompression.cs b/crypto/src/crypto/tls/TlsCompression.cs new file mode 100644 index 000000000..177d64b7e --- /dev/null +++ b/crypto/src/crypto/tls/TlsCompression.cs @@ -0,0 +1,12 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsCompression + { + Stream Compress(Stream output); + + Stream Decompress(Stream output); + } +} diff --git a/crypto/src/crypto/tls/TlsCredentials.cs b/crypto/src/crypto/tls/TlsCredentials.cs new file mode 100644 index 000000000..5c5f1c02e --- /dev/null +++ b/crypto/src/crypto/tls/TlsCredentials.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsCredentials + { + Certificate Certificate { get; } + } +} diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs new file mode 100644 index 000000000..40ac416e0 --- /dev/null +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -0,0 +1,201 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// TLS 1.0 DH key exchange. + /// + internal class TlsDHKeyExchange + : TlsKeyExchange + { + protected TlsClientContext context; + protected KeyExchangeAlgorithm keyExchange; + protected TlsSigner tlsSigner; + + protected AsymmetricKeyParameter serverPublicKey = null; + protected DHPublicKeyParameters dhAgreeServerPublicKey = null; + protected TlsAgreementCredentials agreementCredentials; + protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null; + + internal TlsDHKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange) + { + 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 ArgumentException("unsupported key exchange algorithm", "keyExchange"); + } + + this.context = context; + this.keyExchange = keyExchange; + } + + public virtual void SkipServerCertificate() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure x509Cert = serverCertificate.certs[0]; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + + try + { + this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + } + catch (Exception) + { + throw new TlsFatalAlert(AlertDescription.unsupported_certificate); + } + + if (tlsSigner == null) + { + try + { + this.dhAgreeServerPublicKey = ValidateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey); + } + catch (InvalidCastException) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement); + } + else + { + if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); + } + + // TODO + /* + * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the + * signing algorithm for the certificate must be the same as the algorithm for the + * certificate key." + */ + } + + public virtual void SkipServerKeyExchange() + { + // OK + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + ClientCertificateType[] types = certificateRequest.CertificateTypes; + foreach (ClientCertificateType type in types) + { + switch (type) + { + 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 virtual void SkipClientCredentials() + { + this.agreementCredentials = null; + } + + public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + { + if (clientCredentials is TlsAgreementCredentials) + { + // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')? + + this.agreementCredentials = (TlsAgreementCredentials)clientCredentials; + } + else if (clientCredentials is TlsSignerCredentials) + { + // OK + } + else + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public virtual void GenerateClientKeyExchange(Stream output) + { + /* + * 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) + { + GenerateEphemeralClientKeyExchange(dhAgreeServerPublicKey.Parameters, output); + } + } + + public virtual byte[] GeneratePremasterSecret() + { + if (agreementCredentials != null) + { + return agreementCredentials.GenerateAgreement(dhAgreeServerPublicKey); + } + + return CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey); + } + + protected virtual bool AreCompatibleParameters(DHParameters a, DHParameters b) + { + return a.P.Equals(b.P) && a.G.Equals(b.G); + } + + protected virtual byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey, + DHPrivateKeyParameters privateKey) + { + return TlsDHUtilities.CalculateDHBasicAgreement(publicKey, privateKey); + } + + protected virtual AsymmetricCipherKeyPair GenerateDHKeyPair(DHParameters dhParams) + { + return TlsDHUtilities.GenerateDHKeyPair(context.SecureRandom, dhParams); + } + + protected virtual void GenerateEphemeralClientKeyExchange(DHParameters dhParams, Stream output) + { + this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange( + context.SecureRandom, dhParams, output); + } + + protected virtual DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key) + { + return TlsDHUtilities.ValidateDHPublicKey(key); + } + } +} diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs new file mode 100644 index 000000000..b5deb8b84 --- /dev/null +++ b/crypto/src/crypto/tls/TlsDHUtilities.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class TlsDHUtilities + { + 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, Stream output) + { + AsymmetricCipherKeyPair dhAgreeClientKeyPair = GenerateDHKeyPair(random, dhParams); + DHPrivateKeyParameters dhAgreeClientPrivateKey = + (DHPrivateKeyParameters)dhAgreeClientKeyPair.Private; + + BigInteger Yc = ((DHPublicKeyParameters)dhAgreeClientKeyPair.Public).Y; + byte[] keData = BigIntegers.AsUnsignedByteArray(Yc); + TlsUtilities.WriteOpaque16(keData, output); + + return dhAgreeClientPrivateKey; + } + + public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key) + { + BigInteger Y = key.Y; + DHParameters parameters = key.Parameters; + BigInteger p = parameters.P; + BigInteger g = parameters.G; + + if (!p.IsProbablePrime(2)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + if (g.CompareTo(BigInteger.Two) < 0 || g.CompareTo(p.Subtract(BigInteger.Two)) > 0) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + if (Y.CompareTo(BigInteger.Two) < 0 || Y.CompareTo(p.Subtract(BigInteger.One)) > 0) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + // TODO See RFC 2631 for more discussion of Diffie-Hellman validation + + return key; + } + } +} \ No newline at end of file diff --git a/crypto/src/crypto/tls/TlsDeflateCompression.cs b/crypto/src/crypto/tls/TlsDeflateCompression.cs new file mode 100644 index 000000000..9e1152908 --- /dev/null +++ b/crypto/src/crypto/tls/TlsDeflateCompression.cs @@ -0,0 +1,68 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsDeflateCompression : TlsCompression + { + public const int LEVEL_NONE = JZlib.Z_NO_COMPRESSION; + public const int LEVEL_FASTEST = JZlib.Z_BEST_SPEED; + public const int LEVEL_SMALLEST = JZlib.Z_BEST_COMPRESSION; + public const int LEVEL_DEFAULT = JZlib.Z_DEFAULT_COMPRESSION; + + protected readonly ZStream zIn, zOut; + + public TlsDeflateCompression() + : this(LEVEL_DEFAULT) + { + } + + public TlsDeflateCompression(int level) + { + this.zIn = new ZStream(); + this.zIn.inflateInit(); + + this.zOut = new ZStream(); + this.zOut.deflateInit(level); + } + + public virtual Stream Compress(Stream output) + { + return new DeflateOutputStream(output, zOut, true); + } + + public virtual Stream Decompress(Stream output) + { + return new DeflateOutputStream(output, zIn, false); + } + + protected class DeflateOutputStream : ZOutputStream + { + public DeflateOutputStream(Stream output, ZStream z, bool compress) + : base(output, z) + { + this.compress = compress; + + /* + * See discussion at http://www.bolet.org/~pornin/deflate-flush.html . + */ + this.FlushMode = JZlib.Z_SYNC_FLUSH; + } + + public override void Flush() + { + /* + * TODO The inflateSyncPoint doesn't appear to work the way I hoped at the moment. + * In any case, we may like to accept PARTIAL_FLUSH input, not just SYNC_FLUSH. + * It's not clear how to check this in the Inflater. + */ + //if (!this.compress && (z == null || z.istate == null || z.istate.inflateSyncPoint(z) <= 0)) + //{ + // throw new TlsFatalAlert(AlertDescription.decompression_failure); + //} + } + } + } +} diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs new file mode 100644 index 000000000..725cc1bf3 --- /dev/null +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsDheKeyExchange + : TlsDHKeyExchange + { + internal TlsDheKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange) + : base(context, keyExchange) + { + } + + public override void SkipServerKeyExchange() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public override void ProcessServerKeyExchange(Stream input) + { + SecurityParameters securityParameters = context.SecurityParameters; + + ISigner signer = InitSigner(tlsSigner, securityParameters); + Stream sigIn = new SignerStream(input, signer, null); + + byte[] pBytes = TlsUtilities.ReadOpaque16(sigIn); + byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn); + byte[] YsBytes = TlsUtilities.ReadOpaque16(sigIn); + + byte[] sigByte = TlsUtilities.ReadOpaque16(input); + if (!signer.VerifySignature(sigByte)) + { + throw new TlsFatalAlert(AlertDescription.decrypt_error); + } + + BigInteger p = new BigInteger(1, pBytes); + BigInteger g = new BigInteger(1, gBytes); + BigInteger Ys = new BigInteger(1, YsBytes); + + this.dhAgreeServerPublicKey = ValidateDHPublicKey( + new DHPublicKeyParameters(Ys, new DHParameters(p, g))); + } + + protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + { + ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + return signer; + } + } +} diff --git a/crypto/src/crypto/tls/TlsDsaSigner.cs b/crypto/src/crypto/tls/TlsDsaSigner.cs new file mode 100644 index 000000000..bba114e90 --- /dev/null +++ b/crypto/src/crypto/tls/TlsDsaSigner.cs @@ -0,0 +1,51 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal abstract class TlsDsaSigner + : TlsSigner + { + public virtual byte[] GenerateRawSignature(SecureRandom random, + AsymmetricKeyParameter privateKey, byte[] md5andsha1) + { + ISigner s = MakeSigner(new NullDigest(), true, new ParametersWithRandom(privateKey, random)); + // Note: Only use the SHA1 part of the hash + s.BlockUpdate(md5andsha1, 16, 20); + return s.GenerateSignature(); + } + + public bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5andsha1) + { + ISigner s = MakeSigner(new NullDigest(), false, publicKey); + // Note: Only use the SHA1 part of the hash + s.BlockUpdate(md5andsha1, 16, 20); + return s.VerifySignature(sigBytes); + } + + public virtual ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey) + { + return MakeSigner(new Sha1Digest(), true, new ParametersWithRandom(privateKey, random)); + } + + public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey) + { + return MakeSigner(new Sha1Digest(), false, publicKey); + } + + public abstract bool IsValidPublicKey(AsymmetricKeyParameter publicKey); + + protected virtual ISigner MakeSigner(IDigest d, bool forSigning, ICipherParameters cp) + { + ISigner s = new DsaDigestSigner(CreateDsaImpl(), d); + s.Init(forSigning, cp); + return s; + } + + protected abstract IDsa CreateDsaImpl(); + } +} diff --git a/crypto/src/crypto/tls/TlsDssSigner.cs b/crypto/src/crypto/tls/TlsDssSigner.cs new file mode 100644 index 000000000..c6f1abcec --- /dev/null +++ b/crypto/src/crypto/tls/TlsDssSigner.cs @@ -0,0 +1,21 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsDssSigner + : TlsDsaSigner + { + public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey) + { + return publicKey is DsaPublicKeyParameters; + } + + protected override IDsa CreateDsaImpl() + { + return new DsaSigner(); + } + } +} diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs new file mode 100644 index 000000000..36155346a --- /dev/null +++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * ECDH key exchange (see RFC 4492) + */ + internal class TlsECDHKeyExchange + : TlsKeyExchange + { + protected TlsClientContext context; + protected KeyExchangeAlgorithm keyExchange; + protected TlsSigner tlsSigner; + + protected AsymmetricKeyParameter serverPublicKey; + protected ECPublicKeyParameters ecAgreeServerPublicKey; + protected TlsAgreementCredentials agreementCredentials; + protected ECPrivateKeyParameters ecAgreeClientPrivateKey = null; + + internal TlsECDHKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange) + { + 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 ArgumentException("unsupported key exchange algorithm", "keyExchange"); + } + + this.context = context; + this.keyExchange = keyExchange; + } + + public virtual void SkipServerCertificate() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure x509Cert = serverCertificate.certs[0]; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + + try + { + this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + } + catch (Exception) + { + throw new TlsFatalAlert(AlertDescription.unsupported_certificate); + } + + if (tlsSigner == null) + { + try + { + this.ecAgreeServerPublicKey = ValidateECPublicKey((ECPublicKeyParameters)this.serverPublicKey); + } + catch (InvalidCastException) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement); + } + else + { + if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); + } + + // TODO + /* + * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the + * signing algorithm for the certificate must be the same as the algorithm for the + * certificate key." + */ + } + + public virtual void SkipServerKeyExchange() + { + // do nothing + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + /* + * 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. + */ + ClientCertificateType[] types = certificateRequest.CertificateTypes; + foreach (ClientCertificateType type in types) + { + switch (type) + { + 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 virtual void SkipClientCredentials() + { + this.agreementCredentials = null; + } + + public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + { + if (clientCredentials is TlsAgreementCredentials) + { + // TODO Validate client cert has matching parameters (see 'AreOnSameCurve')? + + this.agreementCredentials = (TlsAgreementCredentials)clientCredentials; + } + else if (clientCredentials is TlsSignerCredentials) + { + // OK + } + else + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public virtual void GenerateClientKeyExchange(Stream output) + { + if (agreementCredentials == null) + { + GenerateEphemeralClientKeyExchange(ecAgreeServerPublicKey.Parameters, output); + } + } + + public virtual byte[] GeneratePremasterSecret() + { + if (agreementCredentials != null) + { + return agreementCredentials.GenerateAgreement(ecAgreeServerPublicKey); + } + + return CalculateECDHBasicAgreement(ecAgreeServerPublicKey, ecAgreeClientPrivateKey); + } + + protected virtual bool AreOnSameCurve(ECDomainParameters a, ECDomainParameters b) + { + // TODO Move to ECDomainParameters.Equals() or other utility method? + return a.Curve.Equals(b.Curve) && a.G.Equals(b.G) && a.N.Equals(b.N) && a.H.Equals(b.H); + } + + protected virtual byte[] ExternalizeKey(ECPublicKeyParameters keyParameters) + { + // TODO Add support for compressed encoding and SPF extension + + /* + * 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. + */ + return keyParameters.Q.GetEncoded(); + } + + protected virtual AsymmetricCipherKeyPair GenerateECKeyPair(ECDomainParameters ecParams) + { + ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); + ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(ecParams, + context.SecureRandom); + keyPairGenerator.Init(keyGenerationParameters); + return keyPairGenerator.GenerateKeyPair(); + } + + protected virtual void GenerateEphemeralClientKeyExchange(ECDomainParameters ecParams, Stream output) + { + AsymmetricCipherKeyPair ecAgreeClientKeyPair = GenerateECKeyPair(ecParams); + this.ecAgreeClientPrivateKey = (ECPrivateKeyParameters)ecAgreeClientKeyPair.Private; + + byte[] keData = ExternalizeKey((ECPublicKeyParameters)ecAgreeClientKeyPair.Public); + TlsUtilities.WriteOpaque8(keData, output); + } + + protected virtual 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); + } + + protected virtual ECPublicKeyParameters ValidateECPublicKey(ECPublicKeyParameters key) + { + // TODO Check RFC 4492 for validation + return key; + } + } +} diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs new file mode 100644 index 000000000..071d06b91 --- /dev/null +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * ECDHE key exchange (see RFC 4492) + */ + internal class TlsECDheKeyExchange : TlsECDHKeyExchange + { + internal TlsECDheKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange) + : base(context, keyExchange) + { + } + + public override void SkipServerKeyExchange() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public override void ProcessServerKeyExchange(Stream input) + { + SecurityParameters securityParameters = context.SecurityParameters; + + ISigner signer = InitSigner(tlsSigner, securityParameters); + Stream sigIn = new SignerStream(input, signer, null); + + ECCurveType curveType = (ECCurveType)TlsUtilities.ReadUint8(sigIn); + ECDomainParameters curve_params; + + // Currently, we only support named curves + if (curveType == ECCurveType.named_curve) + { + NamedCurve namedCurve = (NamedCurve)TlsUtilities.ReadUint16(sigIn); + + // TODO Check namedCurve is one we offered? + + curve_params = NamedCurveHelper.GetECParameters(namedCurve); + } + else + { + // TODO Add support for explicit curve parameters (read from sigIn) + + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + + byte[] publicBytes = TlsUtilities.ReadOpaque8(sigIn); + + byte[] sigByte = TlsUtilities.ReadOpaque16(input); + if (!signer.VerifySignature(sigByte)) + { + throw new TlsFatalAlert(AlertDescription.decrypt_error); + } + + // TODO Check curve_params not null + + ECPoint Q = curve_params.Curve.DecodePoint(publicBytes); + + this.ecAgreeServerPublicKey = ValidateECPublicKey(new ECPublicKeyParameters(Q, curve_params)); + } + + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + /* + * 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. + */ + ClientCertificateType[] types = certificateRequest.CertificateTypes; + foreach (ClientCertificateType type in types) + { + switch (type) + { + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.ecdsa_sign: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + } + } + + public override void ProcessClientCredentials(TlsCredentials clientCredentials) + { + if (clientCredentials is TlsSignerCredentials) + { + // OK + } + else + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + { + ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + return signer; + } + } +} diff --git a/crypto/src/crypto/tls/TlsECDsaSigner.cs b/crypto/src/crypto/tls/TlsECDsaSigner.cs new file mode 100644 index 000000000..3c30fdc0c --- /dev/null +++ b/crypto/src/crypto/tls/TlsECDsaSigner.cs @@ -0,0 +1,21 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsECDsaSigner + : TlsDsaSigner + { + public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey) + { + return publicKey is ECPublicKeyParameters; + } + + protected override IDsa CreateDsaImpl() + { + return new ECDsaSigner(); + } + } +} diff --git a/crypto/src/crypto/tls/TlsException.cs b/crypto/src/crypto/tls/TlsException.cs new file mode 100644 index 000000000..59c129105 --- /dev/null +++ b/crypto/src/crypto/tls/TlsException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class TlsException : Exception + { + public TlsException() : base() { } + public TlsException(string message) : base(message) { } + public TlsException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/crypto/tls/TlsFatalAlert.cs b/crypto/src/crypto/tls/TlsFatalAlert.cs new file mode 100644 index 000000000..0a9cc6f3a --- /dev/null +++ b/crypto/src/crypto/tls/TlsFatalAlert.cs @@ -0,0 +1,21 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsFatalAlert + : IOException + { + private readonly AlertDescription alertDescription; + + public TlsFatalAlert(AlertDescription alertDescription) + { + this.alertDescription = alertDescription; + } + + public AlertDescription AlertDescription + { + get { return alertDescription; } + } + } +} diff --git a/crypto/src/crypto/tls/TlsKeyExchange.cs b/crypto/src/crypto/tls/TlsKeyExchange.cs new file mode 100644 index 000000000..5102edbec --- /dev/null +++ b/crypto/src/crypto/tls/TlsKeyExchange.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A generic interface for key exchange implementations in TLS 1.0. + /// + public interface TlsKeyExchange + { + /// + void SkipServerCertificate(); + + /// + void ProcessServerCertificate(Certificate serverCertificate); + + /// + void SkipServerKeyExchange(); + + /// + void ProcessServerKeyExchange(Stream input); + + /// + void ValidateCertificateRequest(CertificateRequest certificateRequest); + + /// + void SkipClientCredentials(); + + /// + void ProcessClientCredentials(TlsCredentials clientCredentials); + + /// + void GenerateClientKeyExchange(Stream output); + + /// + byte[] GeneratePremasterSecret(); + } +} diff --git a/crypto/src/crypto/tls/TlsMac.cs b/crypto/src/crypto/tls/TlsMac.cs new file mode 100644 index 000000000..862c887ad --- /dev/null +++ b/crypto/src/crypto/tls/TlsMac.cs @@ -0,0 +1,142 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// A generic TLS MAC implementation, which can be used with any kind of + /// IDigest to act as an HMAC. + /// + public class TlsMac + { + protected long seqNo; + protected byte[] secret; + protected HMac mac; + + /** + * Generate a new instance of an TlsMac. + * + * @param digest The digest to use. + * @param key_block A byte-array where the key for this mac is located. + * @param offset The number of bytes to skip, before the key starts in the buffer. + * @param len The length of the key. + */ + public TlsMac( + IDigest digest, + byte[] key_block, + int offset, + int len) + { + this.seqNo = 0; + + KeyParameter param = new KeyParameter(key_block, offset, len); + + this.secret = Arrays.Clone(param.GetKey()); + + this.mac = new HMac(digest); + this.mac.Init(param); + } + + /** + * @return the MAC write secret + */ + public virtual byte[] GetMacSecret() + { + return this.secret; + } + + /** + * @return the current write sequence number + */ + public virtual long SequenceNumber + { + get { return this.seqNo; } + } + + /** + * Increment the current write sequence number + */ + public virtual void IncSequenceNumber() + { + this.seqNo++; + } + + /** + * @return The Keysize of the mac. + */ + public virtual int Size + { + get { return mac.GetMacSize(); } + } + + /** + * Calculate the mac for some given data. + *

+ * TlsMac will keep track of the sequence number internally. + * + * @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 len The length of the message. + * @return A new byte-buffer containing the mac value. + */ + public virtual byte[] CalculateMac(ContentType type, byte[] message, int offset, int len) + { + //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion; + bool isTls = true; + + byte[] macHeader = new byte[isTls ? 13 : 11]; + TlsUtilities.WriteUint64(seqNo++, macHeader, 0); + TlsUtilities.WriteUint8((byte)type, macHeader, 8); + if (isTls) + { + TlsUtilities.WriteVersion(macHeader, 9); + } + TlsUtilities.WriteUint16(len, macHeader, 11); + + mac.BlockUpdate(macHeader, 0, macHeader.Length); + mac.BlockUpdate(message, offset, len); + return MacUtilities.DoFinal(mac); + } + + public virtual byte[] CalculateMacConstantTime(ContentType type, byte[] message, int offset, int len, + int fullLength, byte[] dummyData) + { + // Actual MAC only calculated on 'len' bytes + byte[] result = CalculateMac(type, message, offset, len); + + //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion; + bool isTls = true; + + // ...but ensure a constant number of complete digest blocks are processed (per 'fullLength') + if (isTls) + { + // TODO Currently all TLS digests use a block size of 64, a suffix (length field) of 8, and padding (1+) + int db = 64, ds = 8; + + int L1 = 13 + fullLength; + int L2 = 13 + len; + + // How many extra full blocks do we need to calculate? + int extra = ((L1 + ds) / db) - ((L2 + ds) / db); + + while (--extra >= 0) + { + mac.BlockUpdate(dummyData, 0, db); + } + + // One more byte in case the implementation is "lazy" about processing blocks + mac.Update(dummyData[0]); + mac.Reset(); + } + + return result; + } + } +} diff --git a/crypto/src/crypto/tls/TlsNullCipher.cs b/crypto/src/crypto/tls/TlsNullCipher.cs new file mode 100644 index 000000000..b76f76d9c --- /dev/null +++ b/crypto/src/crypto/tls/TlsNullCipher.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + ///

+ /// A NULL cipher suite, for use during handshake. + /// + public class TlsNullCipher + : TlsCipher + { + public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len) + { + return CopyData(plaintext, offset, len); + } + + public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len) + { + return CopyData(ciphertext, offset, len); + } + + protected virtual byte[] CopyData(byte[] text, int offset, int len) + { + byte[] result = new byte[len]; + Array.Copy(text, offset, result, 0, len); + return result; + } + } +} diff --git a/crypto/src/crypto/tls/TlsNullCompression.cs b/crypto/src/crypto/tls/TlsNullCompression.cs new file mode 100644 index 000000000..45f8fc708 --- /dev/null +++ b/crypto/src/crypto/tls/TlsNullCompression.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsNullCompression + : TlsCompression + { + public virtual Stream Compress(Stream output) + { + return output; + } + + public virtual Stream Decompress(Stream output) + { + return output; + } + } +} diff --git a/crypto/src/crypto/tls/TlsProtocolHandler.cs b/crypto/src/crypto/tls/TlsProtocolHandler.cs new file mode 100644 index 000000000..0a970d251 --- /dev/null +++ b/crypto/src/crypto/tls/TlsProtocolHandler.cs @@ -0,0 +1,1233 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// An implementation of all high level protocols in TLS 1.0. + public class TlsProtocolHandler + { + /* + * Our Connection states + */ + private const short CS_CLIENT_HELLO_SEND = 1; + private const short CS_SERVER_HELLO_RECEIVED = 2; + private const short CS_SERVER_CERTIFICATE_RECEIVED = 3; + private const short CS_SERVER_KEY_EXCHANGE_RECEIVED = 4; + private const short CS_CERTIFICATE_REQUEST_RECEIVED = 5; + private const short CS_SERVER_HELLO_DONE_RECEIVED = 6; + private const short CS_CLIENT_KEY_EXCHANGE_SEND = 7; + private const short CS_CERTIFICATE_VERIFY_SEND = 8; + private const short CS_CLIENT_CHANGE_CIPHER_SPEC_SEND = 9; + private const short CS_CLIENT_FINISHED_SEND = 10; + private const short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 11; + private const short CS_DONE = 12; + + private static readonly byte[] emptybuf = new byte[0]; + + private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack"; + + /* + * Queues for data from some protocols. + */ + + private ByteQueue applicationDataQueue = new ByteQueue(); + private ByteQueue alertQueue = new ByteQueue(2); + private ByteQueue handshakeQueue = new ByteQueue(); + + /* + * The Record Stream we use + */ + private RecordStream rs; + private SecureRandom random; + + private TlsStream tlsStream = null; + + private bool closed = false; + private bool failedWithError = false; + private bool appDataReady = false; + private IDictionary clientExtensions; + + private SecurityParameters securityParameters = null; + + private TlsClientContextImpl tlsClientContext = null; + private TlsClient tlsClient = null; + private CipherSuite[] offeredCipherSuites = null; + private CompressionMethod[] offeredCompressionMethods = null; + private TlsKeyExchange keyExchange = null; + private TlsAuthentication authentication = null; + private CertificateRequest certificateRequest = null; + + private short connection_state = 0; + + 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. + * + * Hopefully, 20 bytes in fast mode are good enough. + */ + byte[] seed = new ThreadedSeedGenerator().GenerateSeed(20, true); + + return new SecureRandom(seed); + } + + public TlsProtocolHandler( + Stream s) + : this(s, s) + { + } + + public TlsProtocolHandler( + Stream s, + SecureRandom sr) + : this(s, s, sr) + { + } + + /// Both streams can be the same object + public TlsProtocolHandler( + Stream inStr, + Stream outStr) + : this(inStr, outStr, CreateSecureRandom()) + { + } + + /// Both streams can be the same object + public TlsProtocolHandler( + Stream inStr, + Stream outStr, + SecureRandom sr) + { + this.rs = new RecordStream(this, inStr, outStr); + this.random = sr; + } + + internal void ProcessData( + ContentType protocol, + byte[] buf, + int offset, + int len) + { + /* + * Have a look at the protocol type, and add it to the correct queue. + */ + switch (protocol) + { + case ContentType.change_cipher_spec: + ProcessChangeCipherSpec(buf, offset, len); + break; + case ContentType.alert: + alertQueue.AddData(buf, offset, len); + ProcessAlert(); + break; + case ContentType.handshake: + handshakeQueue.AddData(buf, offset, len); + ProcessHandshake(); + break; + case ContentType.application_data: + if (!appDataReady) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + } + applicationDataQueue.AddData(buf, offset, len); + ProcessApplicationData(); + break; + default: + /* + * Uh, we don't know this protocol. + * + * RFC2246 defines on page 13, that we should ignore this. + */ + break; + } + } + + private void ProcessHandshake() + { + bool read; + do + { + read = false; + + /* + * We need the first 4 bytes, they contain type and length of + * the message. + */ + if (handshakeQueue.Available >= 4) + { + byte[] beginning = new byte[4]; + handshakeQueue.Read(beginning, 0, 4, 0); + MemoryStream bis = new MemoryStream(beginning, false); + HandshakeType type = (HandshakeType)TlsUtilities.ReadUint8(bis); + int len = TlsUtilities.ReadUint24(bis); + + /* + * Check if we have enough bytes in the buffer to read + * the full message. + */ + if (handshakeQueue.Available >= (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: + case HandshakeType.finished: + break; + default: + rs.UpdateHandshakeData(beginning, 0, 4); + rs.UpdateHandshakeData(buf, 0, len); + break; + } + + /* + * Now, parse the message. + */ + ProcessHandshakeMessage(type, buf); + read = true; + } + } + } + while (read); + } + + private void ProcessHandshakeMessage(HandshakeType type, byte[] buf) + { + MemoryStream inStr = new MemoryStream(buf, false); + + /* + * Check the type. + */ + switch (type) + { + case HandshakeType.certificate: + { + switch (connection_state) + { + case CS_SERVER_HELLO_RECEIVED: + { + // Parse the Certificate message and send to cipher suite + + Certificate serverCertificate = Certificate.Parse(inStr); + + AssertEmpty(inStr); + + this.keyExchange.ProcessServerCertificate(serverCertificate); + + this.authentication = tlsClient.GetAuthentication(); + this.authentication.NotifyServerCertificate(serverCertificate); + + break; + } + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + + connection_state = CS_SERVER_CERTIFICATE_RECEIVED; + break; + } + case HandshakeType.finished: + switch (connection_state) + { + case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED: + /* + * Read the checksum from the finished message, it has always 12 bytes. + */ + byte[] serverVerifyData = new byte[12]; + TlsUtilities.ReadFully(serverVerifyData, inStr); + + AssertEmpty(inStr); + + /* + * Calculate our own checksum. + */ + byte[] expectedServerVerifyData = TlsUtilities.PRF( + securityParameters.masterSecret, "server finished", + rs.GetCurrentHash(), 12); + + /* + * Compare both checksums. + */ + if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData)) + { + /* + * Wrong checksum in the finished message. + */ + this.FailWithError(AlertLevel.fatal, AlertDescription.decrypt_error); + } + + connection_state = CS_DONE; + + /* + * We are now ready to receive application data. + */ + this.appDataReady = true; + break; + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + break; + case HandshakeType.server_hello: + switch (connection_state) + { + case CS_CLIENT_HELLO_SEND: + /* + * Read the server hello message + */ + TlsUtilities.CheckVersion(inStr); + + /* + * Read the server random + */ + securityParameters.serverRandom = new byte[32]; + TlsUtilities.ReadFully(securityParameters.serverRandom, inStr); + + byte[] sessionID = TlsUtilities.ReadOpaque8(inStr); + if (sessionID.Length > 32) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); + } + + this.tlsClient.NotifySessionID(sessionID); + + /* + * Find out which CipherSuite the server has chosen and check that + * it was one of the offered ones. + */ + CipherSuite selectedCipherSuite = (CipherSuite)TlsUtilities.ReadUint16(inStr); + if (!ArrayContains(offeredCipherSuites, selectedCipherSuite) + || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + { + this.FailWithError(AlertLevel.fatal, 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. + */ + CompressionMethod selectedCompressionMethod = (CompressionMethod)TlsUtilities.ReadUint8(inStr); + if (!ArrayContains(offeredCompressionMethods, selectedCompressionMethod)) + { + this.FailWithError(AlertLevel.fatal, 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. + */ + + /* + * 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. + */ + + // ExtensionType -> byte[] + IDictionary serverExtensions = Platform.CreateHashtable(); + + if (inStr.Position < inStr.Length) + { + // Process extensions from extended server hello + byte[] extBytes = TlsUtilities.ReadOpaque16(inStr); + + MemoryStream ext = new MemoryStream(extBytes, false); + while (ext.Position < ext.Length) + { + ExtensionType extType = (ExtensionType)TlsUtilities.ReadUint16(ext); + byte[] extValue = TlsUtilities.ReadOpaque16(ext); + + // Note: RFC 5746 makes a special case for EXT_RenegotiationInfo + if (extType != ExtensionType.renegotiation_info + && !clientExtensions.Contains(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. + */ + this.FailWithError(AlertLevel.fatal, AlertDescription.unsupported_extension); + } + + if (serverExtensions.Contains(extType)) + { + /* + * RFC 3546 2.3 + * Also note that when multiple extensions of different types are + * present in the extended client hello or the extended server hello, + * the extensions may appear in any order. There MUST NOT be more than + * one extension of the same type. + */ + this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); + } + + serverExtensions.Add(extType, extValue); + } + } + + AssertEmpty(inStr); + + /* + * RFC 5746 3.4. When a ServerHello is received, the client MUST check if it + * includes the "renegotiation_info" extension: + */ + { + bool secure_negotiation = serverExtensions.Contains(ExtensionType.renegotiation_info); + + /* + * 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). + */ + if (secure_negotiation) + { + byte[] renegExtValue = (byte[])serverExtensions[ExtensionType.renegotiation_info]; + + if (!Arrays.ConstantTimeAreEqual(renegExtValue, + CreateRenegotiationInfo(emptybuf))) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); + } + } + + tlsClient.NotifySecureRenegotiation(secure_negotiation); + } + + if (clientExtensions != null) + { + tlsClient.ProcessServerExtensions(serverExtensions); + } + + this.keyExchange = tlsClient.GetKeyExchange(); + + connection_state = CS_SERVER_HELLO_RECEIVED; + break; + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + break; + case HandshakeType.server_hello_done: + switch (connection_state) + { + case CS_SERVER_HELLO_RECEIVED: + case CS_SERVER_CERTIFICATE_RECEIVED: + case CS_SERVER_KEY_EXCHANGE_RECEIVED: + case CS_CERTIFICATE_REQUEST_RECEIVED: + + // NB: Original code used case label fall-through + + if (connection_state == CS_SERVER_HELLO_RECEIVED) + { + // There was no server certificate message; check it's OK + this.keyExchange.SkipServerCertificate(); + this.authentication = null; + + // There was no server key exchange message; check it's OK + this.keyExchange.SkipServerKeyExchange(); + } + else if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) + { + // There was no server key exchange message; check it's OK + this.keyExchange.SkipServerKeyExchange(); + } + + AssertEmpty(inStr); + + connection_state = CS_SERVER_HELLO_DONE_RECEIVED; + + TlsCredentials clientCreds = null; + if (certificateRequest == null) + { + this.keyExchange.SkipClientCredentials(); + } + else + { + clientCreds = this.authentication.GetClientCredentials(certificateRequest); + + Certificate clientCert; + if (clientCreds == null) + { + this.keyExchange.SkipClientCredentials(); + clientCert = Certificate.EmptyChain; + } + else + { + this.keyExchange.ProcessClientCredentials(clientCreds); + clientCert = clientCreds.Certificate; + } + + SendClientCertificate(clientCert); + } + + /* + * Send the client key exchange message, depending on the key + * exchange we are using in our CipherSuite. + */ + SendClientKeyExchange(); + + connection_state = CS_CLIENT_KEY_EXCHANGE_SEND; + + if (clientCreds != null && clientCreds is TlsSignerCredentials) + { + TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds; + byte[] md5andsha1 = rs.GetCurrentHash(); + byte[] clientCertificateSignature = signerCreds.GenerateCertificateSignature( + md5andsha1); + SendCertificateVerify(clientCertificateSignature); + + connection_state = CS_CERTIFICATE_VERIFY_SEND; + } + + /* + * Now, we send change cipher state + */ + byte[] cmessage = new byte[1]; + cmessage[0] = 1; + rs.WriteMessage(ContentType.change_cipher_spec, cmessage, 0, cmessage.Length); + + connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND; + + /* + * Calculate the master_secret + */ + byte[] pms = this.keyExchange.GeneratePremasterSecret(); + + securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret", + TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom), + 48); + + // 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. + */ + Array.Clear(pms, 0, pms.Length); + + /* + * Initialize our cipher suite + */ + rs.ClientCipherSpecDecided(tlsClient.GetCompression(), tlsClient.GetCipher()); + + /* + * Send our finished message. + */ + byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret, + "client finished", rs.GetCurrentHash(), 12); + + MemoryStream bos = new MemoryStream(); + TlsUtilities.WriteUint8((byte)HandshakeType.finished, bos); + TlsUtilities.WriteOpaque24(clientVerifyData, bos); + byte[] message = bos.ToArray(); + + rs.WriteMessage(ContentType.handshake, message, 0, message.Length); + + this.connection_state = CS_CLIENT_FINISHED_SEND; + break; + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); + break; + } + break; + case HandshakeType.server_key_exchange: + { + switch (connection_state) + { + case CS_SERVER_HELLO_RECEIVED: + case CS_SERVER_CERTIFICATE_RECEIVED: + { + // NB: Original code used case label fall-through + if (connection_state == CS_SERVER_HELLO_RECEIVED) + { + // There was no server certificate message; check it's OK + this.keyExchange.SkipServerCertificate(); + this.authentication = null; + } + + this.keyExchange.ProcessServerKeyExchange(inStr); + + AssertEmpty(inStr); + break; + } + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + + this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED; + break; + } + case HandshakeType.certificate_request: + switch (connection_state) + { + case CS_SERVER_CERTIFICATE_RECEIVED: + case CS_SERVER_KEY_EXCHANGE_RECEIVED: + { + // NB: Original code used case label fall-through + if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) + { + // There was no server key exchange message; check it's OK + this.keyExchange.SkipServerKeyExchange(); + } + + if (this.authentication == null) + { + /* + * RFC 2246 7.4.4. It is a fatal handshake_failure alert + * for an anonymous server to request client identification. + */ + this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); + } + + int numTypes = TlsUtilities.ReadUint8(inStr); + ClientCertificateType[] certificateTypes = new ClientCertificateType[numTypes]; + for (int i = 0; i < numTypes; ++i) + { + certificateTypes[i] = (ClientCertificateType)TlsUtilities.ReadUint8(inStr); + } + + byte[] authorities = TlsUtilities.ReadOpaque16(inStr); + + AssertEmpty(inStr); + + IList authorityDNs = Platform.CreateArrayList(); + + MemoryStream bis = new MemoryStream(authorities, false); + while (bis.Position < bis.Length) + { + byte[] dnBytes = TlsUtilities.ReadOpaque16(bis); + // TODO Switch to X500Name when available + authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes))); + } + + this.certificateRequest = new CertificateRequest(certificateTypes, + authorityDNs); + this.keyExchange.ValidateCertificateRequest(this.certificateRequest); + + break; + } + default: + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + + this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED; + break; + case HandshakeType.hello_request: + /* + * 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 (connection_state == CS_DONE) + { + // Renegotiation not supported yet + SendAlert(AlertLevel.warning, AlertDescription.no_renegotiation); + } + break; + case HandshakeType.client_key_exchange: + case HandshakeType.certificate_verify: + case HandshakeType.client_hello: + default: + // We do not support this! + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + break; + } + } + + 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() + { + while (alertQueue.Available >= 2) + { + /* + * An alert is always 2 bytes. Read the alert. + */ + byte[] tmp = alertQueue.RemoveData(2, 0); + byte level = tmp[0]; + byte description = tmp[1]; + if (level == (byte)AlertLevel.fatal) + { + this.failedWithError = true; + this.closed = true; + /* + * Now try to Close the stream, ignore errors. + */ + try + { + rs.Close(); + } + catch (Exception) + { + } + throw new IOException(TLS_ERROR_MESSAGE); + } + else + { + if (description == (byte)AlertDescription.close_notify) + { + HandleClose(false); + } + + /* + * If it is just a warning, we continue. + */ + } + } + } + + /** + * 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) + { + for (int i = 0; i < len; ++i) + { + if (buf[off + i] != 1) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.decode_error); + } + + /* + * Check if we are in the correct connection state. + */ + if (this.connection_state != CS_CLIENT_FINISHED_SEND) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); + } + + rs.ServerClientSpecReceived(); + + this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED; + } + } + + private void SendClientCertificate(Certificate clientCert) + { + MemoryStream bos = new MemoryStream(); + TlsUtilities.WriteUint8((byte)HandshakeType.certificate, bos); + + // Reserve space for length + TlsUtilities.WriteUint24(0, bos); + + clientCert.Encode(bos); + byte[] message = bos.ToArray(); + + // Patch actual length back in + TlsUtilities.WriteUint24(message.Length - 4, message, 1); + + rs.WriteMessage(ContentType.handshake, message, 0, message.Length); + } + + private void SendClientKeyExchange() + { + MemoryStream bos = new MemoryStream(); + TlsUtilities.WriteUint8((byte)HandshakeType.client_key_exchange, bos); + + // Reserve space for length + TlsUtilities.WriteUint24(0, bos); + + this.keyExchange.GenerateClientKeyExchange(bos); + byte[] message = bos.ToArray(); + + // Patch actual length back in + TlsUtilities.WriteUint24(message.Length - 4, message, 1); + + rs.WriteMessage(ContentType.handshake, message, 0, message.Length); + } + + private void SendCertificateVerify(byte[] data) + { + /* + * Send signature of handshake messages so far to prove we are the owner of + * the cert See RFC 2246 sections 4.7, 7.4.3 and 7.4.8 + */ + MemoryStream bos = new MemoryStream(); + TlsUtilities.WriteUint8((byte)HandshakeType.certificate_verify, bos); + TlsUtilities.WriteUint24(data.Length + 2, bos); + TlsUtilities.WriteOpaque16(data, bos); + byte[] message = bos.ToArray(); + + rs.WriteMessage(ContentType.handshake, message, 0, message.Length); + } + + /// Connects to the remote system. + /// Will be used when a certificate is received to verify + /// that this certificate is accepted by the client. + /// If handshake was not successful + [Obsolete("Use version taking TlsClient")] + public virtual void Connect( + ICertificateVerifyer verifyer) + { + this.Connect(new LegacyTlsClient(verifyer)); + } + + public virtual void Connect(TlsClient tlsClient) + { + if (tlsClient == null) + throw new ArgumentNullException("tlsClient"); + if (this.tlsClient != null) + throw new InvalidOperationException("Connect can only be called once"); + + /* + * Send Client hello + * + * First, generate some random data. + */ + this.securityParameters = new SecurityParameters(); + this.securityParameters.clientRandom = new byte[32]; + random.NextBytes(securityParameters.clientRandom, 4, 28); + TlsUtilities.WriteGmtUnixTime(securityParameters.clientRandom, 0); + + this.tlsClientContext = new TlsClientContextImpl(random, securityParameters); + this.tlsClient = tlsClient; + this.tlsClient.Init(tlsClientContext); + + MemoryStream outStr = new MemoryStream(); + TlsUtilities.WriteVersion(outStr); + outStr.Write(securityParameters.clientRandom, 0, 32); + + /* + * Length of Session id + */ + TlsUtilities.WriteUint8(0, outStr); + + this.offeredCipherSuites = this.tlsClient.GetCipherSuites(); + + // ExtensionType -> byte[] + this.clientExtensions = this.tlsClient.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. + */ + bool noRenegExt = clientExtensions == null + || !clientExtensions.Contains(ExtensionType.renegotiation_info); + + int count = offeredCipherSuites.Length; + if (noRenegExt) + { + // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + ++count; + } + + TlsUtilities.WriteUint16(2 * count, outStr); + + for (int i = 0; i < offeredCipherSuites.Length; ++i) + { + TlsUtilities.WriteUint16((int)offeredCipherSuites[i], outStr); + } + + if (noRenegExt) + { + TlsUtilities.WriteUint16((int)CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, outStr); + } + } + + /* + * Compression methods, just the null method. + */ + this.offeredCompressionMethods = tlsClient.GetCompressionMethods(); + + { + TlsUtilities.WriteUint8((byte)offeredCompressionMethods.Length, outStr); + for (int i = 0; i < offeredCompressionMethods.Length; ++i) + { + TlsUtilities.WriteUint8((byte)offeredCompressionMethods[i], outStr); + } + } + + // Extensions + if (clientExtensions != null) + { + MemoryStream ext = new MemoryStream(); + + foreach (ExtensionType extType in clientExtensions.Keys) + { + WriteExtension(ext, extType, (byte[])clientExtensions[extType]); + } + + TlsUtilities.WriteOpaque16(ext.ToArray(), outStr); + } + + MemoryStream bos = new MemoryStream(); + TlsUtilities.WriteUint8((byte)HandshakeType.client_hello, bos); + TlsUtilities.WriteUint24((int)outStr.Length, bos); + byte[] outBytes = outStr.ToArray(); + bos.Write(outBytes, 0, outBytes.Length); + byte[] message = bos.ToArray(); + SafeWriteMessage(ContentType.handshake, message, 0, message.Length); + connection_state = CS_CLIENT_HELLO_SEND; + + /* + * We will now read data, until we have completed the handshake. + */ + while (connection_state != CS_DONE) + { + SafeReadData(); + } + + this.tlsStream = new TlsStream(this); + } + + /** + * 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. + */ + internal int ReadApplicationData(byte[] buf, int offset, int len) + { + while (applicationDataQueue.Available == 0) + { + if (this.closed) + { + /* + * We need to read some data. + */ + 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 0; + } + + SafeReadData(); + } + len = System.Math.Min(len, applicationDataQueue.Available); + applicationDataQueue.RemoveData(buf, offset, len, 0); + return len; + } + + private void SafeReadData() + { + try + { + rs.ReadData(); + } + catch (TlsFatalAlert e) + { + if (!this.closed) + { + this.FailWithError(AlertLevel.fatal, e.AlertDescription); + } + throw e; + } + catch (IOException e) + { + if (!this.closed) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); + } + throw e; + } + catch (Exception e) + { + if (!this.closed) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); + } + throw e; + } + } + + private void SafeWriteMessage(ContentType type, byte[] buf, int offset, int len) + { + try + { + rs.WriteMessage(type, buf, offset, len); + } + catch (TlsFatalAlert e) + { + if (!this.closed) + { + this.FailWithError(AlertLevel.fatal, e.AlertDescription); + } + throw e; + } + catch (IOException e) + { + if (!closed) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); + } + throw e; + } + catch (Exception e) + { + if (!closed) + { + this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); + } + throw e; + } + } + + /** + * Send some application data to the remote system. + *

+ * 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. + */ + internal void WriteData(byte[] buf, int offset, int len) + { + 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) + { + /* + * Protect against known IV attack! + * + * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT + * YOU ARE DOING HERE. + */ + SafeWriteMessage(ContentType.application_data, emptybuf, 0, 0); + + /* + * We are only allowed to write fragments up to 2^14 bytes. + */ + int toWrite = System.Math.Min(len, 1 << 14); + + SafeWriteMessage(ContentType.application_data, buf, offset, toWrite); + + offset += toWrite; + len -= toWrite; + } + } + + ///

A Stream which can be used to send data. + [Obsolete("Use 'Stream' property instead")] + public virtual Stream OutputStream + { + get { return this.tlsStream; } + } + + /// A Stream which can be used to read data. + [Obsolete("Use 'Stream' property instead")] + public virtual Stream InputStream + { + get { return this.tlsStream; } + } + + /// The secure bidirectional stream for this connection + public virtual Stream Stream + { + get { return this.tlsStream; } + } + + /** + * Terminate this connection with an alert. + *

+ * Can be used for normal closure too. + * + * @param alertLevel The level of the alert, an be AlertLevel.fatal or AL_warning. + * @param alertDescription The exact alert message. + * @throws IOException If alert was fatal. + */ + private void FailWithError(AlertLevel alertLevel, AlertDescription alertDescription) + { + /* + * Check if the connection is still open. + */ + if (!closed) + { + /* + * Prepare the message + */ + this.closed = true; + + if (alertLevel == AlertLevel.fatal) + { + /* + * This is a fatal message. + */ + this.failedWithError = true; + } + SendAlert(alertLevel, alertDescription); + rs.Close(); + if (alertLevel == AlertLevel.fatal) + { + throw new IOException(TLS_ERROR_MESSAGE); + } + } + else + { + throw new IOException(TLS_ERROR_MESSAGE); + } + } + + internal void SendAlert(AlertLevel alertLevel, AlertDescription alertDescription) + { + byte[] error = new byte[2]; + error[0] = (byte)alertLevel; + error[1] = (byte)alertDescription; + + rs.WriteMessage(ContentType.alert, error, 0, 2); + } + + ///

Closes this connection + /// If something goes wrong during closing. + public virtual void Close() + { + HandleClose(true); + } + + protected virtual void HandleClose(bool user_canceled) + { + if (!closed) + { + if (user_canceled && !appDataReady) + { + SendAlert(AlertLevel.warning, AlertDescription.user_canceled); + } + this.FailWithError(AlertLevel.warning, AlertDescription.close_notify); + } + } + + /** + * Make sure the Stream is now empty. Fail otherwise. + * + * @param is The Stream to check. + * @throws IOException If is is not empty. + */ + internal void AssertEmpty( + MemoryStream inStr) + { + if (inStr.Position < inStr.Length) + { + throw new TlsFatalAlert(AlertDescription.decode_error); + } + } + + internal void Flush() + { + rs.Flush(); + } + + internal bool IsClosed + { + get { return closed; } + } + + private static bool ArrayContains(CipherSuite[] a, CipherSuite n) + { + for (int i = 0; i < a.Length; ++i) + { + if (a[i] == n) + return true; + } + return false; + } + + private static bool ArrayContains(CompressionMethod[] a, CompressionMethod n) + { + for (int i = 0; i < a.Length; ++i) + { + if (a[i] == n) + return true; + } + return false; + } + + private static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection) + { + MemoryStream buf = new MemoryStream(); + TlsUtilities.WriteOpaque8(renegotiated_connection, buf); + return buf.ToArray(); + } + + private static void WriteExtension(Stream output, ExtensionType extType, byte[] extValue) + { + TlsUtilities.WriteUint16((int)extType, output); + TlsUtilities.WriteOpaque16(extValue, output); + } + } +} diff --git a/crypto/src/crypto/tls/TlsPskIdentity.cs b/crypto/src/crypto/tls/TlsPskIdentity.cs new file mode 100644 index 000000000..119064ee7 --- /dev/null +++ b/crypto/src/crypto/tls/TlsPskIdentity.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsPskIdentity + { + void SkipIdentityHint(); + + void NotifyIdentityHint(byte[] psk_identity_hint); + + byte[] GetPskIdentity(); + + byte[] GetPsk(); + } +} diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs new file mode 100644 index 000000000..cadd643ca --- /dev/null +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -0,0 +1,206 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsPskKeyExchange + : TlsKeyExchange + { + protected TlsClientContext context; + protected KeyExchangeAlgorithm keyExchange; + protected TlsPskIdentity pskIdentity; + + protected byte[] psk_identity_hint = null; + + protected DHPublicKeyParameters dhAgreeServerPublicKey = null; + protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null; + + protected AsymmetricKeyParameter serverPublicKey = null; + protected RsaKeyParameters rsaServerPublicKey = null; + protected byte[] premasterSecret; + + internal TlsPskKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange, + TlsPskIdentity pskIdentity) + { + switch (keyExchange) + { + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + case KeyExchangeAlgorithm.DHE_PSK: + break; + default: + throw new ArgumentException("unsupported key exchange algorithm", "keyExchange"); + } + + this.context = context; + this.keyExchange = keyExchange; + this.pskIdentity = pskIdentity; + } + + public virtual void SkipServerCertificate() + { + if (keyExchange == KeyExchangeAlgorithm.RSA_PSK) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + if (keyExchange != KeyExchangeAlgorithm.RSA_PSK) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + X509CertificateStructure x509Cert = serverCertificate.certs[0]; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + + try + { + this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + } + // catch (RuntimeException) + catch (Exception) + { + 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); + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); + + // TODO + /* + * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the + * signing algorithm for the certificate must be the same as the algorithm for the + * certificate key." + */ + } + + public virtual void SkipServerKeyExchange() + { + if (keyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + this.psk_identity_hint = new byte[0]; + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + this.psk_identity_hint = TlsUtilities.ReadOpaque16(input); + + if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + byte[] pBytes = TlsUtilities.ReadOpaque16(input); + byte[] gBytes = TlsUtilities.ReadOpaque16(input); + byte[] YsBytes = TlsUtilities.ReadOpaque16(input); + + BigInteger p = new BigInteger(1, pBytes); + BigInteger g = new BigInteger(1, gBytes); + BigInteger Ys = new BigInteger(1, YsBytes); + + this.dhAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey( + new DHPublicKeyParameters(Ys, new DHParameters(p, g))); + } + else if (this.psk_identity_hint.Length == 0) + { + // TODO Should we enforce that this message should have been skipped if hint is empty? + //throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void SkipClientCredentials() + { + // OK + } + + public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + public virtual void GenerateClientKeyExchange(Stream output) + { + if (psk_identity_hint == null || psk_identity_hint.Length == 0) + { + pskIdentity.SkipIdentityHint(); + } + else + { + pskIdentity.NotifyIdentityHint(psk_identity_hint); + } + + byte[] psk_identity = pskIdentity.GetPskIdentity(); + + TlsUtilities.WriteOpaque16(psk_identity, output); + + if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK) + { + this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret( + context.SecureRandom, this.rsaServerPublicKey, output); + } + else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange( + context.SecureRandom, this.dhAgreeServerPublicKey.Parameters, output); + } + } + + public virtual byte[] GeneratePremasterSecret() + { + byte[] psk = pskIdentity.GetPsk(); + byte[] other_secret = GenerateOtherSecret(psk.Length); + + MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length); + TlsUtilities.WriteOpaque16(other_secret, buf); + TlsUtilities.WriteOpaque16(psk, buf); + return buf.ToArray(); + } + + protected virtual byte[] GenerateOtherSecret(int pskLength) + { + if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + return TlsDHUtilities.CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey); + } + + if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK) + { + return this.premasterSecret; + } + + return new byte[pskLength]; + } + + protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key) + { + // TODO What is the minimum bit length required? + // key.Modulus.BitLength; + + if (!key.Exponent.IsProbablePrime(2)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + return key; + } + } +} diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs new file mode 100644 index 000000000..ad61f08de --- /dev/null +++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs @@ -0,0 +1,165 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// TLS 1.0 RSA key exchange. + /// + internal class TlsRsaKeyExchange + : TlsKeyExchange + { + protected TlsClientContext context; + + protected AsymmetricKeyParameter serverPublicKey = null; + + protected RsaKeyParameters rsaServerPublicKey = null; + + protected byte[] premasterSecret; + + internal TlsRsaKeyExchange(TlsClientContext context) + { + this.context = context; + } + + public virtual void SkipServerCertificate() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure x509Cert = serverCertificate.certs[0]; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + + try + { + this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + } +// catch (RuntimeException) + catch (Exception) + { + 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); + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); + + // TODO + /* + * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the + * signing algorithm for the certificate must be the same as the algorithm for the + * certificate key." + */ + } + + public virtual void SkipServerKeyExchange() + { + // OK + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + ClientCertificateType[] types = certificateRequest.CertificateTypes; + foreach (ClientCertificateType type in types) + { + switch (type) + { + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.ecdsa_sign: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + } + } + + public virtual void SkipClientCredentials() + { + // OK + } + + public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + { + if (!(clientCredentials is TlsSignerCredentials)) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public virtual void GenerateClientKeyExchange(Stream output) + { + this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret( + context.SecureRandom, this.rsaServerPublicKey, output); + } + + public virtual byte[] GeneratePremasterSecret() + { + byte[] tmp = this.premasterSecret; + this.premasterSecret = null; + return tmp; + } + + // Would be needed to process RSA_EXPORT server key exchange +// protected virtual void ProcessRsaServerKeyExchange(Stream input, ISigner signer) +// { +// Stream sigIn = input; +// if (signer != null) +// { +// sigIn = new SignerStream(input, signer, null); +// } +// +// byte[] modulusBytes = TlsUtilities.ReadOpaque16(sigIn); +// byte[] exponentBytes = TlsUtilities.ReadOpaque16(sigIn); +// +// if (signer != null) +// { +// byte[] sigByte = TlsUtilities.ReadOpaque16(input); +// +// if (!signer.VerifySignature(sigByte)) +// { +// handler.FailWithError(AlertLevel.fatal, AlertDescription.decrypt_error); +// } +// } +// +// BigInteger modulus = new BigInteger(1, modulusBytes); +// BigInteger exponent = new BigInteger(1, exponentBytes); +// +// this.rsaServerPublicKey = ValidateRSAPublicKey(new RsaKeyParameters(false, modulus, exponent)); +// } + + protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key) + { + // TODO What is the minimum bit length required? +// key.Modulus.BitLength; + + if (!key.Exponent.IsProbablePrime(2)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + return key; + } + } +} diff --git a/crypto/src/crypto/tls/TlsRsaSigner.cs b/crypto/src/crypto/tls/TlsRsaSigner.cs new file mode 100644 index 000000000..ce18ef5e1 --- /dev/null +++ b/crypto/src/crypto/tls/TlsRsaSigner.cs @@ -0,0 +1,60 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsRsaSigner + : TlsSigner + { + public virtual byte[] GenerateRawSignature(SecureRandom random, + AsymmetricKeyParameter privateKey, byte[] md5AndSha1) + { + IAsymmetricBlockCipher engine = CreateRsaImpl(); + engine.Init(true, new ParametersWithRandom(privateKey, random)); + return engine.ProcessBlock(md5AndSha1, 0, md5AndSha1.Length); + } + + public virtual bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, + byte[] md5AndSha1) + { + IAsymmetricBlockCipher engine = CreateRsaImpl(); + engine.Init(false, publicKey); + byte[] signed = engine.ProcessBlock(sigBytes, 0, sigBytes.Length); + return Arrays.ConstantTimeAreEqual(signed, md5AndSha1); + } + + public virtual ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey) + { + return MakeSigner(new CombinedHash(), true, new ParametersWithRandom(privateKey, random)); + } + + public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey) + { + return MakeSigner(new CombinedHash(), false, publicKey); + } + + public virtual bool IsValidPublicKey(AsymmetricKeyParameter publicKey) + { + return publicKey is RsaKeyParameters && !publicKey.IsPrivate; + } + + protected virtual ISigner MakeSigner(IDigest d, bool forSigning, ICipherParameters cp) + { + ISigner s = new GenericSigner(CreateRsaImpl(), d); + s.Init(forSigning, cp); + return s; + } + + protected virtual IAsymmetricBlockCipher CreateRsaImpl() + { + return new Pkcs1Encoding(new RsaBlindedEngine()); + } + } +} diff --git a/crypto/src/crypto/tls/TlsRsaUtilities.cs b/crypto/src/crypto/tls/TlsRsaUtilities.cs new file mode 100644 index 000000000..4450ba452 --- /dev/null +++ b/crypto/src/crypto/tls/TlsRsaUtilities.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class TlsRsaUtilities + { + public static byte[] GenerateEncryptedPreMasterSecret(SecureRandom random, + RsaKeyParameters rsaServerPublicKey, Stream output) + { + /* + * Choose a PremasterSecret and send it encrypted to the server + */ + byte[] premasterSecret = new byte[48]; + random.NextBytes(premasterSecret); + TlsUtilities.WriteVersion(premasterSecret, 0); + + Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine()); + encoding.Init(true, new ParametersWithRandom(rsaServerPublicKey, random)); + + try + { + byte[] keData = encoding.ProcessBlock(premasterSecret, 0, premasterSecret.Length); + TlsUtilities.WriteOpaque16(keData, output); + } + catch (InvalidCipherTextException) + { + /* + * This should never happen, only during decryption. + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + return premasterSecret; + } + } +} diff --git a/crypto/src/crypto/tls/TlsSigner.cs b/crypto/src/crypto/tls/TlsSigner.cs new file mode 100644 index 000000000..79d468fee --- /dev/null +++ b/crypto/src/crypto/tls/TlsSigner.cs @@ -0,0 +1,18 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSigner + { + byte[] GenerateRawSignature(SecureRandom random, AsymmetricKeyParameter privateKey, + byte[] md5andsha1); + bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5andsha1); + + ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey); + ISigner CreateVerifyer(AsymmetricKeyParameter publicKey); + + bool IsValidPublicKey(AsymmetricKeyParameter publicKey); + } +} diff --git a/crypto/src/crypto/tls/TlsSignerCredentials.cs b/crypto/src/crypto/tls/TlsSignerCredentials.cs new file mode 100644 index 000000000..2adb06c26 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSignerCredentials.cs @@ -0,0 +1,11 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSignerCredentials : TlsCredentials + { + /// + byte[] GenerateCertificateSignature(byte[] md5andsha1); + } +} diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs new file mode 100644 index 000000000..cb4e26e58 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs @@ -0,0 +1,203 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// + /// TLS 1.1 SRP key exchange. + /// + internal class TlsSrpKeyExchange + : TlsKeyExchange + { + protected TlsClientContext context; + protected KeyExchangeAlgorithm keyExchange; + 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(); + + internal TlsSrpKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange, + byte[] identity, byte[] password) + { + 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 ArgumentException("unsupported key exchange algorithm", "keyExchange"); + } + + this.context = context; + this.keyExchange = keyExchange; + this.identity = identity; + this.password = password; + } + + public virtual void SkipServerCertificate() + { + if (tlsSigner != null) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + if (tlsSigner == null) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + X509CertificateStructure x509Cert = serverCertificate.certs[0]; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + + try + { + this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + } +// catch (RuntimeException) + catch (Exception) + { + throw new TlsFatalAlert(AlertDescription.unsupported_certificate); + } + + if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); + + // TODO + /* + * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the + * signing algorithm for the certificate must be the same as the algorithm for the + * certificate key." + */ + } + + public virtual void SkipServerKeyExchange() + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + SecurityParameters securityParameters = context.SecurityParameters; + + Stream sigIn = input; + ISigner signer = null; + + if (tlsSigner != null) + { + signer = InitSigner(tlsSigner, securityParameters); + sigIn = new SignerStream(input, signer, null); + } + + byte[] NBytes = TlsUtilities.ReadOpaque16(sigIn); + byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn); + byte[] sBytes = TlsUtilities.ReadOpaque8(sigIn); + byte[] BBytes = TlsUtilities.ReadOpaque16(sigIn); + + if (signer != null) + { + byte[] sigByte = TlsUtilities.ReadOpaque16(input); + + if (!signer.VerifySignature(sigByte)) + { + 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 = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes)); + } + catch (CryptoException) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + this.srpClient.Init(N, g, new Sha1Digest(), context.SecureRandom); + } + + public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void SkipClientCredentials() + { + // OK + } + + public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + public virtual void GenerateClientKeyExchange(Stream output) + { + byte[] keData = BigIntegers.AsUnsignedByteArray(srpClient.GenerateClientCredentials(s, + this.identity, this.password)); + TlsUtilities.WriteOpaque16(keData, output); + } + + public virtual byte[] GeneratePremasterSecret() + { + try + { + // TODO Check if this needs to be a fixed size + return BigIntegers.AsUnsignedByteArray(srpClient.CalculateSecret(B)); + } + catch (CryptoException) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + } + + protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + { + ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + return signer; + } + } +} diff --git a/crypto/src/crypto/tls/TlsStream.cs b/crypto/src/crypto/tls/TlsStream.cs new file mode 100644 index 000000000..fe24ad3ed --- /dev/null +++ b/crypto/src/crypto/tls/TlsStream.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + internal class TlsStream + : Stream + { + private readonly TlsProtocolHandler handler; + + internal TlsStream( + TlsProtocolHandler handler) + { + this.handler = handler; + } + + public override bool CanRead + { + get { return !handler.IsClosed; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return !handler.IsClosed; } + } + + public override void Close() + { + handler.Close(); + } + + public override void Flush() + { + handler.Flush(); + } + + public override long Length + { + get { throw new NotSupportedException(); } + } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + public override int Read(byte[] buf, int off, int len) + { + return this.handler.ReadApplicationData(buf, off, len); + } + + public override int ReadByte() + { + byte[] buf = new byte[1]; + if (this.Read(buf, 0, 1) <= 0) + return -1; + return buf[0]; + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buf, int off, int len) + { + this.handler.WriteData(buf, off, len); + } + + public override void WriteByte(byte b) + { + this.handler.WriteData(new byte[] { b }, 0, 1); + } + } +} diff --git a/crypto/src/crypto/tls/TlsStreamCipher.cs b/crypto/src/crypto/tls/TlsStreamCipher.cs new file mode 100644 index 000000000..65d6054ff --- /dev/null +++ b/crypto/src/crypto/tls/TlsStreamCipher.cs @@ -0,0 +1,108 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Tls; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsStreamCipher : TlsCipher + { + protected TlsClientContext context; + + protected IStreamCipher encryptCipher; + protected IStreamCipher decryptCipher; + + protected TlsMac writeMac; + protected TlsMac readMac; + + public TlsStreamCipher(TlsClientContext context, IStreamCipher encryptCipher, + IStreamCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize) + { + this.context = context; + this.encryptCipher = encryptCipher; + this.decryptCipher = decryptCipher; + + int prfSize = (2 * cipherKeySize) + writeDigest.GetDigestSize() + + readDigest.GetDigestSize(); + + SecurityParameters securityParameters = context.SecurityParameters; + + byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion", + TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom), + prfSize); + + int offset = 0; + + // Init MACs + writeMac = CreateTlsMac(writeDigest, keyBlock, ref offset); + readMac = CreateTlsMac(readDigest, keyBlock, ref offset); + + // Build keys + KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize); + KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize); + + if (offset != prfSize) + throw new TlsFatalAlert(AlertDescription.internal_error); + + // Init Ciphers + encryptCipher.Init(true, encryptKey); + decryptCipher.Init(false, decryptKey); + } + + public byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len) + { + byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len); + int size = len + mac.Length; + + byte[] outbuf = new byte[size]; + + encryptCipher.ProcessBytes(plaintext, offset, len, outbuf, 0); + encryptCipher.ProcessBytes(mac, 0, mac.Length, outbuf, len); + + return outbuf; + } + + public byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len) + { + byte[] deciphered = new byte[len]; + decryptCipher.ProcessBytes(ciphertext, offset, len, deciphered, 0); + + int plaintextSize = deciphered.Length - readMac.Size; + byte[] plainText = CopyData(deciphered, 0, plaintextSize); + + byte[] receivedMac = CopyData(deciphered, plaintextSize, readMac.Size); + byte[] computedMac = readMac.CalculateMac(type, plainText, 0, plainText.Length); + + if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac)) + { + throw new TlsFatalAlert(AlertDescription.bad_record_mac); + } + + return plainText; + } + + protected virtual TlsMac CreateTlsMac(IDigest digest, byte[] buf, ref int off) + { + int len = digest.GetDigestSize(); + TlsMac mac = new TlsMac(digest, buf, off, len); + off += len; + return mac; + } + + protected virtual KeyParameter CreateKeyParameter(byte[] buf, ref int off, int len) + { + KeyParameter key = new KeyParameter(buf, off, len); + off += len; + return key; + } + + protected virtual byte[] CopyData(byte[] text, int offset, int len) + { + byte[] result = new byte[len]; + Array.Copy(text, offset, result, 0, len); + return result; + } + } +} diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs new file mode 100644 index 000000000..dca842a80 --- /dev/null +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -0,0 +1,286 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /// Some helper functions for MicroTLS. + public class TlsUtilities + { + internal static void WriteUint8(byte i, Stream os) + { + os.WriteByte(i); + } + + internal static void WriteUint8(byte i, byte[] buf, int offset) + { + buf[offset] = i; + } + + internal static void WriteUint16(int i, Stream os) + { + os.WriteByte((byte)(i >> 8)); + os.WriteByte((byte)i); + } + + internal static void WriteUint16(int i, byte[] buf, int offset) + { + buf[offset] = (byte)(i >> 8); + buf[offset + 1] = (byte)i; + } + + internal static void WriteUint24(int i, Stream os) + { + os.WriteByte((byte)(i >> 16)); + os.WriteByte((byte)(i >> 8)); + os.WriteByte((byte)i); + } + + internal 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); + } + + internal static void WriteUint64(long i, Stream os) + { + os.WriteByte((byte)(i >> 56)); + os.WriteByte((byte)(i >> 48)); + os.WriteByte((byte)(i >> 40)); + os.WriteByte((byte)(i >> 32)); + os.WriteByte((byte)(i >> 24)); + os.WriteByte((byte)(i >> 16)); + os.WriteByte((byte)(i >> 8)); + os.WriteByte((byte)i); + } + + internal 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); + } + + internal static void WriteOpaque8(byte[] buf, Stream os) + { + WriteUint8((byte)buf.Length, os); + os.Write(buf, 0, buf.Length); + } + + internal static void WriteOpaque16(byte[] buf, Stream os) + { + WriteUint16(buf.Length, os); + os.Write(buf, 0, buf.Length); + } + + internal static void WriteOpaque24(byte[] buf, Stream os) + { + WriteUint24(buf.Length, os); + os.Write(buf, 0, buf.Length); + } + + internal static void WriteUint8Array(byte[] uints, Stream os) + { + os.Write(uints, 0, uints.Length); + } + + internal static void WriteUint16Array(int[] uints, Stream os) + { + for (int i = 0; i < uints.Length; ++i) + { + WriteUint16(uints[i], os); + } + } + + internal static byte ReadUint8(Stream inStr) + { + int i = inStr.ReadByte(); + if (i < 0) + { + throw new EndOfStreamException(); + } + return (byte)i; + } + + internal static int ReadUint16(Stream inStr) + { + int i1 = inStr.ReadByte(); + int i2 = inStr.ReadByte(); + if ((i1 | i2) < 0) + { + throw new EndOfStreamException(); + } + return i1 << 8 | i2; + } + + internal static int ReadUint24(Stream inStr) + { + int i1 = inStr.ReadByte(); + int i2 = inStr.ReadByte(); + int i3 = inStr.ReadByte(); + if ((i1 | i2 | i3) < 0) + { + throw new EndOfStreamException(); + } + return (i1 << 16) | (i2 << 8) | i3; + } + + internal static void ReadFully(byte[] buf, Stream inStr) + { + if (Streams.ReadFully(inStr, buf, 0, buf.Length) < buf.Length) + throw new EndOfStreamException(); + } + + internal static byte[] ReadOpaque8(Stream inStr) + { + byte length = ReadUint8(inStr); + byte[] bytes = new byte[length]; + ReadFully(bytes, inStr); + return bytes; + } + + internal static byte[] ReadOpaque16(Stream inStr) + { + int length = ReadUint16(inStr); + byte[] bytes = new byte[length]; + ReadFully(bytes, inStr); + return bytes; + } + + internal static void CheckVersion(byte[] readVersion) + { + if ((readVersion[0] != 3) || (readVersion[1] != 1)) + { + throw new TlsFatalAlert(AlertDescription.protocol_version); + } + } + + internal static void CheckVersion(Stream inStr) + { + int i1 = inStr.ReadByte(); + int i2 = inStr.ReadByte(); + if ((i1 != 3) || (i2 != 1)) + { + throw new TlsFatalAlert(AlertDescription.protocol_version); + } + } + + internal static void WriteGmtUnixTime(byte[] buf, int offset) + { + int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L); + buf[offset] = (byte)(t >> 24); + buf[offset + 1] = (byte)(t >> 16); + buf[offset + 2] = (byte)(t >> 8); + buf[offset + 3] = (byte)t; + } + + internal static void WriteVersion(Stream os) + { + os.WriteByte(3); + os.WriteByte(1); + } + + internal static void WriteVersion(byte[] buf, int offset) + { + buf[offset] = 3; + buf[offset + 1] = 1; + } + + private static void hmac_hash(IDigest digest, byte[] secret, byte[] seed, byte[] output) + { + HMac mac = new HMac(digest); + KeyParameter param = new KeyParameter(secret); + byte[] a = seed; + int size = digest.GetDigestSize(); + int iterations = (output.Length + size - 1) / size; + byte[] buf = new byte[mac.GetMacSize()]; + byte[] buf2 = new byte[mac.GetMacSize()]; + for (int i = 0; i < iterations; i++) + { + mac.Init(param); + mac.BlockUpdate(a, 0, a.Length); + mac.DoFinal(buf, 0); + a = buf; + mac.Init(param); + mac.BlockUpdate(a, 0, a.Length); + mac.BlockUpdate(seed, 0, seed.Length); + mac.DoFinal(buf2, 0); + Array.Copy(buf2, 0, output, (size * i), System.Math.Min(size, output.Length - (size * i))); + } + } + + internal static byte[] PRF(byte[] secret, string asciiLabel, byte[] seed, int size) + { + byte[] label = Strings.ToAsciiByteArray(asciiLabel); + + int s_half = (secret.Length + 1) / 2; + byte[] s1 = new byte[s_half]; + byte[] s2 = new byte[s_half]; + Array.Copy(secret, 0, s1, 0, s_half); + Array.Copy(secret, secret.Length - s_half, s2, 0, s_half); + + byte[] ls = Concat(label, seed); + + byte[] buf = new byte[size]; + byte[] prf = new byte[size]; + hmac_hash(new MD5Digest(), s1, ls, prf); + hmac_hash(new Sha1Digest(), s2, ls, buf); + for (int i = 0; i < size; i++) + { + buf[i] ^= prf[i]; + } + return buf; + } + + internal static byte[] PRF_1_2(IDigest digest, byte[] secret, string asciiLabel, byte[] seed, int size) + { + byte[] label = Strings.ToAsciiByteArray(asciiLabel); + byte[] labelSeed = Concat(label, seed); + + byte[] buf = new byte[size]; + hmac_hash(digest, secret, labelSeed, buf); + return buf; + } + + internal static byte[] Concat(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length + b.Length]; + Array.Copy(a, 0, c, 0, a.Length); + Array.Copy(b, 0, c, a.Length, b.Length); + return c; + } + + internal static void ValidateKeyUsage(X509CertificateStructure c, int keyUsageBits) + { + X509Extensions exts = c.TbsCertificate.Extensions; + if (exts != null) + { + X509Extension ext = exts.GetExtension(X509Extensions.KeyUsage); + if (ext != null) + { + DerBitString ku = KeyUsage.GetInstance(ext); + int bits = ku.GetBytes()[0]; + if ((bits & keyUsageBits) != keyUsageBits) + { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + } + } + } + } +} diff --git a/crypto/src/crypto/util/Pack.cs b/crypto/src/crypto/util/Pack.cs new file mode 100644 index 000000000..1fd21ee53 --- /dev/null +++ b/crypto/src/crypto/util/Pack.cs @@ -0,0 +1,257 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Utilities +{ + internal sealed class Pack + { + private Pack() + { + } + + internal static void UInt16_To_BE(ushort n, byte[] bs) + { + bs[0] = (byte)(n >> 8); + bs[1] = (byte)(n); + } + + internal static void UInt16_To_BE(ushort n, byte[] bs, int off) + { + bs[off] = (byte)(n >> 8); + bs[off + 1] = (byte)(n); + } + + internal static ushort BE_To_UInt16(byte[] bs) + { + uint n = (uint)bs[0] << 8 + | (uint)bs[1]; + return (ushort)n; + } + + internal static ushort BE_To_UInt16(byte[] bs, int off) + { + uint n = (uint)bs[off] << 8 + | (uint)bs[off + 1]; + return (ushort)n; + } + + internal static byte[] UInt32_To_BE(uint n) + { + byte[] bs = new byte[4]; + UInt32_To_BE(n, bs, 0); + return bs; + } + + internal static void UInt32_To_BE(uint n, byte[] bs) + { + bs[0] = (byte)(n >> 24); + bs[1] = (byte)(n >> 16); + bs[2] = (byte)(n >> 8); + bs[3] = (byte)(n); + } + + internal static void UInt32_To_BE(uint n, byte[] bs, int off) + { + bs[off] = (byte)(n >> 24); + bs[off + 1] = (byte)(n >> 16); + bs[off + 2] = (byte)(n >> 8); + bs[off + 3] = (byte)(n); + } + + internal static byte[] UInt32_To_BE(uint[] ns) + { + byte[] bs = new byte[4 * ns.Length]; + UInt32_To_BE(ns, bs, 0); + return bs; + } + + internal static void UInt32_To_BE(uint[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.Length; ++i) + { + UInt32_To_BE(ns[i], bs, off); + off += 4; + } + } + + internal static uint BE_To_UInt32(byte[] bs) + { + return (uint)bs[0] << 24 + | (uint)bs[1] << 16 + | (uint)bs[2] << 8 + | (uint)bs[3]; + } + + internal static uint BE_To_UInt32(byte[] bs, int off) + { + return (uint)bs[off] << 24 + | (uint)bs[off + 1] << 16 + | (uint)bs[off + 2] << 8 + | (uint)bs[off + 3]; + } + + internal static void BE_To_UInt32(byte[] bs, int off, uint[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = BE_To_UInt32(bs, off); + off += 4; + } + } + + internal static byte[] UInt64_To_BE(ulong n) + { + byte[] bs = new byte[8]; + UInt64_To_BE(n, bs, 0); + return bs; + } + + internal static void UInt64_To_BE(ulong n, byte[] bs) + { + UInt32_To_BE((uint)(n >> 32), bs); + UInt32_To_BE((uint)(n), bs, 4); + } + + internal static void UInt64_To_BE(ulong n, byte[] bs, int off) + { + UInt32_To_BE((uint)(n >> 32), bs, off); + UInt32_To_BE((uint)(n), bs, off + 4); + } + + internal static ulong BE_To_UInt64(byte[] bs) + { + uint hi = BE_To_UInt32(bs); + uint lo = BE_To_UInt32(bs, 4); + return ((ulong)hi << 32) | (ulong)lo; + } + + internal static ulong BE_To_UInt64(byte[] bs, int off) + { + uint hi = BE_To_UInt32(bs, off); + uint lo = BE_To_UInt32(bs, off + 4); + return ((ulong)hi << 32) | (ulong)lo; + } + + internal static void UInt16_To_LE(ushort n, byte[] bs) + { + bs[0] = (byte)(n); + bs[1] = (byte)(n >> 8); + } + + internal static void UInt16_To_LE(ushort n, byte[] bs, int off) + { + bs[off] = (byte)(n); + bs[off + 1] = (byte)(n >> 8); + } + + internal static ushort LE_To_UInt16(byte[] bs) + { + uint n = (uint)bs[0] + | (uint)bs[1] << 8; + return (ushort)n; + } + + internal static ushort LE_To_UInt16(byte[] bs, int off) + { + uint n = (uint)bs[off] + | (uint)bs[off + 1] << 8; + return (ushort)n; + } + + internal static byte[] UInt32_To_LE(uint n) + { + byte[] bs = new byte[4]; + UInt32_To_LE(n, bs, 0); + return bs; + } + + internal static void UInt32_To_LE(uint n, byte[] bs) + { + bs[0] = (byte)(n); + bs[1] = (byte)(n >> 8); + bs[2] = (byte)(n >> 16); + bs[3] = (byte)(n >> 24); + } + + internal static void UInt32_To_LE(uint n, byte[] bs, int off) + { + bs[off] = (byte)(n); + bs[off + 1] = (byte)(n >> 8); + bs[off + 2] = (byte)(n >> 16); + bs[off + 3] = (byte)(n >> 24); + } + + internal static byte[] UInt32_To_LE(uint[] ns) + { + byte[] bs = new byte[4 * ns.Length]; + UInt32_To_LE(ns, bs, 0); + return bs; + } + + internal static void UInt32_To_LE(uint[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.Length; ++i) + { + UInt32_To_LE(ns[i], bs, off); + off += 4; + } + } + + internal static uint LE_To_UInt32(byte[] bs) + { + return (uint)bs[0] + | (uint)bs[1] << 8 + | (uint)bs[2] << 16 + | (uint)bs[3] << 24; + } + + internal static uint LE_To_UInt32(byte[] bs, int off) + { + return (uint)bs[off] + | (uint)bs[off + 1] << 8 + | (uint)bs[off + 2] << 16 + | (uint)bs[off + 3] << 24; + } + + internal static void LE_To_UInt32(byte[] bs, int off, uint[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = LE_To_UInt32(bs, off); + off += 4; + } + } + + internal static byte[] UInt64_To_LE(ulong n) + { + byte[] bs = new byte[8]; + UInt64_To_LE(n, bs, 0); + return bs; + } + + internal static void UInt64_To_LE(ulong n, byte[] bs) + { + UInt32_To_LE((uint)(n), bs); + UInt32_To_LE((uint)(n >> 32), bs, 4); + } + + internal static void UInt64_To_LE(ulong n, byte[] bs, int off) + { + UInt32_To_LE((uint)(n), bs, off); + UInt32_To_LE((uint)(n >> 32), bs, off + 4); + } + + internal static ulong LE_To_UInt64(byte[] bs) + { + uint lo = LE_To_UInt32(bs); + uint hi = LE_To_UInt32(bs, 4); + return ((ulong)hi << 32) | (ulong)lo; + } + + internal static ulong LE_To_UInt64(byte[] bs, int off) + { + uint lo = LE_To_UInt32(bs, off); + uint hi = LE_To_UInt32(bs, off + 4); + return ((ulong)hi << 32) | (ulong)lo; + } + } +} diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs new file mode 100644 index 000000000..00f8f399d --- /dev/null +++ b/crypto/src/math/BigInteger.cs @@ -0,0 +1,3575 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.Globalization; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class BigInteger + { + // The first few odd primes + /* + 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 + */ + + // Each list has a product < 2^31 + internal static readonly int[][] primeLists = new int[][] + { + new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 }, + new int[]{ 29, 31, 37, 41, 43 }, + new int[]{ 47, 53, 59, 61, 67 }, + new int[]{ 71, 73, 79, 83 }, + new int[]{ 89, 97, 101, 103 }, + + new int[]{ 107, 109, 113, 127 }, + new int[]{ 131, 137, 139, 149 }, + new int[]{ 151, 157, 163, 167 }, + new int[]{ 173, 179, 181, 191 }, + new int[]{ 193, 197, 199, 211 }, + + new int[]{ 223, 227, 229 }, + new int[]{ 233, 239, 241 }, + new int[]{ 251, 257, 263 }, + new int[]{ 269, 271, 277 }, + new int[]{ 281, 283, 293 }, + + new int[]{ 307, 311, 313 }, + new int[]{ 317, 331, 337 }, + new int[]{ 347, 349, 353 }, + new int[]{ 359, 367, 373 }, + new int[]{ 379, 383, 389 }, + + new int[]{ 397, 401, 409 }, + new int[]{ 419, 421, 431 }, + new int[]{ 433, 439, 443 }, + new int[]{ 449, 457, 461 }, + new int[]{ 463, 467, 479 }, + + new int[]{ 487, 491, 499 }, + new int[]{ 503, 509, 521 }, + new int[]{ 523, 541, 547 }, + new int[]{ 557, 563, 569 }, + new int[]{ 571, 577, 587 }, + + new int[]{ 593, 599, 601 }, + new int[]{ 607, 613, 617 }, + new int[]{ 619, 631, 641 }, + new int[]{ 643, 647, 653 }, + new int[]{ 659, 661, 673 }, + + new int[]{ 677, 683, 691 }, + new int[]{ 701, 709, 719 }, + new int[]{ 727, 733, 739 }, + new int[]{ 743, 751, 757 }, + new int[]{ 761, 769, 773 }, + + new int[]{ 787, 797, 809 }, + new int[]{ 811, 821, 823 }, + new int[]{ 827, 829, 839 }, + new int[]{ 853, 857, 859 }, + new int[]{ 863, 877, 881 }, + + new int[]{ 883, 887, 907 }, + new int[]{ 911, 919, 929 }, + new int[]{ 937, 941, 947 }, + new int[]{ 953, 967, 971 }, + new int[]{ 977, 983, 991 }, + + new int[]{ 997, 1009, 1013 }, + new int[]{ 1019, 1021, 1031 }, + new int[]{ 1033, 1039, 1049 }, + new int[]{ 1051, 1061, 1063 }, + new int[]{ 1069, 1087, 1091 }, + + new int[]{ 1093, 1097, 1103 }, + new int[]{ 1109, 1117, 1123 }, + new int[]{ 1129, 1151, 1153 }, + new int[]{ 1163, 1171, 1181 }, + new int[]{ 1187, 1193, 1201 }, + + new int[]{ 1213, 1217, 1223 }, + new int[]{ 1229, 1231, 1237 }, + new int[]{ 1249, 1259, 1277 }, + new int[]{ 1279, 1283, 1289 }, + }; + + internal static readonly int[] primeProducts; + + private const long IMASK = 0xFFFFFFFFL; + private const ulong UIMASK = 0xFFFFFFFFUL; + + private static readonly int[] ZeroMagnitude = new int[0]; + private static readonly byte[] ZeroEncoding = new byte[0]; + + private static readonly BigInteger[] SMALL_CONSTANTS = new BigInteger[17]; + public static readonly BigInteger Zero; + public static readonly BigInteger One; + public static readonly BigInteger Two; + public static readonly BigInteger Three; + public static readonly BigInteger Ten; + + //private readonly static byte[] BitCountTable = + //{ + // 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + // 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + //}; + + private readonly static byte[] BitLengthTable = + { + 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 Parse radix-2 64 bits at a time and radix-8 63 bits at a time + private const int chunk2 = 1, chunk8 = 1, chunk10 = 19, chunk16 = 16; + private static readonly BigInteger radix2, radix2E, radix8, radix8E, radix10, radix10E, radix16, radix16E; + + private static readonly Random RandomSource = new Random(); + + /* + * These are the threshold bit-lengths (of an exponent) where we increase the window size. + * They are calculated according to the expected savings in multiplications. + * Some squares will also be saved on average, but we offset these against the extra storage costs. + */ + private static readonly int[] ExpWindowThresholds = { 7, 25, 81, 241, 673, 1793, 4609, Int32.MaxValue }; + + private const int BitsPerByte = 8; + private const int BitsPerInt = 32; + private const int BytesPerInt = 4; + + static BigInteger() + { + Zero = new BigInteger(0, ZeroMagnitude, false); + Zero.nBits = 0; Zero.nBitLength = 0; + + SMALL_CONSTANTS[0] = Zero; + for (uint i = 1; i < SMALL_CONSTANTS.Length; ++i) + { + SMALL_CONSTANTS[i] = CreateUValueOf(i); + } + + One = SMALL_CONSTANTS[1]; + Two = SMALL_CONSTANTS[2]; + Three = SMALL_CONSTANTS[3]; + Ten = SMALL_CONSTANTS[10]; + + radix2 = ValueOf(2); + radix2E = radix2.Pow(chunk2); + + radix8 = ValueOf(8); + radix8E = radix8.Pow(chunk8); + + radix10 = ValueOf(10); + radix10E = radix10.Pow(chunk10); + + radix16 = ValueOf(16); + radix16E = radix16.Pow(chunk16); + + primeProducts = new int[primeLists.Length]; + + for (int i = 0; i < primeLists.Length; ++i) + { + int[] primeList = primeLists[i]; + int product = primeList[0]; + for (int j = 1; j < primeList.Length; ++j) + { + product *= primeList[j]; + } + primeProducts[i] = product; + } + } + + private int[] magnitude; // array of ints with [0] being the most significant + private int sign; // -1 means -ve; +1 means +ve; 0 means 0; + private int nBits = -1; // cache BitCount() value + private int nBitLength = -1; // cache BitLength() value + private int mQuote = 0; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised + + private static int GetByteLength( + int nBits) + { + return (nBits + BitsPerByte - 1) / BitsPerByte; + } + + private BigInteger( + int signum, + int[] mag, + bool checkMag) + { + if (checkMag) + { + int i = 0; + while (i < mag.Length && mag[i] == 0) + { + ++i; + } + + if (i == mag.Length) + { + this.sign = 0; + this.magnitude = ZeroMagnitude; + } + else + { + this.sign = signum; + + if (i == 0) + { + this.magnitude = mag; + } + else + { + // strip leading 0 words + this.magnitude = new int[mag.Length - i]; + Array.Copy(mag, i, this.magnitude, 0, this.magnitude.Length); + } + } + } + else + { + this.sign = signum; + this.magnitude = mag; + } + } + + public BigInteger( + string value) + : this(value, 10) + { + } + + public BigInteger( + string str, + int radix) + { + if (str.Length == 0) + throw new FormatException("Zero length BigInteger"); + + NumberStyles style; + int chunk; + BigInteger r; + BigInteger rE; + + switch (radix) + { + case 2: + // Is there anyway to restrict to binary digits? + style = NumberStyles.Integer; + chunk = chunk2; + r = radix2; + rE = radix2E; + break; + case 8: + // Is there anyway to restrict to octal digits? + style = NumberStyles.Integer; + chunk = chunk8; + r = radix8; + rE = radix8E; + break; + case 10: + // This style seems to handle spaces and minus sign already (our processing redundant?) + style = NumberStyles.Integer; + chunk = chunk10; + r = radix10; + rE = radix10E; + break; + case 16: + // TODO Should this be HexNumber? + style = NumberStyles.AllowHexSpecifier; + chunk = chunk16; + r = radix16; + rE = radix16E; + break; + default: + throw new FormatException("Only bases 2, 8, 10, or 16 allowed"); + } + + + int index = 0; + sign = 1; + + if (str[0] == '-') + { + if (str.Length == 1) + throw new FormatException("Zero length BigInteger"); + + sign = -1; + index = 1; + } + + // strip leading zeros from the string str + while (index < str.Length && Int32.Parse(str[index].ToString(), style) == 0) + { + index++; + } + + if (index >= str.Length) + { + // zero value - we're done + sign = 0; + magnitude = ZeroMagnitude; + return; + } + + ////// + // could we work out the max number of ints required to store + // str.Length digits in the given base, then allocate that + // storage in one hit?, then Generate the magnitude in one hit too? + ////// + + BigInteger b = Zero; + + + int next = index + chunk; + + if (next <= str.Length) + { + do + { + string s = str.Substring(index, chunk); + ulong i = ulong.Parse(s, style); + BigInteger bi = CreateUValueOf(i); + + switch (radix) + { + case 2: + // TODO Need this because we are parsing in radix 10 above + if (i >= 2) + throw new FormatException("Bad character in radix 2 string: " + s); + + // TODO Parse 64 bits at a time + b = b.ShiftLeft(1); + break; + case 8: + // TODO Need this because we are parsing in radix 10 above + if (i >= 8) + throw new FormatException("Bad character in radix 8 string: " + s); + + // TODO Parse 63 bits at a time + b = b.ShiftLeft(3); + break; + case 16: + b = b.ShiftLeft(64); + break; + default: + b = b.Multiply(rE); + break; + } + + b = b.Add(bi); + + index = next; + next += chunk; + } + while (next <= str.Length); + } + + if (index < str.Length) + { + string s = str.Substring(index); + ulong i = ulong.Parse(s, style); + BigInteger bi = CreateUValueOf(i); + + if (b.sign > 0) + { + if (radix == 2) + { + // NB: Can't reach here since we are parsing one char at a time + Debug.Assert(false); + + // TODO Parse all bits at once +// b = b.ShiftLeft(s.Length); + } + else if (radix == 8) + { + // NB: Can't reach here since we are parsing one char at a time + Debug.Assert(false); + + // TODO Parse all bits at once +// b = b.ShiftLeft(s.Length * 3); + } + else if (radix == 16) + { + b = b.ShiftLeft(s.Length << 2); + } + else + { + b = b.Multiply(r.Pow(s.Length)); + } + + b = b.Add(bi); + } + else + { + b = bi; + } + } + + // Note: This is the previous (slower) algorithm +// while (index < value.Length) +// { +// char c = value[index]; +// string s = c.ToString(); +// int i = Int32.Parse(s, style); +// +// b = b.Multiply(r).Add(ValueOf(i)); +// index++; +// } + + magnitude = b.magnitude; + } + + public BigInteger( + byte[] bytes) + : this(bytes, 0, bytes.Length) + { + } + + public BigInteger( + byte[] bytes, + int offset, + int length) + { + if (length == 0) + throw new FormatException("Zero length BigInteger"); + + // TODO Move this processing into MakeMagnitude (provide sign argument) + if ((sbyte)bytes[offset] < 0) + { + this.sign = -1; + + int end = offset + length; + + int iBval; + // strip leading sign bytes + for (iBval = offset; iBval < end && ((sbyte)bytes[iBval] == -1); iBval++) + { + } + + if (iBval >= end) + { + this.magnitude = One.magnitude; + } + else + { + int numBytes = end - iBval; + byte[] inverse = new byte[numBytes]; + + int index = 0; + while (index < numBytes) + { + inverse[index++] = (byte)~bytes[iBval++]; + } + + Debug.Assert(iBval == end); + + while (inverse[--index] == byte.MaxValue) + { + inverse[index] = byte.MinValue; + } + + inverse[index]++; + + this.magnitude = MakeMagnitude(inverse, 0, inverse.Length); + } + } + else + { + // strip leading zero bytes and return magnitude bytes + this.magnitude = MakeMagnitude(bytes, offset, length); + this.sign = this.magnitude.Length > 0 ? 1 : 0; + } + } + + private static int[] MakeMagnitude( + byte[] bytes, + int offset, + int length) + { + int end = offset + length; + + // strip leading zeros + int firstSignificant; + for (firstSignificant = offset; firstSignificant < end + && bytes[firstSignificant] == 0; firstSignificant++) + { + } + + if (firstSignificant >= end) + { + return ZeroMagnitude; + } + + int nInts = (end - firstSignificant + 3) / BytesPerInt; + int bCount = (end - firstSignificant) % BytesPerInt; + if (bCount == 0) + { + bCount = BytesPerInt; + } + + if (nInts < 1) + { + return ZeroMagnitude; + } + + int[] mag = new int[nInts]; + + int v = 0; + int magnitudeIndex = 0; + for (int i = firstSignificant; i < end; ++i) + { + v <<= 8; + v |= bytes[i] & 0xff; + bCount--; + if (bCount <= 0) + { + mag[magnitudeIndex] = v; + magnitudeIndex++; + bCount = BytesPerInt; + v = 0; + } + } + + if (magnitudeIndex < mag.Length) + { + mag[magnitudeIndex] = v; + } + + return mag; + } + + public BigInteger( + int sign, + byte[] bytes) + : this(sign, bytes, 0, bytes.Length) + { + } + + public BigInteger( + int sign, + byte[] bytes, + int offset, + int length) + { + if (sign < -1 || sign > 1) + throw new FormatException("Invalid sign value"); + + if (sign == 0) + { + this.sign = 0; + this.magnitude = ZeroMagnitude; + } + else + { + // copy bytes + this.magnitude = MakeMagnitude(bytes, offset, length); + this.sign = this.magnitude.Length < 1 ? 0 : sign; + } + } + + public BigInteger( + int sizeInBits, + Random random) + { + if (sizeInBits < 0) + throw new ArgumentException("sizeInBits must be non-negative"); + + this.nBits = -1; + this.nBitLength = -1; + + if (sizeInBits == 0) + { + this.sign = 0; + this.magnitude = ZeroMagnitude; + return; + } + + int nBytes = GetByteLength(sizeInBits); + byte[] b = new byte[nBytes]; + random.NextBytes(b); + + // strip off any excess bits in the MSB + int xBits = BitsPerByte * nBytes - sizeInBits; + b[0] &= (byte)(255U >> xBits); + + this.magnitude = MakeMagnitude(b, 0, b.Length); + this.sign = this.magnitude.Length < 1 ? 0 : 1; + } + + public BigInteger( + int bitLength, + int certainty, + Random random) + { + if (bitLength < 2) + throw new ArithmeticException("bitLength < 2"); + + this.sign = 1; + this.nBitLength = bitLength; + + if (bitLength == 2) + { + this.magnitude = random.Next(2) == 0 + ? Two.magnitude + : Three.magnitude; + return; + } + + int nBytes = GetByteLength(bitLength); + byte[] b = new byte[nBytes]; + + int xBits = BitsPerByte * nBytes - bitLength; + byte mask = (byte)(255U >> xBits); + + for (;;) + { + random.NextBytes(b); + + // strip off any excess bits in the MSB + b[0] &= mask; + + // ensure the leading bit is 1 (to meet the strength requirement) + b[0] |= (byte)(1 << (7 - xBits)); + + // ensure the trailing bit is 1 (i.e. must be odd) + b[nBytes - 1] |= 1; + + this.magnitude = MakeMagnitude(b, 0, b.Length); + this.nBits = -1; + this.mQuote = 0; + + if (certainty < 1) + break; + + if (CheckProbablePrime(certainty, random)) + break; + + if (bitLength > 32) + { + for (int rep = 0; rep < 10000; ++rep) + { + int n = 33 + random.Next(bitLength - 2); + this.magnitude[this.magnitude.Length - (n >> 5)] ^= (1 << (n & 31)); + this.magnitude[this.magnitude.Length - 1] ^= ((random.Next() + 1) << 1); + this.mQuote = 0; + + if (CheckProbablePrime(certainty, random)) + return; + } + } + } + } + + public BigInteger Abs() + { + return sign >= 0 ? this : Negate(); + } + + /** + * return a = a + b - b preserved. + */ + private static int[] AddMagnitudes( + int[] a, + int[] b) + { + int tI = a.Length - 1; + int vI = b.Length - 1; + long m = 0; + + while (vI >= 0) + { + m += ((long)(uint)a[tI] + (long)(uint)b[vI--]); + a[tI--] = (int)m; + m = (long)((ulong)m >> 32); + } + + if (m != 0) + { + while (tI >= 0 && ++a[tI--] == 0) + { + } + } + + return a; + } + + public BigInteger Add( + BigInteger value) + { + if (this.sign == 0) + return value; + + if (this.sign != value.sign) + { + if (value.sign == 0) + return this; + + if (value.sign < 0) + return Subtract(value.Negate()); + + return value.Subtract(Negate()); + } + + return AddToMagnitude(value.magnitude); + } + + private BigInteger AddToMagnitude( + int[] magToAdd) + { + int[] big, small; + if (this.magnitude.Length < magToAdd.Length) + { + big = magToAdd; + small = this.magnitude; + } + else + { + big = this.magnitude; + small = magToAdd; + } + + // Conservatively avoid over-allocation when no overflow possible + uint limit = uint.MaxValue; + if (big.Length == small.Length) + limit -= (uint) small[0]; + + bool possibleOverflow = (uint) big[0] >= limit; + + int[] bigCopy; + if (possibleOverflow) + { + bigCopy = new int[big.Length + 1]; + big.CopyTo(bigCopy, 1); + } + else + { + bigCopy = (int[]) big.Clone(); + } + + bigCopy = AddMagnitudes(bigCopy, small); + + return new BigInteger(this.sign, bigCopy, possibleOverflow); + } + + public BigInteger And( + BigInteger value) + { + if (this.sign == 0 || value.sign == 0) + { + return Zero; + } + + int[] aMag = this.sign > 0 + ? this.magnitude + : Add(One).magnitude; + + int[] bMag = value.sign > 0 + ? value.magnitude + : value.Add(One).magnitude; + + bool resultNeg = sign < 0 && value.sign < 0; + int resultLength = System.Math.Max(aMag.Length, bMag.Length); + int[] resultMag = new int[resultLength]; + + int aStart = resultMag.Length - aMag.Length; + int bStart = resultMag.Length - bMag.Length; + + for (int i = 0; i < resultMag.Length; ++i) + { + int aWord = i >= aStart ? aMag[i - aStart] : 0; + int bWord = i >= bStart ? bMag[i - bStart] : 0; + + if (this.sign < 0) + { + aWord = ~aWord; + } + + if (value.sign < 0) + { + bWord = ~bWord; + } + + resultMag[i] = aWord & bWord; + + if (resultNeg) + { + resultMag[i] = ~resultMag[i]; + } + } + + BigInteger result = new BigInteger(1, resultMag, true); + + // TODO Optimise this case + if (resultNeg) + { + result = result.Not(); + } + + return result; + } + + public BigInteger AndNot( + BigInteger val) + { + return And(val.Not()); + } + + public int BitCount + { + get + { + if (nBits == -1) + { + if (sign < 0) + { + // TODO Optimise this case + nBits = Not().BitCount; + } + else + { + int sum = 0; + for (int i = 0; i < magnitude.Length; ++i) + { + sum += BitCnt(magnitude[i]); + } + nBits = sum; + } + } + + return nBits; + } + } + + public static int BitCnt(int i) + { + uint u = (uint)i; + u = u - ((u >> 1) & 0x55555555); + u = (u & 0x33333333) + ((u >> 2) & 0x33333333); + u = (u + (u >> 4)) & 0x0f0f0f0f; + u += (u >> 8); + u += (u >> 16); + u &= 0x3f; + return (int)u; + } + + private static int CalcBitLength(int sign, int indx, int[] mag) + { + for (;;) + { + if (indx >= mag.Length) + return 0; + + if (mag[indx] != 0) + break; + + ++indx; + } + + // bit length for everything after the first int + int bitLength = 32 * ((mag.Length - indx) - 1); + + // and determine bitlength of first int + int firstMag = mag[indx]; + bitLength += BitLen(firstMag); + + // Check for negative powers of two + if (sign < 0 && ((firstMag & -firstMag) == firstMag)) + { + do + { + if (++indx >= mag.Length) + { + --bitLength; + break; + } + } + while (mag[indx] == 0); + } + + return bitLength; + } + + public int BitLength + { + get + { + if (nBitLength == -1) + { + nBitLength = sign == 0 + ? 0 + : CalcBitLength(sign, 0, magnitude); + } + + return nBitLength; + } + } + + // + // BitLen(value) is the number of bits in value. + // + private static int BitLen(int w) + { + uint v = (uint)w; + uint t = v >> 24; + if (t != 0) + return 24 + BitLengthTable[t]; + t = v >> 16; + if (t != 0) + return 16 + BitLengthTable[t]; + t = v >> 8; + if (t != 0) + return 8 + BitLengthTable[t]; + return BitLengthTable[v]; + } + + private bool QuickPow2Check() + { + return sign > 0 && nBits == 1; + } + + public int CompareTo( + object obj) + { + return CompareTo((BigInteger)obj); + } + + /** + * unsigned comparison on two arrays - note the arrays may + * start with leading zeros. + */ + private static int CompareTo( + int xIndx, + int[] x, + int yIndx, + int[] y) + { + while (xIndx != x.Length && x[xIndx] == 0) + { + xIndx++; + } + + while (yIndx != y.Length && y[yIndx] == 0) + { + yIndx++; + } + + return CompareNoLeadingZeroes(xIndx, x, yIndx, y); + } + + private static int CompareNoLeadingZeroes( + int xIndx, + int[] x, + int yIndx, + int[] y) + { + int diff = (x.Length - y.Length) - (xIndx - yIndx); + + if (diff != 0) + { + return diff < 0 ? -1 : 1; + } + + // lengths of magnitudes the same, test the magnitude values + + while (xIndx < x.Length) + { + uint v1 = (uint)x[xIndx++]; + uint v2 = (uint)y[yIndx++]; + + if (v1 != v2) + return v1 < v2 ? -1 : 1; + } + + return 0; + } + + public int CompareTo( + BigInteger value) + { + return sign < value.sign ? -1 + : sign > value.sign ? 1 + : sign == 0 ? 0 + : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude); + } + + /** + * return z = x / y - done in place (z value preserved, x contains the + * remainder) + */ + private int[] Divide( + int[] x, + int[] y) + { + int xStart = 0; + while (xStart < x.Length && x[xStart] == 0) + { + ++xStart; + } + + int yStart = 0; + while (yStart < y.Length && y[yStart] == 0) + { + ++yStart; + } + + Debug.Assert(yStart < y.Length); + + int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); + int[] count; + + if (xyCmp > 0) + { + int yBitLength = CalcBitLength(1, yStart, y); + int xBitLength = CalcBitLength(1, xStart, x); + int shift = xBitLength - yBitLength; + + int[] iCount; + int iCountStart = 0; + + int[] c; + int cStart = 0; + int cBitLength = yBitLength; + if (shift > 0) + { +// iCount = ShiftLeft(One.magnitude, shift); + iCount = new int[(shift >> 5) + 1]; + iCount[0] = 1 << (shift % 32); + + c = ShiftLeft(y, shift); + cBitLength += shift; + } + else + { + iCount = new int[] { 1 }; + + int len = y.Length - yStart; + c = new int[len]; + Array.Copy(y, yStart, c, 0, len); + } + + count = new int[iCount.Length]; + + for (;;) + { + if (cBitLength < xBitLength + || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0) + { + Subtract(xStart, x, cStart, c); + AddMagnitudes(count, iCount); + + while (x[xStart] == 0) + { + if (++xStart == x.Length) + return count; + } + + //xBitLength = CalcBitLength(xStart, x); + xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]); + + if (xBitLength <= yBitLength) + { + if (xBitLength < yBitLength) + return count; + + xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); + + if (xyCmp <= 0) + break; + } + } + + shift = cBitLength - xBitLength; + + // NB: The case where c[cStart] is 1-bit is harmless + if (shift == 1) + { + uint firstC = (uint) c[cStart] >> 1; + uint firstX = (uint) x[xStart]; + if (firstC > firstX) + ++shift; + } + + if (shift < 2) + { + ShiftRightOneInPlace(cStart, c); + --cBitLength; + ShiftRightOneInPlace(iCountStart, iCount); + } + else + { + ShiftRightInPlace(cStart, c, shift); + cBitLength -= shift; + ShiftRightInPlace(iCountStart, iCount, shift); + } + + //cStart = c.Length - ((cBitLength + 31) / 32); + while (c[cStart] == 0) + { + ++cStart; + } + + while (iCount[iCountStart] == 0) + { + ++iCountStart; + } + } + } + else + { + count = new int[1]; + } + + if (xyCmp == 0) + { + AddMagnitudes(count, One.magnitude); + Array.Clear(x, xStart, x.Length - xStart); + } + + return count; + } + + public BigInteger Divide( + BigInteger val) + { + if (val.sign == 0) + throw new ArithmeticException("Division by zero error"); + + if (sign == 0) + return Zero; + + if (val.QuickPow2Check()) // val is power of two + { + BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1); + return val.sign == this.sign ? result : result.Negate(); + } + + int[] mag = (int[]) this.magnitude.Clone(); + + return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true); + } + + public BigInteger[] DivideAndRemainder( + BigInteger val) + { + if (val.sign == 0) + throw new ArithmeticException("Division by zero error"); + + BigInteger[] biggies = new BigInteger[2]; + + if (sign == 0) + { + biggies[0] = Zero; + biggies[1] = Zero; + } + else if (val.QuickPow2Check()) // val is power of two + { + int e = val.Abs().BitLength - 1; + BigInteger quotient = this.Abs().ShiftRight(e); + int[] remainder = this.LastNBits(e); + + biggies[0] = val.sign == this.sign ? quotient : quotient.Negate(); + biggies[1] = new BigInteger(this.sign, remainder, true); + } + else + { + int[] remainder = (int[]) this.magnitude.Clone(); + int[] quotient = Divide(remainder, val.magnitude); + + biggies[0] = new BigInteger(this.sign * val.sign, quotient, true); + biggies[1] = new BigInteger(this.sign, remainder, true); + } + + return biggies; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + BigInteger biggie = obj as BigInteger; + if (biggie == null) + return false; + + return sign == biggie.sign && IsEqualMagnitude(biggie); + } + + private bool IsEqualMagnitude(BigInteger x) + { + int[] xMag = x.magnitude; + if (magnitude.Length != x.magnitude.Length) + return false; + for (int i = 0; i < magnitude.Length; i++) + { + if (magnitude[i] != x.magnitude[i]) + return false; + } + return true; + } + + public BigInteger Gcd( + BigInteger value) + { + if (value.sign == 0) + return Abs(); + + if (sign == 0) + return value.Abs(); + + BigInteger r; + BigInteger u = this; + BigInteger v = value; + + while (v.sign != 0) + { + r = u.Mod(v); + u = v; + v = r; + } + + return u; + } + + public override int GetHashCode() + { + int hc = magnitude.Length; + if (magnitude.Length > 0) + { + hc ^= magnitude[0]; + + if (magnitude.Length > 1) + { + hc ^= magnitude[magnitude.Length - 1]; + } + } + + return sign < 0 ? ~hc : hc; + } + + // TODO Make public? + private BigInteger Inc() + { + if (this.sign == 0) + return One; + + if (this.sign < 0) + return new BigInteger(-1, doSubBigLil(this.magnitude, One.magnitude), true); + + return AddToMagnitude(One.magnitude); + } + + public int IntValue + { + get + { + if (sign == 0) + return 0; + + int n = magnitude.Length; + + int v = magnitude[n - 1]; + + return sign < 0 ? -v : v; + } + } + + /** + * return whether or not a BigInteger is probably prime with a + * probability of 1 - (1/2)**certainty. + *

From Knuth Vol 2, pg 395.

+ */ + public bool IsProbablePrime( + int certainty) + { + if (certainty <= 0) + return true; + + BigInteger n = Abs(); + + if (!n.TestBit(0)) + return n.Equals(Two); + + if (n.Equals(One)) + return false; + + return n.CheckProbablePrime(certainty, RandomSource); + } + + private bool CheckProbablePrime( + int certainty, + Random random) + { + Debug.Assert(certainty > 0); + Debug.Assert(CompareTo(Two) > 0); + Debug.Assert(TestBit(0)); + + + // Try to reduce the penalty for really small numbers + int numLists = System.Math.Min(BitLength - 1, primeLists.Length); + + for (int i = 0; i < numLists; ++i) + { + int test = Remainder(primeProducts[i]); + + int[] primeList = primeLists[i]; + for (int j = 0; j < primeList.Length; ++j) + { + int prime = primeList[j]; + int qRem = test % prime; + if (qRem == 0) + { + // We may find small numbers in the list + return BitLength < 16 && IntValue == prime; + } + } + } + + + // TODO Special case for < 10^16 (RabinMiller fixed list) +// if (BitLength < 30) +// { +// RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient +// } + + + // TODO Is it worth trying to create a hybrid of these two? + return RabinMillerTest(certainty, random); +// return SolovayStrassenTest(certainty, random); + +// bool rbTest = RabinMillerTest(certainty, random); +// bool ssTest = SolovayStrassenTest(certainty, random); +// +// Debug.Assert(rbTest == ssTest); +// +// return rbTest; + } + + public bool RabinMillerTest(int certainty, Random random) + { + Debug.Assert(certainty > 0); + Debug.Assert(BitLength > 2); + Debug.Assert(TestBit(0)); + + // let n = 1 + d . 2^s + BigInteger n = this; + int s = n.GetLowestSetBitMaskFirst(-1 << 1); + Debug.Assert(s >= 1); + BigInteger r = n.ShiftRight(s); + + // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead + + BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n); + BigInteger minusMontRadix = n.Subtract(montRadix); + + do + { + BigInteger a; + do + { + a = new BigInteger(n.BitLength, random); + } + while (a.sign == 0 || a.CompareTo(n) >= 0 + || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix)); + + BigInteger y = ModPowMonty(a, r, n, false); + + if (!y.Equals(montRadix)) + { + int j = 0; + while (!y.Equals(minusMontRadix)) + { + if (++j == s) + return false; + + y = ModPowMonty(y, Two, n, false); + + if (y.Equals(montRadix)) + return false; + } + } + + certainty -= 2; // composites pass for only 1/4 possible 'a' + } + while (certainty > 0); + + return true; + } + +// private bool SolovayStrassenTest( +// int certainty, +// Random random) +// { +// Debug.Assert(certainty > 0); +// Debug.Assert(CompareTo(Two) > 0); +// Debug.Assert(TestBit(0)); +// +// BigInteger n = this; +// BigInteger nMinusOne = n.Subtract(One); +// BigInteger e = nMinusOne.ShiftRight(1); +// +// do +// { +// BigInteger a; +// do +// { +// a = new BigInteger(nBitLength, random); +// } +// // NB: Spec says 0 < x < n, but 1 is trivial +// while (a.CompareTo(One) <= 0 || a.CompareTo(n) >= 0); +// +// +// // TODO Check this is redundant given the way Jacobi() works? +//// if (!a.Gcd(n).Equals(One)) +//// return false; +// +// int x = Jacobi(a, n); +// +// if (x == 0) +// return false; +// +// BigInteger check = a.ModPow(e, n); +// +// if (x == 1 && !check.Equals(One)) +// return false; +// +// if (x == -1 && !check.Equals(nMinusOne)) +// return false; +// +// --certainty; +// } +// while (certainty > 0); +// +// return true; +// } +// +// private static int Jacobi( +// BigInteger a, +// BigInteger b) +// { +// Debug.Assert(a.sign >= 0); +// Debug.Assert(b.sign > 0); +// Debug.Assert(b.TestBit(0)); +// Debug.Assert(a.CompareTo(b) < 0); +// +// int totalS = 1; +// for (;;) +// { +// if (a.sign == 0) +// return 0; +// +// if (a.Equals(One)) +// break; +// +// int e = a.GetLowestSetBit(); +// +// int bLsw = b.magnitude[b.magnitude.Length - 1]; +// if ((e & 1) != 0 && ((bLsw & 7) == 3 || (bLsw & 7) == 5)) +// totalS = -totalS; +// +// // TODO Confirm this is faster than later a1.Equals(One) test +// if (a.BitLength == e + 1) +// break; +// BigInteger a1 = a.ShiftRight(e); +//// if (a1.Equals(One)) +//// break; +// +// int a1Lsw = a1.magnitude[a1.magnitude.Length - 1]; +// if ((bLsw & 3) == 3 && (a1Lsw & 3) == 3) +// totalS = -totalS; +// +//// a = b.Mod(a1); +// a = b.Remainder(a1); +// b = a1; +// } +// return totalS; +// } + + public long LongValue + { + get + { + if (sign == 0) + return 0; + + int n = magnitude.Length; + + long v = magnitude[n - 1] & IMASK; + if (n > 1) + { + v |= (magnitude[n - 2] & IMASK) << 32; + } + + return sign < 0 ? -v : v; + } + } + + public BigInteger Max( + BigInteger value) + { + return CompareTo(value) > 0 ? this : value; + } + + public BigInteger Min( + BigInteger value) + { + return CompareTo(value) < 0 ? this : value; + } + + public BigInteger Mod( + BigInteger m) + { + if (m.sign < 1) + throw new ArithmeticException("Modulus must be positive"); + + BigInteger biggie = Remainder(m); + + return (biggie.sign >= 0 ? biggie : biggie.Add(m)); + } + + public BigInteger ModInverse( + BigInteger m) + { + if (m.sign < 1) + throw new ArithmeticException("Modulus must be positive"); + + // TODO Too slow at the moment +// // "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel +// if (m.TestBit(0)) +// { +// //The Almost Inverse Algorithm +// int k = 0; +// BigInteger B = One, C = Zero, F = this, G = m, tmp; +// +// for (;;) +// { +// // While F is even, do F=F/u, C=C*u, k=k+1. +// int zeroes = F.GetLowestSetBit(); +// if (zeroes > 0) +// { +// F = F.ShiftRight(zeroes); +// C = C.ShiftLeft(zeroes); +// k += zeroes; +// } +// +// // If F = 1, then return B,k. +// if (F.Equals(One)) +// { +// BigInteger half = m.Add(One).ShiftRight(1); +// BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m); +// return B.Multiply(halfK).Mod(m); +// } +// +// if (F.CompareTo(G) < 0) +// { +// tmp = G; G = F; F = tmp; +// tmp = B; B = C; C = tmp; +// } +// +// F = F.Add(G); +// B = B.Add(C); +// } +// } + + if (m.QuickPow2Check()) + { + return ModInversePow2(m); + } + + BigInteger d = this.Remainder(m); + BigInteger x; + BigInteger gcd = ExtEuclid(d, m, out x); + + if (!gcd.Equals(One)) + throw new ArithmeticException("Numbers not relatively prime."); + + if (x.sign < 0) + { + x = x.Add(m); + } + + return x; + } + + private BigInteger ModInversePow2(BigInteger m) + { + Debug.Assert(m.SignValue > 0); + Debug.Assert(m.BitCount == 1); + + if (!TestBit(0)) + { + throw new ArithmeticException("Numbers not relatively prime."); + } + + int pow = m.BitLength - 1; + + long inv64 = ModInverse64(LongValue); + if (pow < 64) + { + inv64 &= ((1L << pow) - 1); + } + + BigInteger x = BigInteger.ValueOf(inv64); + + if (pow > 64) + { + BigInteger d = this.Remainder(m); + int bitsCorrect = 64; + + do + { + BigInteger t = x.Multiply(d).Remainder(m); + x = x.Multiply(Two.Subtract(t)).Remainder(m); + bitsCorrect <<= 1; + } + while (bitsCorrect < pow); + + if (x.sign < 0) + { + x = x.Add(m); + } + } + + return x; + } + + private static int ModInverse32(int d) + { + // Newton's method with initial estimate "correct to 4 bits" + Debug.Assert((d & 1) != 0); + int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4 + Debug.Assert(((d * x) & 15) == 1); + x *= 2 - d * x; // d.x == 1 mod 2**8 + x *= 2 - d * x; // d.x == 1 mod 2**16 + x *= 2 - d * x; // d.x == 1 mod 2**32 + Debug.Assert(d * x == 1); + return x; + } + + private static long ModInverse64(long d) + { + // Newton's method with initial estimate "correct to 4 bits" + Debug.Assert((d & 1L) != 0); + long x = d + (((d + 1L) & 4L) << 1); // d.x == 1 mod 2**4 + Debug.Assert(((d * x) & 15L) == 1L); + x *= 2 - d * x; // d.x == 1 mod 2**8 + x *= 2 - d * x; // d.x == 1 mod 2**16 + x *= 2 - d * x; // d.x == 1 mod 2**32 + x *= 2 - d * x; // d.x == 1 mod 2**64 + Debug.Assert(d * x == 1L); + return x; + } + + /** + * Calculate the numbers u1, u2, and u3 such that: + * + * u1 * a + u2 * b = u3 + * + * where u3 is the greatest common divider of a and b. + * a and b using the extended Euclid algorithm (refer p. 323 + * of The Art of Computer Programming vol 2, 2nd ed). + * This also seems to have the side effect of calculating + * some form of multiplicative inverse. + * + * @param a First number to calculate gcd for + * @param b Second number to calculate gcd for + * @param u1Out the return object for the u1 value + * @param u2Out the return object for the u2 value + * @return The greatest common divisor of a and b + */ + private static BigInteger ExtEuclid( + BigInteger a, + BigInteger b, + out BigInteger u1Out) + //BigInteger u2Out) + { + BigInteger u1 = One; + BigInteger u3 = a; + BigInteger v1 = Zero; + BigInteger v3 = b; + + while (v3.sign > 0) + { + BigInteger[] q = u3.DivideAndRemainder(v3); + + BigInteger tmp = v1.Multiply(q[0]); + BigInteger tn = u1.Subtract(tmp); + u1 = v1; + v1 = tn; + + u3 = v3; + v3 = q[1]; + } + + //if (u1Out != null) + //{ + // u1Out.sign = u1.sign; + // u1Out.magnitude = u1.magnitude; + //} + u1Out = u1; + + //if (u2Out != null) + //{ + // BigInteger tmp = u1.Multiply(a); + // tmp = u3.Subtract(tmp); + // BigInteger res = tmp.Divide(b); + // u2Out.sign = res.sign; + // u2Out.magnitude = res.magnitude; + //} + + return u3; + } + + private static void ZeroOut( + int[] x) + { + Array.Clear(x, 0, x.Length); + } + + public BigInteger ModPow(BigInteger e, BigInteger m) + { + if (m.sign < 1) + throw new ArithmeticException("Modulus must be positive"); + + if (m.Equals(One)) + return Zero; + + if (e.sign == 0) + return One; + + if (sign == 0) + return Zero; + + bool negExp = e.sign < 0; + if (negExp) + e = e.Negate(); + + BigInteger result = this.Mod(m); + if (!e.Equals(One)) + { + if ((m.magnitude[m.magnitude.Length - 1] & 1) == 0) + { + result = ModPowBarrett(result, e, m); + } + else + { + result = ModPowMonty(result, e, m, true); + } + } + + if (negExp) + result = result.ModInverse(m); + + return result; + } + + private static BigInteger ModPowBarrett(BigInteger b, BigInteger e, BigInteger m) + { + int k = m.magnitude.Length; + BigInteger mr = One.ShiftLeft((k + 1) << 5); + BigInteger yu = One.ShiftLeft(k << 6).Divide(m); + + // Sliding window from MSW to LSW + int extraBits = 0, expLength = e.BitLength; + while (expLength > ExpWindowThresholds[extraBits]) + { + ++extraBits; + } + + int numPowers = 1 << extraBits; + BigInteger[] oddPowers = new BigInteger[numPowers]; + oddPowers[0] = b; + + BigInteger b2 = ReduceBarrett(b.Square(), m, mr, yu); + + for (int i = 1; i < numPowers; ++i) + { + oddPowers[i] = ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu); + } + + int[] windowList = GetWindowList(e.magnitude, extraBits); + Debug.Assert(windowList.Length > 0); + + int window = windowList[0]; + int mult = window & 0xFF, lastZeroes = window >> 8; + + BigInteger y; + if (mult == 1) + { + y = b2; + --lastZeroes; + } + else + { + y = oddPowers[mult >> 1]; + } + + int windowPos = 1; + while ((window = windowList[windowPos++]) != -1) + { + mult = window & 0xFF; + + int bits = lastZeroes + BitLengthTable[mult]; + for (int j = 0; j < bits; ++j) + { + y = ReduceBarrett(y.Square(), m, mr, yu); + } + + y = ReduceBarrett(y.Multiply(oddPowers[mult >> 1]), m, mr, yu); + + lastZeroes = window >> 8; + } + + for (int i = 0; i < lastZeroes; ++i) + { + y = ReduceBarrett(y.Square(), m, mr, yu); + } + + return y; + } + + private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu) + { + int xLen = x.BitLength, mLen = m.BitLength; + if (xLen < mLen) + return x; + + if (xLen - mLen > 1) + { + int k = m.magnitude.Length; + + BigInteger q1 = x.DivideWords(k - 1); + BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here + BigInteger q3 = q2.DivideWords(k + 1); + + BigInteger r1 = x.RemainderWords(k + 1); + BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here + BigInteger r3 = r2.RemainderWords(k + 1); + + x = r1.Subtract(r3); + if (x.sign < 0) + { + x = x.Add(mr); + } + } + + while (x.CompareTo(m) >= 0) + { + x = x.Subtract(m); + } + + return x; + } + + private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert) + { + int n = m.magnitude.Length; + int powR = 32 * n; + bool smallMontyModulus = m.BitLength + 2 <= powR; + uint mDash = (uint)m.GetMQuote(); + + // tmp = this * R mod m + if (convert) + { + b = b.ShiftLeft(powR).Remainder(m); + } + + int[] yAccum = new int[n + 1]; + + int[] zVal = b.magnitude; + Debug.Assert(zVal.Length <= n); + if (zVal.Length < n) + { + int[] tmp = new int[n]; + zVal.CopyTo(tmp, n - zVal.Length); + zVal = tmp; + } + + // Sliding window from MSW to LSW + + int extraBits = 0; + + // Filter the common case of small RSA exponents with few bits set + if (e.magnitude.Length > 1 || e.BitCount > 2) + { + int expLength = e.BitLength; + while (expLength > ExpWindowThresholds[extraBits]) + { + ++extraBits; + } + } + + int numPowers = 1 << extraBits; + int[][] oddPowers = new int[numPowers][]; + oddPowers[0] = zVal; + + int[] zSquared = Arrays.Clone(zVal); + SquareMonty(yAccum, zSquared, m.magnitude, mDash, smallMontyModulus); + + for (int i = 1; i < numPowers; ++i) + { + oddPowers[i] = Arrays.Clone(oddPowers[i - 1]); + MultiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus); + } + + int[] windowList = GetWindowList(e.magnitude, extraBits); + Debug.Assert(windowList.Length > 1); + + int window = windowList[0]; + int mult = window & 0xFF, lastZeroes = window >> 8; + + int[] yVal; + if (mult == 1) + { + yVal = zSquared; + --lastZeroes; + } + else + { + yVal = Arrays.Clone(oddPowers[mult >> 1]); + } + + int windowPos = 1; + while ((window = windowList[windowPos++]) != -1) + { + mult = window & 0xFF; + + int bits = lastZeroes + BitLengthTable[mult]; + for (int j = 0; j < bits; ++j) + { + SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus); + } + + MultiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.magnitude, mDash, smallMontyModulus); + + lastZeroes = window >> 8; + } + + for (int i = 0; i < lastZeroes; ++i) + { + SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus); + } + + if (convert) + { + // Return y * R^(-1) mod m + MontgomeryReduce(yVal, m.magnitude, mDash); + } + else if (smallMontyModulus && CompareTo(0, yVal, 0, m.magnitude) >= 0) + { + Subtract(0, yVal, 0, m.magnitude); + } + + return new BigInteger(1, yVal, true); + } + + private static int[] GetWindowList(int[] mag, int extraBits) + { + int v = mag[0]; + Debug.Assert(v != 0); + + int leadingBits = BitLen(v); + + int resultSize = (((mag.Length - 1) << 5) + leadingBits) / (1 + extraBits) + 2; + int[] result = new int[resultSize]; + int resultPos = 0; + + int bitPos = 33 - leadingBits; + v <<= bitPos; + + int mult = 1, multLimit = 1 << extraBits; + int zeroes = 0; + + int i = 0; + for (; ; ) + { + for (; bitPos < 32; ++bitPos) + { + if (mult < multLimit) + { + mult = (mult << 1) | (int)((uint)v >> 31); + } + else if (v < 0) + { + result[resultPos++] = CreateWindowEntry(mult, zeroes); + mult = 1; + zeroes = 0; + } + else + { + ++zeroes; + } + + v <<= 1; + } + + if (++i == mag.Length) + { + result[resultPos++] = CreateWindowEntry(mult, zeroes); + break; + } + + v = mag[i]; + bitPos = 0; + } + + result[resultPos] = -1; + return result; + } + + private static int CreateWindowEntry(int mult, int zeroes) + { + while ((mult & 1) == 0) + { + mult >>= 1; + ++zeroes; + } + + return mult | (zeroes << 8); + } + + /** + * return w with w = x * x - w is assumed to have enough space. + */ + private static int[] Square( + int[] w, + int[] x) + { + // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit +// if (w.Length != 2 * x.Length) +// throw new ArgumentException("no I don't think so..."); + + ulong c; + + int wBase = w.Length - 1; + + for (int i = x.Length - 1; i > 0; --i) + { + ulong v = (uint)x[i]; + + c = v * v + (uint)w[wBase]; + w[wBase] = (int)c; + c >>= 32; + + for (int j = i - 1; j >= 0; --j) + { + ulong prod = v * (uint)x[j]; + + c += ((uint)w[--wBase] & UIMASK) + ((uint)prod << 1); + w[wBase] = (int)c; + c = (c >> 32) + (prod >> 31); + } + + c += (uint)w[--wBase]; + w[wBase] = (int)c; + + if (--wBase >= 0) + { + w[wBase] = (int)(c >> 32); + } + else + { + Debug.Assert((c >> 32) == 0); + } + + wBase += i; + } + + c = (uint)x[0]; + + c = c * c + (uint)w[wBase]; + w[wBase] = (int)c; + + if (--wBase >= 0) + { + w[wBase] += (int)(c >> 32); + } + else + { + Debug.Assert((c >> 32) == 0); + } + + return w; + } + + /** + * return x with x = y * z - x is assumed to have enough space. + */ + private static int[] Multiply(int[] x, int[] y, int[] z) + { + int i = z.Length; + + if (i < 1) + return x; + + int xBase = x.Length - y.Length; + + do + { + long a = z[--i] & IMASK; + long val = 0; + + if (a != 0) + { + for (int j = y.Length - 1; j >= 0; j--) + { + val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK); + + x[xBase + j] = (int)val; + + val = (long)((ulong)val >> 32); + } + } + + --xBase; + + if (xBase >= 0) + { + x[xBase] = (int)val; + } + else + { + Debug.Assert(val == 0); + } + } + while (i > 0); + + return x; + } + + /** + * Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size) + */ + private int GetMQuote() + { + if (mQuote != 0) + { + return mQuote; // already calculated + } + + Debug.Assert(this.sign > 0); + + int d = -magnitude[magnitude.Length - 1]; + + Debug.Assert((d & 1) != 0); + + return mQuote = ModInverse32(d); + } + + private static void MontgomeryReduce(int[] x, int[] m, uint mDash) // mDash = -m^(-1) mod b + { + // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m) + Debug.Assert(x.Length == m.Length); + + int n = m.Length; + + for (int i = n - 1; i >= 0; --i) + { + uint x0 = (uint)x[n - 1]; + ulong t = x0 * mDash; + + ulong carry = t * (uint)m[n - 1] + x0; + Debug.Assert((uint)carry == 0); + carry >>= 32; + + for (int j = n - 2; j >= 0; --j) + { + carry += t * (uint)m[j] + (uint)x[j]; + x[j + 1] = (int)carry; + carry >>= 32; + } + + x[0] = (int)carry; + Debug.Assert(carry >> 32 == 0); + } + + if (CompareTo(0, x, 0, m) >= 0) + { + Subtract(0, x, 0, m); + } + } + + /** + * Montgomery multiplication: a = x * y * R^(-1) mod m + *
+ * Based algorithm 14.36 of Handbook of Applied Cryptography. + *
+ *
  • m, x, y should have length n
  • + *
  • a should have length (n + 1)
  • + *
  • b = 2^32, R = b^n
  • + *
    + * The result is put in x + *
    + * NOTE: the indices of x, y, m, a different in HAC and in Java + */ + private static void MultiplyMonty(int[] a, int[] x, int[] y, int[] m, uint mDash, bool smallMontyModulus) + // mDash = -m^(-1) mod b + { + int n = m.Length; + + if (n == 1) + { + x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], mDash); + return; + } + + uint y0 = (uint)y[n - 1]; + + { + ulong xi = (uint)x[n - 1]; + + ulong carry = xi * y0; + ulong t = (uint)carry * mDash; + + ulong prod2 = t * (uint)m[n - 1]; + carry += (uint)prod2; + Debug.Assert((uint)carry == 0); + carry = (carry >> 32) + (prod2 >> 32); + + for (int j = n - 2; j >= 0; --j) + { + ulong prod1 = xi * (uint)y[j]; + prod2 = t * (uint)m[j]; + + carry += (prod1 & UIMASK) + (uint)prod2; + a[j + 2] = (int)carry; + carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); + } + + a[1] = (int)carry; + a[0] = (int)(carry >> 32); + } + + for (int i = n - 2; i >= 0; --i) + { + uint a0 = (uint)a[n]; + ulong xi = (uint)x[i]; + + ulong prod1 = xi * y0; + ulong carry = (prod1 & UIMASK) + a0; + ulong t = (uint)carry * mDash; + + ulong prod2 = t * (uint)m[n - 1]; + carry += (uint)prod2; + Debug.Assert((uint)carry == 0); + carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); + + for (int j = n - 2; j >= 0; --j) + { + prod1 = xi * (uint)y[j]; + prod2 = t * (uint)m[j]; + + carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[j + 1]; + a[j + 2] = (int)carry; + carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); + } + + carry += (uint)a[0]; + a[1] = (int)carry; + a[0] = (int)(carry >> 32); + } + + if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0) + { + Subtract(0, a, 0, m); + } + + Array.Copy(a, 1, x, 0, n); + } + + private static void SquareMonty(int[] a, int[] x, int[] m, uint mDash, bool smallMontyModulus) + // mDash = -m^(-1) mod b + { + int n = m.Length; + + if (n == 1) + { + uint xVal = (uint)x[0]; + x[0] = (int)MultiplyMontyNIsOne(xVal, xVal, (uint)m[0], mDash); + return; + } + + ulong x0 = (uint)x[n - 1]; + + { + ulong carry = x0 * x0; + ulong t = (uint)carry * mDash; + + ulong prod2 = t * (uint)m[n - 1]; + carry += (uint)prod2; + Debug.Assert((uint)carry == 0); + carry = (carry >> 32) + (prod2 >> 32); + + for (int j = n - 2; j >= 0; --j) + { + ulong prod1 = x0 * (uint)x[j]; + prod2 = t * (uint)m[j]; + + carry += (prod2 & UIMASK) + ((uint)prod1 << 1); + a[j + 2] = (int)carry; + carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32); + } + + a[1] = (int)carry; + a[0] = (int)(carry >> 32); + } + + for (int i = n - 2; i >= 0; --i) + { + uint a0 = (uint)a[n]; + ulong t = a0 * mDash; + + ulong carry = t * (uint)m[n - 1] + a0; + Debug.Assert((uint)carry == 0); + carry >>= 32; + + for (int j = n - 2; j > i; --j) + { + carry += t * (uint)m[j] + (uint)a[j + 1]; + a[j + 2] = (int)carry; + carry >>= 32; + } + + ulong xi = (uint)x[i]; + + { + ulong prod1 = xi * xi; + ulong prod2 = t * (uint)m[i]; + + carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[i + 1]; + a[i + 2] = (int)carry; + carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); + } + + for (int j = i - 1; j >= 0; --j) + { + ulong prod1 = xi * (uint)x[j]; + ulong prod2 = t * (uint)m[j]; + + carry += (prod2 & UIMASK) + ((uint)prod1 << 1) + (uint)a[j + 1]; + a[j + 2] = (int)carry; + carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32); + } + + carry += (uint)a[0]; + a[1] = (int)carry; + a[0] = (int)(carry >> 32); + } + + if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0) + { + Subtract(0, a, 0, m); + } + + Array.Copy(a, 1, x, 0, n); + } + + private static uint MultiplyMontyNIsOne(uint x, uint y, uint m, uint mDash) + { + ulong carry = (ulong)x * y; + uint t = (uint)carry * mDash; + ulong um = m; + ulong prod2 = um * t; + carry += (uint)prod2; + Debug.Assert((uint)carry == 0); + carry = (carry >> 32) + (prod2 >> 32); + if (carry > um) + { + carry -= um; + } + Debug.Assert(carry < um); + return (uint)carry; + } + + public BigInteger Multiply( + BigInteger val) + { + if (val == this) + return Square(); + + if ((sign & val.sign) == 0) + return Zero; + + if (val.QuickPow2Check()) // val is power of two + { + BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1); + return val.sign > 0 ? result : result.Negate(); + } + + if (this.QuickPow2Check()) // this is power of two + { + BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1); + return this.sign > 0 ? result : result.Negate(); + } + + int resLength = magnitude.Length + val.magnitude.Length; + int[] res = new int[resLength]; + + Multiply(res, this.magnitude, val.magnitude); + + int resSign = sign ^ val.sign ^ 1; + return new BigInteger(resSign, res, true); + } + + public BigInteger Square() + { + if (sign == 0) + return Zero; + if (this.QuickPow2Check()) + return ShiftLeft(Abs().BitLength - 1); + int resLength = magnitude.Length << 1; + if ((uint)magnitude[0] >> 16 == 0) + --resLength; + int[] res = new int[resLength]; + Square(res, magnitude); + return new BigInteger(1, res, false); + } + + public BigInteger Negate() + { + if (sign == 0) + return this; + + return new BigInteger(-sign, magnitude, false); + } + + public BigInteger NextProbablePrime() + { + if (sign < 0) + throw new ArithmeticException("Cannot be called on value < 0"); + + if (CompareTo(Two) < 0) + return Two; + + BigInteger n = Inc().SetBit(0); + + while (!n.CheckProbablePrime(100, RandomSource)) + { + n = n.Add(Two); + } + + return n; + } + + public BigInteger Not() + { + return Inc().Negate(); + } + + public BigInteger Pow(int exp) + { + if (exp <= 0) + { + if (exp < 0) + throw new ArithmeticException("Negative exponent"); + + return One; + } + + if (sign == 0) + { + return this; + } + + if (QuickPow2Check()) + { + long powOf2 = (long)exp * (BitLength - 1); + if (powOf2 > Int32.MaxValue) + { + throw new ArithmeticException("Result too large"); + } + return One.ShiftLeft((int)powOf2); + } + + BigInteger y = One; + BigInteger z = this; + + for (;;) + { + if ((exp & 0x1) == 1) + { + y = y.Multiply(z); + } + exp >>= 1; + if (exp == 0) break; + z = z.Multiply(z); + } + + return y; + } + + public static BigInteger ProbablePrime( + int bitLength, + Random random) + { + return new BigInteger(bitLength, 100, random); + } + + private int Remainder( + int m) + { + Debug.Assert(m > 0); + + long acc = 0; + for (int pos = 0; pos < magnitude.Length; ++pos) + { + long posVal = (uint) magnitude[pos]; + acc = (acc << 32 | posVal) % m; + } + + return (int) acc; + } + + /** + * return x = x % y - done in place (y value preserved) + */ + private static int[] Remainder( + int[] x, + int[] y) + { + int xStart = 0; + while (xStart < x.Length && x[xStart] == 0) + { + ++xStart; + } + + int yStart = 0; + while (yStart < y.Length && y[yStart] == 0) + { + ++yStart; + } + + Debug.Assert(yStart < y.Length); + + int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); + + if (xyCmp > 0) + { + int yBitLength = CalcBitLength(1, yStart, y); + int xBitLength = CalcBitLength(1, xStart, x); + int shift = xBitLength - yBitLength; + + int[] c; + int cStart = 0; + int cBitLength = yBitLength; + if (shift > 0) + { + c = ShiftLeft(y, shift); + cBitLength += shift; + Debug.Assert(c[0] != 0); + } + else + { + int len = y.Length - yStart; + c = new int[len]; + Array.Copy(y, yStart, c, 0, len); + } + + for (;;) + { + if (cBitLength < xBitLength + || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0) + { + Subtract(xStart, x, cStart, c); + + while (x[xStart] == 0) + { + if (++xStart == x.Length) + return x; + } + + //xBitLength = CalcBitLength(xStart, x); + xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]); + + if (xBitLength <= yBitLength) + { + if (xBitLength < yBitLength) + return x; + + xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); + + if (xyCmp <= 0) + break; + } + } + + shift = cBitLength - xBitLength; + + // NB: The case where c[cStart] is 1-bit is harmless + if (shift == 1) + { + uint firstC = (uint) c[cStart] >> 1; + uint firstX = (uint) x[xStart]; + if (firstC > firstX) + ++shift; + } + + if (shift < 2) + { + ShiftRightOneInPlace(cStart, c); + --cBitLength; + } + else + { + ShiftRightInPlace(cStart, c, shift); + cBitLength -= shift; + } + + //cStart = c.Length - ((cBitLength + 31) / 32); + while (c[cStart] == 0) + { + ++cStart; + } + } + } + + if (xyCmp == 0) + { + Array.Clear(x, xStart, x.Length - xStart); + } + + return x; + } + + public BigInteger Remainder( + BigInteger n) + { + if (n.sign == 0) + throw new ArithmeticException("Division by zero error"); + + if (this.sign == 0) + return Zero; + + // For small values, use fast remainder method + if (n.magnitude.Length == 1) + { + int val = n.magnitude[0]; + + if (val > 0) + { + if (val == 1) + return Zero; + + // TODO Make this func work on uint, and handle val == 1? + int rem = Remainder(val); + + return rem == 0 + ? Zero + : new BigInteger(sign, new int[]{ rem }, false); + } + } + + if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0) + return this; + + int[] result; + if (n.QuickPow2Check()) // n is power of two + { + // TODO Move before small values branch above? + result = LastNBits(n.Abs().BitLength - 1); + } + else + { + result = (int[]) this.magnitude.Clone(); + result = Remainder(result, n.magnitude); + } + + return new BigInteger(sign, result, true); + } + + private int[] LastNBits( + int n) + { + if (n < 1) + return ZeroMagnitude; + + int numWords = (n + BitsPerInt - 1) / BitsPerInt; + numWords = System.Math.Min(numWords, this.magnitude.Length); + int[] result = new int[numWords]; + + Array.Copy(this.magnitude, this.magnitude.Length - numWords, result, 0, numWords); + + int excessBits = (numWords << 5) - n; + if (excessBits > 0) + { + result[0] &= (int)(UInt32.MaxValue >> excessBits); + } + + return result; + } + + private BigInteger DivideWords(int w) + { + Debug.Assert(w >= 0); + int n = magnitude.Length; + if (w >= n) + return Zero; + int[] mag = new int[n - w]; + Array.Copy(magnitude, 0, mag, 0, n - w); + return new BigInteger(sign, mag, false); + } + + private BigInteger RemainderWords(int w) + { + Debug.Assert(w >= 0); + int n = magnitude.Length; + if (w >= n) + return this; + int[] mag = new int[w]; + Array.Copy(magnitude, n - w, mag, 0, w); + return new BigInteger(sign, mag, false); + } + + /** + * do a left shift - this returns a new array. + */ + private static int[] ShiftLeft( + int[] mag, + int n) + { + int nInts = (int)((uint)n >> 5); + int nBits = n & 0x1f; + int magLen = mag.Length; + int[] newMag; + + if (nBits == 0) + { + newMag = new int[magLen + nInts]; + mag.CopyTo(newMag, 0); + } + else + { + int i = 0; + int nBits2 = 32 - nBits; + int highBits = (int)((uint)mag[0] >> nBits2); + + if (highBits != 0) + { + newMag = new int[magLen + nInts + 1]; + newMag[i++] = highBits; + } + else + { + newMag = new int[magLen + nInts]; + } + + int m = mag[0]; + for (int j = 0; j < magLen - 1; j++) + { + int next = mag[j + 1]; + + newMag[i++] = (m << nBits) | (int)((uint)next >> nBits2); + m = next; + } + + newMag[i] = mag[magLen - 1] << nBits; + } + + return newMag; + } + + private static int ShiftLeftOneInPlace(int[] x, int carry) + { + Debug.Assert(carry == 0 || carry == 1); + int pos = x.Length; + while (--pos >= 0) + { + uint val = (uint)x[pos]; + x[pos] = (int)(val << 1) | carry; + carry = (int)(val >> 31); + } + return carry; + } + + public BigInteger ShiftLeft( + int n) + { + if (sign == 0 || magnitude.Length == 0) + return Zero; + + if (n == 0) + return this; + + if (n < 0) + return ShiftRight(-n); + + BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true); + + if (this.nBits != -1) + { + result.nBits = sign > 0 + ? this.nBits + : this.nBits + n; + } + + if (this.nBitLength != -1) + { + result.nBitLength = this.nBitLength + n; + } + + return result; + } + + /** + * do a right shift - this does it in place. + */ + private static void ShiftRightInPlace( + int start, + int[] mag, + int n) + { + int nInts = (int)((uint)n >> 5) + start; + int nBits = n & 0x1f; + int magEnd = mag.Length - 1; + + if (nInts != start) + { + int delta = (nInts - start); + + for (int i = magEnd; i >= nInts; i--) + { + mag[i] = mag[i - delta]; + } + for (int i = nInts - 1; i >= start; i--) + { + mag[i] = 0; + } + } + + if (nBits != 0) + { + int nBits2 = 32 - nBits; + int m = mag[magEnd]; + + for (int i = magEnd; i > nInts; --i) + { + int next = mag[i - 1]; + + mag[i] = (int)((uint)m >> nBits) | (next << nBits2); + m = next; + } + + mag[nInts] = (int)((uint)mag[nInts] >> nBits); + } + } + + /** + * do a right shift by one - this does it in place. + */ + private static void ShiftRightOneInPlace( + int start, + int[] mag) + { + int i = mag.Length; + int m = mag[i - 1]; + + while (--i > start) + { + int next = mag[i - 1]; + mag[i] = ((int)((uint)m >> 1)) | (next << 31); + m = next; + } + + mag[start] = (int)((uint)mag[start] >> 1); + } + + public BigInteger ShiftRight( + int n) + { + if (n == 0) + return this; + + if (n < 0) + return ShiftLeft(-n); + + if (n >= BitLength) + return (this.sign < 0 ? One.Negate() : Zero); + +// int[] res = (int[]) this.magnitude.Clone(); +// +// ShiftRightInPlace(0, res, n); +// +// return new BigInteger(this.sign, res, true); + + int resultLength = (BitLength - n + 31) >> 5; + int[] res = new int[resultLength]; + + int numInts = n >> 5; + int numBits = n & 31; + + if (numBits == 0) + { + Array.Copy(this.magnitude, 0, res, 0, res.Length); + } + else + { + int numBits2 = 32 - numBits; + + int magPos = this.magnitude.Length - 1 - numInts; + for (int i = resultLength - 1; i >= 0; --i) + { + res[i] = (int)((uint) this.magnitude[magPos--] >> numBits); + + if (magPos >= 0) + { + res[i] |= this.magnitude[magPos] << numBits2; + } + } + } + + Debug.Assert(res[0] != 0); + + return new BigInteger(this.sign, res, false); + } + + public int SignValue + { + get { return sign; } + } + + /** + * returns x = x - y - we assume x is >= y + */ + private static int[] Subtract( + int xStart, + int[] x, + int yStart, + int[] y) + { + Debug.Assert(yStart < y.Length); + Debug.Assert(x.Length - xStart >= y.Length - yStart); + + int iT = x.Length; + int iV = y.Length; + long m; + int borrow = 0; + + do + { + m = (x[--iT] & IMASK) - (y[--iV] & IMASK) + borrow; + x[iT] = (int) m; + +// borrow = (m < 0) ? -1 : 0; + borrow = (int)(m >> 63); + } + while (iV > yStart); + + if (borrow != 0) + { + while (--x[--iT] == -1) + { + } + } + + return x; + } + + public BigInteger Subtract( + BigInteger n) + { + if (n.sign == 0) + return this; + + if (this.sign == 0) + return n.Negate(); + + if (this.sign != n.sign) + return Add(n.Negate()); + + int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude); + if (compare == 0) + return Zero; + + BigInteger bigun, lilun; + if (compare < 0) + { + bigun = n; + lilun = this; + } + else + { + bigun = this; + lilun = n; + } + + return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true); + } + + private static int[] doSubBigLil( + int[] bigMag, + int[] lilMag) + { + int[] res = (int[]) bigMag.Clone(); + + return Subtract(0, res, 0, lilMag); + } + + public byte[] ToByteArray() + { + return ToByteArray(false); + } + + public byte[] ToByteArrayUnsigned() + { + return ToByteArray(true); + } + + private byte[] ToByteArray( + bool unsigned) + { + if (sign == 0) + return unsigned ? ZeroEncoding : new byte[1]; + + int nBits = (unsigned && sign > 0) + ? BitLength + : BitLength + 1; + + int nBytes = GetByteLength(nBits); + byte[] bytes = new byte[nBytes]; + + int magIndex = magnitude.Length; + int bytesIndex = bytes.Length; + + if (sign > 0) + { + while (magIndex > 1) + { + uint mag = (uint) magnitude[--magIndex]; + bytes[--bytesIndex] = (byte) mag; + bytes[--bytesIndex] = (byte)(mag >> 8); + bytes[--bytesIndex] = (byte)(mag >> 16); + bytes[--bytesIndex] = (byte)(mag >> 24); + } + + uint lastMag = (uint) magnitude[0]; + while (lastMag > byte.MaxValue) + { + bytes[--bytesIndex] = (byte) lastMag; + lastMag >>= 8; + } + + bytes[--bytesIndex] = (byte) lastMag; + } + else // sign < 0 + { + bool carry = true; + + while (magIndex > 1) + { + uint mag = ~((uint) magnitude[--magIndex]); + + if (carry) + { + carry = (++mag == uint.MinValue); + } + + bytes[--bytesIndex] = (byte) mag; + bytes[--bytesIndex] = (byte)(mag >> 8); + bytes[--bytesIndex] = (byte)(mag >> 16); + bytes[--bytesIndex] = (byte)(mag >> 24); + } + + uint lastMag = (uint) magnitude[0]; + + if (carry) + { + // Never wraps because magnitude[0] != 0 + --lastMag; + } + + while (lastMag > byte.MaxValue) + { + bytes[--bytesIndex] = (byte) ~lastMag; + lastMag >>= 8; + } + + bytes[--bytesIndex] = (byte) ~lastMag; + + if (bytesIndex > 0) + { + bytes[--bytesIndex] = byte.MaxValue; + } + } + + return bytes; + } + + public override string ToString() + { + return ToString(10); + } + + public string ToString(int radix) + { + // TODO Make this method work for other radices (ideally 2 <= radix <= 36 as in Java) + + switch (radix) + { + case 2: + case 8: + case 10: + case 16: + break; + default: + throw new FormatException("Only bases 2, 8, 10, 16 are allowed"); + } + + // NB: Can only happen to internally managed instances + if (magnitude == null) + return "null"; + + if (sign == 0) + return "0"; + + + // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits + int firstNonZero = 0; + while (firstNonZero < magnitude.Length) + { + if (magnitude[firstNonZero] != 0) + { + break; + } + ++firstNonZero; + } + + if (firstNonZero == magnitude.Length) + { + return "0"; + } + + + StringBuilder sb = new StringBuilder(); + if (sign == -1) + { + sb.Append('-'); + } + + switch (radix) + { + case 2: + { + int pos = firstNonZero; + sb.Append(Convert.ToString(magnitude[pos], 2)); + while (++pos < magnitude.Length) + { + AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 2), 32); + } + break; + } + case 8: + { + int mask = (1 << 30) - 1; + BigInteger u = this.Abs(); + int bits = u.BitLength; + IList S = Platform.CreateArrayList(); + while (bits > 30) + { + S.Add(Convert.ToString(u.IntValue & mask, 8)); + u = u.ShiftRight(30); + bits -= 30; + } + sb.Append(Convert.ToString(u.IntValue, 8)); + for (int i = S.Count - 1; i >= 0; --i) + { + AppendZeroExtendedString(sb, (string)S[i], 10); + } + break; + } + case 16: + { + int pos = firstNonZero; + sb.Append(Convert.ToString(magnitude[pos], 16)); + while (++pos < magnitude.Length) + { + AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 16), 8); + } + break; + } + // TODO This could work for other radices if there is an alternative to Convert.ToString method + //default: + case 10: + { + BigInteger q = this.Abs(); + if (q.BitLength < 64) + { + sb.Append(Convert.ToString(q.LongValue, radix)); + break; + } + + // Based on algorithm 1a from chapter 4.4 in Seminumerical Algorithms (Knuth) + + // Work out the largest power of 'rdx' that is a positive 64-bit integer + // TODO possibly cache power/exponent against radix? + long limit = Int64.MaxValue / radix; + long power = radix; + int exponent = 1; + while (power <= limit) + { + power *= radix; + ++exponent; + } + + BigInteger bigPower = BigInteger.ValueOf(power); + + IList S = Platform.CreateArrayList(); + while (q.CompareTo(bigPower) >= 0) + { + BigInteger[] qr = q.DivideAndRemainder(bigPower); + S.Add(Convert.ToString(qr[1].LongValue, radix)); + q = qr[0]; + } + + sb.Append(Convert.ToString(q.LongValue, radix)); + for (int i = S.Count - 1; i >= 0; --i) + { + AppendZeroExtendedString(sb, (string)S[i], exponent); + } + break; + } + } + + return sb.ToString(); + } + + private static void AppendZeroExtendedString(StringBuilder sb, string s, int minLength) + { + for (int len = s.Length; len < minLength; ++len) + { + sb.Append('0'); + } + sb.Append(s); + } + + private static BigInteger CreateUValueOf( + ulong value) + { + int msw = (int)(value >> 32); + int lsw = (int)value; + + if (msw != 0) + return new BigInteger(1, new int[] { msw, lsw }, false); + + if (lsw != 0) + { + BigInteger n = new BigInteger(1, new int[] { lsw }, false); + // Check for a power of two + if ((lsw & -lsw) == lsw) + { + n.nBits = 1; + } + return n; + } + + return Zero; + } + + private static BigInteger CreateValueOf( + long value) + { + if (value < 0) + { + if (value == long.MinValue) + return CreateValueOf(~value).Not(); + + return CreateValueOf(-value).Negate(); + } + + return CreateUValueOf((ulong)value); + } + + public static BigInteger ValueOf( + long value) + { + if (value >= 0 && value < SMALL_CONSTANTS.Length) + { + return SMALL_CONSTANTS[value]; + } + + return CreateValueOf(value); + } + + public int GetLowestSetBit() + { + if (this.sign == 0) + return -1; + + return GetLowestSetBitMaskFirst(-1); + } + + private int GetLowestSetBitMaskFirst(int firstWordMask) + { + int w = magnitude.Length, offset = 0; + + uint word = (uint)(magnitude[--w] & firstWordMask); + Debug.Assert(magnitude[0] != 0); + + while (word == 0) + { + word = (uint)magnitude[--w]; + offset += 32; + } + + while ((word & 0xFF) == 0) + { + word >>= 8; + offset += 8; + } + + while ((word & 1) == 0) + { + word >>= 1; + ++offset; + } + + return offset; + } + + public bool TestBit( + int n) + { + if (n < 0) + throw new ArithmeticException("Bit position must not be negative"); + + if (sign < 0) + return !Not().TestBit(n); + + int wordNum = n / 32; + if (wordNum >= magnitude.Length) + return false; + + int word = magnitude[magnitude.Length - 1 - wordNum]; + return ((word >> (n % 32)) & 1) > 0; + } + + public BigInteger Or( + BigInteger value) + { + if (this.sign == 0) + return value; + + if (value.sign == 0) + return this; + + int[] aMag = this.sign > 0 + ? this.magnitude + : Add(One).magnitude; + + int[] bMag = value.sign > 0 + ? value.magnitude + : value.Add(One).magnitude; + + bool resultNeg = sign < 0 || value.sign < 0; + int resultLength = System.Math.Max(aMag.Length, bMag.Length); + int[] resultMag = new int[resultLength]; + + int aStart = resultMag.Length - aMag.Length; + int bStart = resultMag.Length - bMag.Length; + + for (int i = 0; i < resultMag.Length; ++i) + { + int aWord = i >= aStart ? aMag[i - aStart] : 0; + int bWord = i >= bStart ? bMag[i - bStart] : 0; + + if (this.sign < 0) + { + aWord = ~aWord; + } + + if (value.sign < 0) + { + bWord = ~bWord; + } + + resultMag[i] = aWord | bWord; + + if (resultNeg) + { + resultMag[i] = ~resultMag[i]; + } + } + + BigInteger result = new BigInteger(1, resultMag, true); + + // TODO Optimise this case + if (resultNeg) + { + result = result.Not(); + } + + return result; + } + + public BigInteger Xor( + BigInteger value) + { + if (this.sign == 0) + return value; + + if (value.sign == 0) + return this; + + int[] aMag = this.sign > 0 + ? this.magnitude + : Add(One).magnitude; + + int[] bMag = value.sign > 0 + ? value.magnitude + : value.Add(One).magnitude; + + // TODO Can just replace with sign != value.sign? + bool resultNeg = (sign < 0 && value.sign >= 0) || (sign >= 0 && value.sign < 0); + int resultLength = System.Math.Max(aMag.Length, bMag.Length); + int[] resultMag = new int[resultLength]; + + int aStart = resultMag.Length - aMag.Length; + int bStart = resultMag.Length - bMag.Length; + + for (int i = 0; i < resultMag.Length; ++i) + { + int aWord = i >= aStart ? aMag[i - aStart] : 0; + int bWord = i >= bStart ? bMag[i - bStart] : 0; + + if (this.sign < 0) + { + aWord = ~aWord; + } + + if (value.sign < 0) + { + bWord = ~bWord; + } + + resultMag[i] = aWord ^ bWord; + + if (resultNeg) + { + resultMag[i] = ~resultMag[i]; + } + } + + BigInteger result = new BigInteger(1, resultMag, true); + + // TODO Optimise this case + if (resultNeg) + { + result = result.Not(); + } + + return result; + } + + public BigInteger SetBit( + int n) + { + if (n < 0) + throw new ArithmeticException("Bit address less than zero"); + + if (TestBit(n)) + return this; + + // TODO Handle negative values and zero + if (sign > 0 && n < (BitLength - 1)) + return FlipExistingBit(n); + + return Or(One.ShiftLeft(n)); + } + + public BigInteger ClearBit( + int n) + { + if (n < 0) + throw new ArithmeticException("Bit address less than zero"); + + if (!TestBit(n)) + return this; + + // TODO Handle negative values + if (sign > 0 && n < (BitLength - 1)) + return FlipExistingBit(n); + + return AndNot(One.ShiftLeft(n)); + } + + public BigInteger FlipBit( + int n) + { + if (n < 0) + throw new ArithmeticException("Bit address less than zero"); + + // TODO Handle negative values and zero + if (sign > 0 && n < (BitLength - 1)) + return FlipExistingBit(n); + + return Xor(One.ShiftLeft(n)); + } + + private BigInteger FlipExistingBit( + int n) + { + Debug.Assert(sign > 0); + Debug.Assert(n >= 0); + Debug.Assert(n < BitLength - 1); + + int[] mag = (int[]) this.magnitude.Clone(); + mag[mag.Length - 1 - (n >> 5)] ^= (1 << (n & 31)); // Flip bit + //mag[mag.Length - 1 - (n / 32)] ^= (1 << (n % 32)); + return new BigInteger(this.sign, mag, false); + } + } +} diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs new file mode 100644 index 000000000..be4fd1b14 --- /dev/null +++ b/crypto/src/math/ec/ECAlgorithms.cs @@ -0,0 +1,93 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Math.EC +{ + public class ECAlgorithms + { + public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, + ECPoint Q, BigInteger b) + { + ECCurve c = P.Curve; + if (!c.Equals(Q.Curve)) + throw new ArgumentException("P and Q must be on same curve"); + + // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick + if (c is F2mCurve) + { + F2mCurve f2mCurve = (F2mCurve) c; + if (f2mCurve.IsKoblitz) + { + return P.Multiply(a).Add(Q.Multiply(b)); + } + } + + return ImplShamirsTrick(P, a, Q, b); + } + + /* + * "Shamir's Trick", originally due to E. G. Straus + * (Addition chains of vectors. American Mathematical Monthly, + * 71(7):806-808, Aug./Sept. 1964) + * + * 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 + */ + public static ECPoint ShamirsTrick( + ECPoint P, + BigInteger k, + ECPoint Q, + BigInteger l) + { + if (!P.Curve.Equals(Q.Curve)) + throw new ArgumentException("P and Q must be on same curve"); + + return ImplShamirsTrick(P, k, Q, l); + } + + private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k, + ECPoint Q, BigInteger l) + { + int m = System.Math.Max(k.BitLength, l.BitLength); + ECPoint Z = P.Add(Q); + ECPoint R = P.Curve.Infinity; + + for (int i = m - 1; i >= 0; --i) + { + R = R.Twice(); + + if (k.TestBit(i)) + { + if (l.TestBit(i)) + { + R = R.Add(Z); + } + else + { + R = R.Add(P); + } + } + else + { + if (l.TestBit(i)) + { + R = R.Add(Q); + } + } + } + + return R; + } + } +} diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs new file mode 100644 index 000000000..396d42f28 --- /dev/null +++ b/crypto/src/math/ec/ECCurve.cs @@ -0,0 +1,651 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Math.EC.Abc; + +namespace Org.BouncyCastle.Math.EC +{ + /// Base class for an elliptic curve. + public abstract class ECCurve + { + internal ECFieldElement a, b; + + public abstract int FieldSize { get; } + public abstract ECFieldElement FromBigInteger(BigInteger x); + public abstract ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression); + public abstract ECPoint Infinity { get; } + + public ECFieldElement A + { + get { return a; } + } + + public ECFieldElement B + { + get { return b; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECCurve other = obj as ECCurve; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECCurve other) + { + return a.Equals(other.a) && b.Equals(other.b); + } + + public override int GetHashCode() + { + return a.GetHashCode() ^ b.GetHashCode(); + } + + protected abstract ECPoint DecompressPoint(int yTilde, BigInteger X1); + + /** + * Decode a point on this curve from its ASN.1 encoding. The different + * encodings are taken account of, including point compression for + * Fp (X9.62 s 4.2.1 pg 17). + * @return The decoded point. + */ + public virtual ECPoint DecodePoint(byte[] encoded) + { + ECPoint p = null; + int expectedLength = (FieldSize + 7) / 8; + + switch (encoded[0]) + { + case 0x00: // infinity + { + if (encoded.Length != 1) + throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); + + p = Infinity; + break; + } + + case 0x02: // compressed + case 0x03: // compressed + { + if (encoded.Length != (expectedLength + 1)) + throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); + + int yTilde = encoded[0] & 1; + BigInteger X1 = new BigInteger(1, encoded, 1, expectedLength); + + p = DecompressPoint(yTilde, X1); + break; + } + + case 0x04: // uncompressed + case 0x06: // hybrid + case 0x07: // hybrid + { + if (encoded.Length != (2 * expectedLength + 1)) + throw new ArgumentException("Incorrect length for uncompressed/hybrid encoding", "encoded"); + + BigInteger X1 = new BigInteger(1, encoded, 1, expectedLength); + BigInteger Y1 = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); + + p = CreatePoint(X1, Y1, false); + break; + } + + default: + throw new FormatException("Invalid point encoding " + encoded[0]); + } + + return p; + } + } + + /** + * Elliptic curve over Fp + */ + public class FpCurve : ECCurve + { + private readonly BigInteger q; + private readonly FpPoint infinity; + + public FpCurve(BigInteger q, BigInteger a, BigInteger b) + { + this.q = q; + this.a = FromBigInteger(a); + this.b = FromBigInteger(b); + this.infinity = new FpPoint(this, null, null); + } + + public BigInteger Q + { + get { return q; } + } + + public override ECPoint Infinity + { + get { return infinity; } + } + + public override int FieldSize + { + get { return q.BitLength; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new FpFieldElement(this.q, x); + } + + public override ECPoint CreatePoint( + BigInteger X1, + BigInteger Y1, + bool withCompression) + { + // TODO Validation of X1, Y1? + return new FpPoint( + this, + FromBigInteger(X1), + FromBigInteger(Y1), + withCompression); + } + + protected override ECPoint DecompressPoint( + int yTilde, + BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1); + ECFieldElement alpha = x.Multiply(x.Square().Add(a)).Add(b); + ECFieldElement beta = alpha.Sqrt(); + + // + // if we can't find a sqrt we haven't got a point on the + // curve - run! + // + if (beta == null) + throw new ArithmeticException("Invalid point compression"); + + BigInteger betaValue = beta.ToBigInteger(); + int bit0 = betaValue.TestBit(0) ? 1 : 0; + + if (bit0 != yTilde) + { + // Use the other root + beta = FromBigInteger(q.Subtract(betaValue)); + } + + return new FpPoint(this, x, beta, true); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + FpCurve other = obj as FpCurve; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + FpCurve other) + { + return base.Equals(other) && q.Equals(other.q); + } + + public override int GetHashCode() + { + return base.GetHashCode() ^ q.GetHashCode(); + } + } + + /** + * Elliptic curves over F2m. The Weierstrass equation is given by + * y2 + xy = x3 + ax2 + b. + */ + public class F2mCurve : ECCurve + { + /** + * The exponent m of F2m. + */ + private readonly int m; + + /** + * TPB: The integer k where xm + + * xk + 1 represents the reduction polynomial + * f(z).
    + * PPB: The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private readonly int k1; + + /** + * TPB: Always set to 0
    + * PPB: The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private readonly int k2; + + /** + * TPB: Always set to 0
    + * PPB: The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private readonly int k3; + + /** + * The order of the base point of the curve. + */ + private readonly BigInteger n; + + /** + * The cofactor of the curve. + */ + private readonly BigInteger h; + + /** + * The point at infinity on this curve. + */ + private readonly F2mPoint infinity; + + /** + * The parameter μ of the elliptic curve if this is + * a Koblitz curve. + */ + private sbyte mu = 0; + + /** + * The auxiliary values s0 and + * s1 used for partial modular reduction for + * Koblitz curves. + */ + private BigInteger[] si = null; + + /** + * Constructor for Trinomial Polynomial Basis (TPB). + * @param m The exponent m of + * F2m. + * @param k The integer k where xm + + * xk + 1 represents the reduction + * polynomial f(z). + * @param a The coefficient a in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param b The coefficient b in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + */ + public F2mCurve( + 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 m of + * F2m. + * @param k The integer k where xm + + * xk + 1 represents the reduction + * polynomial f(z). + * @param a The coefficient a in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param b The coefficient b in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param n The order of the main subgroup of the elliptic curve. + * @param h The cofactor of the elliptic curve, i.e. + * #Ea(F2m) = h * n. + */ + public F2mCurve( + int m, + int k, + BigInteger a, + BigInteger b, + BigInteger n, + BigInteger h) + : this(m, k, 0, 0, a, b, n, h) + { + } + + /** + * Constructor for Pentanomial Polynomial Basis (PPB). + * @param m The exponent m of + * F2m. + * @param k1 The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k2 The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k3 The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param a The coefficient a in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param b The coefficient b in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + */ + public F2mCurve( + 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 m of + * F2m. + * @param k1 The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k2 The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k3 The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param a The coefficient a in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param b The coefficient b in the Weierstrass equation + * for non-supersingular elliptic curves over + * F2m. + * @param n The order of the main subgroup of the elliptic curve. + * @param h The cofactor of the elliptic curve, i.e. + * #Ea(F2m) = h * n. + */ + public F2mCurve( + int m, + int k1, + int k2, + int k3, + BigInteger a, + BigInteger b, + BigInteger n, + BigInteger h) + { + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + this.n = n; + this.h = h; + this.infinity = new F2mPoint(this, null, null); + + if (k1 == 0) + throw new ArgumentException("k1 must be > 0"); + + if (k2 == 0) + { + if (k3 != 0) + throw new ArgumentException("k3 must be 0 if k2 == 0"); + } + else + { + if (k2 <= k1) + throw new ArgumentException("k2 must be > k1"); + + if (k3 <= k2) + throw new ArgumentException("k3 must be > k2"); + } + + this.a = FromBigInteger(a); + this.b = FromBigInteger(b); + } + + public override ECPoint Infinity + { + get { return infinity; } + } + + public override int FieldSize + { + get { return m; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x); + } + + /** + * Returns true if this is a Koblitz curve (ABC curve). + * @return true if this is a Koblitz curve (ABC curve), false otherwise + */ + public bool IsKoblitz + { + get + { + return n != null && h != null + && (a.ToBigInteger().Equals(BigInteger.Zero) + || a.ToBigInteger().Equals(BigInteger.One)) + && b.ToBigInteger().Equals(BigInteger.One); + } + } + + /** + * Returns the parameter μ of the elliptic curve. + * @return μ of the elliptic curve. + * @throws ArgumentException if the given ECCurve is not a + * Koblitz curve. + */ + internal sbyte GetMu() + { + if (mu == 0) + { + lock (this) + { + if (mu == 0) + { + mu = Tnaf.GetMu(this); + } + } + } + + return mu; + } + + /** + * @return the auxiliary values s0 and + * s1 used for partial modular reduction for + * Koblitz curves. + */ + internal BigInteger[] GetSi() + { + if (si == null) + { + lock (this) + { + if (si == null) + { + si = Tnaf.GetSi(this); + } + } + } + return si; + } + + public override ECPoint CreatePoint( + BigInteger X1, + BigInteger Y1, + bool withCompression) + { + // TODO Validation of X1, Y1? + return new F2mPoint( + this, + FromBigInteger(X1), + FromBigInteger(Y1), + withCompression); + } + + protected override ECPoint DecompressPoint( + int yTilde, + BigInteger X1) + { + ECFieldElement xp = FromBigInteger(X1); + ECFieldElement yp = null; + if (xp.ToBigInteger().SignValue == 0) + { + yp = (F2mFieldElement)b; + for (int i = 0; i < m - 1; i++) + { + yp = yp.Square(); + } + } + else + { + ECFieldElement beta = xp.Add(a).Add(b.Multiply(xp.Square().Invert())); + ECFieldElement z = solveQuadradicEquation(beta); + + if (z == null) + throw new ArithmeticException("Invalid point compression"); + + int zBit = z.ToBigInteger().TestBit(0) ? 1 : 0; + if (zBit != yTilde) + { + z = z.Add(FromBigInteger(BigInteger.One)); + } + + yp = xp.Multiply(z); + } + + return new F2mPoint(this, xp, yp, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the qradratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement solveQuadradicEquation(ECFieldElement beta) + { + if (beta.ToBigInteger().SignValue == 0) + { + return FromBigInteger(BigInteger.Zero); + } + + ECFieldElement z = null; + ECFieldElement gamma = FromBigInteger(BigInteger.Zero); + + while (gamma.ToBigInteger().SignValue == 0) + { + ECFieldElement t = FromBigInteger(new BigInteger(m, new Random())); + z = FromBigInteger(BigInteger.Zero); + + ECFieldElement w = beta; + for (int i = 1; i <= m - 1; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (w.ToBigInteger().SignValue != 0) + { + return null; + } + gamma = z.Square().Add(z); + } + return z; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + F2mCurve other = obj as F2mCurve; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + F2mCurve other) + { + return m == other.m + && k1 == other.k1 + && k2 == other.k2 + && k3 == other.k3 + && base.Equals(other); + } + + public override int GetHashCode() + { + return base.GetHashCode() ^ m ^ k1 ^ k2 ^ k3; + } + + public int M + { + get { return m; } + } + + /** + * Return true if curve uses a Trinomial basis. + * + * @return true if curve Trinomial, false otherwise. + */ + public bool IsTrinomial() + { + return k2 == 0 && k3 == 0; + } + + public int K1 + { + get { return k1; } + } + + public int K2 + { + get { return k2; } + } + + public int K3 + { + get { return k3; } + } + + public BigInteger N + { + get { return n; } + } + + public BigInteger H + { + get { return h; } + } + } +} diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs new file mode 100644 index 000000000..5235c6c0e --- /dev/null +++ b/crypto/src/math/ec/ECFieldElement.cs @@ -0,0 +1,1253 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC +{ + public abstract class ECFieldElement + { + public abstract BigInteger ToBigInteger(); + public abstract string FieldName { get; } + public abstract int FieldSize { get; } + public abstract ECFieldElement Add(ECFieldElement b); + public abstract ECFieldElement Subtract(ECFieldElement b); + public abstract ECFieldElement Multiply(ECFieldElement b); + public abstract ECFieldElement Divide(ECFieldElement b); + public abstract ECFieldElement Negate(); + public abstract ECFieldElement Square(); + public abstract ECFieldElement Invert(); + public abstract ECFieldElement Sqrt(); + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECFieldElement other = obj as ECFieldElement; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + ECFieldElement other) + { + return ToBigInteger().Equals(other.ToBigInteger()); + } + + public override int GetHashCode() + { + return ToBigInteger().GetHashCode(); + } + + public override string ToString() + { + return this.ToBigInteger().ToString(2); + } + } + + public class FpFieldElement + : ECFieldElement + { + private readonly BigInteger q, x; + + public FpFieldElement( + BigInteger q, + BigInteger x) + { + if (x.CompareTo(q) >= 0) + throw new ArgumentException("x value too large in field element"); + + this.q = q; + this.x = x; + } + + public override BigInteger ToBigInteger() + { + return x; + } + + /** + * return the field name for this field. + * + * @return the string "Fp". + */ + public override string FieldName + { + get { return "Fp"; } + } + + public override int FieldSize + { + get { return q.BitLength; } + } + + public BigInteger Q + { + get { return q; } + } + + public override ECFieldElement Add( + ECFieldElement b) + { + return new FpFieldElement(q, x.Add(b.ToBigInteger()).Mod(q)); + } + + public override ECFieldElement Subtract( + ECFieldElement b) + { + return new FpFieldElement(q, x.Subtract(b.ToBigInteger()).Mod(q)); + } + + public override ECFieldElement Multiply( + ECFieldElement b) + { + return new FpFieldElement(q, x.Multiply(b.ToBigInteger()).Mod(q)); + } + + public override ECFieldElement Divide( + ECFieldElement b) + { + return new FpFieldElement(q, x.Multiply(b.ToBigInteger().ModInverse(q)).Mod(q)); + } + + public override ECFieldElement Negate() + { + return new FpFieldElement(q, x.Negate().Mod(q)); + } + + public override ECFieldElement Square() + { + return new FpFieldElement(q, x.Multiply(x).Mod(q)); + } + + public override ECFieldElement Invert() + { + return new FpFieldElement(q, x.ModInverse(q)); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation + * returns the right value - if none exists it returns null. + */ + public override ECFieldElement Sqrt() + { + if (!q.TestBit(0)) + throw Platform.CreateNotImplementedException("even value of q"); + + // p mod 4 == 3 + if (q.TestBit(1)) + { + // TODO Can this be optimised (inline the Square?) + // z = g^(u+1) + p, p = 4u + 3 + ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q)); + + return this.Equals(z.Square()) ? z : null; + } + + // p mod 4 == 1 + BigInteger qMinusOne = q.Subtract(BigInteger.One); + + BigInteger legendreExponent = qMinusOne.ShiftRight(1); + if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) + return null; + + BigInteger u = qMinusOne.ShiftRight(2); + BigInteger k = u.ShiftLeft(1).Add(BigInteger.One); + + BigInteger Q = this.x; + BigInteger fourQ = Q.ShiftLeft(2).Mod(q); + + BigInteger U, V; + do + { + Random rand = new Random(); + BigInteger P; + do + { + P = new BigInteger(q.BitLength, rand); + } + while (P.CompareTo(q) >= 0 + || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne))); + + BigInteger[] result = fastLucasSequence(q, P, Q, k); + U = result[0]; + V = result[1]; + + if (V.Multiply(V).Mod(q).Equals(fourQ)) + { + // Integer division by 2, mod q + if (V.TestBit(0)) + { + V = V.Add(q); + } + + V = V.ShiftRight(1); + + Debug.Assert(V.Multiply(V).Mod(q).Equals(x)); + + return new FpFieldElement(q, V); + } + } + while (U.Equals(BigInteger.One) || U.Equals(qMinusOne)); + + return null; + + +// BigInteger qMinusOne = q.Subtract(BigInteger.One); +// +// BigInteger legendreExponent = qMinusOne.ShiftRight(1); +// if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) +// return null; +// +// Random rand = new Random(); +// BigInteger fourX = x.ShiftLeft(2); +// +// BigInteger r; +// do +// { +// r = new BigInteger(q.BitLength, rand); +// } +// while (r.CompareTo(q) >= 0 +// || !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne))); +// +// BigInteger n1 = qMinusOne.ShiftRight(2); +// BigInteger n2 = n1.Add(BigInteger.One); +// +// BigInteger wOne = WOne(r, x, q); +// BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q); +// BigInteger twoR = r.ShiftLeft(1); +// +// BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q) +// .Multiply(x).Mod(q) +// .Multiply(wSum).Mod(q); +// +// return new FpFieldElement(q, root); + } + +// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) +// { +// if (n.Equals(BigInteger.One)) +// return wOne; +// +// bool isEven = !n.TestBit(0); +// n = n.ShiftRight(1); +// if (isEven) +// { +// BigInteger w = W(n, wOne, p); +// return w.Multiply(w).Subtract(BigInteger.Two).Mod(p); +// } +// BigInteger w1 = W(n.Add(BigInteger.One), wOne, p); +// BigInteger w2 = W(n, wOne, p); +// return w1.Multiply(w2).Subtract(wOne).Mod(p); +// } +// +// private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) +// { +// return r.Multiply(r).Multiply(x.ModPow(q.Subtract(BigInteger.Two), q)).Subtract(BigInteger.Two).Mod(p); +// } + + private static BigInteger[] fastLucasSequence( + BigInteger p, + BigInteger P, + BigInteger Q, + BigInteger k) + { + // TODO Research and apply "common-multiplicand multiplication here" + + int n = k.BitLength; + int s = k.GetLowestSetBit(); + + Debug.Assert(k.TestBit(s)); + + BigInteger Uh = BigInteger.One; + BigInteger Vl = BigInteger.Two; + BigInteger Vh = P; + BigInteger Ql = BigInteger.One; + BigInteger Qh = BigInteger.One; + + for (int j = n - 1; j >= s + 1; --j) + { + Ql = Ql.Multiply(Qh).Mod(p); + + if (k.TestBit(j)) + { + Qh = Ql.Multiply(Q).Mod(p); + Uh = Uh.Multiply(Vh).Mod(p); + Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); + Vh = Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)).Mod(p); + } + else + { + Qh = Ql; + Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); + Vh = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); + Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); + } + } + + Ql = Ql.Multiply(Qh).Mod(p); + Qh = Ql.Multiply(Q).Mod(p); + Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); + Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); + Ql = Ql.Multiply(Qh).Mod(p); + + for (int j = 1; j <= s; ++j) + { + Uh = Uh.Multiply(Vl).Mod(p); + Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); + Ql = Ql.Multiply(Ql).Mod(p); + } + + return new BigInteger[]{ Uh, Vl }; + } + +// private static BigInteger[] verifyLucasSequence( +// BigInteger p, +// BigInteger P, +// BigInteger Q, +// BigInteger k) +// { +// BigInteger[] actual = fastLucasSequence(p, P, Q, k); +// BigInteger[] plus1 = fastLucasSequence(p, P, Q, k.Add(BigInteger.One)); +// BigInteger[] plus2 = fastLucasSequence(p, P, Q, k.Add(BigInteger.Two)); +// +// BigInteger[] check = stepLucasSequence(p, P, Q, actual, plus1); +// +// Debug.Assert(check[0].Equals(plus2[0])); +// Debug.Assert(check[1].Equals(plus2[1])); +// +// return actual; +// } +// +// private static BigInteger[] stepLucasSequence( +// BigInteger p, +// BigInteger P, +// BigInteger Q, +// BigInteger[] backTwo, +// BigInteger[] backOne) +// { +// return new BigInteger[] +// { +// P.Multiply(backOne[0]).Subtract(Q.Multiply(backTwo[0])).Mod(p), +// P.Multiply(backOne[1]).Subtract(Q.Multiply(backTwo[1])).Mod(p) +// }; +// } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + FpFieldElement other = obj as FpFieldElement; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + FpFieldElement other) + { + return q.Equals(other.q) && base.Equals(other); + } + + public override int GetHashCode() + { + return q.GetHashCode() ^ base.GetHashCode(); + } + } + +// /** +// * Class representing the Elements of the finite field +// * F2m 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 class F2mFieldElement +// : ECFieldElement +// { +// /** +// * Indicates gaussian normal basis representation (GNB). Number chosen +// * according to X9.62. GNB is not implemented at present. +// */ +// public const int Gnb = 1; +// +// /** +// * Indicates trinomial basis representation (Tpb). Number chosen +// * according to X9.62. +// */ +// public const int Tpb = 2; +// +// /** +// * Indicates pentanomial basis representation (Ppb). Number chosen +// * according to X9.62. +// */ +// public const int Ppb = 3; +// +// /** +// * Tpb or Ppb. +// */ +// private int representation; +// +// /** +// * The exponent m of F2m. +// */ +// private int m; +// +// /** +// * Tpb: The integer k where xm + +// * xk + 1 represents the reduction polynomial +// * f(z).
    +// * Ppb: The integer k1 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// private int k1; +// +// /** +// * Tpb: Always set to 0
    +// * Ppb: The integer k2 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// private int k2; +// +// /** +// * Tpb: Always set to 0
    +// * Ppb: The integer k3 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// private int k3; +// +// /** +// * Constructor for Ppb. +// * @param m The exponent m of +// * F2m. +// * @param k1 The integer k1 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z). +// * @param k2 The integer k2 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z). +// * @param k3 The integer k3 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z). +// * @param x The BigInteger representing the value of the field element. +// */ +// public F2mFieldElement( +// int m, +// int k1, +// int k2, +// int k3, +// BigInteger x) +// : base(x) +// { +// if ((k2 == 0) && (k3 == 0)) +// { +// this.representation = Tpb; +// } +// else +// { +// if (k2 >= k3) +// throw new ArgumentException("k2 must be smaller than k3"); +// if (k2 <= 0) +// throw new ArgumentException("k2 must be larger than 0"); +// +// this.representation = Ppb; +// } +// +// if (x.SignValue < 0) +// throw new ArgumentException("x value cannot be negative"); +// +// this.m = m; +// this.k1 = k1; +// this.k2 = k2; +// this.k3 = k3; +// } +// +// /** +// * Constructor for Tpb. +// * @param m The exponent m of +// * F2m. +// * @param k The integer k where xm + +// * xk + 1 represents the reduction +// * polynomial f(z). +// * @param x The BigInteger representing the value of the field element. +// */ +// public F2mFieldElement( +// int m, +// int k, +// BigInteger x) +// : this(m, k, 0, 0, x) +// { +// // Set k1 to k, and set k2 and k3 to 0 +// } +// +// public override string FieldName +// { +// get { return "F2m"; } +// } +// +// /** +// * Checks, if the ECFieldElements a and b +// * are elements of the same field F2m +// * (having the same representation). +// * @param a field element. +// * @param b field element to be compared. +// * @throws ArgumentException if a and b +// * are not elements of the same field +// * F2m (having the same +// * representation). +// */ +// public static void CheckFieldElements( +// ECFieldElement a, +// ECFieldElement b) +// { +// if (!(a is F2mFieldElement) || !(b is F2mFieldElement)) +// { +// throw new ArgumentException("Field elements are not " +// + "both instances of F2mFieldElement"); +// } +// +// if ((a.x.SignValue < 0) || (b.x.SignValue < 0)) +// { +// throw new ArgumentException( +// "x value may not be negative"); +// } +// +// F2mFieldElement aF2m = (F2mFieldElement)a; +// F2mFieldElement bF2m = (F2mFieldElement)b; +// +// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) +// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) +// { +// throw new ArgumentException("Field elements are not " +// + "elements of the same field F2m"); +// } +// +// if (aF2m.representation != bF2m.representation) +// { +// // Should never occur +// throw new ArgumentException( +// "One of the field " +// + "elements are not elements has incorrect representation"); +// } +// } +// +// /** +// * Computes z * a(z) mod f(z), where f(z) is +// * the reduction polynomial of this. +// * @param a The polynomial a(z) to be multiplied by +// * z mod f(z). +// * @return z * a(z) mod f(z) +// */ +// private BigInteger multZModF( +// BigInteger a) +// { +// // Left-shift of a(z) +// BigInteger az = a.ShiftLeft(1); +// if (az.TestBit(this.m)) +// { +// // If the coefficient of z^m in a(z) Equals 1, reduction +// // modulo f(z) is performed: Add f(z) to to a(z): +// // Step 1: Unset mth coeffient of a(z) +// az = az.ClearBit(this.m); +// +// // Step 2: Add r(z) to a(z), where r(z) is defined as +// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of +// // the non-zero coefficients in r(z) +// az = az.FlipBit(0); +// az = az.FlipBit(this.k1); +// if (this.representation == Ppb) +// { +// az = az.FlipBit(this.k2); +// az = az.FlipBit(this.k3); +// } +// } +// return az; +// } +// +// public override ECFieldElement Add( +// ECFieldElement b) +// { +// // No check performed here for performance reasons. Instead the +// // elements involved are checked in ECPoint.F2m +// // checkFieldElements(this, b); +// if (b.x.SignValue == 0) +// return this; +// +// return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, this.x.Xor(b.x)); +// } +// +// public override ECFieldElement Subtract( +// ECFieldElement b) +// { +// // Addition and subtraction are the same in F2m +// return Add(b); +// } +// +// public override ECFieldElement Multiply( +// ECFieldElement b) +// { +// // Left-to-right shift-and-add field multiplication in F2m +// // Input: Binary polynomials a(z) and b(z) of degree at most m-1 +// // Output: c(z) = a(z) * b(z) mod f(z) +// +// // No check performed here for performance reasons. Instead the +// // elements involved are checked in ECPoint.F2m +// // checkFieldElements(this, b); +// BigInteger az = this.x; +// BigInteger bz = b.x; +// BigInteger cz; +// +// // Compute c(z) = a(z) * b(z) mod f(z) +// if (az.TestBit(0)) +// { +// cz = bz; +// } +// else +// { +// cz = BigInteger.Zero; +// } +// +// for (int i = 1; i < this.m; i++) +// { +// // b(z) := z * b(z) mod f(z) +// bz = multZModF(bz); +// +// if (az.TestBit(i)) +// { +// // If the coefficient of x^i in a(z) Equals 1, b(z) is added +// // to c(z) +// cz = cz.Xor(bz); +// } +// } +// return new F2mFieldElement(m, this.k1, this.k2, this.k3, cz); +// } +// +// +// public override ECFieldElement Divide( +// ECFieldElement b) +// { +// // There may be more efficient implementations +// ECFieldElement bInv = b.Invert(); +// return Multiply(bInv); +// } +// +// public override ECFieldElement Negate() +// { +// // -x == x holds for all x in F2m +// return this; +// } +// +// public override ECFieldElement Square() +// { +// // Naive implementation, can probably be speeded up using modular +// // reduction +// return Multiply(this); +// } +// +// public override ECFieldElement Invert() +// { +// // Inversion in F2m using the extended Euclidean algorithm +// // Input: A nonzero polynomial a(z) of degree at most m-1 +// // Output: a(z)^(-1) mod f(z) +// +// // u(z) := a(z) +// BigInteger uz = this.x; +// if (uz.SignValue <= 0) +// { +// throw new ArithmeticException("x is zero or negative, " + +// "inversion is impossible"); +// } +// +// // v(z) := f(z) +// BigInteger vz = BigInteger.One.ShiftLeft(m); +// vz = vz.SetBit(0); +// vz = vz.SetBit(this.k1); +// if (this.representation == Ppb) +// { +// vz = vz.SetBit(this.k2); +// vz = vz.SetBit(this.k3); +// } +// +// // g1(z) := 1, g2(z) := 0 +// BigInteger g1z = BigInteger.One; +// BigInteger g2z = BigInteger.Zero; +// +// // while u != 1 +// while (uz.SignValue != 0) +// { +// // j := deg(u(z)) - deg(v(z)) +// int j = uz.BitLength - vz.BitLength; +// +// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j +// if (j < 0) +// { +// BigInteger uzCopy = uz; +// uz = vz; +// vz = uzCopy; +// +// BigInteger g1zCopy = g1z; +// g1z = g2z; +// g2z = g1zCopy; +// +// j = -j; +// } +// +// // u(z) := u(z) + z^j * v(z) +// // Note, that no reduction modulo f(z) is required, because +// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) +// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) +// // = deg(u(z)) +// uz = uz.Xor(vz.ShiftLeft(j)); +// +// // g1(z) := g1(z) + z^j * g2(z) +// g1z = g1z.Xor(g2z.ShiftLeft(j)); +// // if (g1z.BitLength() > this.m) { +// // throw new ArithmeticException( +// // "deg(g1z) >= m, g1z = " + g1z.ToString(2)); +// // } +// } +// return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, g2z); +// } +// +// public override ECFieldElement Sqrt() +// { +// throw new ArithmeticException("Not implemented"); +// } +// +// /** +// * @return the representation of the field +// * F2m, either of +// * {@link F2mFieldElement.Tpb} (trinomial +// * basis representation) or +// * {@link F2mFieldElement.Ppb} (pentanomial +// * basis representation). +// */ +// public int Representation +// { +// get { return this.representation; } +// } +// +// /** +// * @return the degree m of the reduction polynomial +// * f(z). +// */ +// public int M +// { +// get { return this.m; } +// } +// +// /** +// * @return Tpb: The integer k where xm + +// * xk + 1 represents the reduction polynomial +// * f(z).
    +// * Ppb: The integer k1 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// public int K1 +// { +// get { return this.k1; } +// } +// +// /** +// * @return Tpb: Always returns 0
    +// * Ppb: The integer k2 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// public int K2 +// { +// get { return this.k2; } +// } +// +// /** +// * @return Tpb: Always set to 0
    +// * Ppb: The integer k3 where xm + +// * xk3 + xk2 + xk1 + 1 +// * represents the reduction polynomial f(z).
    +// */ +// public int K3 +// { +// get { return this.k3; } +// } +// +// public override bool Equals( +// object obj) +// { +// if (obj == this) +// return true; +// +// F2mFieldElement other = obj as F2mFieldElement; +// +// if (other == null) +// return false; +// +// return Equals(other); +// } +// +// protected bool Equals( +// F2mFieldElement other) +// { +// return m == other.m +// && k1 == other.k1 +// && k2 == other.k2 +// && k3 == other.k3 +// && representation == other.representation +// && base.Equals(other); +// } +// +// public override int GetHashCode() +// { +// return base.GetHashCode() ^ m ^ k1 ^ k2 ^ k3; +// } +// } + + /** + * Class representing the Elements of the finite field + * F2m 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 class F2mFieldElement + : ECFieldElement + { + /** + * Indicates gaussian normal basis representation (GNB). Number chosen + * according to X9.62. GNB is not implemented at present. + */ + public const int Gnb = 1; + + /** + * Indicates trinomial basis representation (Tpb). Number chosen + * according to X9.62. + */ + public const int Tpb = 2; + + /** + * Indicates pentanomial basis representation (Ppb). Number chosen + * according to X9.62. + */ + public const int Ppb = 3; + + /** + * Tpb or Ppb. + */ + private int representation; + + /** + * The exponent m of F2m. + */ + private int m; + + /** + * Tpb: The integer k where xm + + * xk + 1 represents the reduction polynomial + * f(z).
    + * Ppb: The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private int k1; + + /** + * Tpb: Always set to 0
    + * Ppb: The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private int k2; + + /** + * Tpb: Always set to 0
    + * Ppb: The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + private int k3; + + /** + * The IntArray holding the bits. + */ + private IntArray x; + + /** + * The number of ints required to hold m bits. + */ + private readonly int t; + + /** + * Constructor for Ppb. + * @param m The exponent m of + * F2m. + * @param k1 The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k2 The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param k3 The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z). + * @param x The BigInteger representing the value of the field element. + */ + public F2mFieldElement( + int m, + int k1, + int k2, + int k3, + BigInteger x) + { + // t = m / 32 rounded up to the next integer + this.t = (m + 31) >> 5; + this.x = new IntArray(x, t); + + if ((k2 == 0) && (k3 == 0)) + { + this.representation = Tpb; + } + else + { + if (k2 >= k3) + throw new ArgumentException("k2 must be smaller than k3"); + if (k2 <= 0) + throw new ArgumentException("k2 must be larger than 0"); + + this.representation = Ppb; + } + + if (x.SignValue < 0) + throw new ArgumentException("x value cannot be negative"); + + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + } + + /** + * Constructor for Tpb. + * @param m The exponent m of + * F2m. + * @param k The integer k where xm + + * xk + 1 represents the reduction + * polynomial f(z). + * @param x The BigInteger representing the value of the field element. + */ + public F2mFieldElement( + int m, + int k, + BigInteger x) + : this(m, k, 0, 0, x) + { + // Set k1 to k, and set k2 and k3 to 0 + } + + private F2mFieldElement(int m, int k1, int k2, int k3, IntArray x) + { + t = (m + 31) >> 5; + this.x = x; + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + + if ((k2 == 0) && (k3 == 0)) + { + this.representation = Tpb; + } + else + { + this.representation = Ppb; + } + } + + public override BigInteger ToBigInteger() + { + return x.ToBigInteger(); + } + + public override string FieldName + { + get { return "F2m"; } + } + + public override int FieldSize + { + get { return m; } + } + + /** + * Checks, if the ECFieldElements a and b + * are elements of the same field F2m + * (having the same representation). + * @param a field element. + * @param b field element to be compared. + * @throws ArgumentException if a and b + * are not elements of the same field + * F2m (having the same + * representation). + */ + public static void CheckFieldElements( + ECFieldElement a, + ECFieldElement b) + { + if (!(a is F2mFieldElement) || !(b is F2mFieldElement)) + { + throw new ArgumentException("Field elements are not " + + "both instances of F2mFieldElement"); + } + + F2mFieldElement aF2m = (F2mFieldElement)a; + F2mFieldElement bF2m = (F2mFieldElement)b; + + if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) + || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) + { + throw new ArgumentException("Field elements are not " + + "elements of the same field F2m"); + } + + if (aF2m.representation != bF2m.representation) + { + // Should never occur + throw new ArgumentException( + "One of the field " + + "elements are not elements has incorrect representation"); + } + } + + public override ECFieldElement Add( + ECFieldElement b) + { + // No check performed here for performance reasons. Instead the + // elements involved are checked in ECPoint.F2m + // checkFieldElements(this, b); + IntArray iarrClone = (IntArray) this.x.Copy(); + F2mFieldElement bF2m = (F2mFieldElement) b; + iarrClone.AddShifted(bF2m.x, 0); + return new F2mFieldElement(m, k1, k2, k3, iarrClone); + } + + public override ECFieldElement Subtract( + ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply( + ECFieldElement b) + { + // Right-to-left comb multiplication in the IntArray + // Input: Binary polynomials a(z) and b(z) of degree at most m-1 + // Output: c(z) = a(z) * b(z) mod f(z) + + // No check performed here for performance reasons. Instead the + // elements involved are checked in ECPoint.F2m + // checkFieldElements(this, b); + F2mFieldElement bF2m = (F2mFieldElement) b; + IntArray mult = x.Multiply(bF2m.x, m); + mult.Reduce(m, new int[]{k1, k2, k3}); + return new F2mFieldElement(m, k1, k2, k3, mult); + } + + public override ECFieldElement Divide( + ECFieldElement b) + { + // There may be more efficient implementations + ECFieldElement bInv = b.Invert(); + return Multiply(bInv); + } + + public override ECFieldElement Negate() + { + // -x == x holds for all x in F2m + return this; + } + + public override ECFieldElement Square() + { + IntArray squared = x.Square(m); + squared.Reduce(m, new int[]{k1, k2, k3}); + return new F2mFieldElement(m, k1, k2, k3, squared); + } + + public override ECFieldElement Invert() + { + // Inversion in F2m using the extended Euclidean algorithm + // Input: A nonzero polynomial a(z) of degree at most m-1 + // Output: a(z)^(-1) mod f(z) + + // u(z) := a(z) + IntArray uz = (IntArray)this.x.Copy(); + + // v(z) := f(z) + IntArray vz = new IntArray(t); + vz.SetBit(m); + vz.SetBit(0); + vz.SetBit(this.k1); + if (this.representation == Ppb) + { + vz.SetBit(this.k2); + vz.SetBit(this.k3); + } + + // g1(z) := 1, g2(z) := 0 + IntArray g1z = new IntArray(t); + g1z.SetBit(0); + IntArray g2z = new IntArray(t); + + // while u != 0 + while (uz.GetUsedLength() > 0) +// while (uz.bitLength() > 1) + { + // j := deg(u(z)) - deg(v(z)) + int j = uz.BitLength - vz.BitLength; + + // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j + if (j < 0) + { + IntArray uzCopy = uz; + uz = vz; + vz = uzCopy; + + IntArray g1zCopy = g1z; + g1z = g2z; + g2z = g1zCopy; + + j = -j; + } + + // u(z) := u(z) + z^j * v(z) + // Note, that no reduction modulo f(z) is required, because + // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) + // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) + // = deg(u(z)) + // uz = uz.xor(vz.ShiftLeft(j)); + // jInt = n / 32 + int jInt = j >> 5; + // jInt = n % 32 + int jBit = j & 0x1F; + IntArray vzShift = vz.ShiftLeft(jBit); + uz.AddShifted(vzShift, jInt); + + // g1(z) := g1(z) + z^j * g2(z) +// g1z = g1z.xor(g2z.ShiftLeft(j)); + IntArray g2zShift = g2z.ShiftLeft(jBit); + g1z.AddShifted(g2zShift, jInt); + } + return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, g2z); + } + + public override ECFieldElement Sqrt() + { + throw new ArithmeticException("Not implemented"); + } + + /** + * @return the representation of the field + * F2m, either of + * {@link F2mFieldElement.Tpb} (trinomial + * basis representation) or + * {@link F2mFieldElement.Ppb} (pentanomial + * basis representation). + */ + public int Representation + { + get { return this.representation; } + } + + /** + * @return the degree m of the reduction polynomial + * f(z). + */ + public int M + { + get { return this.m; } + } + + /** + * @return Tpb: The integer k where xm + + * xk + 1 represents the reduction polynomial + * f(z).
    + * Ppb: The integer k1 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + public int K1 + { + get { return this.k1; } + } + + /** + * @return Tpb: Always returns 0
    + * Ppb: The integer k2 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + public int K2 + { + get { return this.k2; } + } + + /** + * @return Tpb: Always set to 0
    + * Ppb: The integer k3 where xm + + * xk3 + xk2 + xk1 + 1 + * represents the reduction polynomial f(z).
    + */ + public int K3 + { + get { return this.k3; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + F2mFieldElement other = obj as F2mFieldElement; + + if (other == null) + return false; + + return Equals(other); + } + + protected bool Equals( + F2mFieldElement other) + { + return m == other.m + && k1 == other.k1 + && k2 == other.k2 + && k3 == other.k3 + && representation == other.representation + && base.Equals(other); + } + + public override int GetHashCode() + { + return m.GetHashCode() + ^ k1.GetHashCode() + ^ k2.GetHashCode() + ^ k3.GetHashCode() + ^ representation.GetHashCode() + ^ base.GetHashCode(); + } + } +} diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs new file mode 100644 index 000000000..6a06be4d1 --- /dev/null +++ b/crypto/src/math/ec/ECPoint.cs @@ -0,0 +1,572 @@ +using System; +using System.Collections; +using System.Diagnostics; + +using Org.BouncyCastle.Asn1.X9; + +using Org.BouncyCastle.Math.EC.Multiplier; + +namespace Org.BouncyCastle.Math.EC +{ + /** + * base class for points on elliptic curves. + */ + public abstract class ECPoint + { + internal readonly ECCurve curve; + internal readonly ECFieldElement x, y; + internal readonly bool withCompression; + internal ECMultiplier multiplier = null; + internal PreCompInfo preCompInfo = null; + + protected internal ECPoint( + ECCurve curve, + ECFieldElement x, + ECFieldElement y, + bool withCompression) + { + if (curve == null) + throw new ArgumentNullException("curve"); + + this.curve = curve; + this.x = x; + this.y = y; + this.withCompression = withCompression; + } + + public ECCurve Curve + { + get { return curve; } + } + + public ECFieldElement X + { + get { return x; } + } + + public ECFieldElement Y + { + get { return y; } + } + + public bool IsInfinity + { + get { return x == null && y == null; } + } + + public bool IsCompressed + { + get { return withCompression; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + ECPoint o = obj as ECPoint; + + if (o == null) + return false; + + if (this.IsInfinity) + return o.IsInfinity; + + return x.Equals(o.x) && y.Equals(o.y); + } + + public override int GetHashCode() + { + if (this.IsInfinity) + return 0; + + return x.GetHashCode() ^ y.GetHashCode(); + } + +// /** +// * Mainly for testing. Explicitly set the ECMultiplier. +// * @param multiplier The ECMultiplier to be used to multiply +// * this ECPoint. +// */ +// internal void SetECMultiplier( +// ECMultiplier multiplier) +// { +// this.multiplier = multiplier; +// } + + /** + * Sets the PreCompInfo. Used by ECMultipliers + * to save the precomputation for this ECPoint to store the + * precomputation result for use by subsequent multiplication. + * @param preCompInfo The values precomputed by the + * ECMultiplier. + */ + internal void SetPreCompInfo( + PreCompInfo preCompInfo) + { + this.preCompInfo = preCompInfo; + } + + public virtual byte[] GetEncoded() + { + return GetEncoded(withCompression); + } + + public abstract byte[] GetEncoded(bool compressed); + + public abstract ECPoint Add(ECPoint b); + public abstract ECPoint Subtract(ECPoint b); + public abstract ECPoint Negate(); + public abstract ECPoint Twice(); + public abstract ECPoint Multiply(BigInteger b); + + /** + * Sets the appropriate ECMultiplier, unless already set. + */ + internal virtual void AssertECMultiplier() + { + if (this.multiplier == null) + { + lock (this) + { + if (this.multiplier == null) + { + this.multiplier = new FpNafMultiplier(); + } + } + } + } + } + + public abstract class ECPointBase + : ECPoint + { + protected internal ECPointBase( + ECCurve curve, + ECFieldElement x, + ECFieldElement y, + bool withCompression) + : base(curve, x, y, withCompression) + { + } + + protected internal abstract bool YTilde { get; } + + /** + * return the field element encoded with point compression. (S 4.3.6) + */ + public override byte[] GetEncoded(bool compressed) + { + if (this.IsInfinity) + return new byte[1]; + + // Note: some of the tests rely on calculating byte length from the field element + // (since the test cases use mismatching fields for curve/elements) + int byteLength = X9IntegerConverter.GetByteLength(x); + byte[] X = X9IntegerConverter.IntegerToBytes(this.X.ToBigInteger(), byteLength); + byte[] PO; + + if (compressed) + { + PO = new byte[1 + X.Length]; + + PO[0] = (byte)(YTilde ? 0x03 : 0x02); + } + else + { + byte[] Y = X9IntegerConverter.IntegerToBytes(this.Y.ToBigInteger(), byteLength); + PO = new byte[1 + X.Length + Y.Length]; + + PO[0] = 0x04; + + Y.CopyTo(PO, 1 + X.Length); + } + + X.CopyTo(PO, 1); + + return PO; + } + + /** + * Multiplies this ECPoint by the given number. + * @param k The multiplicator. + * @return k * this. + */ + public override ECPoint Multiply( + BigInteger k) + { + if (k.SignValue < 0) + throw new ArgumentException("The multiplicator cannot be negative", "k"); + + if (this.IsInfinity) + return this; + + if (k.SignValue == 0) + return this.curve.Infinity; + + AssertECMultiplier(); + return this.multiplier.Multiply(this, k, preCompInfo); + } + } + + /** + * Elliptic curve points over Fp + */ + public class FpPoint + : ECPointBase + { + /** + * Create a point which encodes with point compression. + * + * @param curve the curve to use + * @param x affine x co-ordinate + * @param y affine y co-ordinate + */ + public FpPoint( + ECCurve curve, + ECFieldElement x, + ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve the curve to use + * @param x affine x co-ordinate + * @param y affine y co-ordinate + * @param withCompression if true encode with point compression + */ + public FpPoint( + ECCurve curve, + ECFieldElement x, + ECFieldElement y, + bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + protected internal override bool YTilde + { + get + { + return this.Y.ToBigInteger().TestBit(0); + } + } + + // B.3 pg 62 + public override ECPoint Add( + ECPoint b) + { + if (this.IsInfinity) + return b; + + if (b.IsInfinity) + return this; + + // Check if b = this or b = -this + if (this.x.Equals(b.x)) + { + if (this.y.Equals(b.y)) + { + // this = b, i.e. this must be doubled + return this.Twice(); + } + + Debug.Assert(this.y.Equals(b.y.Negate())); + + // this = -b, i.e. the result is the point at infinity + return this.curve.Infinity; + } + + ECFieldElement gamma = b.y.Subtract(this.y).Divide(b.x.Subtract(this.x)); + + ECFieldElement x3 = gamma.Square().Subtract(this.x).Subtract(b.x); + ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y); + + return new FpPoint(curve, x3, y3, withCompression); + } + + // B.3 pg 62 + public override ECPoint Twice() + { + // Twice identity element (point at infinity) is identity + if (this.IsInfinity) + return this; + + // if y1 == 0, then (x1, y1) == (x1, -y1) + // and hence this = -this and thus 2(x1, y1) == infinity + if (this.y.ToBigInteger().SignValue == 0) + return this.curve.Infinity; + + ECFieldElement TWO = this.curve.FromBigInteger(BigInteger.Two); + ECFieldElement THREE = this.curve.FromBigInteger(BigInteger.Three); + ECFieldElement gamma = this.x.Square().Multiply(THREE).Add(curve.a).Divide(y.Multiply(TWO)); + + ECFieldElement x3 = gamma.Square().Subtract(this.x.Multiply(TWO)); + ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y); + + return new FpPoint(curve, x3, y3, this.withCompression); + } + + // D.3.2 pg 102 (see Note:) + public override ECPoint Subtract( + ECPoint b) + { + if (b.IsInfinity) + return this; + + // Add -b + return Add(b.Negate()); + } + + public override ECPoint Negate() + { + return new FpPoint(this.curve, this.x, this.y.Negate(), this.withCompression); + } + + /** + * Sets the default ECMultiplier, unless already set. + */ + internal override void AssertECMultiplier() + { + if (this.multiplier == null) + { + lock (this) + { + if (this.multiplier == null) + { + this.multiplier = new WNafMultiplier(); + } + } + } + } + } + + /** + * Elliptic curve points over F2m + */ + public class F2mPoint + : ECPointBase + { + /** + * @param curve base curve + * @param x x point + * @param y y point + */ + public F2mPoint( + ECCurve curve, + ECFieldElement x, + ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @param curve base curve + * @param x x point + * @param y y point + * @param withCompression true if encode with point compression. + */ + public F2mPoint( + ECCurve curve, + ECFieldElement x, + ECFieldElement y, + bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x != null && y == null) || (x == null && y != null)) + { + throw new ArgumentException("Exactly one of the field elements is null"); + } + + if (x != null) + { + // Check if x and y are elements of the same field + F2mFieldElement.CheckFieldElements(this.x, this.y); + + // Check if x and a are elements of the same field + F2mFieldElement.CheckFieldElements(this.x, this.curve.A); + } + } + + /** + * Constructor for point at infinity + */ + [Obsolete("Use ECCurve.Infinity property")] + public F2mPoint( + ECCurve curve) + : this(curve, null, null) + { + } + + protected internal override bool YTilde + { + get + { + // X9.62 4.2.2 and 4.3.6: + // if x = 0 then ypTilde := 0, else ypTilde is the rightmost + // bit of y * x^(-1) + return this.X.ToBigInteger().SignValue != 0 + && this.Y.Multiply(this.X.Invert()).ToBigInteger().TestBit(0); + } + } + + /** + * Check, if two ECPoints can be added or subtracted. + * @param a The first ECPoint to check. + * @param b The second ECPoint to check. + * @throws IllegalArgumentException if a and b + * cannot be added. + */ + private static void CheckPoints( + ECPoint a, + ECPoint b) + { + // Check, if points are on the same curve + if (!a.curve.Equals(b.curve)) + throw new ArgumentException("Only points on the same curve can be added or subtracted"); + +// F2mFieldElement.CheckFieldElements(a.x, b.x); + } + + /* (non-Javadoc) + * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) + */ + public override ECPoint Add(ECPoint b) + { + CheckPoints(this, b); + return AddSimple((F2mPoint) b); + } + + /** + * Adds another ECPoints.F2m to this 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 ECPoints.F2m to add to + * this. + * @return this + b + */ + internal F2mPoint AddSimple(F2mPoint b) + { + if (this.IsInfinity) + return b; + + if (b.IsInfinity) + return this; + + F2mFieldElement x2 = (F2mFieldElement) b.X; + F2mFieldElement y2 = (F2mFieldElement) b.Y; + + // Check if b == this or b == -this + if (this.x.Equals(x2)) + { + // this == b, i.e. this must be doubled + if (this.y.Equals(y2)) + return (F2mPoint) this.Twice(); + + // this = -other, i.e. the result is the point at infinity + return (F2mPoint) this.curve.Infinity; + } + + ECFieldElement xSum = this.x.Add(x2); + + F2mFieldElement lambda + = (F2mFieldElement)(this.y.Add(y2)).Divide(xSum); + + F2mFieldElement x3 + = (F2mFieldElement)lambda.Square().Add(lambda).Add(xSum).Add(this.curve.A); + + F2mFieldElement y3 + = (F2mFieldElement)lambda.Multiply(this.x.Add(x3)).Add(x3).Add(this.y); + + return new F2mPoint(curve, x3, y3, withCompression); + } + + /* (non-Javadoc) + * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) + */ + public override ECPoint Subtract( + ECPoint b) + { + CheckPoints(this, b); + return SubtractSimple((F2mPoint) b); + } + + /** + * Subtracts another ECPoints.F2m from this + * 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 ECPoints.F2m to subtract from + * this. + * @return this - b + */ + internal F2mPoint SubtractSimple( + F2mPoint b) + { + if (b.IsInfinity) + return this; + + // Add -b + return AddSimple((F2mPoint) b.Negate()); + } + + /* (non-Javadoc) + * @see Org.BouncyCastle.Math.EC.ECPoint#twice() + */ + public override ECPoint Twice() + { + // Twice identity element (point at infinity) is identity + if (this.IsInfinity) + return this; + + // if x1 == 0, then (x1, y1) == (x1, x1 + y1) + // and hence this = -this and thus 2(x1, y1) == infinity + if (this.x.ToBigInteger().SignValue == 0) + return this.curve.Infinity; + + F2mFieldElement lambda = (F2mFieldElement) this.x.Add(this.y.Divide(this.x)); + F2mFieldElement x2 = (F2mFieldElement)lambda.Square().Add(lambda).Add(this.curve.A); + ECFieldElement ONE = this.curve.FromBigInteger(BigInteger.One); + F2mFieldElement y2 = (F2mFieldElement)this.x.Square().Add( + x2.Multiply(lambda.Add(ONE))); + + return new F2mPoint(this.curve, x2, y2, withCompression); + } + + public override ECPoint Negate() + { + return new F2mPoint(curve, this.x, this.x.Add(this.y), withCompression); + } + + /** + * Sets the appropriate ECMultiplier, unless already set. + */ + internal override void AssertECMultiplier() + { + if (this.multiplier == null) + { + lock (this) + { + if (this.multiplier == null) + { + if (((F2mCurve) this.curve).IsKoblitz) + { + this.multiplier = new WTauNafMultiplier(); + } + else + { + this.multiplier = new WNafMultiplier(); + } + } + } + } + } + } +} diff --git a/crypto/src/math/ec/IntArray.cs b/crypto/src/math/ec/IntArray.cs new file mode 100644 index 000000000..1089966a8 --- /dev/null +++ b/crypto/src/math/ec/IntArray.cs @@ -0,0 +1,485 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Math.EC +{ + internal class IntArray + { + // TODO make m fixed for the IntArray, and hence compute T once and for all + + // TODO Use uint's internally? + private int[] m_ints; + + public IntArray(int intLen) + { + m_ints = new int[intLen]; + } + + private IntArray(int[] ints) + { + m_ints = ints; + } + + public IntArray(BigInteger bigInt) + : this(bigInt, 0) + { + } + + public IntArray(BigInteger bigInt, int minIntLen) + { + if (bigInt.SignValue == -1) + throw new ArgumentException("Only positive Integers allowed", "bigint"); + + if (bigInt.SignValue == 0) + { + m_ints = new int[] { 0 }; + return; + } + + byte[] barr = bigInt.ToByteArrayUnsigned(); + int barrLen = barr.Length; + + int intLen = (barrLen + 3) / 4; + m_ints = new int[System.Math.Max(intLen, minIntLen)]; + + int rem = barrLen % 4; + int barrI = 0; + + if (0 < rem) + { + int temp = (int) barr[barrI++]; + while (barrI < rem) + { + temp = temp << 8 | (int) barr[barrI++]; + } + m_ints[--intLen] = temp; + } + + while (intLen > 0) + { + int temp = (int) barr[barrI++]; + for (int i = 1; i < 4; i++) + { + temp = temp << 8 | (int) barr[barrI++]; + } + m_ints[--intLen] = temp; + } + } + + public int GetUsedLength() + { + int highestIntPos = m_ints.Length; + + if (highestIntPos < 1) + return 0; + + // Check if first element will act as sentinel + if (m_ints[0] != 0) + { + while (m_ints[--highestIntPos] == 0) + { + } + return highestIntPos + 1; + } + + do + { + if (m_ints[--highestIntPos] != 0) + { + return highestIntPos + 1; + } + } + while (highestIntPos > 0); + + return 0; + } + + public int BitLength + { + get + { + // JDK 1.5: see Integer.numberOfLeadingZeros() + int intLen = GetUsedLength(); + if (intLen == 0) + return 0; + + int last = intLen - 1; + uint highest = (uint) m_ints[last]; + int bits = (last << 5) + 1; + + // A couple of binary search steps + if (highest > 0x0000ffff) + { + if (highest > 0x00ffffff) + { + bits += 24; + highest >>= 24; + } + else + { + bits += 16; + highest >>= 16; + } + } + else if (highest > 0x000000ff) + { + bits += 8; + highest >>= 8; + } + + while (highest > 1) + { + ++bits; + highest >>= 1; + } + + return bits; + } + } + + private int[] resizedInts(int newLen) + { + int[] newInts = new int[newLen]; + int oldLen = m_ints.Length; + int copyLen = oldLen < newLen ? oldLen : newLen; + Array.Copy(m_ints, 0, newInts, 0, copyLen); + return newInts; + } + + public BigInteger ToBigInteger() + { + int usedLen = GetUsedLength(); + if (usedLen == 0) + { + return BigInteger.Zero; + } + + int highestInt = m_ints[usedLen - 1]; + byte[] temp = new byte[4]; + int barrI = 0; + bool trailingZeroBytesDone = false; + for (int j = 3; j >= 0; j--) + { + byte thisByte = (byte)((int)((uint) highestInt >> (8 * j))); + if (trailingZeroBytesDone || (thisByte != 0)) + { + trailingZeroBytesDone = true; + temp[barrI++] = thisByte; + } + } + + int barrLen = 4 * (usedLen - 1) + barrI; + byte[] barr = new byte[barrLen]; + for (int j = 0; j < barrI; j++) + { + barr[j] = temp[j]; + } + // Highest value int is done now + + for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) + { + for (int j = 3; j >= 0; j--) + { + barr[barrI++] = (byte)((int)((uint)m_ints[iarrJ] >> (8 * j))); + } + } + return new BigInteger(1, barr); + } + + public void ShiftLeft() + { + int usedLen = GetUsedLength(); + if (usedLen == 0) + { + return; + } + if (m_ints[usedLen - 1] < 0) + { + // highest bit of highest used byte is set, so shifting left will + // make the IntArray one byte longer + usedLen++; + if (usedLen > m_ints.Length) + { + // make the m_ints one byte longer, because we need one more + // byte which is not available in m_ints + m_ints = resizedInts(m_ints.Length + 1); + } + } + + bool carry = false; + for (int i = 0; i < usedLen; i++) + { + // nextCarry is true if highest bit is set + bool nextCarry = m_ints[i] < 0; + m_ints[i] <<= 1; + if (carry) + { + // set lowest bit + m_ints[i] |= 1; + } + carry = nextCarry; + } + } + + public IntArray ShiftLeft(int n) + { + int usedLen = GetUsedLength(); + if (usedLen == 0) + { + return this; + } + + if (n == 0) + { + return this; + } + + if (n > 31) + { + throw new ArgumentException("shiftLeft() for max 31 bits " + + ", " + n + "bit shift is not possible", "n"); + } + + int[] newInts = new int[usedLen + 1]; + + int nm32 = 32 - n; + newInts[0] = m_ints[0] << n; + for (int i = 1; i < usedLen; i++) + { + newInts[i] = (m_ints[i] << n) | (int)((uint)m_ints[i - 1] >> nm32); + } + newInts[usedLen] = (int)((uint)m_ints[usedLen - 1] >> nm32); + + return new IntArray(newInts); + } + + public void AddShifted(IntArray other, int shift) + { + int usedLenOther = other.GetUsedLength(); + int newMinUsedLen = usedLenOther + shift; + if (newMinUsedLen > m_ints.Length) + { + m_ints = resizedInts(newMinUsedLen); + //Console.WriteLine("Resize required"); + } + + for (int i = 0; i < usedLenOther; i++) + { + m_ints[i + shift] ^= other.m_ints[i]; + } + } + + public int Length + { + get { return m_ints.Length; } + } + + public bool TestBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int tester = 1 << theBit; + return ((m_ints[theInt] & tester) != 0); + } + + public void FlipBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int flipper = 1 << theBit; + m_ints[theInt] ^= flipper; + } + + public void SetBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int setter = 1 << theBit; + m_ints[theInt] |= setter; + } + + public IntArray Multiply(IntArray other, int m) + { + // Lenght of c is 2m bits rounded up to the next int (32 bit) + int t = (m + 31) >> 5; + if (m_ints.Length < t) + { + m_ints = resizedInts(t); + } + + IntArray b = new IntArray(other.resizedInts(other.Length + 1)); + IntArray c = new IntArray((m + m + 31) >> 5); + // IntArray c = new IntArray(t + t); + int testBit = 1; + for (int k = 0; k < 32; k++) + { + for (int j = 0; j < t; j++) + { + if ((m_ints[j] & testBit) != 0) + { + // The kth bit of m_ints[j] is set + c.AddShifted(b, j); + } + } + testBit <<= 1; + b.ShiftLeft(); + } + return c; + } + + // public IntArray multiplyLeftToRight(IntArray other, int m) { + // // Lenght of c is 2m bits rounded up to the next int (32 bit) + // int t = (m + 31) / 32; + // if (m_ints.Length < t) { + // m_ints = resizedInts(t); + // } + // + // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); + // IntArray c = new IntArray((m + m + 31) / 32); + // // IntArray c = new IntArray(t + t); + // int testBit = 1 << 31; + // for (int k = 31; k >= 0; k--) { + // for (int j = 0; j < t; j++) { + // if ((m_ints[j] & testBit) != 0) { + // // The kth bit of m_ints[j] is set + // c.addShifted(b, j); + // } + // } + // testBit >>>= 1; + // if (k > 0) { + // c.shiftLeft(); + // } + // } + // return c; + // } + + // TODO note, redPol.Length must be 3 for TPB and 5 for PPB + public void Reduce(int m, int[] redPol) + { + for (int i = m + m - 2; i >= m; i--) + { + if (TestBit(i)) + { + int bit = i - m; + FlipBit(bit); + FlipBit(i); + int l = redPol.Length; + while (--l >= 0) + { + FlipBit(redPol[l] + bit); + } + } + } + m_ints = resizedInts((m + 31) >> 5); + } + + public IntArray Square(int m) + { + // TODO make the table static readonly + int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40, + 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; + + int t = (m + 31) >> 5; + if (m_ints.Length < t) + { + m_ints = resizedInts(t); + } + + IntArray c = new IntArray(t + t); + + // TODO twice the same code, put in separate private method + for (int i = 0; i < t; i++) + { + int v0 = 0; + for (int j = 0; j < 4; j++) + { + v0 = (int)((uint) v0 >> 8); + int u = (int)((uint)m_ints[i] >> (j * 4)) & 0xF; + int w = table[u] << 24; + v0 |= w; + } + c.m_ints[i + i] = v0; + + v0 = 0; + int upper = (int)((uint) m_ints[i] >> 16); + for (int j = 0; j < 4; j++) + { + v0 = (int)((uint) v0 >> 8); + int u = (int)((uint)upper >> (j * 4)) & 0xF; + int w = table[u] << 24; + v0 |= w; + } + c.m_ints[i + i + 1] = v0; + } + return c; + } + + public override bool Equals(object o) + { + if (!(o is IntArray)) + { + return false; + } + IntArray other = (IntArray) o; + int usedLen = GetUsedLength(); + if (other.GetUsedLength() != usedLen) + { + return false; + } + for (int i = 0; i < usedLen; i++) + { + if (m_ints[i] != other.m_ints[i]) + { + return false; + } + } + return true; + } + + public override int GetHashCode() + { + int i = GetUsedLength(); + int hc = i; + while (--i >= 0) + { + hc *= 17; + hc ^= m_ints[i]; + } + return hc; + } + + internal IntArray Copy() + { + return new IntArray((int[]) m_ints.Clone()); + } + + public override string ToString() + { + int usedLen = GetUsedLength(); + if (usedLen == 0) + { + return "0"; + } + + StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[usedLen - 1], 2)); + for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) + { + string hexString = Convert.ToString(m_ints[iarrJ], 2); + + // Add leading zeroes, except for highest significant int + for (int i = hexString.Length; i < 8; i++) + { + hexString = "0" + hexString; + } + sb.Append(hexString); + } + return sb.ToString(); + } + } +} diff --git a/crypto/src/math/ec/abc/SimpleBigDecimal.cs b/crypto/src/math/ec/abc/SimpleBigDecimal.cs new file mode 100644 index 000000000..d5664dbfd --- /dev/null +++ b/crypto/src/math/ec/abc/SimpleBigDecimal.cs @@ -0,0 +1,241 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Math.EC.Abc +{ + /** + * Class representing a simple version of a big decimal. A + * SimpleBigDecimal 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 scale of the SimpleBigDecimal. + * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted + * automatically, but must be set manually. All SimpleBigDecimals + * taking part in the same arithmetic operation must have equal scale. The + * result of a multiplication of two SimpleBigDecimals returns a + * SimpleBigDecimal with double scale. + */ + internal class SimpleBigDecimal + // : Number + { + // private static final long serialVersionUID = 1L; + + private readonly BigInteger bigInt; + private readonly int scale; + + /** + * Returns a SimpleBigDecimal representing the same numerical + * value as value. + * @param value The value of the SimpleBigDecimal to be + * created. + * @param scale The scale of the SimpleBigDecimal to be + * created. + * @return The such created SimpleBigDecimal. + */ + public static SimpleBigDecimal GetInstance(BigInteger val, int scale) + { + return new SimpleBigDecimal(val.ShiftLeft(scale), scale); + } + + /** + * Constructor for SimpleBigDecimal. The value of the + * constructed SimpleBigDecimal Equals bigInt / + * 2scale. + * @param bigInt The bigInt value parameter. + * @param scale The scale of the constructed SimpleBigDecimal. + */ + public SimpleBigDecimal(BigInteger bigInt, int scale) + { + if (scale < 0) + throw new ArgumentException("scale may not be negative"); + + this.bigInt = bigInt; + this.scale = scale; + } + + private SimpleBigDecimal(SimpleBigDecimal limBigDec) + { + bigInt = limBigDec.bigInt; + scale = limBigDec.scale; + } + + private void CheckScale(SimpleBigDecimal b) + { + if (scale != b.scale) + throw new ArgumentException("Only SimpleBigDecimal of same scale allowed in arithmetic operations"); + } + + public SimpleBigDecimal AdjustScale(int newScale) + { + if (newScale < 0) + throw new ArgumentException("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(BigInteger.One, 1); + return Add(oneHalf.AdjustScale(scale)).Floor(); + } + + public int IntValue + { + get { return Floor().IntValue; } + } + + public long LongValue + { + get { return Floor().LongValue; } + } + +// public double doubleValue() +// { +// return new Double(ToString()).doubleValue(); +// } +// +// public float floatValue() +// { +// return new Float(ToString()).floatValue(); +// } + + public int Scale + { + get { return scale; } + } + + public override string ToString() + { + if (scale == 0) + return bigInt.ToString(); + + BigInteger floorBigInt = Floor(); + + BigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale)); + if (bigInt.SignValue < 0) + { + fract = BigInteger.One.ShiftLeft(scale).Subtract(fract); + } + + if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero)))) + { + floorBigInt = floorBigInt.Add(BigInteger.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[j]; + } + string rightOfPoint = new string(fractCharArr); + + StringBuilder sb = new StringBuilder(leftOfPoint); + sb.Append("."); + sb.Append(rightOfPoint); + + return sb.ToString(); + } + + public override bool Equals( + object obj) + { + if (this == obj) + return true; + + SimpleBigDecimal other = obj as SimpleBigDecimal; + + if (other == null) + return false; + + return bigInt.Equals(other.bigInt) + && scale == other.scale; + } + + public override int GetHashCode() + { + return bigInt.GetHashCode() ^ scale; + } + + } +} diff --git a/crypto/src/math/ec/abc/Tnaf.cs b/crypto/src/math/ec/abc/Tnaf.cs new file mode 100644 index 000000000..225fc3075 --- /dev/null +++ b/crypto/src/math/ec/abc/Tnaf.cs @@ -0,0 +1,834 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Abc +{ + /** + * Class holding methods for point multiplication based on the window + * τ-adic nonadjacent form (WTNAF). The algorithms are based on the + * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves" + * by Jerome A. Solinas. The paper first appeared in the Proceedings of + * Crypto 1997. + */ + internal class Tnaf + { + private static readonly BigInteger MinusOne = BigInteger.One.Negate(); + private static readonly BigInteger MinusTwo = BigInteger.Two.Negate(); + private static readonly BigInteger MinusThree = BigInteger.Three.Negate(); + private static readonly BigInteger Four = BigInteger.ValueOf(4); + + /** + * 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 + * αu'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 const sbyte Width = 4; + + /** + * 24 + */ + public const sbyte Pow2Width = 16; + + /** + * The αu's for a=0 as an array + * of ZTauElements. + */ + public static readonly ZTauElement[] Alpha0 = + { + null, + new ZTauElement(BigInteger.One, BigInteger.Zero), null, + new ZTauElement(MinusThree, MinusOne), null, + new ZTauElement(MinusOne, MinusOne), null, + new ZTauElement(BigInteger.One, MinusOne), null + }; + + /** + * The αu's for a=0 as an array + * of TNAFs. + */ + public static readonly sbyte[][] Alpha0Tnaf = + { + null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, 1} + }; + + /** + * The αu's for a=1 as an array + * of ZTauElements. + */ + public static readonly ZTauElement[] Alpha1 = + { + null, + new ZTauElement(BigInteger.One, BigInteger.Zero), null, + new ZTauElement(MinusThree, BigInteger.One), null, + new ZTauElement(MinusOne, BigInteger.One), null, + new ZTauElement(BigInteger.One, BigInteger.One), null + }; + + /** + * The αu's for a=1 as an array + * of TNAFs. + */ + public static readonly sbyte[][] Alpha1Tnaf = + { + null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, -1} + }; + + /** + * Computes the norm of an element λ of + * Z[τ]. + * @param mu The parameter μ of the elliptic curve. + * @param lambda The element λ of + * Z[τ]. + * @return The norm of λ. + */ + public static BigInteger Norm(sbyte 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 ArgumentException("mu must be 1 or -1"); + } + + return norm; + } + + /** + * Computes the norm of an element λ of + * R[τ], where λ = u + vτ + * and u and u are real numbers (elements of + * R). + * @param mu The parameter μ of the elliptic curve. + * @param u The real part of the element λ of + * R[τ]. + * @param v The τ-adic part of the element + * λ of R[τ]. + * @return The norm of λ. + */ + public static SimpleBigDecimal Norm(sbyte 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 ArgumentException("mu must be 1 or -1"); + } + + return norm; + } + + /** + * Rounds an element λ of R[τ] + * to an element of Z[τ], such that their difference + * has minimal norm. λ is given as + * λ = λ0 + λ1τ. + * @param lambda0 The component λ0. + * @param lambda1 The component λ1. + * @param mu The parameter μ of the elliptic curve. Must + * equal 1 or -1. + * @return The rounded element of Z[τ]. + * @throws ArgumentException if lambda0 and + * lambda1 do not have same scale. + */ + public static ZTauElement Round(SimpleBigDecimal lambda0, + SimpleBigDecimal lambda1, sbyte mu) + { + int scale = lambda0.Scale; + if (lambda1.Scale != scale) + throw new ArgumentException("lambda0 and lambda1 do not have same scale"); + + if (!((mu == 1) || (mu == -1))) + throw new ArgumentException("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); + } + + sbyte h0 = 0; + sbyte h1 = 0; + + // if eta >= 1 + if (eta.CompareTo(BigInteger.One) >= 0) + { + if (check1.CompareTo(MinusOne) < 0) + { + h1 = mu; + } + else + { + h0 = 1; + } + } + else + { + // eta < 1 + if (check2.CompareTo(BigInteger.Two) >= 0) + { + h1 = mu; + } + } + + // if eta < -1 + if (eta.CompareTo(MinusOne) < 0) + { + if (check1.CompareTo(BigInteger.One) >= 0) + { + h1 = (sbyte)-mu; + } + else + { + h0 = -1; + } + } + else + { + // eta >= -1 + if (check2.CompareTo(MinusTwo) < 0) + { + h1 = (sbyte)-mu; + } + } + + BigInteger q0 = f0.Add(BigInteger.ValueOf(h0)); + BigInteger q1 = f1.Add(BigInteger.ValueOf(h1)); + return new ZTauElement(q0, q1); + } + + /** + * Approximate division by n. For an integer + * k, the value λ = s k / n is + * computed to c bits of accuracy. + * @param k The parameter k. + * @param s The curve parameter s0 or + * s1. + * @param vm The Lucas Sequence element Vm. + * @param a The parameter a of the elliptic curve. + * @param m The bit length of the finite field + * Fm. + * @param c The number of bits of accuracy, i.e. the scale of the returned + * SimpleBigDecimal. + * @return The value λ = s k / n computed to + * c bits of accuracy. + */ + public static SimpleBigDecimal ApproximateDivisionByN(BigInteger k, + BigInteger s, BigInteger vm, sbyte 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(BigInteger.One); + } + + return new SimpleBigDecimal(ls, c); + } + + /** + * Computes the τ-adic NAF (non-adjacent form) of an + * element λ of Z[τ]. + * @param mu The parameter μ of the elliptic curve. + * @param lambda The element λ of + * Z[τ]. + * @return The τ-adic NAF of λ. + */ + public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda) + { + if (!((mu == 1) || (mu == -1))) + throw new ArgumentException("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 + sbyte[] u = new sbyte[maxLength]; + int i = 0; + + // The actual length of the TNAF + int length = 0; + + BigInteger r0 = lambda.u; + BigInteger r1 = lambda.v; + + while(!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero)))) + { + // If r0 is odd + if (r0.TestBit(0)) + { + u[i] = (sbyte) BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue; + + // r0 = r0 - u[i] + if (u[i] == 1) + { + r0 = r0.ClearBit(0); + } + else + { + // u[i] == -1 + r0 = r0.Add(BigInteger.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 + sbyte[] tnaf = new sbyte[length]; + Array.Copy(u, 0, tnaf, 0, length); + return tnaf; + } + + /** + * Applies the operation τ() to an + * F2mPoint. + * @param p The F2mPoint to which τ() is applied. + * @return τ(p) + */ + public static F2mPoint Tau(F2mPoint p) + { + if (p.IsInfinity) + return p; + + ECFieldElement x = p.X; + ECFieldElement y = p.Y; + + return new F2mPoint(p.Curve, x.Square(), y.Square(), p.IsCompressed); + } + + /** + * Returns the parameter μ of the elliptic curve. + * @param curve The elliptic curve from which to obtain μ. + * The curve must be a Koblitz curve, i.e. a Equals + * 0 or 1 and b Equals + * 1. + * @return μ of the elliptic curve. + * @throws ArgumentException if the given ECCurve is not a Koblitz + * curve. + */ + public static sbyte GetMu(F2mCurve curve) + { + BigInteger a = curve.A.ToBigInteger(); + + sbyte mu; + if (a.SignValue == 0) + { + mu = -1; + } + else if (a.Equals(BigInteger.One)) + { + mu = 1; + } + else + { + throw new ArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible"); + } + return mu; + } + + /** + * Calculates the Lucas Sequence elements Uk-1 and + * Uk or Vk-1 and + * Vk. + * @param mu The parameter μ 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 Vk-1 and + * Vk, otherwise Uk-1 and + * Uk. + * @return An array with 2 elements, containing Uk-1 + * and Uk or Vk-1 + * and Vk. + */ + public static BigInteger[] GetLucas(sbyte mu, int k, bool doV) + { + if (!(mu == 1 || mu == -1)) + throw new ArgumentException("mu must be 1 or -1"); + + BigInteger u0; + BigInteger u1; + BigInteger u2; + + if (doV) + { + u0 = BigInteger.Two; + u1 = BigInteger.ValueOf(mu); + } + else + { + u0 = BigInteger.Zero; + u1 = BigInteger.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 tw. If the width is + * 4, then for mu = 1, tw = 6 and for + * mu = -1, tw = 10 + * @param mu The parameter μ of the elliptic curve. + * @param w The window width of the WTNAF. + * @return the auxiliary value tw + */ + public static BigInteger GetTw(sbyte 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 = BigInteger.Zero.SetBit(w); + BigInteger u1invert = us[1].ModInverse(twoToW); + BigInteger tw; + tw = BigInteger.Two.Multiply(us[0]).Multiply(u1invert).Mod(twoToW); + //System.out.println("mu = " + mu); + //System.out.println("tw = " + tw); + return tw; + } + } + + /** + * Computes the auxiliary values s0 and + * s1 used for partial modular reduction. + * @param curve The elliptic curve for which to compute + * s0 and s1. + * @throws ArgumentException if curve is not a + * Koblitz curve (Anomalous Binary Curve, ABC). + */ + public static BigInteger[] GetSi(F2mCurve curve) + { + if (!curve.IsKoblitz) + throw new ArgumentException("si is defined for Koblitz curves only"); + + int m = curve.M; + int a = curve.A.ToBigInteger().IntValue; + sbyte mu = curve.GetMu(); + int h = curve.H.IntValue; + int index = m + 3 - a; + BigInteger[] ui = GetLucas(mu, index, false); + + BigInteger dividend0; + BigInteger dividend1; + if (mu == 1) + { + dividend0 = BigInteger.One.Subtract(ui[1]); + dividend1 = BigInteger.One.Subtract(ui[0]); + } + else if (mu == -1) + { + dividend0 = BigInteger.One.Add(ui[1]); + dividend1 = BigInteger.One.Add(ui[0]); + } + else + { + throw new ArgumentException("mu must be 1 or -1"); + } + + BigInteger[] si = new BigInteger[2]; + + if (h == 2) + { + si[0] = dividend0.ShiftRight(1); + si[1] = dividend1.ShiftRight(1).Negate(); + } + else if (h == 4) + { + si[0] = dividend0.ShiftRight(2); + si[1] = dividend1.ShiftRight(2).Negate(); + } + else + { + throw new ArgumentException("h (Cofactor) must be 2 or 4"); + } + + return si; + } + + /** + * Partial modular reduction modulo + * m - 1)/(τ - 1). + * @param k The integer to be reduced. + * @param m The bitlength of the underlying finite field. + * @param a The parameter a of the elliptic curve. + * @param s The auxiliary values s0 and + * s1. + * @param mu The parameter μ of the elliptic curve. + * @param c The precision (number of bits of accuracy) of the partial + * modular reduction. + * @return ρ := k partmod (τm - 1)/(τ - 1) + */ + public static ZTauElement PartModReduction(BigInteger k, int m, sbyte a, + BigInteger[] s, sbyte mu, sbyte 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.F2mPoint F2mPoint} + * by a BigInteger using the reduced τ-adic + * NAF (RTNAF) method. + * @param p The F2mPoint to Multiply. + * @param k The BigInteger by which to Multiply p. + * @return k * p + */ + public static F2mPoint MultiplyRTnaf(F2mPoint p, BigInteger k) + { + F2mCurve curve = (F2mCurve) p.Curve; + int m = curve.M; + sbyte a = (sbyte) curve.A.ToBigInteger().IntValue; + sbyte mu = curve.GetMu(); + BigInteger[] s = curve.GetSi(); + ZTauElement rho = PartModReduction(k, m, a, s, mu, (sbyte)10); + + return MultiplyTnaf(p, rho); + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * by an element λ of Z[τ] + * using the τ-adic NAF (TNAF) method. + * @param p The F2mPoint to Multiply. + * @param lambda The element λ of + * Z[τ]. + * @return λ * p + */ + public static F2mPoint MultiplyTnaf(F2mPoint p, ZTauElement lambda) + { + F2mCurve curve = (F2mCurve)p.Curve; + sbyte mu = curve.GetMu(); + sbyte[] u = TauAdicNaf(mu, lambda); + + F2mPoint q = MultiplyFromTnaf(p, u); + + return q; + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * by an element λ of Z[τ] + * using the τ-adic NAF (TNAF) method, given the TNAF + * of λ. + * @param p The F2mPoint to Multiply. + * @param u The the TNAF of λ.. + * @return λ * p + */ + public static F2mPoint MultiplyFromTnaf(F2mPoint p, sbyte[] u) + { + F2mCurve curve = (F2mCurve)p.Curve; + F2mPoint q = (F2mPoint) curve.Infinity; + for (int i = u.Length - 1; i >= 0; i--) + { + q = Tau(q); + if (u[i] == 1) + { + q = (F2mPoint)q.AddSimple(p); + } + else if (u[i] == -1) + { + q = (F2mPoint)q.SubtractSimple(p); + } + } + return q; + } + + /** + * Computes the [τ]-adic window NAF of an element + * λ of Z[τ]. + * @param mu The parameter μ of the elliptic curve. + * @param lambda The element λ of + * Z[τ] of which to compute the + * [τ]-adic NAF. + * @param width The window width of the resulting WNAF. + * @param pow2w 2width. + * @param tw The auxiliary value tw. + * @param alpha The αu's for the window width. + * @return The [τ]-adic window NAF of + * λ. + */ + public static sbyte[] TauAdicWNaf(sbyte mu, ZTauElement lambda, + sbyte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha) + { + if (!((mu == 1) || (mu == -1))) + throw new ArgumentException("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 + sbyte[] u = new sbyte[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(BigInteger.Zero))&&(r1.Equals(BigInteger.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); + + sbyte uLocal; + // if uUnMod >= 2^(width - 1) + if (uUnMod.CompareTo(pow2wMin1) >= 0) + { + uLocal = (sbyte) uUnMod.Subtract(pow2w).IntValue; + } + else + { + uLocal = (sbyte) uUnMod.IntValue; + } + // uLocal is now in [-2^(width-1), 2^(width-1)-1] + + u[i] = uLocal; + bool s = true; + if (uLocal < 0) + { + s = false; + uLocal = (sbyte)-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 ECPoint for which to do the precomputation. + * @param a The parameter a of the elliptic curve. + * @return The precomputation array for p. + */ + public static F2mPoint[] GetPreComp(F2mPoint p, sbyte a) + { + F2mPoint[] pu; + pu = new F2mPoint[16]; + pu[1] = p; + sbyte[][] alphaTnaf; + if (a == 0) + { + alphaTnaf = Tnaf.Alpha0Tnaf; + } + else + { + // a == 1 + alphaTnaf = Tnaf.Alpha1Tnaf; + } + + int precompLen = alphaTnaf.Length; + for (int i = 3; i < precompLen; i = i + 2) + { + pu[i] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]); + } + + return pu; + } + } +} diff --git a/crypto/src/math/ec/abc/ZTauElement.cs b/crypto/src/math/ec/abc/ZTauElement.cs new file mode 100644 index 000000000..4fcbf1bdf --- /dev/null +++ b/crypto/src/math/ec/abc/ZTauElement.cs @@ -0,0 +1,36 @@ +namespace Org.BouncyCastle.Math.EC.Abc +{ + /** + * Class representing an element of Z[τ]. Let + * λ be an element of Z[τ]. Then + * λ is given as λ = u + vτ. The + * components u and v may be used directly, there + * are no accessor methods. + * Immutable class. + */ + internal class ZTauElement + { + /** + * The "real" part of λ. + */ + public readonly BigInteger u; + + /** + * The "τ-adic" part of λ. + */ + public readonly BigInteger v; + + /** + * Constructor for an element λ of + * Z[τ]. + * @param u The "real" part of λ. + * @param v The "τ-adic" part of + * λ. + */ + public ZTauElement(BigInteger u, BigInteger v) + { + this.u = u; + this.v = v; + } + } +} diff --git a/crypto/src/math/ec/multiplier/ECMultiplier.cs b/crypto/src/math/ec/multiplier/ECMultiplier.cs new file mode 100644 index 000000000..c6d768ea8 --- /dev/null +++ b/crypto/src/math/ec/multiplier/ECMultiplier.cs @@ -0,0 +1,18 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Interface for classes encapsulating a point multiplication algorithm + * for ECPoints. + */ + internal interface ECMultiplier + { + /** + * Multiplies the ECPoint p by k, i.e. + * p is added k times to itself. + * @param p The ECPoint to be multiplied. + * @param k The factor by which p i multiplied. + * @return p multiplied by k. + */ + ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo); + } +} diff --git a/crypto/src/math/ec/multiplier/FpNafMultiplier.cs b/crypto/src/math/ec/multiplier/FpNafMultiplier.cs new file mode 100644 index 000000000..f5a98501a --- /dev/null +++ b/crypto/src/math/ec/multiplier/FpNafMultiplier.cs @@ -0,0 +1,39 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm. + */ + internal class FpNafMultiplier + : ECMultiplier + { + /** + * D.3.2 pg 101 + * @see org.bouncycastle.math.ec.multiplier.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) + */ + public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + { + // TODO Probably should try to add this + // BigInteger e = k.Mod(n); // n == order of p + BigInteger e = k; + BigInteger h = e.Multiply(BigInteger.Three); + + ECPoint neg = p.Negate(); + ECPoint R = p; + + for (int i = h.BitLength - 2; i > 0; --i) + { + R = R.Twice(); + + bool hBit = h.TestBit(i); + bool eBit = e.TestBit(i); + + if (hBit != eBit) + { + R = R.Add(hBit ? p : neg); + } + } + + return R; + } + } +} diff --git a/crypto/src/math/ec/multiplier/PreCompInfo.cs b/crypto/src/math/ec/multiplier/PreCompInfo.cs new file mode 100644 index 000000000..d379508c8 --- /dev/null +++ b/crypto/src/math/ec/multiplier/PreCompInfo.cs @@ -0,0 +1,11 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Interface for classes storing precomputation data for multiplication + * algorithms. Used as a Memento (see GOF patterns) for + * WNafMultiplier. + */ + internal interface PreCompInfo + { + } +} diff --git a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs new file mode 100644 index 000000000..cdccffc2d --- /dev/null +++ b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs @@ -0,0 +1,30 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + internal class ReferenceMultiplier + : ECMultiplier + { + /** + * Simple shift-and-add multiplication. Serves as reference implementation + * to verify (possibly faster) implementations in + * {@link org.bouncycastle.math.ec.ECPoint ECPoint}. + * + * @param p The point to multiply. + * @param k The factor by which to multiply. + * @return The result of the point multiplication k * p. + */ + public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + { + ECPoint q = p.Curve.Infinity; + int t = k.BitLength; + for (int i = 0; i < t; i++) + { + if (k.TestBit(i)) + { + q = q.Add(p); + } + p = p.Twice(); + } + return q; + } + } +} diff --git a/crypto/src/math/ec/multiplier/WNafMultiplier.cs b/crypto/src/math/ec/multiplier/WNafMultiplier.cs new file mode 100644 index 000000000..b5cf34ba8 --- /dev/null +++ b/crypto/src/math/ec/multiplier/WNafMultiplier.cs @@ -0,0 +1,241 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Class implementing the WNAF (Window Non-Adjacent Form) multiplication + * algorithm. + */ + internal class WNafMultiplier + : ECMultiplier + { + /** + * Computes the Window NAF (non-adjacent Form) of an integer. + * @param width The width w of the Window NAF. The width is + * defined as the minimal number w, such that for any + * w 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: + * k = −i=0l-1 ki2i + * , where the ki denote the elements of the + * returned sbyte[]. + */ + public sbyte[] WindowNaf(sbyte width, BigInteger k) + { + // The window NAF is at most 1 element longer than the binary + // representation of the integer k. sbyte can be used instead of short or + // int unless the window width is larger than 8. For larger width use + // short or int. However, a width of more than 8 is not efficient for + // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than + // 1000 Bits are currently not used in practice. + sbyte[] wnaf = new sbyte[k.BitLength + 1]; + + // 2^width as short and BigInteger + short pow2wB = (short)(1 << width); + BigInteger pow2wBI = BigInteger.ValueOf(pow2wB); + + int i = 0; + + // The actual length of the WNAF + int length = 0; + + // while k >= 1 + while (k.SignValue > 0) + { + // if k is odd + if (k.TestBit(0)) + { + // k Mod 2^width + BigInteger remainder = k.Mod(pow2wBI); + + // if remainder > 2^(width - 1) - 1 + if (remainder.TestBit(width - 1)) + { + wnaf[i] = (sbyte)(remainder.IntValue - pow2wB); + } + else + { + wnaf[i] = (sbyte)remainder.IntValue; + } + // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1] + + k = k.Subtract(BigInteger.ValueOf(wnaf[i])); + length = i; + } + else + { + wnaf[i] = 0; + } + + // k = k/2 + k = k.ShiftRight(1); + i++; + } + + length++; + + // Reduce the WNAF array to its actual length + sbyte[] wnafShort = new sbyte[length]; + Array.Copy(wnaf, 0, wnafShort, 0, length); + return wnafShort; + } + + /** + * Multiplies this by an integer k using the + * Window NAF method. + * @param k The integer by which this is multiplied. + * @return A new ECPoint which equals this + * multiplied by k. + */ + public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + { + WNafPreCompInfo wnafPreCompInfo; + + if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo)) + { + wnafPreCompInfo = (WNafPreCompInfo)preCompInfo; + } + else + { + // Ignore empty PreCompInfo or PreCompInfo of incorrect type + wnafPreCompInfo = new WNafPreCompInfo(); + } + + // floor(log2(k)) + int m = k.BitLength; + + // width of the Window NAF + sbyte width; + + // Required length of precomputation array + int reqPreCompLen; + + // Determine optimal width and corresponding length of precomputation + // array based on literature values + if (m < 13) + { + width = 2; + reqPreCompLen = 1; + } + else + { + if (m < 41) + { + width = 3; + reqPreCompLen = 2; + } + else + { + if (m < 121) + { + width = 4; + reqPreCompLen = 4; + } + else + { + if (m < 337) + { + width = 5; + reqPreCompLen = 8; + } + else + { + if (m < 897) + { + width = 6; + reqPreCompLen = 16; + } + else + { + if (m < 2305) + { + width = 7; + reqPreCompLen = 32; + } + else + { + width = 8; + reqPreCompLen = 127; + } + } + } + } + } + } + + // The length of the precomputation array + int preCompLen = 1; + + ECPoint[] preComp = wnafPreCompInfo.GetPreComp(); + ECPoint twiceP = wnafPreCompInfo.GetTwiceP(); + + // Check if the precomputed ECPoints already exist + if (preComp == null) + { + // Precomputation must be performed from scratch, create an empty + // precomputation array of desired length + preComp = new ECPoint[]{ p }; + } + else + { + // Take the already precomputed ECPoints to start with + preCompLen = preComp.Length; + } + + if (twiceP == null) + { + // Compute twice(p) + twiceP = p.Twice(); + } + + if (preCompLen < reqPreCompLen) + { + // Precomputation array must be made bigger, copy existing preComp + // array into the larger new preComp array + ECPoint[] oldPreComp = preComp; + preComp = new ECPoint[reqPreCompLen]; + Array.Copy(oldPreComp, 0, preComp, 0, preCompLen); + + for (int i = preCompLen; i < reqPreCompLen; i++) + { + // Compute the new ECPoints for the precomputation array. + // The values 1, 3, 5, ..., 2^(width-1)-1 times p are + // computed + preComp[i] = twiceP.Add(preComp[i - 1]); + } + } + + // Compute the Window NAF of the desired width + sbyte[] wnaf = WindowNaf(width, k); + int l = wnaf.Length; + + // Apply the Window NAF to p using the precomputed ECPoint values. + ECPoint q = p.Curve.Infinity; + for (int i = l - 1; i >= 0; i--) + { + q = q.Twice(); + + if (wnaf[i] != 0) + { + if (wnaf[i] > 0) + { + q = q.Add(preComp[(wnaf[i] - 1)/2]); + } + else + { + // wnaf[i] < 0 + q = q.Subtract(preComp[(-wnaf[i] - 1)/2]); + } + } + } + + // Set PreCompInfo in ECPoint, such that it is available for next + // multiplication. + wnafPreCompInfo.SetPreComp(preComp); + wnafPreCompInfo.SetTwiceP(twiceP); + p.SetPreCompInfo(wnafPreCompInfo); + return q; + } + } +} diff --git a/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs b/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs new file mode 100644 index 000000000..d9305dace --- /dev/null +++ b/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs @@ -0,0 +1,46 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Class holding precomputation data for the WNAF (Window Non-Adjacent Form) + * algorithm. + */ + internal class WNafPreCompInfo + : PreCompInfo + { + /** + * Array holding the precomputed ECPoints used for the Window + * NAF multiplication in + * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply() + * WNafMultiplier.multiply()}. + */ + private ECPoint[] preComp = null; + + /** + * Holds an ECPoint representing twice(this). Used for the + * Window NAF multiplication in + * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply() + * WNafMultiplier.multiply()}. + */ + private ECPoint twiceP = null; + + internal ECPoint[] GetPreComp() + { + return preComp; + } + + internal void SetPreComp(ECPoint[] preComp) + { + this.preComp = preComp; + } + + internal ECPoint GetTwiceP() + { + return twiceP; + } + + internal void SetTwiceP(ECPoint twiceThis) + { + this.twiceP = twiceThis; + } + } +} diff --git a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs new file mode 100644 index 000000000..f1a605770 --- /dev/null +++ b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs @@ -0,0 +1,120 @@ +using System; + +using Org.BouncyCastle.Math.EC.Abc; + +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Class implementing the WTNAF (Window + * τ-adic Non-Adjacent Form) algorithm. + */ + internal class WTauNafMultiplier + : ECMultiplier + { + /** + * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * by k using the reduced τ-adic NAF (RTNAF) + * method. + * @param p The F2mPoint to multiply. + * @param k The integer by which to multiply k. + * @return p multiplied by k. + */ + public ECPoint Multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo) + { + if (!(point is F2mPoint)) + throw new ArgumentException("Only F2mPoint can be used in WTauNafMultiplier"); + + F2mPoint p = (F2mPoint)point; + + F2mCurve curve = (F2mCurve) p.Curve; + int m = curve.M; + sbyte a = (sbyte) curve.A.ToBigInteger().IntValue; + sbyte mu = curve.GetMu(); + BigInteger[] s = curve.GetSi(); + + ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10); + + return MultiplyWTnaf(p, rho, preCompInfo, a, mu); + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * by an element λ of Z[τ] using + * the τ-adic NAF (TNAF) method. + * @param p The F2mPoint to multiply. + * @param lambda The element λ of + * Z[τ] of which to compute the + * [τ]-adic NAF. + * @return p multiplied by λ. + */ + private F2mPoint MultiplyWTnaf(F2mPoint p, ZTauElement lambda, + PreCompInfo preCompInfo, sbyte a, sbyte mu) + { + ZTauElement[] alpha; + if (a == 0) + { + alpha = Tnaf.Alpha0; + } + else + { + // a == 1 + alpha = Tnaf.Alpha1; + } + + BigInteger tw = Tnaf.GetTw(mu, Tnaf.Width); + + sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width, + BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha); + + return MultiplyFromWTnaf(p, u, preCompInfo); + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * by an element λ of Z[τ] + * using the window τ-adic NAF (TNAF) method, given the + * WTNAF of λ. + * @param p The F2mPoint to multiply. + * @param u The the WTNAF of λ.. + * @return λ * p + */ + private static F2mPoint MultiplyFromWTnaf(F2mPoint p, sbyte[] u, + PreCompInfo preCompInfo) + { + F2mCurve curve = (F2mCurve)p.Curve; + sbyte a = (sbyte) curve.A.ToBigInteger().IntValue; + + F2mPoint[] pu; + if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo)) + { + pu = Tnaf.GetPreComp(p, a); + p.SetPreCompInfo(new WTauNafPreCompInfo(pu)); + } + else + { + pu = ((WTauNafPreCompInfo)preCompInfo).GetPreComp(); + } + + // q = infinity + F2mPoint q = (F2mPoint) p.Curve.Infinity; + for (int i = u.Length - 1; i >= 0; i--) + { + q = Tnaf.Tau(q); + if (u[i] != 0) + { + if (u[i] > 0) + { + q = q.AddSimple(pu[u[i]]); + } + else + { + // u[i] < 0 + q = q.SubtractSimple(pu[-u[i]]); + } + } + } + + return q; + } + } +} diff --git a/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs new file mode 100644 index 000000000..cede4a05d --- /dev/null +++ b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs @@ -0,0 +1,41 @@ +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + /** + * Class holding precomputation data for the WTNAF (Window + * τ-adic Non-Adjacent Form) algorithm. + */ + internal class WTauNafPreCompInfo + : PreCompInfo + { + /** + * Array holding the precomputed F2mPoints used for the + * WTNAF multiplication in + * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() + * WTauNafMultiplier.multiply()}. + */ + private readonly F2mPoint[] preComp; + + /** + * Constructor for WTauNafPreCompInfo + * @param preComp Array holding the precomputed F2mPoints + * used for the WTNAF multiplication in + * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() + * WTauNafMultiplier.multiply()}. + */ + internal WTauNafPreCompInfo(F2mPoint[] preComp) + { + this.preComp = preComp; + } + + /** + * @return the array holding the precomputed F2mPoints + * used for the WTNAF multiplication in + * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() + * WTauNafMultiplier.multiply()}. + */ + internal F2mPoint[] GetPreComp() + { + return preComp; + } + } +} diff --git a/crypto/src/ocsp/BasicOCSPResp.cs b/crypto/src/ocsp/BasicOCSPResp.cs new file mode 100644 index 000000000..4253726bb --- /dev/null +++ b/crypto/src/ocsp/BasicOCSPResp.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Ocsp +{ + /// + /// + /// BasicOcspResponse ::= SEQUENCE { + /// tbsResponseData ResponseData, + /// signatureAlgorithm AlgorithmIdentifier, + /// signature BIT STRING, + /// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL + /// } + /// + /// + public class BasicOcspResp + : X509ExtensionBase + { + private readonly BasicOcspResponse resp; + private readonly ResponseData data; +// private readonly X509Certificate[] chain; + + public BasicOcspResp( + BasicOcspResponse resp) + { + this.resp = resp; + this.data = resp.TbsResponseData; + } + + /// The DER encoding of the tbsResponseData field. + /// In the event of an encoding error. + public byte[] GetTbsResponseData() + { + try + { + return data.GetDerEncoded(); + } + catch (IOException e) + { + throw new OcspException("problem encoding tbsResponseData", e); + } + } + + public int Version + { + get { return data.Version.Value.IntValue + 1; } + } + + public RespID ResponderId + { + get { return new RespID(data.ResponderID); } + } + + public DateTime ProducedAt + { + get { return data.ProducedAt.ToDateTime(); } + } + + public SingleResp[] Responses + { + get + { + Asn1Sequence s = data.Responses; + SingleResp[] rs = new SingleResp[s.Count]; + + for (int i = 0; i != rs.Length; i++) + { + rs[i] = new SingleResp(SingleResponse.GetInstance(s[i])); + } + + return rs; + } + } + + public X509Extensions ResponseExtensions + { + get { return data.ResponseExtensions; } + } + + protected override X509Extensions GetX509Extensions() + { + return ResponseExtensions; + } + + public string SignatureAlgName + { + get { return OcspUtilities.GetAlgorithmName(resp.SignatureAlgorithm.ObjectID); } + } + + public string SignatureAlgOid + { + get { return resp.SignatureAlgorithm.ObjectID.Id; } + } + + [Obsolete("RespData class is no longer required as all functionality is available on this class")] + public RespData GetResponseData() + { + return new RespData(data); + } + + public byte[] GetSignature() + { + return resp.Signature.GetBytes(); + } + + private IList GetCertList() + { + // load the certificates and revocation lists if we have any + + IList certs = Platform.CreateArrayList(); + Asn1Sequence s = resp.Certs; + + if (s != null) + { + foreach (Asn1Encodable ae in s) + { + try + { + certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded())); + } + catch (IOException ex) + { + throw new OcspException("can't re-encode certificate!", ex); + } + catch (CertificateException ex) + { + throw new OcspException("can't re-encode certificate!", ex); + } + } + } + + return certs; + } + + public X509Certificate[] GetCerts() + { + IList certs = GetCertList(); + X509Certificate[] result = new X509Certificate[certs.Count]; + for (int i = 0; i < certs.Count; ++i) + { + result[i] = (X509Certificate)certs[i]; + } + return result; + } + + /// The certificates, if any, associated with the response. + /// In the event of an encoding error. + public IX509Store GetCertificates( + string type) + { + try + { + return X509StoreFactory.Create( + "Certificate/" + type, + new X509CollectionStoreParameters(this.GetCertList())); + } + catch (Exception e) + { + throw new OcspException("can't setup the CertStore", e); + } + } + + /// + /// Verify the signature against the tbsResponseData object we contain. + /// + public bool Verify( + AsymmetricKeyParameter publicKey) + { + try + { + ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgName); + signature.Init(false, publicKey); + byte[] bs = data.GetDerEncoded(); + signature.BlockUpdate(bs, 0, bs.Length); + + return signature.VerifySignature(this.GetSignature()); + } + catch (Exception e) + { + throw new OcspException("exception processing sig: " + e, e); + } + } + + /// The ASN.1 encoded representation of this object. + public byte[] GetEncoded() + { + return resp.GetEncoded(); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + BasicOcspResp other = obj as BasicOcspResp; + + if (other == null) + return false; + + return resp.Equals(other.resp); + } + + public override int GetHashCode() + { + return resp.GetHashCode(); + } + } +} diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs new file mode 100644 index 000000000..5ff4bd9cc --- /dev/null +++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + /** + * Generator for basic OCSP response objects. + */ + public class BasicOcspRespGenerator + { + private readonly IList list = Platform.CreateArrayList(); + + private X509Extensions responseExtensions; + private RespID responderID; + + private class ResponseObject + { + internal CertificateID certId; + internal CertStatus certStatus; + internal DerGeneralizedTime thisUpdate; + internal DerGeneralizedTime nextUpdate; + internal X509Extensions extensions; + + public ResponseObject( + CertificateID certId, + CertificateStatus certStatus, + DateTime thisUpdate, + X509Extensions extensions) + : this(certId, certStatus, new DerGeneralizedTime(thisUpdate), null, extensions) + { + } + + public ResponseObject( + CertificateID certId, + CertificateStatus certStatus, + DateTime thisUpdate, + DateTime nextUpdate, + X509Extensions extensions) + : this(certId, certStatus, new DerGeneralizedTime(thisUpdate), new DerGeneralizedTime(nextUpdate), extensions) + { + } + + private ResponseObject( + CertificateID certId, + CertificateStatus certStatus, + DerGeneralizedTime thisUpdate, + DerGeneralizedTime nextUpdate, + X509Extensions extensions) + { + this.certId = certId; + + if (certStatus == null) + { + this.certStatus = new CertStatus(); + } + else if (certStatus is UnknownStatus) + { + this.certStatus = new CertStatus(2, DerNull.Instance); + } + else + { + RevokedStatus rs = (RevokedStatus) certStatus; + CrlReason revocationReason = rs.HasRevocationReason + ? new CrlReason(rs.RevocationReason) + : null; + + this.certStatus = new CertStatus( + new RevokedInfo(new DerGeneralizedTime(rs.RevocationTime), revocationReason)); + } + + this.thisUpdate = thisUpdate; + this.nextUpdate = nextUpdate; + + this.extensions = extensions; + } + + public SingleResponse ToResponse() + { + return new SingleResponse(certId.ToAsn1Object(), certStatus, thisUpdate, nextUpdate, extensions); + } + } + + /** + * basic constructor + */ + public BasicOcspRespGenerator( + RespID responderID) + { + this.responderID = responderID; + } + + /** + * construct with the responderID to be the SHA-1 keyHash of the passed in public key. + */ + public BasicOcspRespGenerator( + AsymmetricKeyParameter publicKey) + { + this.responderID = new RespID(publicKey); + } + + /** + * Add a response for a particular Certificate ID. + * + * @param certID certificate ID details + * @param certStatus status of the certificate - null if okay + */ + public void AddResponse( + CertificateID certID, + CertificateStatus certStatus) + { + list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null)); + } + + /** + * Add a response for a particular Certificate ID. + * + * @param certID certificate ID details + * @param certStatus status of the certificate - null if okay + * @param singleExtensions optional extensions + */ + public void AddResponse( + CertificateID certID, + CertificateStatus certStatus, + X509Extensions singleExtensions) + { + list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, singleExtensions)); + } + + /** + * Add a response for a particular Certificate ID. + * + * @param certID certificate ID details + * @param nextUpdate date when next update should be requested + * @param certStatus status of the certificate - null if okay + * @param singleExtensions optional extensions + */ + public void AddResponse( + CertificateID certID, + CertificateStatus certStatus, + DateTime nextUpdate, + X509Extensions singleExtensions) + { + list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, nextUpdate, singleExtensions)); + } + + /** + * Add a response for a particular Certificate ID. + * + * @param certID certificate ID details + * @param thisUpdate date this response was valid on + * @param nextUpdate date when next update should be requested + * @param certStatus status of the certificate - null if okay + * @param singleExtensions optional extensions + */ + public void AddResponse( + CertificateID certID, + CertificateStatus certStatus, + DateTime thisUpdate, + DateTime nextUpdate, + X509Extensions singleExtensions) + { + list.Add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions)); + } + + /** + * Set the extensions for the response. + * + * @param responseExtensions the extension object to carry. + */ + public void SetResponseExtensions( + X509Extensions responseExtensions) + { + this.responseExtensions = responseExtensions; + } + + private BasicOcspResp GenerateResponse( + string signatureName, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain, + DateTime producedAt, + SecureRandom random) + { + DerObjectIdentifier signingAlgorithm; + try + { + signingAlgorithm = OcspUtilities.GetAlgorithmOid(signatureName); + } + catch (Exception e) + { + throw new ArgumentException("unknown signing algorithm specified", e); + } + + Asn1EncodableVector responses = new Asn1EncodableVector(); + + foreach (ResponseObject respObj in list) + { + try + { + responses.Add(respObj.ToResponse()); + } + catch (Exception e) + { + throw new OcspException("exception creating Request", e); + } + } + + ResponseData tbsResp = new ResponseData(responderID.ToAsn1Object(), new DerGeneralizedTime(producedAt), new DerSequence(responses), responseExtensions); + + ISigner sig = null; + + try + { + sig = SignerUtilities.GetSigner(signatureName); + + if (random != null) + { + sig.Init(true, new ParametersWithRandom(privateKey, random)); + } + else + { + sig.Init(true, privateKey); + } + } + catch (Exception e) + { + throw new OcspException("exception creating signature: " + e, e); + } + + DerBitString bitSig = null; + + try + { + byte[] encoded = tbsResp.GetDerEncoded(); + sig.BlockUpdate(encoded, 0, encoded.Length); + + bitSig = new DerBitString(sig.GenerateSignature()); + } + catch (Exception e) + { + throw new OcspException("exception processing TBSRequest: " + e, e); + } + + AlgorithmIdentifier sigAlgId = OcspUtilities.GetSigAlgID(signingAlgorithm); + + DerSequence chainSeq = null; + if (chain != null && chain.Length > 0) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + try + { + for (int i = 0; i != chain.Length; i++) + { + v.Add( + X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(chain[i].GetEncoded()))); + } + } + catch (IOException e) + { + throw new OcspException("error processing certs", e); + } + catch (CertificateEncodingException e) + { + throw new OcspException("error encoding certs", e); + } + + chainSeq = new DerSequence(v); + } + + return new BasicOcspResp(new BasicOcspResponse(tbsResp, sigAlgId, bitSig, chainSeq)); + } + + public BasicOcspResp Generate( + string signingAlgorithm, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain, + DateTime thisUpdate) + { + return Generate(signingAlgorithm, privateKey, chain, thisUpdate, null); + } + + public BasicOcspResp Generate( + string signingAlgorithm, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain, + DateTime producedAt, + SecureRandom random) + { + if (signingAlgorithm == null) + { + throw new ArgumentException("no signing algorithm specified"); + } + + return GenerateResponse(signingAlgorithm, privateKey, chain, producedAt, random); + } + + /** + * Return an IEnumerable of the signature names supported by the generator. + * + * @return an IEnumerable containing recognised names. + */ + public IEnumerable SignatureAlgNames + { + get { return OcspUtilities.AlgNames; } + } + } +} diff --git a/crypto/src/ocsp/CertificateID.cs b/crypto/src/ocsp/CertificateID.cs new file mode 100644 index 000000000..a8f035759 --- /dev/null +++ b/crypto/src/ocsp/CertificateID.cs @@ -0,0 +1,141 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + public class CertificateID + { + public const string HashSha1 = "1.3.14.3.2.26"; + + private readonly CertID id; + + public CertificateID( + CertID id) + { + if (id == null) + throw new ArgumentNullException("id"); + + this.id = id; + } + + /** + * create from an issuer certificate and the serial number of the + * certificate it signed. + * @exception OcspException if any problems occur creating the id fields. + */ + public CertificateID( + string hashAlgorithm, + X509Certificate issuerCert, + BigInteger serialNumber) + { + AlgorithmIdentifier hashAlg = new AlgorithmIdentifier( + new DerObjectIdentifier(hashAlgorithm), DerNull.Instance); + + this.id = CreateCertID(hashAlg, issuerCert, new DerInteger(serialNumber)); + } + + public string HashAlgOid + { + get { return id.HashAlgorithm.ObjectID.Id; } + } + + public byte[] GetIssuerNameHash() + { + return id.IssuerNameHash.GetOctets(); + } + + public byte[] GetIssuerKeyHash() + { + return id.IssuerKeyHash.GetOctets(); + } + + /** + * return the serial number for the certificate associated + * with this request. + */ + public BigInteger SerialNumber + { + get { return id.SerialNumber.Value; } + } + + public bool MatchesIssuer( + X509Certificate issuerCert) + { + return CreateCertID(id.HashAlgorithm, issuerCert, id.SerialNumber).Equals(id); + } + + public CertID ToAsn1Object() + { + return id; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + CertificateID other = obj as CertificateID; + + if (other == null) + return false; + + return id.ToAsn1Object().Equals(other.id.ToAsn1Object()); + } + + public override int GetHashCode() + { + return id.ToAsn1Object().GetHashCode(); + } + + + /** + * Create a new CertificateID for a new serial number derived from a previous one + * calculated for the same CA certificate. + * + * @param original the previously calculated CertificateID for the CA. + * @param newSerialNumber the serial number for the new certificate of interest. + * + * @return a new CertificateID for newSerialNumber + */ + public static CertificateID DeriveCertificateID(CertificateID original, BigInteger newSerialNumber) + { + return new CertificateID(new CertID(original.id.HashAlgorithm, original.id.IssuerNameHash, + original.id.IssuerKeyHash, new DerInteger(newSerialNumber))); + } + + private static CertID CreateCertID( + AlgorithmIdentifier hashAlg, + X509Certificate issuerCert, + DerInteger serialNumber) + { + try + { + String hashAlgorithm = hashAlg.ObjectID.Id; + + X509Name issuerName = PrincipalUtilities.GetSubjectX509Principal(issuerCert); + byte[] issuerNameHash = DigestUtilities.CalculateDigest( + hashAlgorithm, issuerName.GetEncoded()); + + AsymmetricKeyParameter issuerKey = issuerCert.GetPublicKey(); + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKey); + byte[] issuerKeyHash = DigestUtilities.CalculateDigest( + hashAlgorithm, info.PublicKeyData.GetBytes()); + + return new CertID(hashAlg, new DerOctetString(issuerNameHash), + new DerOctetString(issuerKeyHash), serialNumber); + } + catch (Exception e) + { + throw new OcspException("problem creating ID: " + e, e); + } + } + } +} diff --git a/crypto/src/ocsp/CertificateStatus.cs b/crypto/src/ocsp/CertificateStatus.cs new file mode 100644 index 000000000..edfcc2582 --- /dev/null +++ b/crypto/src/ocsp/CertificateStatus.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.Ocsp +{ + public abstract class CertificateStatus + { + public static readonly CertificateStatus Good = null; + } +} diff --git a/crypto/src/ocsp/OCSPException.cs b/crypto/src/ocsp/OCSPException.cs new file mode 100644 index 000000000..db53e559a --- /dev/null +++ b/crypto/src/ocsp/OCSPException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Ocsp +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class OcspException + : Exception + { + public OcspException() + { + } + + public OcspException( + string message) + : base(message) + { + } + + public OcspException( + string message, + Exception e) + : base(message, e) + { + } + } +} diff --git a/crypto/src/ocsp/OCSPReq.cs b/crypto/src/ocsp/OCSPReq.cs new file mode 100644 index 000000000..84808e50a --- /dev/null +++ b/crypto/src/ocsp/OCSPReq.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Ocsp +{ + /** + *
    +	 * OcspRequest     ::=     SEQUENCE {
    +	 *       tbsRequest                  TBSRequest,
    +	 *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
    +	 *
    +	 *   TBSRequest      ::=     SEQUENCE {
    +	 *       version             [0]     EXPLICIT Version DEFAULT v1,
    +	 *       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
    +	 *       requestList                 SEQUENCE OF Request,
    +	 *       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
    +	 *
    +	 *   Signature       ::=     SEQUENCE {
    +	 *       signatureAlgorithm      AlgorithmIdentifier,
    +	 *       signature               BIT STRING,
    +	 *       certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
    +	 *
    +	 *   Version         ::=             INTEGER  {  v1(0) }
    +	 *
    +	 *   Request         ::=     SEQUENCE {
    +	 *       reqCert                     CertID,
    +	 *       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
    +	 *
    +	 *   CertID          ::=     SEQUENCE {
    +	 *       hashAlgorithm       AlgorithmIdentifier,
    +	 *       issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
    +	 *       issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
    +	 *       serialNumber        CertificateSerialNumber }
    +	 * 
    + */ + public class OcspReq + : X509ExtensionBase + { + private OcspRequest req; + + public OcspReq( + OcspRequest req) + { + this.req = req; + } + + public OcspReq( + byte[] req) + : this(new Asn1InputStream(req)) + { + } + + public OcspReq( + Stream inStr) + : this(new Asn1InputStream(inStr)) + { + } + + private OcspReq( + Asn1InputStream aIn) + { + try + { + this.req = OcspRequest.GetInstance(aIn.ReadObject()); + } + catch (ArgumentException e) + { + throw new IOException("malformed request: " + e.Message); + } + catch (InvalidCastException e) + { + throw new IOException("malformed request: " + e.Message); + } + } + + /** + * Return the DER encoding of the tbsRequest field. + * @return DER encoding of tbsRequest + * @throws OcspException in the event of an encoding error. + */ + public byte[] GetTbsRequest() + { + try + { + return req.TbsRequest.GetEncoded(); + } + catch (IOException e) + { + throw new OcspException("problem encoding tbsRequest", e); + } + } + + public int Version + { + get { return req.TbsRequest.Version.Value.IntValue + 1; } + } + + public GeneralName RequestorName + { + get { return GeneralName.GetInstance(req.TbsRequest.RequestorName); } + } + + public Req[] GetRequestList() + { + Asn1Sequence seq = req.TbsRequest.RequestList; + Req[] requests = new Req[seq.Count]; + + for (int i = 0; i != requests.Length; i++) + { + requests[i] = new Req(Request.GetInstance(seq[i])); + } + + return requests; + } + + public X509Extensions RequestExtensions + { + get { return X509Extensions.GetInstance(req.TbsRequest.RequestExtensions); } + } + + protected override X509Extensions GetX509Extensions() + { + return RequestExtensions; + } + + /** + * return the object identifier representing the signature algorithm + */ + public string SignatureAlgOid + { + get + { + if (!this.IsSigned) + return null; + + return req.OptionalSignature.SignatureAlgorithm.ObjectID.Id; + } + } + + public byte[] GetSignature() + { + if (!this.IsSigned) + return null; + + return req.OptionalSignature.SignatureValue.GetBytes(); + } + + private IList GetCertList() + { + // load the certificates if we have any + + IList certs = Platform.CreateArrayList(); + Asn1Sequence s = req.OptionalSignature.Certs; + + if (s != null) + { + foreach (Asn1Encodable ae in s) + { + try + { + certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded())); + } + catch (Exception e) + { + throw new OcspException("can't re-encode certificate!", e); + } + } + } + + return certs; + } + + public X509Certificate[] GetCerts() + { + if (!this.IsSigned) + return null; + + IList certs = this.GetCertList(); + X509Certificate[] result = new X509Certificate[certs.Count]; + for (int i = 0; i < certs.Count; ++i) + { + result[i] = (X509Certificate)certs[i]; + } + return result; + } + + /** + * If the request is signed return a possibly empty CertStore containing the certificates in the + * request. If the request is not signed the method returns null. + * + * @return null if not signed, a CertStore otherwise + * @throws OcspException + */ + public IX509Store GetCertificates( + string type) + { + if (!this.IsSigned) + return null; + + try + { + return X509StoreFactory.Create( + "Certificate/" + type, + new X509CollectionStoreParameters(this.GetCertList())); + } + catch (Exception e) + { + throw new OcspException("can't setup the CertStore", e); + } + } + + /** + * Return whether or not this request is signed. + * + * @return true if signed false otherwise. + */ + public bool IsSigned + { + get { return req.OptionalSignature != null; } + } + + /** + * Verify the signature against the TBSRequest object we contain. + */ + public bool Verify( + AsymmetricKeyParameter publicKey) + { + if (!this.IsSigned) + throw new OcspException("attempt to Verify signature on unsigned object"); + + try + { + ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgOid); + + signature.Init(false, publicKey); + + byte[] encoded = req.TbsRequest.GetEncoded(); + + signature.BlockUpdate(encoded, 0, encoded.Length); + + return signature.VerifySignature(this.GetSignature()); + } + catch (Exception e) + { + throw new OcspException("exception processing sig: " + e, e); + } + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return req.GetEncoded(); + } + } +} diff --git a/crypto/src/ocsp/OCSPReqGenerator.cs b/crypto/src/ocsp/OCSPReqGenerator.cs new file mode 100644 index 000000000..8032a4598 --- /dev/null +++ b/crypto/src/ocsp/OCSPReqGenerator.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + public class OcspReqGenerator + { + private IList list = Platform.CreateArrayList(); + private GeneralName requestorName = null; + private X509Extensions requestExtensions = null; + + private class RequestObject + { + internal CertificateID certId; + internal X509Extensions extensions; + + public RequestObject( + CertificateID certId, + X509Extensions extensions) + { + this.certId = certId; + this.extensions = extensions; + } + + public Request ToRequest() + { + return new Request(certId.ToAsn1Object(), extensions); + } + } + + /** + * Add a request for the given CertificateID. + * + * @param certId certificate ID of interest + */ + public void AddRequest( + CertificateID certId) + { + list.Add(new RequestObject(certId, null)); + } + + /** + * Add a request with extensions + * + * @param certId certificate ID of interest + * @param singleRequestExtensions the extensions to attach to the request + */ + public void AddRequest( + CertificateID certId, + X509Extensions singleRequestExtensions) + { + list.Add(new RequestObject(certId, singleRequestExtensions)); + } + + /** + * Set the requestor name to the passed in X509Principal + * + * @param requestorName a X509Principal representing the requestor name. + */ + public void SetRequestorName( + X509Name requestorName) + { + try + { + this.requestorName = new GeneralName(GeneralName.DirectoryName, requestorName); + } + catch (Exception e) + { + throw new ArgumentException("cannot encode principal", e); + } + } + + public void SetRequestorName( + GeneralName requestorName) + { + this.requestorName = requestorName; + } + + public void SetRequestExtensions( + X509Extensions requestExtensions) + { + this.requestExtensions = requestExtensions; + } + + private OcspReq GenerateRequest( + DerObjectIdentifier signingAlgorithm, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain, + SecureRandom random) + { + Asn1EncodableVector requests = new Asn1EncodableVector(); + + foreach (RequestObject reqObj in list) + { + try + { + requests.Add(reqObj.ToRequest()); + } + catch (Exception e) + { + throw new OcspException("exception creating Request", e); + } + } + + TbsRequest tbsReq = new TbsRequest(requestorName, new DerSequence(requests), requestExtensions); + + ISigner sig = null; + Signature signature = null; + + if (signingAlgorithm != null) + { + if (requestorName == null) + { + throw new OcspException("requestorName must be specified if request is signed."); + } + + try + { + sig = SignerUtilities.GetSigner(signingAlgorithm.Id); + if (random != null) + { + sig.Init(true, new ParametersWithRandom(privateKey, random)); + } + else + { + sig.Init(true, privateKey); + } + } + catch (Exception e) + { + throw new OcspException("exception creating signature: " + e, e); + } + + DerBitString bitSig = null; + + try + { + byte[] encoded = tbsReq.GetEncoded(); + sig.BlockUpdate(encoded, 0, encoded.Length); + + bitSig = new DerBitString(sig.GenerateSignature()); + } + catch (Exception e) + { + throw new OcspException("exception processing TBSRequest: " + e, e); + } + + AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, DerNull.Instance); + + if (chain != null && chain.Length > 0) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + try + { + for (int i = 0; i != chain.Length; i++) + { + v.Add( + X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(chain[i].GetEncoded()))); + } + } + catch (IOException e) + { + throw new OcspException("error processing certs", e); + } + catch (CertificateEncodingException e) + { + throw new OcspException("error encoding certs", e); + } + + signature = new Signature(sigAlgId, bitSig, new DerSequence(v)); + } + else + { + signature = new Signature(sigAlgId, bitSig); + } + } + + return new OcspReq(new OcspRequest(tbsReq, signature)); + } + + /** + * Generate an unsigned request + * + * @return the OcspReq + * @throws OcspException + */ + public OcspReq Generate() + { + return GenerateRequest(null, null, null, null); + } + + public OcspReq Generate( + string signingAlgorithm, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain) + { + return Generate(signingAlgorithm, privateKey, chain, null); + } + + public OcspReq Generate( + string signingAlgorithm, + AsymmetricKeyParameter privateKey, + X509Certificate[] chain, + SecureRandom random) + { + if (signingAlgorithm == null) + throw new ArgumentException("no signing algorithm specified"); + + try + { + DerObjectIdentifier oid = OcspUtilities.GetAlgorithmOid(signingAlgorithm); + + return GenerateRequest(oid, privateKey, chain, random); + } + catch (ArgumentException) + { + throw new ArgumentException("unknown signing algorithm specified: " + signingAlgorithm); + } + } + + /** + * Return an IEnumerable of the signature names supported by the generator. + * + * @return an IEnumerable containing recognised names. + */ + public IEnumerable SignatureAlgNames + { + get { return OcspUtilities.AlgNames; } + } + } +} diff --git a/crypto/src/ocsp/OCSPResp.cs b/crypto/src/ocsp/OCSPResp.cs new file mode 100644 index 000000000..dc99c6a9a --- /dev/null +++ b/crypto/src/ocsp/OCSPResp.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; + +namespace Org.BouncyCastle.Ocsp +{ + public class OcspResp + { + private OcspResponse resp; + + public OcspResp( + OcspResponse resp) + { + this.resp = resp; + } + + public OcspResp( + byte[] resp) + : this(new Asn1InputStream(resp)) + { + } + + public OcspResp( + Stream inStr) + : this(new Asn1InputStream(inStr)) + { + } + + private OcspResp( + Asn1InputStream aIn) + { + try + { + this.resp = OcspResponse.GetInstance(aIn.ReadObject()); + } + catch (Exception e) + { + throw new IOException("malformed response: " + e.Message, e); + } + } + + public int Status + { + get { return this.resp.ResponseStatus.Value.IntValue; } + } + + public object GetResponseObject() + { + ResponseBytes rb = this.resp.ResponseBytes; + + if (rb == null) + return null; + + if (rb.ResponseType.Equals(OcspObjectIdentifiers.PkixOcspBasic)) + { + try + { + return new BasicOcspResp( + BasicOcspResponse.GetInstance( + Asn1Object.FromByteArray(rb.Response.GetOctets()))); + } + catch (Exception e) + { + throw new OcspException("problem decoding object: " + e, e); + } + } + + return rb.Response; + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return resp.GetEncoded(); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + OcspResp other = obj as OcspResp; + + if (other == null) + return false; + + return resp.Equals(other.resp); + } + + public override int GetHashCode() + { + return resp.GetHashCode(); + } + } +} diff --git a/crypto/src/ocsp/OCSPRespGenerator.cs b/crypto/src/ocsp/OCSPRespGenerator.cs new file mode 100644 index 000000000..e0eb9ae90 --- /dev/null +++ b/crypto/src/ocsp/OCSPRespGenerator.cs @@ -0,0 +1,54 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; + +namespace Org.BouncyCastle.Ocsp +{ + /** + * base generator for an OCSP response - at the moment this only supports the + * generation of responses containing BasicOCSP responses. + */ + public class OCSPRespGenerator + { + public const int Successful = 0; // Response has valid confirmations + public const int MalformedRequest = 1; // Illegal confirmation request + public const int InternalError = 2; // Internal error in issuer + public const int TryLater = 3; // Try again later + // (4) is not used + public const int SigRequired = 5; // Must sign the request + public const int Unauthorized = 6; // Request unauthorized + + public OcspResp Generate( + int status, + object response) + { + if (response == null) + { + return new OcspResp(new OcspResponse(new OcspResponseStatus(status),null)); + } + if (response is BasicOcspResp) + { + BasicOcspResp r = (BasicOcspResp)response; + Asn1OctetString octs; + + try + { + octs = new DerOctetString(r.GetEncoded()); + } + catch (Exception e) + { + throw new OcspException("can't encode object.", e); + } + + ResponseBytes rb = new ResponseBytes( + OcspObjectIdentifiers.PkixOcspBasic, octs); + + return new OcspResp(new OcspResponse( + new OcspResponseStatus(status), rb)); + } + + throw new OcspException("unknown response object"); + } + } +} diff --git a/crypto/src/ocsp/OCSPRespStatus.cs b/crypto/src/ocsp/OCSPRespStatus.cs new file mode 100644 index 000000000..9c00c7035 --- /dev/null +++ b/crypto/src/ocsp/OCSPRespStatus.cs @@ -0,0 +1,22 @@ +using System; + +namespace Org.BouncyCastle.Ocsp +{ + [Obsolete("Use version with correct spelling 'OcspRespStatus'")] + public abstract class OcscpRespStatus : OcspRespStatus + { + } + + public abstract class OcspRespStatus + { + /** + * note 4 is not used. + */ + public const int Successful = 0; // --Response has valid confirmations + public const int MalformedRequest = 1; // --Illegal confirmation request + public const int InternalError = 2; // --Internal error in issuer + public const int TryLater = 3; // --Try again later + public const int SigRequired = 5; // --Must sign the request + public const int Unauthorized = 6; // --Request unauthorized + } +} diff --git a/crypto/src/ocsp/OCSPUtil.cs b/crypto/src/ocsp/OCSPUtil.cs new file mode 100644 index 000000000..cbc1e95f5 --- /dev/null +++ b/crypto/src/ocsp/OCSPUtil.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Ocsp +{ + class OcspUtilities + { + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary oids = Platform.CreateHashtable(); + private static readonly ISet noParams = new HashSet(); + + static OcspUtilities() + { + algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption); + algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption); + algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption); + algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption); + algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption); + algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption); + algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1); + algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1); + algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224); + algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256); + algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + + oids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2WITHRSA"); + oids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512WITHRSA"); + oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, "RIPEMD160WITHRSA"); + oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, "RIPEMD128WITHRSA"); + oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, "RIPEMD256WITHRSA"); + oids.Add(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1WITHDSA"); + oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA"); + oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512WITHECDSA"); + oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411WITHGOST3410"); + + // + // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. + // The parameters field SHALL be NULL for RSA based signature algorithms. + // + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512); + noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1); + noParams.Add(NistObjectIdentifiers.DsaWithSha224); + noParams.Add(NistObjectIdentifiers.DsaWithSha256); + } + + internal static DerObjectIdentifier GetAlgorithmOid( + string algorithmName) + { + algorithmName = Platform.ToUpperInvariant(algorithmName); + + if (algorithms.Contains(algorithmName)) + { + return (DerObjectIdentifier)algorithms[algorithmName]; + } + + return new DerObjectIdentifier(algorithmName); + } + + + internal static string GetAlgorithmName( + DerObjectIdentifier oid) + { + if (oids.Contains(oid)) + { + return (string)oids[oid]; + } + + return oid.Id; + } + + internal static AlgorithmIdentifier GetSigAlgID( + DerObjectIdentifier sigOid) + { + if (noParams.Contains(sigOid)) + { + return new AlgorithmIdentifier(sigOid); + } + + return new AlgorithmIdentifier(sigOid, DerNull.Instance); + } + + internal static IEnumerable AlgNames + { + get { return new EnumerableProxy(algorithms.Keys); } + } + } +} diff --git a/crypto/src/ocsp/Req.cs b/crypto/src/ocsp/Req.cs new file mode 100644 index 000000000..68fd9f12a --- /dev/null +++ b/crypto/src/ocsp/Req.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + public class Req + : X509ExtensionBase + { + private Request req; + + public Req( + Request req) + { + this.req = req; + } + + public CertificateID GetCertID() + { + return new CertificateID(req.ReqCert); + } + + public X509Extensions SingleRequestExtensions + { + get { return req.SingleRequestExtensions; } + } + + protected override X509Extensions GetX509Extensions() + { + return SingleRequestExtensions; + } + } +} diff --git a/crypto/src/ocsp/RespData.cs b/crypto/src/ocsp/RespData.cs new file mode 100644 index 000000000..105726ca7 --- /dev/null +++ b/crypto/src/ocsp/RespData.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + public class RespData + : X509ExtensionBase + { + internal readonly ResponseData data; + + public RespData( + ResponseData data) + { + this.data = data; + } + + public int Version + { + get { return data.Version.Value.IntValue + 1; } + } + + public RespID GetResponderId() + { + return new RespID(data.ResponderID); + } + + public DateTime ProducedAt + { + get { return data.ProducedAt.ToDateTime(); } + } + + public SingleResp[] GetResponses() + { + Asn1Sequence s = data.Responses; + SingleResp[] rs = new SingleResp[s.Count]; + + for (int i = 0; i != rs.Length; i++) + { + rs[i] = new SingleResp(SingleResponse.GetInstance(s[i])); + } + + return rs; + } + + public X509Extensions ResponseExtensions + { + get { return data.ResponseExtensions; } + } + + protected override X509Extensions GetX509Extensions() + { + return ResponseExtensions; + } + } +} diff --git a/crypto/src/ocsp/RespID.cs b/crypto/src/ocsp/RespID.cs new file mode 100644 index 000000000..3238b26da --- /dev/null +++ b/crypto/src/ocsp/RespID.cs @@ -0,0 +1,72 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + /** + * Carrier for a ResponderID. + */ + public class RespID + { + internal readonly ResponderID id; + + public RespID( + ResponderID id) + { + this.id = id; + } + + public RespID( + X509Name name) + { + this.id = new ResponderID(name); + } + + public RespID( + AsymmetricKeyParameter publicKey) + { + try + { + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); + + byte[] keyHash = DigestUtilities.CalculateDigest("SHA1", info.PublicKeyData.GetBytes()); + + this.id = new ResponderID(new DerOctetString(keyHash)); + } + catch (Exception e) + { + throw new OcspException("problem creating ID: " + e, e); + } + } + + public ResponderID ToAsn1Object() + { + return id; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + RespID other = obj as RespID; + + if (other == null) + return false; + + return id.Equals(other.id); + } + + public override int GetHashCode() + { + return id.GetHashCode(); + } + } +} diff --git a/crypto/src/ocsp/RevokedStatus.cs b/crypto/src/ocsp/RevokedStatus.cs new file mode 100644 index 000000000..6e5ad1b26 --- /dev/null +++ b/crypto/src/ocsp/RevokedStatus.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Ocsp +{ + /** + * wrapper for the RevokedInfo object + */ + public class RevokedStatus + : CertificateStatus + { + internal readonly RevokedInfo info; + + public RevokedStatus( + RevokedInfo info) + { + this.info = info; + } + + public RevokedStatus( + DateTime revocationDate, + int reason) + { + this.info = new RevokedInfo(new DerGeneralizedTime(revocationDate), new CrlReason(reason)); + } + + public DateTime RevocationTime + { + get { return info.RevocationTime.ToDateTime(); } + } + + public bool HasRevocationReason + { + get { return (info.RevocationReason != null); } + } + + /** + * return the revocation reason. Note: this field is optional, test for it + * with hasRevocationReason() first. + * @exception InvalidOperationException if a reason is asked for and none is avaliable + */ + public int RevocationReason + { + get + { + if (info.RevocationReason == null) + { + throw new InvalidOperationException("attempt to get a reason where none is available"); + } + + return info.RevocationReason.Value.IntValue; + } + } + } +} diff --git a/crypto/src/ocsp/SingleResp.cs b/crypto/src/ocsp/SingleResp.cs new file mode 100644 index 000000000..b8979c538 --- /dev/null +++ b/crypto/src/ocsp/SingleResp.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp +{ + public class SingleResp + : X509ExtensionBase + { + internal readonly SingleResponse resp; + + public SingleResp( + SingleResponse resp) + { + this.resp = resp; + } + + public CertificateID GetCertID() + { + return new CertificateID(resp.CertId); + } + + /** + * Return the status object for the response - null indicates good. + * + * @return the status object for the response, null if it is good. + */ + public object GetCertStatus() + { + CertStatus s = resp.CertStatus; + + if (s.TagNo == 0) + { + return null; // good + } + + if (s.TagNo == 1) + { + return new RevokedStatus(RevokedInfo.GetInstance(s.Status)); + } + + return new UnknownStatus(); + } + + public DateTime ThisUpdate + { + get { return resp.ThisUpdate.ToDateTime(); } + } + + /** + * return the NextUpdate value - note: this is an optional field so may + * be returned as null. + * + * @return nextUpdate, or null if not present. + */ + public DateTimeObject NextUpdate + { + get + { + return resp.NextUpdate == null + ? null + : new DateTimeObject(resp.NextUpdate.ToDateTime()); + } + } + + public X509Extensions SingleExtensions + { + get { return resp.SingleExtensions; } + } + + protected override X509Extensions GetX509Extensions() + { + return SingleExtensions; + } + } +} diff --git a/crypto/src/ocsp/UnknownStatus.cs b/crypto/src/ocsp/UnknownStatus.cs new file mode 100644 index 000000000..c0f7a3a64 --- /dev/null +++ b/crypto/src/ocsp/UnknownStatus.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.Ocsp +{ + /** + * wrapper for the UnknownInfo object + */ + public class UnknownStatus + : CertificateStatus + { + public UnknownStatus() + { + } + } +} diff --git a/crypto/src/openpgp/IStreamGenerator.cs b/crypto/src/openpgp/IStreamGenerator.cs new file mode 100644 index 000000000..379213a66 --- /dev/null +++ b/crypto/src/openpgp/IStreamGenerator.cs @@ -0,0 +1,7 @@ +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public interface IStreamGenerator + { + void Close(); + } +} diff --git a/crypto/src/openpgp/PGPKeyRing.cs b/crypto/src/openpgp/PGPKeyRing.cs new file mode 100644 index 000000000..6426f3f25 --- /dev/null +++ b/crypto/src/openpgp/PGPKeyRing.cs @@ -0,0 +1,79 @@ +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public abstract class PgpKeyRing + : PgpObject + { + internal PgpKeyRing() + { + } + + internal static TrustPacket ReadOptionalTrustPacket( + BcpgInputStream bcpgInput) + { + return (bcpgInput.NextPacketTag() == PacketTag.Trust) + ? (TrustPacket) bcpgInput.ReadPacket() + : null; + } + + internal static IList ReadSignaturesAndTrust( + BcpgInputStream bcpgInput) + { + try + { + IList sigList = Platform.CreateArrayList(); + + while (bcpgInput.NextPacketTag() == PacketTag.Signature) + { + SignaturePacket signaturePacket = (SignaturePacket) bcpgInput.ReadPacket(); + TrustPacket trustPacket = ReadOptionalTrustPacket(bcpgInput); + + sigList.Add(new PgpSignature(signaturePacket, trustPacket)); + } + + return sigList; + } + catch (PgpException e) + { + throw new IOException("can't create signature object: " + e.Message, e); + } + } + + internal static void ReadUserIDs( + BcpgInputStream bcpgInput, + out IList ids, + out IList idTrusts, + out IList idSigs) + { + ids = Platform.CreateArrayList(); + idTrusts = Platform.CreateArrayList(); + idSigs = Platform.CreateArrayList(); + + while (bcpgInput.NextPacketTag() == PacketTag.UserId + || bcpgInput.NextPacketTag() == PacketTag.UserAttribute) + { + Packet obj = bcpgInput.ReadPacket(); + if (obj is UserIdPacket) + { + UserIdPacket id = (UserIdPacket)obj; + ids.Add(id.GetId()); + } + else + { + UserAttributePacket user = (UserAttributePacket) obj; + ids.Add(new PgpUserAttributeSubpacketVector(user.GetSubpackets())); + } + + idTrusts.Add( + ReadOptionalTrustPacket(bcpgInput)); + + idSigs.Add( + ReadSignaturesAndTrust(bcpgInput)); + } + } + } +} diff --git a/crypto/src/openpgp/PGPObject.cs b/crypto/src/openpgp/PGPObject.cs new file mode 100644 index 000000000..d38276cb6 --- /dev/null +++ b/crypto/src/openpgp/PGPObject.cs @@ -0,0 +1,9 @@ +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public abstract class PgpObject + { + internal PgpObject() + { + } + } +} diff --git a/crypto/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs b/crypto/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs new file mode 100644 index 000000000..9d56c8bc3 --- /dev/null +++ b/crypto/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Bcpg.Attr; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public class PgpUserAttributeSubpacketVectorGenerator + { + private IList list = Platform.CreateArrayList(); + + public virtual void SetImageAttribute( + ImageAttrib.Format imageType, + byte[] imageData) + { + if (imageData == null) + throw new ArgumentException("attempt to set null image", "imageData"); + + list.Add(new ImageAttrib(imageType, imageData)); + } + + public virtual PgpUserAttributeSubpacketVector Generate() + { + UserAttributeSubpacket[] a = new UserAttributeSubpacket[list.Count]; + for (int i = 0; i < list.Count; ++i) + { + a[i] = (UserAttributeSubpacket)list[i]; + } + return new PgpUserAttributeSubpacketVector(a); + } + } +} diff --git a/crypto/src/openpgp/PgpCompressedData.cs b/crypto/src/openpgp/PgpCompressedData.cs new file mode 100644 index 000000000..e64a17c9c --- /dev/null +++ b/crypto/src/openpgp/PgpCompressedData.cs @@ -0,0 +1,50 @@ +using System.IO; + +using Org.BouncyCastle.Apache.Bzip2; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Compressed data objects + public class PgpCompressedData + : PgpObject + { + private readonly CompressedDataPacket data; + + public PgpCompressedData( + BcpgInputStream bcpgInput) + { + data = (CompressedDataPacket) bcpgInput.ReadPacket(); + } + + /// The algorithm used for compression + public CompressionAlgorithmTag Algorithm + { + get { return data.Algorithm; } + } + + /// Get the raw input stream contained in the object. + public Stream GetInputStream() + { + return data.GetInputStream(); + } + + /// Return an uncompressed input stream which allows reading of the compressed data. + public Stream GetDataStream() + { + switch (Algorithm) + { + case CompressionAlgorithmTag.Uncompressed: + return GetInputStream(); + case CompressionAlgorithmTag.Zip: + return new ZInputStream(GetInputStream(), true); + case CompressionAlgorithmTag.ZLib: + return new ZInputStream(GetInputStream()); + case CompressionAlgorithmTag.BZip2: + return new CBZip2InputStream(GetInputStream()); + default: + throw new PgpException("can't recognise compression algorithm: " + Algorithm); + } + } + } +} diff --git a/crypto/src/openpgp/PgpCompressedDataGenerator.cs b/crypto/src/openpgp/PgpCompressedDataGenerator.cs new file mode 100644 index 000000000..7f4ec8e53 --- /dev/null +++ b/crypto/src/openpgp/PgpCompressedDataGenerator.cs @@ -0,0 +1,197 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Apache.Bzip2; +using Org.BouncyCastle.Utilities.Zlib; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Class for producing compressed data packets. + public class PgpCompressedDataGenerator + : IStreamGenerator + { + private readonly CompressionAlgorithmTag algorithm; + private readonly int compression; + + private Stream dOut; + private BcpgOutputStream pkOut; + + public PgpCompressedDataGenerator( + CompressionAlgorithmTag algorithm) + : this(algorithm, JZlib.Z_DEFAULT_COMPRESSION) + { + } + + public PgpCompressedDataGenerator( + CompressionAlgorithmTag algorithm, + int compression) + { + switch (algorithm) + { + case CompressionAlgorithmTag.Uncompressed: + case CompressionAlgorithmTag.Zip: + case CompressionAlgorithmTag.ZLib: + case CompressionAlgorithmTag.BZip2: + break; + default: + throw new ArgumentException("unknown compression algorithm", "algorithm"); + } + + if (compression != JZlib.Z_DEFAULT_COMPRESSION) + { + if ((compression < JZlib.Z_NO_COMPRESSION) || (compression > JZlib.Z_BEST_COMPRESSION)) + { + throw new ArgumentException("unknown compression level: " + compression); + } + } + + this.algorithm = algorithm; + this.compression = compression; + } + + /// + ///

    + /// Return an output stream which will save the data being written to + /// the compressed object. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///
    + /// Stream to be used for output. + /// A Stream for output of the compressed data. + /// + /// + /// + public Stream Open( + Stream outStr) + { + if (dOut != null) + throw new InvalidOperationException("generator already in open state"); + if (outStr == null) + throw new ArgumentNullException("outStr"); + + this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData); + + doOpen(); + + return new WrappedGeneratorStream(this, dOut); + } + + /// + ///

    + /// Return an output stream which will compress the data as it is written to it. + /// The stream will be written out in chunks according to the size of the passed in buffer. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///

    + /// Note: if the buffer is not a power of 2 in length only the largest power of 2 + /// bytes worth of the buffer will be used. + ///

    + ///

    + /// Note: using this may break compatibility with RFC 1991 compliant tools. + /// Only recent OpenPGP implementations are capable of accepting these streams. + ///

    + ///
    + /// Stream to be used for output. + /// The buffer to use. + /// A Stream for output of the compressed data. + /// + /// + /// + /// + public Stream Open( + Stream outStr, + byte[] buffer) + { + if (dOut != null) + throw new InvalidOperationException("generator already in open state"); + if (outStr == null) + throw new ArgumentNullException("outStr"); + if (buffer == null) + throw new ArgumentNullException("buffer"); + + this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData, buffer); + + doOpen(); + + return new WrappedGeneratorStream(this, dOut); + } + + private void doOpen() + { + pkOut.WriteByte((byte) algorithm); + + switch (algorithm) + { + case CompressionAlgorithmTag.Uncompressed: + dOut = pkOut; + break; + case CompressionAlgorithmTag.Zip: + dOut = new SafeZOutputStream(pkOut, compression, true); + break; + case CompressionAlgorithmTag.ZLib: + dOut = new SafeZOutputStream(pkOut, compression, false); + break; + case CompressionAlgorithmTag.BZip2: + dOut = new SafeCBZip2OutputStream(pkOut); + break; + default: + // Constructor should guard against this possibility + throw new InvalidOperationException(); + } + } + + /// Close the compressed object.summary> + public void Close() + { + if (dOut != null) + { + if (dOut != pkOut) + { + dOut.Close(); + dOut.Flush(); + } + + dOut = null; + + pkOut.Finish(); + pkOut.Flush(); + pkOut = null; + } + } + + private class SafeCBZip2OutputStream : CBZip2OutputStream + { + public SafeCBZip2OutputStream(Stream output) + : base(output) + { + } + + public override void Close() + { + Finish(); + } + } + + private class SafeZOutputStream : ZOutputStream + { + public SafeZOutputStream(Stream output, int level, bool nowrap) + : base(output, level, nowrap) + { + } + + public override void Close() + { + Finish(); + End(); + } + } + } +} diff --git a/crypto/src/openpgp/PgpDataValidationException.cs b/crypto/src/openpgp/PgpDataValidationException.cs new file mode 100644 index 000000000..aab5165b2 --- /dev/null +++ b/crypto/src/openpgp/PgpDataValidationException.cs @@ -0,0 +1,18 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Thrown if the IV at the start of a data stream indicates the wrong key is being used. + /// +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PgpDataValidationException + : PgpException + { + public PgpDataValidationException() : base() {} + public PgpDataValidationException(string message) : base(message) {} + public PgpDataValidationException(string message, Exception exception) : base(message, exception) {} + } +} diff --git a/crypto/src/openpgp/PgpEncryptedData.cs b/crypto/src/openpgp/PgpEncryptedData.cs new file mode 100644 index 000000000..0d237b56c --- /dev/null +++ b/crypto/src/openpgp/PgpEncryptedData.cs @@ -0,0 +1,151 @@ +using System; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public abstract class PgpEncryptedData + { + internal class TruncatedStream + : BaseInputStream + { + private const int LookAheadSize = 22; + private const int LookAheadBufSize = 512; + private const int LookAheadBufLimit = LookAheadBufSize - LookAheadSize; + + private readonly Stream inStr; + private readonly byte[] lookAhead = new byte[LookAheadBufSize]; + private int bufStart, bufEnd; + + internal TruncatedStream( + Stream inStr) + { + int numRead = Streams.ReadFully(inStr, lookAhead, 0, lookAhead.Length); + + if (numRead < LookAheadSize) + throw new EndOfStreamException(); + + this.inStr = inStr; + this.bufStart = 0; + this.bufEnd = numRead - LookAheadSize; + } + + private int FillBuffer() + { + if (bufEnd < LookAheadBufLimit) + return 0; + + Debug.Assert(bufStart == LookAheadBufLimit); + Debug.Assert(bufEnd == LookAheadBufLimit); + + Array.Copy(lookAhead, LookAheadBufLimit, lookAhead, 0, LookAheadSize); + bufEnd = Streams.ReadFully(inStr, lookAhead, LookAheadSize, LookAheadBufLimit); + bufStart = 0; + return bufEnd; + } + + public override int ReadByte() + { + if (bufStart < bufEnd) + return lookAhead[bufStart++]; + + if (FillBuffer() < 1) + return -1; + + return lookAhead[bufStart++]; + } + + public override int Read(byte[] buf, int off, int len) + { + int avail = bufEnd - bufStart; + + int pos = off; + while (len > avail) + { + Array.Copy(lookAhead, bufStart, buf, pos, avail); + + bufStart += avail; + pos += avail; + len -= avail; + + if ((avail = FillBuffer()) < 1) + return pos - off; + } + + Array.Copy(lookAhead, bufStart, buf, pos, len); + bufStart += len; + + return pos + len - off;; + } + + internal byte[] GetLookAhead() + { + byte[] temp = new byte[LookAheadSize]; + Array.Copy(lookAhead, bufStart, temp, 0, LookAheadSize); + return temp; + } + } + + internal InputStreamPacket encData; + internal Stream encStream; + internal TruncatedStream truncStream; + + internal PgpEncryptedData( + InputStreamPacket encData) + { + this.encData = encData; + } + + /// Return the raw input stream for the data stream. + public virtual Stream GetInputStream() + { + return encData.GetInputStream(); + } + + /// Return true if the message is integrity protected. + /// True, if there is a modification detection code namespace associated + /// with this stream. + public bool IsIntegrityProtected() + { + return encData is SymmetricEncIntegrityPacket; + } + + /// Note: This can only be called after the message has been read. + /// True, if the message verifies, false otherwise + public bool Verify() + { + if (!IsIntegrityProtected()) + throw new PgpException("data not integrity protected."); + + DigestStream dIn = (DigestStream) encStream; + + // + // make sure we are at the end. + // + while (encStream.ReadByte() >= 0) + { + // do nothing + } + + // + // process the MDC packet + // + byte[] lookAhead = truncStream.GetLookAhead(); + + IDigest hash = dIn.ReadDigest(); + hash.BlockUpdate(lookAhead, 0, 2); + byte[] digest = DigestUtilities.DoFinal(hash); + + byte[] streamDigest = new byte[digest.Length]; + Array.Copy(lookAhead, 2, streamDigest, 0, streamDigest.Length); + + return Arrays.ConstantTimeAreEqual(digest, streamDigest); + } + } +} diff --git a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs new file mode 100644 index 000000000..f46f99d37 --- /dev/null +++ b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs @@ -0,0 +1,506 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Generator for encrypted objects. + public class PgpEncryptedDataGenerator + : IStreamGenerator + { + private BcpgOutputStream pOut; + private CipherStream cOut; + private IBufferedCipher c; + private bool withIntegrityPacket; + private bool oldFormat; + private DigestStream digestOut; + + private abstract class EncMethod + : ContainedPacket + { + protected byte[] sessionInfo; + protected SymmetricKeyAlgorithmTag encAlgorithm; + protected KeyParameter key; + + public abstract void AddSessionInfo(byte[] si, SecureRandom random); + } + + private class PbeMethod + : EncMethod + { + private S2k s2k; + + internal PbeMethod( + SymmetricKeyAlgorithmTag encAlgorithm, + S2k s2k, + KeyParameter key) + { + this.encAlgorithm = encAlgorithm; + this.s2k = s2k; + this.key = key; + } + + public KeyParameter GetKey() + { + return key; + } + + public override void AddSessionInfo( + byte[] si, + SecureRandom random) + { + string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); + IBufferedCipher c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); + + byte[] iv = new byte[c.GetBlockSize()]; + c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), random)); + + this.sessionInfo = c.DoFinal(si, 0, si.Length - 2); + } + + public override void Encode(BcpgOutputStream pOut) + { + SymmetricKeyEncSessionPacket pk = new SymmetricKeyEncSessionPacket( + encAlgorithm, s2k, sessionInfo); + + pOut.WritePacket(pk); + } + } + + private class PubMethod + : EncMethod + { + internal PgpPublicKey pubKey; + internal BigInteger[] data; + + internal PubMethod( + PgpPublicKey pubKey) + { + this.pubKey = pubKey; + } + + public override void AddSessionInfo( + byte[] si, + SecureRandom random) + { + IBufferedCipher c; + + switch (pubKey.Algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + c = CipherUtilities.GetCipher("RSA//PKCS1Padding"); + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + c = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding"); + break; + case PublicKeyAlgorithmTag.Dsa: + throw new PgpException("Can't use DSA for encryption."); + case PublicKeyAlgorithmTag.ECDsa: + throw new PgpException("Can't use ECDSA for encryption."); + default: + throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm); + } + + AsymmetricKeyParameter akp = pubKey.GetKey(); + + c.Init(true, new ParametersWithRandom(akp, random)); + + byte[] encKey = c.DoFinal(si); + + switch (pubKey.Algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + data = new BigInteger[]{ new BigInteger(1, encKey) }; + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + int halfLength = encKey.Length / 2; + data = new BigInteger[] + { + new BigInteger(1, encKey, 0, halfLength), + new BigInteger(1, encKey, halfLength, halfLength) + }; + break; + default: + throw new PgpException("unknown asymmetric algorithm: " + encAlgorithm); + } + } + + public override void Encode(BcpgOutputStream pOut) + { + PublicKeyEncSessionPacket pk = new PublicKeyEncSessionPacket( + pubKey.KeyId, pubKey.Algorithm, data); + + pOut.WritePacket(pk); + } + } + + private readonly IList methods = Platform.CreateArrayList(); + private readonly SymmetricKeyAlgorithmTag defAlgorithm; + private readonly SecureRandom rand; + + public PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag encAlgorithm) + { + this.defAlgorithm = encAlgorithm; + this.rand = new SecureRandom(); + } + + public PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag encAlgorithm, + bool withIntegrityPacket) + { + this.defAlgorithm = encAlgorithm; + this.withIntegrityPacket = withIntegrityPacket; + this.rand = new SecureRandom(); + } + + /// Existing SecureRandom constructor. + /// The symmetric algorithm to use. + /// Source of randomness. + public PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag encAlgorithm, + SecureRandom rand) + { + this.defAlgorithm = encAlgorithm; + this.rand = rand; + } + + /// Creates a cipher stream which will have an integrity packet associated with it. + public PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag encAlgorithm, + bool withIntegrityPacket, + SecureRandom rand) + { + this.defAlgorithm = encAlgorithm; + this.rand = rand; + this.withIntegrityPacket = withIntegrityPacket; + } + + /// Base constructor. + /// The symmetric algorithm to use. + /// Source of randomness. + /// PGP 2.6.x compatibility required. + public PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag encAlgorithm, + SecureRandom rand, + bool oldFormat) + { + this.defAlgorithm = encAlgorithm; + this.rand = rand; + this.oldFormat = oldFormat; + } + + /// + /// Add a PBE encryption method to the encrypted object using the default algorithm (S2K_SHA1). + /// + public void AddMethod( + char[] passPhrase) + { + AddMethod(passPhrase, HashAlgorithmTag.Sha1); + } + + /// Add a PBE encryption method to the encrypted object. + public void AddMethod( + char[] passPhrase, + HashAlgorithmTag s2kDigest) + { + byte[] iv = new byte[8]; + rand.NextBytes(iv); + + S2k s2k = new S2k(s2kDigest, iv, 0x60); + + methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.MakeKeyFromPassPhrase(defAlgorithm, s2k, passPhrase))); + } + + /// Add a public key encrypted session key to the encrypted object. + public void AddMethod( + PgpPublicKey key) + { + if (!key.IsEncryptionKey) + { + throw new ArgumentException("passed in key not an encryption key!"); + } + + methods.Add(new PubMethod(key)); + } + + private void AddCheckSum( + byte[] sessionInfo) + { + Debug.Assert(sessionInfo != null); + Debug.Assert(sessionInfo.Length >= 3); + + int check = 0; + + for (int i = 1; i < sessionInfo.Length - 2; i++) + { + check += sessionInfo[i]; + } + + sessionInfo[sessionInfo.Length - 2] = (byte)(check >> 8); + sessionInfo[sessionInfo.Length - 1] = (byte)(check); + } + + private byte[] CreateSessionInfo( + SymmetricKeyAlgorithmTag algorithm, + KeyParameter key) + { + byte[] keyBytes = key.GetKey(); + byte[] sessionInfo = new byte[keyBytes.Length + 3]; + sessionInfo[0] = (byte) algorithm; + keyBytes.CopyTo(sessionInfo, 1); + AddCheckSum(sessionInfo); + return sessionInfo; + } + + /// + ///

    + /// If buffer is non null stream assumed to be partial, otherwise the length will be used + /// to output a fixed length packet. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///
    + private Stream Open( + Stream outStr, + long length, + byte[] buffer) + { + if (cOut != null) + throw new InvalidOperationException("generator already in open state"); + if (methods.Count == 0) + throw new InvalidOperationException("No encryption methods specified"); + if (outStr == null) + throw new ArgumentNullException("outStr"); + + pOut = new BcpgOutputStream(outStr); + + KeyParameter key; + + if (methods.Count == 1) + { + if (methods[0] is PbeMethod) + { + PbeMethod m = (PbeMethod)methods[0]; + + key = m.GetKey(); + } + else + { + key = PgpUtilities.MakeRandomKey(defAlgorithm, rand); + + byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key); + PubMethod m = (PubMethod)methods[0]; + + try + { + m.AddSessionInfo(sessionInfo, rand); + } + catch (Exception e) + { + throw new PgpException("exception encrypting session key", e); + } + } + + pOut.WritePacket((ContainedPacket)methods[0]); + } + else // multiple methods + { + key = PgpUtilities.MakeRandomKey(defAlgorithm, rand); + byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key); + + for (int i = 0; i != methods.Count; i++) + { + EncMethod m = (EncMethod)methods[i]; + + try + { + m.AddSessionInfo(sessionInfo, rand); + } + catch (Exception e) + { + throw new PgpException("exception encrypting session key", e); + } + + pOut.WritePacket(m); + } + } + + string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm); + if (cName == null) + { + throw new PgpException("null cipher specified"); + } + + try + { + if (withIntegrityPacket) + { + cName += "/CFB/NoPadding"; + } + else + { + cName += "/OpenPGPCFB/NoPadding"; + } + + c = CipherUtilities.GetCipher(cName); + + // TODO Confirm the IV should be all zero bytes (not inLineIv - see below) + byte[] iv = new byte[c.GetBlockSize()]; + c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand)); + + if (buffer == null) + { + // + // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected + // + if (withIntegrityPacket) + { + pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22); + pOut.WriteByte(1); // version number + } + else + { + pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat); + } + } + else + { + if (withIntegrityPacket) + { + pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer); + pOut.WriteByte(1); // version number + } + else + { + pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer); + } + } + + int blockSize = c.GetBlockSize(); + byte[] inLineIv = new byte[blockSize + 2]; + rand.NextBytes(inLineIv, 0, blockSize); + Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2); + + Stream myOut = cOut = new CipherStream(pOut, null, c); + + if (withIntegrityPacket) + { + string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); + IDigest digest = DigestUtilities.GetDigest(digestName); + myOut = digestOut = new DigestStream(myOut, null, digest); + } + + myOut.Write(inLineIv, 0, inLineIv.Length); + + return new WrappedGeneratorStream(this, myOut); + } + catch (Exception e) + { + throw new PgpException("Exception creating cipher", e); + } + } + + /// + ///

    + /// Return an output stream which will encrypt the data as it is written to it. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///
    + public Stream Open( + Stream outStr, + long length) + { + return Open(outStr, length, null); + } + + /// + ///

    + /// Return an output stream which will encrypt the data as it is written to it. + /// The stream will be written out in chunks according to the size of the passed in buffer. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///

    + /// Note: if the buffer is not a power of 2 in length only the largest power of 2 + /// bytes worth of the buffer will be used. + ///

    + ///
    + public Stream Open( + Stream outStr, + byte[] buffer) + { + return Open(outStr, 0, buffer); + } + + /// + ///

    + /// Close off the encrypted object - this is equivalent to calling Close() on the stream + /// returned by the Open() method. + ///

    + ///

    + /// Note: This does not close the underlying output stream, only the stream on top of + /// it created by the Open() method. + ///

    + ///
    + public void Close() + { + if (cOut != null) + { + // TODO Should this all be under the try/catch block? + if (digestOut != null) + { + // + // hand code a mod detection packet + // + BcpgOutputStream bOut = new BcpgOutputStream( + digestOut, PacketTag.ModificationDetectionCode, 20); + + bOut.Flush(); + digestOut.Flush(); + + // TODO + byte[] dig = DigestUtilities.DoFinal(digestOut.WriteDigest()); + cOut.Write(dig, 0, dig.Length); + } + + cOut.Flush(); + + try + { + pOut.Write(c.DoFinal()); + pOut.Finish(); + } + catch (Exception e) + { + throw new IOException(e.Message, e); + } + + cOut = null; + pOut = null; + } + } + } +} diff --git a/crypto/src/openpgp/PgpEncryptedDataList.cs b/crypto/src/openpgp/PgpEncryptedDataList.cs new file mode 100644 index 000000000..8dded7c05 --- /dev/null +++ b/crypto/src/openpgp/PgpEncryptedDataList.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A holder for a list of PGP encryption method packets. + public class PgpEncryptedDataList + : PgpObject + { + private IList list = Platform.CreateArrayList(); + private InputStreamPacket data; + + public PgpEncryptedDataList( + BcpgInputStream bcpgInput) + { + while (bcpgInput.NextPacketTag() == PacketTag.PublicKeyEncryptedSession + || bcpgInput.NextPacketTag() == PacketTag.SymmetricKeyEncryptedSessionKey) + { + list.Add(bcpgInput.ReadPacket()); + } + + data = (InputStreamPacket)bcpgInput.ReadPacket(); + + for (int i = 0; i != list.Count; i++) + { + if (list[i] is SymmetricKeyEncSessionPacket) + { + list[i] = new PgpPbeEncryptedData((SymmetricKeyEncSessionPacket) list[i], data); + } + else + { + list[i] = new PgpPublicKeyEncryptedData((PublicKeyEncSessionPacket) list[i], data); + } + } + } + + public PgpEncryptedData this[int index] + { + get { return (PgpEncryptedData) list[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public object Get(int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return list.Count; } + } + + public int Count + { + get { return list.Count; } + } + + public bool IsEmpty + { + get { return list.Count == 0; } + } + + public IEnumerable GetEncryptedDataObjects() + { + return new EnumerableProxy(list); + } + } +} diff --git a/crypto/src/openpgp/PgpException.cs b/crypto/src/openpgp/PgpException.cs new file mode 100644 index 000000000..378b16a56 --- /dev/null +++ b/crypto/src/openpgp/PgpException.cs @@ -0,0 +1,22 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Generic exception class for PGP encoding/decoding problems. +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PgpException + : Exception + { + public PgpException() : base() {} + public PgpException(string message) : base(message) {} + public PgpException(string message, Exception exception) : base(message, exception) {} + + [Obsolete("Use InnerException property")] + public Exception UnderlyingException + { + get { return InnerException; } + } + } +} diff --git a/crypto/src/openpgp/PgpExperimental.cs b/crypto/src/openpgp/PgpExperimental.cs new file mode 100644 index 000000000..8518335a1 --- /dev/null +++ b/crypto/src/openpgp/PgpExperimental.cs @@ -0,0 +1,16 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public class PgpExperimental + : PgpObject + { + private readonly ExperimentalPacket p; + + public PgpExperimental( + BcpgInputStream bcpgIn) + { + p = (ExperimentalPacket) bcpgIn.ReadPacket(); + } + } +} diff --git a/crypto/src/openpgp/PgpKeyFlags.cs b/crypto/src/openpgp/PgpKeyFlags.cs new file mode 100644 index 000000000..ea1800606 --- /dev/null +++ b/crypto/src/openpgp/PgpKeyFlags.cs @@ -0,0 +1,13 @@ +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Key flag values for the KeyFlags subpacket. + public abstract class PgpKeyFlags + { + public const int CanCertify = 0x01; // This key may be used to certify other keys. + public const int CanSign = 0x02; // This key may be used to sign data. + public const int CanEncryptCommunications = 0x04; // This key may be used to encrypt communications. + public const int CanEncryptStorage = 0x08; // This key may be used to encrypt storage. + public const int MaybeSplit = 0x10; // The private component of this key may have been split by a secret-sharing mechanism. + public const int MaybeShared = 0x80; // The private component of this key may be in the possession of more than one person. + } +} diff --git a/crypto/src/openpgp/PgpKeyPair.cs b/crypto/src/openpgp/PgpKeyPair.cs new file mode 100644 index 000000000..6efb03a42 --- /dev/null +++ b/crypto/src/openpgp/PgpKeyPair.cs @@ -0,0 +1,67 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// General class to handle JCA key pairs and convert them into OpenPGP ones. + ///

    + /// A word for the unwary, the KeyId for an OpenPGP public key is calculated from + /// a hash that includes the time of creation, if you pass a different date to the + /// constructor below with the same public private key pair the KeyIs will not be the + /// same as for previous generations of the key, so ideally you only want to do + /// this once. + ///

    + ///
    + public class PgpKeyPair + { + private readonly PgpPublicKey pub; + private readonly PgpPrivateKey priv; + + public PgpKeyPair( + PublicKeyAlgorithmTag algorithm, + AsymmetricCipherKeyPair keyPair, + DateTime time) + : this(algorithm, keyPair.Public, keyPair.Private, time) + { + } + + public PgpKeyPair( + PublicKeyAlgorithmTag algorithm, + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey, + DateTime time) + { + this.pub = new PgpPublicKey(algorithm, pubKey, time); + this.priv = new PgpPrivateKey(privKey, pub.KeyId); + } + + /// Create a key pair from a PgpPrivateKey and a PgpPublicKey. + /// The public key. + /// The private key. + public PgpKeyPair( + PgpPublicKey pub, + PgpPrivateKey priv) + { + this.pub = pub; + this.priv = priv; + } + + /// The keyId associated with this key pair. + public long KeyId + { + get { return pub.KeyId; } + } + + public PgpPublicKey PublicKey + { + get { return pub; } + } + + public PgpPrivateKey PrivateKey + { + get { return priv; } + } + } +} diff --git a/crypto/src/openpgp/PgpKeyRingGenerator.cs b/crypto/src/openpgp/PgpKeyRingGenerator.cs new file mode 100644 index 000000000..e85fc2eef --- /dev/null +++ b/crypto/src/openpgp/PgpKeyRingGenerator.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Generator for a PGP master and subkey ring. + /// This class will generate both the secret and public key rings + /// + public class PgpKeyRingGenerator + { + private IList keys = Platform.CreateArrayList(); + private string id; + private SymmetricKeyAlgorithmTag encAlgorithm; + private int certificationLevel; + private char[] passPhrase; + private bool useSha1; + private PgpKeyPair masterKey; + private PgpSignatureSubpacketVector hashedPacketVector; + private PgpSignatureSubpacketVector unhashedPacketVector; + private SecureRandom rand; + + /// + /// Create a new key ring generator using old style checksumming. It is recommended to use + /// SHA1 checksumming where possible. + /// + /// The certification level for keys on this ring. + /// The master key pair. + /// The id to be associated with the ring. + /// The algorithm to be used to protect secret keys. + /// The passPhrase to be used to protect secret keys. + /// Packets to be included in the certification hash. + /// Packets to be attached unhashed to the certification. + /// input secured random. + public PgpKeyRingGenerator( + int certificationLevel, + PgpKeyPair masterKey, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + : this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand) + { + } + + /// + /// Create a new key ring generator. + /// + /// The certification level for keys on this ring. + /// The master key pair. + /// The id to be associated with the ring. + /// The algorithm to be used to protect secret keys. + /// The passPhrase to be used to protect secret keys. + /// Checksum the secret keys with SHA1 rather than the older 16 bit checksum. + /// Packets to be included in the certification hash. + /// Packets to be attached unhashed to the certification. + /// input secured random. + public PgpKeyRingGenerator( + int certificationLevel, + PgpKeyPair masterKey, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + bool useSha1, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + { + this.certificationLevel = certificationLevel; + this.masterKey = masterKey; + this.id = id; + this.encAlgorithm = encAlgorithm; + this.passPhrase = passPhrase; + this.useSha1 = useSha1; + this.hashedPacketVector = hashedPackets; + this.unhashedPacketVector = unhashedPackets; + this.rand = rand; + + keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)); + } + + /// Add a subkey to the key ring to be generated with default certification. + public void AddSubKey( + PgpKeyPair keyPair) + { + AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector); + } + + /// + /// Add a subkey with specific hashed and unhashed packets associated with it and + /// default certification. + /// + /// Public/private key pair. + /// Hashed packet values to be included in certification. + /// Unhashed packets values to be included in certification. + /// + public void AddSubKey( + PgpKeyPair keyPair, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets) + { + try + { + PgpSignatureGenerator sGen = new PgpSignatureGenerator( + masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + + // + // Generate the certification + // + sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey); + + sGen.SetHashedSubpackets(hashedPackets); + sGen.SetUnhashedSubpackets(unhashedPackets); + + IList subSigs = Platform.CreateArrayList(); + + subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); + + keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand)); + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("exception adding subkey: ", e); + } + } + + /// Return the secret key ring. + public PgpSecretKeyRing GenerateSecretKeyRing() + { + return new PgpSecretKeyRing(keys); + } + + /// Return the public key ring that corresponds to the secret key ring. + public PgpPublicKeyRing GeneratePublicKeyRing() + { + IList pubKeys = Platform.CreateArrayList(); + + IEnumerator enumerator = keys.GetEnumerator(); + enumerator.MoveNext(); + + PgpSecretKey pgpSecretKey = (PgpSecretKey) enumerator.Current; + pubKeys.Add(pgpSecretKey.PublicKey); + + while (enumerator.MoveNext()) + { + pgpSecretKey = (PgpSecretKey) enumerator.Current; + + PgpPublicKey k = new PgpPublicKey(pgpSecretKey.PublicKey); + k.publicPk = new PublicSubkeyPacket( + k.Algorithm, k.CreationTime, k.publicPk.Key); + + pubKeys.Add(k); + } + + return new PgpPublicKeyRing(pubKeys); + } + } +} diff --git a/crypto/src/openpgp/PgpKeyValidationException.cs b/crypto/src/openpgp/PgpKeyValidationException.cs new file mode 100644 index 000000000..d6419b27b --- /dev/null +++ b/crypto/src/openpgp/PgpKeyValidationException.cs @@ -0,0 +1,18 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Thrown if the key checksum is invalid. + /// +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PgpKeyValidationException + : PgpException + { + public PgpKeyValidationException() : base() {} + public PgpKeyValidationException(string message) : base(message) {} + public PgpKeyValidationException(string message, Exception exception) : base(message, exception) {} + } +} diff --git a/crypto/src/openpgp/PgpLiteralData.cs b/crypto/src/openpgp/PgpLiteralData.cs new file mode 100644 index 000000000..79bbc3984 --- /dev/null +++ b/crypto/src/openpgp/PgpLiteralData.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Class for processing literal data objects. + public class PgpLiteralData + : PgpObject + { + public const char Binary = 'b'; + public const char Text = 't'; + public const char Utf8 = 'u'; + + /// The special name indicating a "for your eyes only" packet. + public const string Console = "_CONSOLE"; + + private LiteralDataPacket data; + + public PgpLiteralData( + BcpgInputStream bcpgInput) + { + data = (LiteralDataPacket) bcpgInput.ReadPacket(); + } + + /// The format of the data stream - Binary or Text + public int Format + { + get { return data.Format; } + } + + /// The file name that's associated with the data stream. + public string FileName + { + get { return data.FileName; } + } + + /// Return the file name as an unintrepreted byte array. + public byte[] GetRawFileName() + { + return data.GetRawFileName(); + } + + /// The modification time for the file. + public DateTime ModificationTime + { + get { return DateTimeUtilities.UnixMsToDateTime(data.ModificationTime); } + } + + /// The raw input stream for the data stream. + public Stream GetInputStream() + { + return data.GetInputStream(); + } + + /// The input stream representing the data stream. + public Stream GetDataStream() + { + return GetInputStream(); + } + } +} diff --git a/crypto/src/openpgp/PgpLiteralDataGenerator.cs b/crypto/src/openpgp/PgpLiteralDataGenerator.cs new file mode 100644 index 000000000..3b1f2fe74 --- /dev/null +++ b/crypto/src/openpgp/PgpLiteralDataGenerator.cs @@ -0,0 +1,180 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Class for producing literal data packets. + public class PgpLiteralDataGenerator + : IStreamGenerator + { + public const char Binary = PgpLiteralData.Binary; + public const char Text = PgpLiteralData.Text; + public const char Utf8 = PgpLiteralData.Utf8; + + /// The special name indicating a "for your eyes only" packet. + public const string Console = PgpLiteralData.Console; + + private BcpgOutputStream pkOut; + private bool oldFormat; + + public PgpLiteralDataGenerator() + { + } + + /// + /// Generates literal data objects in the old format. + /// This is important if you need compatibility with PGP 2.6.x. + /// + /// If true, uses old format. + public PgpLiteralDataGenerator( + bool oldFormat) + { + this.oldFormat = oldFormat; + } + + private void WriteHeader( + BcpgOutputStream outStr, + char format, + byte[] encName, + long modificationTime) + { + outStr.Write( + (byte) format, + (byte) encName.Length); + + outStr.Write(encName); + + long modDate = modificationTime / 1000L; + + outStr.Write( + (byte)(modDate >> 24), + (byte)(modDate >> 16), + (byte)(modDate >> 8), + (byte)modDate); + } + + /// + ///

    + /// Open a literal data packet, returning a stream to store the data inside the packet. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///
    + /// The stream we want the packet in. + /// The format we are using. + /// The name of the 'file'. + /// The length of the data we will write. + /// The time of last modification we want stored. + public Stream Open( + Stream outStr, + char format, + string name, + long length, + DateTime modificationTime) + { + if (pkOut != null) + throw new InvalidOperationException("generator already in open state"); + if (outStr == null) + throw new ArgumentNullException("outStr"); + + // Do this first, since it might throw an exception + long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime); + + byte[] encName = Strings.ToUtf8ByteArray(name); + + pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, + length + 2 + encName.Length + 4, oldFormat); + + WriteHeader(pkOut, format, encName, unixMs); + + return new WrappedGeneratorStream(this, pkOut); + } + + /// + ///

    + /// Open a literal data packet, returning a stream to store the data inside the packet, + /// as an indefinite length stream. The stream is written out as a series of partial + /// packets with a chunk size determined by the size of the passed in buffer. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///

    + /// Note: if the buffer is not a power of 2 in length only the largest power of 2 + /// bytes worth of the buffer will be used.

    + ///
    + /// The stream we want the packet in. + /// The format we are using. + /// The name of the 'file'. + /// The time of last modification we want stored. + /// The buffer to use for collecting data to put into chunks. + public Stream Open( + Stream outStr, + char format, + string name, + DateTime modificationTime, + byte[] buffer) + { + if (pkOut != null) + throw new InvalidOperationException("generator already in open state"); + if (outStr == null) + throw new ArgumentNullException("outStr"); + + // Do this first, since it might throw an exception + long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime); + + byte[] encName = Strings.ToUtf8ByteArray(name); + + pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, buffer); + + WriteHeader(pkOut, format, encName, unixMs); + + return new WrappedGeneratorStream(this, pkOut); + } + + /// + ///

    + /// Open a literal data packet for the passed in FileInfo object, returning + /// an output stream for saving the file contents. + ///

    + ///

    + /// The stream created can be closed off by either calling Close() + /// on the stream or Close() on the generator. Closing the returned + /// stream does not close off the Stream parameter outStr. + ///

    + ///
    + /// The stream we want the packet in. + /// The format we are using. + /// The FileInfo object containg the packet details. + public Stream Open( + Stream outStr, + char format, + FileInfo file) + { + return Open(outStr, format, file.Name, file.Length, file.LastWriteTime); + } + + /// + /// Close the literal data packet - this is equivalent to calling Close() + /// on the stream returned by the Open() method. + /// + public void Close() + { + if (pkOut != null) + { + pkOut.Finish(); + pkOut.Flush(); + pkOut = null; + } + } + } +} diff --git a/crypto/src/openpgp/PgpMarker.cs b/crypto/src/openpgp/PgpMarker.cs new file mode 100644 index 000000000..733e4e959 --- /dev/null +++ b/crypto/src/openpgp/PgpMarker.cs @@ -0,0 +1,18 @@ +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// A PGP marker packet - in general these should be ignored other than where + /// the idea is to preserve the original input stream. + /// + public class PgpMarker + : PgpObject + { + private readonly MarkerPacket p; + + public PgpMarker( + BcpgInputStream bcpgIn) + { + p = (MarkerPacket) bcpgIn.ReadPacket(); + } + } +} diff --git a/crypto/src/openpgp/PgpObjectFactory.cs b/crypto/src/openpgp/PgpObjectFactory.cs new file mode 100644 index 000000000..c5c6fcb68 --- /dev/null +++ b/crypto/src/openpgp/PgpObjectFactory.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// General class for reading a PGP object stream. + ///

    + /// Note: if this class finds a PgpPublicKey or a PgpSecretKey it + /// will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each + /// key found. If all you are trying to do is read a key ring file use + /// either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.

    + ///
    + public class PgpObjectFactory + { + private readonly BcpgInputStream bcpgIn; + + public PgpObjectFactory( + Stream inputStream) + { + this.bcpgIn = BcpgInputStream.Wrap(inputStream); + } + + public PgpObjectFactory( + byte[] bytes) + : this(new MemoryStream(bytes, false)) + { + } + + /// Return the next object in the stream, or null if the end is reached. + /// On a parse error + public PgpObject NextPgpObject() + { + PacketTag tag = bcpgIn.NextPacketTag(); + + if ((int) tag == -1) return null; + + switch (tag) + { + case PacketTag.Signature: + { + IList l = Platform.CreateArrayList(); + + while (bcpgIn.NextPacketTag() == PacketTag.Signature) + { + try + { + l.Add(new PgpSignature(bcpgIn)); + } + catch (PgpException e) + { + throw new IOException("can't create signature object: " + e); + } + } + + PgpSignature[] sigs = new PgpSignature[l.Count]; + for (int i = 0; i < l.Count; ++i) + { + sigs[i] = (PgpSignature)l[i]; + } + return new PgpSignatureList(sigs); + } + case PacketTag.SecretKey: + try + { + return new PgpSecretKeyRing(bcpgIn); + } + catch (PgpException e) + { + throw new IOException("can't create secret key object: " + e); + } + case PacketTag.PublicKey: + return new PgpPublicKeyRing(bcpgIn); + // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing +// case PacketTag.PublicSubkey: +// return PgpPublicKeyRing.ReadSubkey(bcpgIn); + case PacketTag.CompressedData: + return new PgpCompressedData(bcpgIn); + case PacketTag.LiteralData: + return new PgpLiteralData(bcpgIn); + case PacketTag.PublicKeyEncryptedSession: + case PacketTag.SymmetricKeyEncryptedSessionKey: + return new PgpEncryptedDataList(bcpgIn); + case PacketTag.OnePassSignature: + { + IList l = Platform.CreateArrayList(); + + while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature) + { + try + { + l.Add(new PgpOnePassSignature(bcpgIn)); + } + catch (PgpException e) + { + throw new IOException("can't create one pass signature object: " + e); + } + } + + PgpOnePassSignature[] sigs = new PgpOnePassSignature[l.Count]; + for (int i = 0; i < l.Count; ++i) + { + sigs[i] = (PgpOnePassSignature)l[i]; + } + return new PgpOnePassSignatureList(sigs); + } + case PacketTag.Marker: + return new PgpMarker(bcpgIn); + case PacketTag.Experimental1: + case PacketTag.Experimental2: + case PacketTag.Experimental3: + case PacketTag.Experimental4: + return new PgpExperimental(bcpgIn); + } + + throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag()); + } + + [Obsolete("Use NextPgpObject() instead")] + public object NextObject() + { + return NextPgpObject(); + } + + /// + /// Return all available objects in a list. + /// + /// An IList containing all objects from this factory, in order. + public IList AllPgpObjects() + { + IList result = Platform.CreateArrayList(); + PgpObject pgpObject; + while ((pgpObject = NextPgpObject()) != null) + { + result.Add(pgpObject); + } + return result; + } + } +} diff --git a/crypto/src/openpgp/PgpOnePassSignature.cs b/crypto/src/openpgp/PgpOnePassSignature.cs new file mode 100644 index 000000000..68fc5994d --- /dev/null +++ b/crypto/src/openpgp/PgpOnePassSignature.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A one pass signature object. + public class PgpOnePassSignature + { + private OnePassSignaturePacket sigPack; + private int signatureType; + private ISigner sig; + private byte lastb; + + internal PgpOnePassSignature( + BcpgInputStream bcpgInput) + : this((OnePassSignaturePacket) bcpgInput.ReadPacket()) + { + } + + internal PgpOnePassSignature( + OnePassSignaturePacket sigPack) + { + this.sigPack = sigPack; + this.signatureType = sigPack.SignatureType; + } + + /// Initialise the signature object for verification. + public void InitVerify( + PgpPublicKey pubKey) + { + lastb = 0; + + try + { + sig = SignerUtilities.GetSigner( + PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm)); + } + catch (Exception e) + { + throw new PgpException("can't set up signature object.", e); + } + + try + { + sig.Init(false, pubKey.GetKey()); + } + catch (InvalidKeyException e) + { + throw new PgpException("invalid key.", e); + } + } + + public void Update( + byte b) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + doCanonicalUpdateByte(b); + } + else + { + sig.Update(b); + } + } + + private void doCanonicalUpdateByte( + byte b) + { + if (b == '\r') + { + doUpdateCRLF(); + } + else if (b == '\n') + { + if (lastb != '\r') + { + doUpdateCRLF(); + } + } + else + { + sig.Update(b); + } + + lastb = b; + } + + private void doUpdateCRLF() + { + sig.Update((byte)'\r'); + sig.Update((byte)'\n'); + } + + public void Update( + byte[] bytes) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + for (int i = 0; i != bytes.Length; i++) + { + doCanonicalUpdateByte(bytes[i]); + } + } + else + { + sig.BlockUpdate(bytes, 0, bytes.Length); + } + } + + public void Update( + byte[] bytes, + int off, + int length) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + int finish = off + length; + + for (int i = off; i != finish; i++) + { + doCanonicalUpdateByte(bytes[i]); + } + } + else + { + sig.BlockUpdate(bytes, off, length); + } + } + + /// Verify the calculated signature against the passed in PgpSignature. + public bool Verify( + PgpSignature pgpSig) + { + byte[] trailer = pgpSig.GetSignatureTrailer(); + + sig.BlockUpdate(trailer, 0, trailer.Length); + + return sig.VerifySignature(pgpSig.GetSignature()); + } + + public long KeyId + { + get { return sigPack.KeyId; } + } + + public int SignatureType + { + get { return sigPack.SignatureType; } + } + + public HashAlgorithmTag HashAlgorithm + { + get { return sigPack.HashAlgorithm; } + } + + public PublicKeyAlgorithmTag KeyAlgorithm + { + get { return sigPack.KeyAlgorithm; } + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + BcpgOutputStream.Wrap(outStr).WritePacket(sigPack); + } + } +} diff --git a/crypto/src/openpgp/PgpOnePassSignatureList.cs b/crypto/src/openpgp/PgpOnePassSignatureList.cs new file mode 100644 index 000000000..37c4288e3 --- /dev/null +++ b/crypto/src/openpgp/PgpOnePassSignatureList.cs @@ -0,0 +1,51 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Holder for a list of PgpOnePassSignature objects. + public class PgpOnePassSignatureList + : PgpObject + { + private readonly PgpOnePassSignature[] sigs; + + public PgpOnePassSignatureList( + PgpOnePassSignature[] sigs) + { + this.sigs = (PgpOnePassSignature[]) sigs.Clone(); + } + + public PgpOnePassSignatureList( + PgpOnePassSignature sig) + { + this.sigs = new PgpOnePassSignature[]{ sig }; + } + + public PgpOnePassSignature this[int index] + { + get { return sigs[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public PgpOnePassSignature Get( + int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return sigs.Length; } + } + + public int Count + { + get { return sigs.Length; } + } + + public bool IsEmpty + { + get { return (sigs.Length == 0); } + } + } +} diff --git a/crypto/src/openpgp/PgpPbeEncryptedData.cs b/crypto/src/openpgp/PgpPbeEncryptedData.cs new file mode 100644 index 000000000..c5fe89407 --- /dev/null +++ b/crypto/src/openpgp/PgpPbeEncryptedData.cs @@ -0,0 +1,135 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A password based encryption object. + public class PgpPbeEncryptedData + : PgpEncryptedData + { + private readonly SymmetricKeyEncSessionPacket keyData; + + internal PgpPbeEncryptedData( + SymmetricKeyEncSessionPacket keyData, + InputStreamPacket encData) + : base(encData) + { + this.keyData = keyData; + } + + /// Return the raw input stream for the data stream. + public override Stream GetInputStream() + { + return encData.GetInputStream(); + } + + /// Return the decrypted input stream, using the passed in passphrase. + public Stream GetDataStream( + char[] passPhrase) + { + try + { + SymmetricKeyAlgorithmTag keyAlgorithm = keyData.EncAlgorithm; + + KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase( + keyAlgorithm, keyData.S2k, passPhrase); + + + byte[] secKeyData = keyData.GetSecKeyData(); + if (secKeyData != null && secKeyData.Length > 0) + { + IBufferedCipher keyCipher = CipherUtilities.GetCipher( + PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/CFB/NoPadding"); + + keyCipher.Init(false, + new ParametersWithIV(key, new byte[keyCipher.GetBlockSize()])); + + byte[] keyBytes = keyCipher.DoFinal(secKeyData); + + keyAlgorithm = (SymmetricKeyAlgorithmTag) keyBytes[0]; + + key = ParameterUtilities.CreateKeyParameter( + PgpUtilities.GetSymmetricCipherName(keyAlgorithm), + keyBytes, 1, keyBytes.Length - 1); + } + + + IBufferedCipher c = CreateStreamCipher(keyAlgorithm); + + byte[] iv = new byte[c.GetBlockSize()]; + + c.Init(false, new ParametersWithIV(key, iv)); + + encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c, null)); + + if (encData is SymmetricEncIntegrityPacket) + { + truncStream = new TruncatedStream(encStream); + + string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); + IDigest digest = DigestUtilities.GetDigest(digestName); + + encStream = new DigestStream(truncStream, digest, null); + } + + if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length) + throw new EndOfStreamException("unexpected end of stream."); + + int v1 = encStream.ReadByte(); + int v2 = encStream.ReadByte(); + + if (v1 < 0 || v2 < 0) + throw new EndOfStreamException("unexpected end of stream."); + + + // Note: the oracle attack on the "quick check" bytes is not deemed + // a security risk for PBE (see PgpPublicKeyEncryptedData) + + bool repeatCheckPassed = + iv[iv.Length - 2] == (byte)v1 + && iv[iv.Length - 1] == (byte)v2; + + // Note: some versions of PGP appear to produce 0 for the extra + // bytes rather than repeating the two previous bytes + bool zeroesCheckPassed = + v1 == 0 + && v2 == 0; + + if (!repeatCheckPassed && !zeroesCheckPassed) + { + throw new PgpDataValidationException("quick check failed."); + } + + + return encStream; + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception creating cipher", e); + } + } + + private IBufferedCipher CreateStreamCipher( + SymmetricKeyAlgorithmTag keyAlgorithm) + { + string mode = (encData is SymmetricEncIntegrityPacket) + ? "CFB" + : "OpenPGPCFB"; + + string cName = PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + + "/" + mode + "/NoPadding"; + + return CipherUtilities.GetCipher(cName); + } + } +} diff --git a/crypto/src/openpgp/PgpPrivateKey.cs b/crypto/src/openpgp/PgpPrivateKey.cs new file mode 100644 index 000000000..154c87cd7 --- /dev/null +++ b/crypto/src/openpgp/PgpPrivateKey.cs @@ -0,0 +1,42 @@ +using System; + +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// General class to contain a private key for use with other OpenPGP objects. + public class PgpPrivateKey + { + private readonly long keyId; + private readonly AsymmetricKeyParameter privateKey; + + /// + /// Create a PgpPrivateKey from a regular private key and the ID of its + /// associated public key. + /// + /// Private key to use. + /// ID of the corresponding public key. + public PgpPrivateKey( + AsymmetricKeyParameter privateKey, + long keyId) + { + if (!privateKey.IsPrivate) + throw new ArgumentException("Expected a private key", "privateKey"); + + this.privateKey = privateKey; + this.keyId = keyId; + } + + /// The keyId associated with the contained private key. + public long KeyId + { + get { return keyId; } + } + + /// The contained private key. + public AsymmetricKeyParameter Key + { + get { return privateKey; } + } + } +} diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs new file mode 100644 index 000000000..b0720146c --- /dev/null +++ b/crypto/src/openpgp/PgpPublicKey.cs @@ -0,0 +1,890 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// General class to handle a PGP public key object. + public class PgpPublicKey + { + private static readonly int[] MasterKeyCertificationTypes = new int[] + { + PgpSignature.PositiveCertification, + PgpSignature.CasualCertification, + PgpSignature.NoCertification, + PgpSignature.DefaultCertification + }; + + private long keyId; + private byte[] fingerprint; + private int keyStrength; + + internal PublicKeyPacket publicPk; + internal TrustPacket trustPk; + internal IList keySigs = Platform.CreateArrayList(); + internal IList ids = Platform.CreateArrayList(); + internal IList idTrusts = Platform.CreateArrayList(); + internal IList idSigs = Platform.CreateArrayList(); + internal IList subSigs; + + private void Init() + { + IBcpgKey key = publicPk.Key; + + if (publicPk.Version <= 3) + { + RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key; + + this.keyId = rK.Modulus.LongValue; + + try + { + IDigest digest = DigestUtilities.GetDigest("MD5"); + + byte[] bytes = rK.Modulus.ToByteArrayUnsigned(); + digest.BlockUpdate(bytes, 0, bytes.Length); + + bytes = rK.PublicExponent.ToByteArrayUnsigned(); + digest.BlockUpdate(bytes, 0, bytes.Length); + + this.fingerprint = DigestUtilities.DoFinal(digest); + } + //catch (NoSuchAlgorithmException) + catch (Exception e) + { + throw new IOException("can't find MD5", e); + } + + this.keyStrength = rK.Modulus.BitLength; + } + else + { + byte[] kBytes = publicPk.GetEncodedContents(); + + try + { + IDigest digest = DigestUtilities.GetDigest("SHA1"); + + digest.Update(0x99); + digest.Update((byte)(kBytes.Length >> 8)); + digest.Update((byte)kBytes.Length); + digest.BlockUpdate(kBytes, 0, kBytes.Length); + this.fingerprint = DigestUtilities.DoFinal(digest); + } + catch (Exception e) + { + throw new IOException("can't find SHA1", e); + } + + this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56) + | ((ulong)fingerprint[fingerprint.Length - 7] << 48) + | ((ulong)fingerprint[fingerprint.Length - 6] << 40) + | ((ulong)fingerprint[fingerprint.Length - 5] << 32) + | ((ulong)fingerprint[fingerprint.Length - 4] << 24) + | ((ulong)fingerprint[fingerprint.Length - 3] << 16) + | ((ulong)fingerprint[fingerprint.Length - 2] << 8) + | (ulong)fingerprint[fingerprint.Length - 1]); + + if (key is RsaPublicBcpgKey) + { + this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength; + } + else if (key is DsaPublicBcpgKey) + { + this.keyStrength = ((DsaPublicBcpgKey)key).P.BitLength; + } + else if (key is ElGamalPublicBcpgKey) + { + this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength; + } + } + } + + /// + /// Create a PgpPublicKey from the passed in lightweight one. + /// + /// + /// Note: the time passed in affects the value of the key's keyId, so you probably only want + /// to do this once for a lightweight key, or make sure you keep track of the time you used. + /// + /// Asymmetric algorithm type representing the public key. + /// Actual public key to associate. + /// Date of creation. + /// If pubKey is not public. + /// On key creation problem. + public PgpPublicKey( + PublicKeyAlgorithmTag algorithm, + AsymmetricKeyParameter pubKey, + DateTime time) + { + if (pubKey.IsPrivate) + throw new ArgumentException("Expected a public key", "pubKey"); + + IBcpgKey bcpgKey; + if (pubKey is RsaKeyParameters) + { + RsaKeyParameters rK = (RsaKeyParameters) pubKey; + + bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent); + } + else if (pubKey is DsaPublicKeyParameters) + { + DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey; + DsaParameters dP = dK.Parameters; + + bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y); + } + else if (pubKey is ElGamalPublicKeyParameters) + { + ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey; + ElGamalParameters eS = eK.Parameters; + + bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y); + } + else + { + throw new PgpException("unknown key class"); + } + + this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey); + this.ids = Platform.CreateArrayList(); + this.idSigs = Platform.CreateArrayList(); + + try + { + Init(); + } + catch (IOException e) + { + throw new PgpException("exception calculating keyId", e); + } + } + + /// Constructor for a sub-key. + internal PgpPublicKey( + PublicKeyPacket publicPk, + TrustPacket trustPk, + IList sigs) + { + this.publicPk = publicPk; + this.trustPk = trustPk; + this.subSigs = sigs; + + Init(); + } + + internal PgpPublicKey( + PgpPublicKey key, + TrustPacket trust, + IList subSigs) + { + this.publicPk = key.publicPk; + this.trustPk = trust; + this.subSigs = subSigs; + + this.fingerprint = key.fingerprint; + this.keyId = key.keyId; + this.keyStrength = key.keyStrength; + } + + /// Copy constructor. + /// The public key to copy. + internal PgpPublicKey( + PgpPublicKey pubKey) + { + this.publicPk = pubKey.publicPk; + + this.keySigs = Platform.CreateArrayList(pubKey.keySigs); + this.ids = Platform.CreateArrayList(pubKey.ids); + this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts); + this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count); + for (int i = 0; i != pubKey.idSigs.Count; i++) + { + this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i])); + } + + if (pubKey.subSigs != null) + { + this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count); + for (int i = 0; i != pubKey.subSigs.Count; i++) + { + this.subSigs.Add(pubKey.subSigs[i]); + } + } + + this.fingerprint = pubKey.fingerprint; + this.keyId = pubKey.keyId; + this.keyStrength = pubKey.keyStrength; + } + + internal PgpPublicKey( + PublicKeyPacket publicPk, + TrustPacket trustPk, + IList keySigs, + IList ids, + IList idTrusts, + IList idSigs) + { + this.publicPk = publicPk; + this.trustPk = trustPk; + this.keySigs = keySigs; + this.ids = ids; + this.idTrusts = idTrusts; + this.idSigs = idSigs; + + Init(); + } + + internal PgpPublicKey( + PublicKeyPacket publicPk, + IList ids, + IList idSigs) + { + this.publicPk = publicPk; + this.ids = ids; + this.idSigs = idSigs; + Init(); + } + + /// The version of this key. + public int Version + { + get { return publicPk.Version; } + } + + /// The creation time of this key. + public DateTime CreationTime + { + get { return publicPk.GetTime(); } + } + + /// The number of valid days from creation time - zero means no expiry. + public int ValidDays + { + get + { + if (publicPk.Version > 3) + { + return (int)(GetValidSeconds() / (24 * 60 * 60)); + } + + return publicPk.ValidDays; + } + } + + /// Return the trust data associated with the public key, if present. + /// A byte array with trust data, null otherwise. + public byte[] GetTrustData() + { + if (trustPk == null) + { + return null; + } + + return trustPk.GetLevelAndTrustAmount(); + } + + /// The number of valid seconds from creation time - zero means no expiry. + public long GetValidSeconds() + { + if (publicPk.Version > 3) + { + if (IsMasterKey) + { + for (int i = 0; i != MasterKeyCertificationTypes.Length; i++) + { + long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]); + + if (seconds >= 0) + { + return seconds; + } + } + } + else + { + long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding); + + if (seconds >= 0) + { + return seconds; + } + } + + return 0; + } + + return (long) publicPk.ValidDays * 24 * 60 * 60; + } + + private long GetExpirationTimeFromSig( + bool selfSigned, + int signatureType) + { + foreach (PgpSignature sig in GetSignaturesOfType(signatureType)) + { + if (!selfSigned || sig.KeyId == KeyId) + { + PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets(); + + if (hashed != null) + { + return hashed.GetKeyExpirationTime(); + } + + return 0; + } + } + + return -1; + } + + /// The keyId associated with the public key. + public long KeyId + { + get { return keyId; } + } + + /// The fingerprint of the key + public byte[] GetFingerprint() + { + return (byte[]) fingerprint.Clone(); + } + + /// + /// Check if this key has an algorithm type that makes it suitable to use for encryption. + /// + /// + /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for + /// determining the preferred use of the key. + /// + /// + /// true if this key algorithm is suitable for encryption. + /// + public bool IsEncryptionKey + { + get + { + switch (publicPk.Algorithm) + { + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + return true; + default: + return false; + } + } + } + + /// True, if this is a master key. + public bool IsMasterKey + { + get { return subSigs == null; } + } + + /// The algorithm code associated with the public key. + public PublicKeyAlgorithmTag Algorithm + { + get { return publicPk.Algorithm; } + } + + /// The strength of the key in bits. + public int BitStrength + { + get { return keyStrength; } + } + + /// The public key contained in the object. + /// A lightweight public key. + /// If the key algorithm is not recognised. + public AsymmetricKeyParameter GetKey() + { + try + { + switch (publicPk.Algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key; + return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent); + case PublicKeyAlgorithmTag.Dsa: + DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key; + return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G)); + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key; + return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G)); + default: + throw new PgpException("unknown public key algorithm encountered"); + } + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("exception constructing public key", e); + } + } + + /// Allows enumeration of any user IDs associated with the key. + /// An IEnumerable of string objects. + public IEnumerable GetUserIds() + { + IList temp = Platform.CreateArrayList(); + + foreach (object o in ids) + { + if (o is string) + { + temp.Add(o); + } + } + + return new EnumerableProxy(temp); + } + + /// Allows enumeration of any user attribute vectors associated with the key. + /// An IEnumerable of PgpUserAttributeSubpacketVector objects. + public IEnumerable GetUserAttributes() + { + IList temp = Platform.CreateArrayList(); + + foreach (object o in ids) + { + if (o is PgpUserAttributeSubpacketVector) + { + temp.Add(o); + } + } + + return new EnumerableProxy(temp); + } + + /// Allows enumeration of any signatures associated with the passed in id. + /// The ID to be matched. + /// An IEnumerable of PgpSignature objects. + public IEnumerable GetSignaturesForId( + string id) + { + if (id == null) + throw new ArgumentNullException("id"); + + for (int i = 0; i != ids.Count; i++) + { + if (id.Equals(ids[i])) + { + return new EnumerableProxy((IList)idSigs[i]); + } + } + + return null; + } + + /// Allows enumeration of signatures associated with the passed in user attributes. + /// The vector of user attributes to be matched. + /// An IEnumerable of PgpSignature objects. + public IEnumerable GetSignaturesForUserAttribute( + PgpUserAttributeSubpacketVector userAttributes) + { + for (int i = 0; i != ids.Count; i++) + { + if (userAttributes.Equals(ids[i])) + { + return new EnumerableProxy((IList) idSigs[i]); + } + } + + return null; + } + + /// Allows enumeration of signatures of the passed in type that are on this key. + /// The type of the signature to be returned. + /// An IEnumerable of PgpSignature objects. + public IEnumerable GetSignaturesOfType( + int signatureType) + { + IList temp = Platform.CreateArrayList(); + + foreach (PgpSignature sig in GetSignatures()) + { + if (sig.SignatureType == signatureType) + { + temp.Add(sig); + } + } + + return new EnumerableProxy(temp); + } + + /// Allows enumeration of all signatures/certifications associated with this key. + /// An IEnumerable with all signatures/certifications. + public IEnumerable GetSignatures() + { + IList sigs; + if (subSigs != null) + { + sigs = subSigs; + } + else + { + sigs = Platform.CreateArrayList(keySigs); + + foreach (ICollection extraSigs in idSigs) + { + CollectionUtilities.AddRange(sigs, extraSigs); + } + } + + return new EnumerableProxy(sigs); + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + Encode(bOut); + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr); + + bcpgOut.WritePacket(publicPk); + if (trustPk != null) + { + bcpgOut.WritePacket(trustPk); + } + + if (subSigs == null) // not a sub-key + { + foreach (PgpSignature keySig in keySigs) + { + keySig.Encode(bcpgOut); + } + + for (int i = 0; i != ids.Count; i++) + { + if (ids[i] is string) + { + string id = (string) ids[i]; + + bcpgOut.WritePacket(new UserIdPacket(id)); + } + else + { + PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i]; + bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray())); + } + + if (idTrusts[i] != null) + { + bcpgOut.WritePacket((ContainedPacket)idTrusts[i]); + } + + foreach (PgpSignature sig in (IList) idSigs[i]) + { + sig.Encode(bcpgOut); + } + } + } + else + { + foreach (PgpSignature subSig in subSigs) + { + subSig.Encode(bcpgOut); + } + } + } + + /// Check whether this (sub)key has a revocation signature on it. + /// True, if this (sub)key has been revoked. + public bool IsRevoked() + { + int ns = 0; + bool revoked = false; + if (IsMasterKey) // Master key + { + while (!revoked && (ns < keySigs.Count)) + { + if (((PgpSignature)keySigs[ns++]).SignatureType == PgpSignature.KeyRevocation) + { + revoked = true; + } + } + } + else // Sub-key + { + while (!revoked && (ns < subSigs.Count)) + { + if (((PgpSignature)subSigs[ns++]).SignatureType == PgpSignature.SubkeyRevocation) + { + revoked = true; + } + } + } + return revoked; + } + + /// Add a certification for an id to the given public key. + /// The key the certification is to be added to. + /// The ID the certification is associated with. + /// The new certification. + /// The re-certified key. + public static PgpPublicKey AddCertification( + PgpPublicKey key, + string id, + PgpSignature certification) + { + return AddCert(key, id, certification); + } + + /// Add a certification for the given UserAttributeSubpackets to the given public key. + /// The key the certification is to be added to. + /// The attributes the certification is associated with. + /// The new certification. + /// The re-certified key. + public static PgpPublicKey AddCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes, + PgpSignature certification) + { + return AddCert(key, userAttributes, certification); + } + + private static PgpPublicKey AddCert( + PgpPublicKey key, + object id, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + IList sigList = null; + + for (int i = 0; i != returnKey.ids.Count; i++) + { + if (id.Equals(returnKey.ids[i])) + { + sigList = (IList) returnKey.idSigs[i]; + } + } + + if (sigList != null) + { + sigList.Add(certification); + } + else + { + sigList = Platform.CreateArrayList(); + sigList.Add(certification); + returnKey.ids.Add(id); + returnKey.idTrusts.Add(null); + returnKey.idSigs.Add(sigList); + } + + return returnKey; + } + + /// + /// Remove any certifications associated with a user attribute subpacket on a key. + /// + /// The key the certifications are to be removed from. + /// The attributes to be removed. + /// + /// The re-certified key, or null if the user attribute subpacket was not found on the key. + /// + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes) + { + return RemoveCert(key, userAttributes); + } + + /// Remove any certifications associated with a given ID on a key. + /// The key the certifications are to be removed from. + /// The ID that is to be removed. + /// The re-certified key, or null if the ID was not found on the key. + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + string id) + { + return RemoveCert(key, id); + } + + private static PgpPublicKey RemoveCert( + PgpPublicKey key, + object id) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + bool found = false; + + for (int i = 0; i < returnKey.ids.Count; i++) + { + if (id.Equals(returnKey.ids[i])) + { + found = true; + returnKey.ids.RemoveAt(i); + returnKey.idTrusts.RemoveAt(i); + returnKey.idSigs.RemoveAt(i); + } + } + + return found ? returnKey : null; + } + + /// Remove a certification associated with a given ID on a key. + /// The key the certifications are to be removed from. + /// The ID that the certfication is to be removed from. + /// The certfication to be removed. + /// The re-certified key, or null if the certification was not found. + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + string id, + PgpSignature certification) + { + return RemoveCert(key, id, certification); + } + + /// Remove a certification associated with a given user attributes on a key. + /// The key the certifications are to be removed from. + /// The user attributes that the certfication is to be removed from. + /// The certification to be removed. + /// The re-certified key, or null if the certification was not found. + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes, + PgpSignature certification) + { + return RemoveCert(key, userAttributes, certification); + } + + private static PgpPublicKey RemoveCert( + PgpPublicKey key, + object id, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + bool found = false; + + for (int i = 0; i < returnKey.ids.Count; i++) + { + if (id.Equals(returnKey.ids[i])) + { + IList certs = (IList) returnKey.idSigs[i]; + found = certs.Contains(certification); + + if (found) + { + certs.Remove(certification); + } + } + } + + return found ? returnKey : null; + } + + /// Add a revocation or some other key certification to a key. + /// The key the revocation is to be added to. + /// The key signature to be added. + /// The new changed public key object. + public static PgpPublicKey AddCertification( + PgpPublicKey key, + PgpSignature certification) + { + if (key.IsMasterKey) + { + if (certification.SignatureType == PgpSignature.SubkeyRevocation) + { + throw new ArgumentException("signature type incorrect for master key revocation."); + } + } + else + { + if (certification.SignatureType == PgpSignature.KeyRevocation) + { + throw new ArgumentException("signature type incorrect for sub-key revocation."); + } + } + + PgpPublicKey returnKey = new PgpPublicKey(key); + + if (returnKey.subSigs != null) + { + returnKey.subSigs.Add(certification); + } + else + { + returnKey.keySigs.Add(certification); + } + + return returnKey; + } + + /// Remove a certification from the key. + /// The key the certifications are to be removed from. + /// The certfication to be removed. + /// The modified key, null if the certification was not found. + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + IList sigs = returnKey.subSigs != null + ? returnKey.subSigs + : returnKey.keySigs; + +// bool found = sigs.Remove(certification); + int pos = sigs.IndexOf(certification); + bool found = pos >= 0; + + if (found) + { + sigs.RemoveAt(pos); + } + else + { + foreach (String id in key.GetUserIds()) + { + foreach (object sig in key.GetSignaturesForId(id)) + { + // TODO Is this the right type of equality test? + if (certification == sig) + { + found = true; + returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); + } + } + } + + if (!found) + { + foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes()) + { + foreach (object sig in key.GetSignaturesForUserAttribute(id)) + { + // TODO Is this the right type of equality test? + if (certification == sig) + { + found = true; + returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); + } + } + } + } + } + + return returnKey; + } + } +} diff --git a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs new file mode 100644 index 000000000..b6504cbcd --- /dev/null +++ b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs @@ -0,0 +1,252 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A public key encrypted data object. + public class PgpPublicKeyEncryptedData + : PgpEncryptedData + { + private PublicKeyEncSessionPacket keyData; + + internal PgpPublicKeyEncryptedData( + PublicKeyEncSessionPacket keyData, + InputStreamPacket encData) + : base(encData) + { + this.keyData = keyData; + } + + private static IBufferedCipher GetKeyCipher( + PublicKeyAlgorithmTag algorithm) + { + try + { + switch (algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + return CipherUtilities.GetCipher("RSA//PKCS1Padding"); + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + return CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding"); + default: + throw new PgpException("unknown asymmetric algorithm: " + algorithm); + } + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception creating cipher", e); + } + } + + private bool ConfirmCheckSum( + byte[] sessionInfo) + { + int check = 0; + + for (int i = 1; i != sessionInfo.Length - 2; i++) + { + check += sessionInfo[i] & 0xff; + } + + return (sessionInfo[sessionInfo.Length - 2] == (byte)(check >> 8)) + && (sessionInfo[sessionInfo.Length - 1] == (byte)(check)); + } + + /// The key ID for the key used to encrypt the data. + public long KeyId + { + get { return keyData.KeyId; } + } + + /// + /// Return the algorithm code for the symmetric algorithm used to encrypt the data. + /// + public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm( + PgpPrivateKey privKey) + { + byte[] plain = fetchSymmetricKeyData(privKey); + + return (SymmetricKeyAlgorithmTag) plain[0]; + } + + /// Return the decrypted data stream for the packet. + public Stream GetDataStream( + PgpPrivateKey privKey) + { + byte[] plain = fetchSymmetricKeyData(privKey); + + IBufferedCipher c2; + string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]); + string cName = cipherName; + + try + { + if (encData is SymmetricEncIntegrityPacket) + { + cName += "/CFB/NoPadding"; + } + else + { + cName += "/OpenPGPCFB/NoPadding"; + } + + c2 = CipherUtilities.GetCipher(cName); + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("exception creating cipher", e); + } + + if (c2 == null) + return encData.GetInputStream(); + + try + { + KeyParameter key = ParameterUtilities.CreateKeyParameter( + cipherName, plain, 1, plain.Length - 3); + + byte[] iv = new byte[c2.GetBlockSize()]; + + c2.Init(false, new ParametersWithIV(key, iv)); + + encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null)); + + if (encData is SymmetricEncIntegrityPacket) + { + truncStream = new TruncatedStream(encStream); + + string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); + IDigest digest = DigestUtilities.GetDigest(digestName); + + encStream = new DigestStream(truncStream, digest, null); + } + + if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length) + throw new EndOfStreamException("unexpected end of stream."); + + int v1 = encStream.ReadByte(); + int v2 = encStream.ReadByte(); + + if (v1 < 0 || v2 < 0) + throw new EndOfStreamException("unexpected end of stream."); + + // Note: the oracle attack on the "quick check" bytes is deemed + // a security risk for typical public key encryption usages, + // therefore we do not perform the check. + +// bool repeatCheckPassed = +// iv[iv.Length - 2] == (byte)v1 +// && iv[iv.Length - 1] == (byte)v2; +// +// // Note: some versions of PGP appear to produce 0 for the extra +// // bytes rather than repeating the two previous bytes +// bool zeroesCheckPassed = +// v1 == 0 +// && v2 == 0; +// +// if (!repeatCheckPassed && !zeroesCheckPassed) +// { +// throw new PgpDataValidationException("quick check failed."); +// } + + return encStream; + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception starting decryption", e); + } + } + + private byte[] fetchSymmetricKeyData( + PgpPrivateKey privKey) + { + IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm); + + try + { + c1.Init(false, privKey.Key); + } + catch (InvalidKeyException e) + { + throw new PgpException("error setting asymmetric cipher", e); + } + + BigInteger[] keyD = keyData.GetEncSessionKey(); + + if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt + || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral) + { + c1.ProcessBytes(keyD[0].ToByteArrayUnsigned()); + } + else + { + ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key; + int size = (k.Parameters.P.BitLength + 7) / 8; + + byte[] bi = keyD[0].ToByteArray(); + + int diff = bi.Length - size; + if (diff >= 0) + { + c1.ProcessBytes(bi, diff, size); + } + else + { + byte[] zeros = new byte[-diff]; + c1.ProcessBytes(zeros); + c1.ProcessBytes(bi); + } + + bi = keyD[1].ToByteArray(); + + diff = bi.Length - size; + if (diff >= 0) + { + c1.ProcessBytes(bi, diff, size); + } + else + { + byte[] zeros = new byte[-diff]; + c1.ProcessBytes(zeros); + c1.ProcessBytes(bi); + } + } + + byte[] plain; + try + { + plain = c1.DoFinal(); + } + catch (Exception e) + { + throw new PgpException("exception decrypting secret key", e); + } + + if (!ConfirmCheckSum(plain)) + throw new PgpKeyValidationException("key checksum failed"); + + return plain; + } + } +} diff --git a/crypto/src/openpgp/PgpPublicKeyRing.cs b/crypto/src/openpgp/PgpPublicKeyRing.cs new file mode 100644 index 000000000..ecb935e4b --- /dev/null +++ b/crypto/src/openpgp/PgpPublicKeyRing.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Class to hold a single master public key and its subkeys. + ///

    + /// Often PGP keyring files consist of multiple master keys, if you are trying to process + /// or construct one of these you should use the PgpPublicKeyRingBundle class. + ///

    + ///
    + public class PgpPublicKeyRing + : PgpKeyRing + { + private readonly IList keys; + + public PgpPublicKeyRing( + byte[] encoding) + : this(new MemoryStream(encoding, false)) + { + } + + internal PgpPublicKeyRing( + IList pubKeys) + { + this.keys = pubKeys; + } + + public PgpPublicKeyRing( + Stream inputStream) + { + this.keys = Platform.CreateArrayList(); + + BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream); + + PacketTag initialTag = bcpgInput.NextPacketTag(); + if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey) + { + throw new IOException("public key ring doesn't start with public key tag: " + + "tag 0x" + ((int)initialTag).ToString("X")); + } + + PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();; + TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput); + + // direct signatures and revocations + IList keySigs = ReadSignaturesAndTrust(bcpgInput); + + IList ids, idTrusts, idSigs; + ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs); + + keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs)); + + + // Read subkeys + while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey) + { + keys.Add(ReadSubkey(bcpgInput)); + } + } + + /// Return the first public key in the ring. + public PgpPublicKey GetPublicKey() + { + return (PgpPublicKey) keys[0]; + } + + /// Return the public key referred to by the passed in key ID if it is present. + public PgpPublicKey GetPublicKey( + long keyId) + { + foreach (PgpPublicKey k in keys) + { + if (keyId == k.KeyId) + { + return k; + } + } + + return null; + } + + /// Allows enumeration of all the public keys. + /// An IEnumerable of PgpPublicKey objects. + public IEnumerable GetPublicKeys() + { + return new EnumerableProxy(keys); + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + foreach (PgpPublicKey k in keys) + { + k.Encode(outStr); + } + } + + /// + /// Returns a new key ring with the public key passed in either added or + /// replacing an existing one. + /// + /// The public key ring to be modified. + /// The public key to be inserted. + /// A new PgpPublicKeyRing + public static PgpPublicKeyRing InsertPublicKey( + PgpPublicKeyRing pubRing, + PgpPublicKey pubKey) + { + IList keys = Platform.CreateArrayList(pubRing.keys); + bool found = false; + bool masterFound = false; + + for (int i = 0; i != keys.Count; i++) + { + PgpPublicKey key = (PgpPublicKey) keys[i]; + + if (key.KeyId == pubKey.KeyId) + { + found = true; + keys[i] = pubKey; + } + if (key.IsMasterKey) + { + masterFound = true; + } + } + + if (!found) + { + if (pubKey.IsMasterKey) + { + if (masterFound) + throw new ArgumentException("cannot add a master key to a ring that already has one"); + + keys.Insert(0, pubKey); + } + else + { + keys.Add(pubKey); + } + } + + return new PgpPublicKeyRing(keys); + } + + /// Returns a new key ring with the public key passed in removed from the key ring. + /// The public key ring to be modified. + /// The public key to be removed. + /// A new PgpPublicKeyRing, or null if pubKey is not found. + public static PgpPublicKeyRing RemovePublicKey( + PgpPublicKeyRing pubRing, + PgpPublicKey pubKey) + { + IList keys = Platform.CreateArrayList(pubRing.keys); + bool found = false; + + for (int i = 0; i < keys.Count; i++) + { + PgpPublicKey key = (PgpPublicKey) keys[i]; + + if (key.KeyId == pubKey.KeyId) + { + found = true; + keys.RemoveAt(i); + } + } + + return found ? new PgpPublicKeyRing(keys) : null; + } + + internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput) + { + PublicKeyPacket pk = (PublicKeyPacket) bcpgInput.ReadPacket(); + TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput); + + // PGP 8 actually leaves out the signature. + IList sigList = ReadSignaturesAndTrust(bcpgInput); + + return new PgpPublicKey(pk, kTrust, sigList); + } + } +} diff --git a/crypto/src/openpgp/PgpPublicKeyRingBundle.cs b/crypto/src/openpgp/PgpPublicKeyRingBundle.cs new file mode 100644 index 000000000..519a2f884 --- /dev/null +++ b/crypto/src/openpgp/PgpPublicKeyRingBundle.cs @@ -0,0 +1,279 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Often a PGP key ring file is made up of a succession of master/sub-key key rings. + /// If you want to read an entire public key file in one hit this is the class for you. + /// + public class PgpPublicKeyRingBundle + { + private readonly IDictionary pubRings; + private readonly IList order; + + private PgpPublicKeyRingBundle( + IDictionary pubRings, + IList order) + { + this.pubRings = pubRings; + this.order = order; + } + + public PgpPublicKeyRingBundle( + byte[] encoding) + : this(new MemoryStream(encoding, false)) + { + } + + /// Build a PgpPublicKeyRingBundle from the passed in input stream. + /// Input stream containing data. + /// If a problem parsing the stream occurs. + /// If an object is encountered which isn't a PgpPublicKeyRing. + public PgpPublicKeyRingBundle( + Stream inputStream) + : this(new PgpObjectFactory(inputStream).AllPgpObjects()) + { + } + + public PgpPublicKeyRingBundle( + IEnumerable e) + { + this.pubRings = Platform.CreateHashtable(); + this.order = Platform.CreateArrayList(); + + foreach (object obj in e) + { + PgpPublicKeyRing pgpPub = obj as PgpPublicKeyRing; + + if (pgpPub == null) + { + throw new PgpException(obj.GetType().FullName + " found where PgpPublicKeyRing expected"); + } + + long key = pgpPub.GetPublicKey().KeyId; + pubRings.Add(key, pgpPub); + order.Add(key); + } + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return order.Count; } + } + + /// Return the number of key rings in this collection. + public int Count + { + get { return order.Count; } + } + + /// Allow enumeration of the public key rings making up this collection. + public IEnumerable GetKeyRings() + { + return new EnumerableProxy(pubRings.Values); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId) + { + return GetKeyRings(userId, false, false); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// If true, userId need only be a substring of an actual ID string to match. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId, + bool matchPartial) + { + return GetKeyRings(userId, matchPartial, false); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// If true, userId need only be a substring of an actual ID string to match. + /// If true, case is ignored in user ID comparisons. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId, + bool matchPartial, + bool ignoreCase) + { + IList rings = Platform.CreateArrayList(); + + if (ignoreCase) + { + userId = Platform.ToLowerInvariant(userId); + } + + foreach (PgpPublicKeyRing pubRing in GetKeyRings()) + { + foreach (string nextUserID in pubRing.GetPublicKey().GetUserIds()) + { + string next = nextUserID; + if (ignoreCase) + { + next = Platform.ToLowerInvariant(next); + } + + if (matchPartial) + { + if (next.IndexOf(userId) > -1) + { + rings.Add(pubRing); + } + } + else + { + if (next.Equals(userId)) + { + rings.Add(pubRing); + } + } + } + } + + return new EnumerableProxy(rings); + } + + /// Return the PGP public key associated with the given key id. + /// The ID of the public key to return. + public PgpPublicKey GetPublicKey( + long keyId) + { + foreach (PgpPublicKeyRing pubRing in GetKeyRings()) + { + PgpPublicKey pub = pubRing.GetPublicKey(keyId); + + if (pub != null) + { + return pub; + } + } + + return null; + } + + /// Return the public key ring which contains the key referred to by keyId + /// key ID to match against + public PgpPublicKeyRing GetPublicKeyRing( + long keyId) + { + if (pubRings.Contains(keyId)) + { + return (PgpPublicKeyRing)pubRings[keyId]; + } + + foreach (PgpPublicKeyRing pubRing in GetKeyRings()) + { + PgpPublicKey pub = pubRing.GetPublicKey(keyId); + + if (pub != null) + { + return pubRing; + } + } + + return null; + } + + /// + /// Return true if a key matching the passed in key ID is present, false otherwise. + /// + /// key ID to look for. + public bool Contains( + long keyID) + { + return GetPublicKey(keyID) != null; + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr); + + foreach (long key in order) + { + PgpPublicKeyRing sec = (PgpPublicKeyRing) pubRings[key]; + + sec.Encode(bcpgOut); + } + } + + /// + /// Return a new bundle containing the contents of the passed in bundle and + /// the passed in public key ring. + /// + /// The PgpPublicKeyRingBundle the key ring is to be added to. + /// The key ring to be added. + /// A new PgpPublicKeyRingBundle merging the current one with the passed in key ring. + /// If the keyId for the passed in key ring is already present. + public static PgpPublicKeyRingBundle AddPublicKeyRing( + PgpPublicKeyRingBundle bundle, + PgpPublicKeyRing publicKeyRing) + { + long key = publicKeyRing.GetPublicKey().KeyId; + + if (bundle.pubRings.Contains(key)) + { + throw new ArgumentException("Bundle already contains a key with a keyId for the passed in ring."); + } + + IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings); + IList newOrder = Platform.CreateArrayList(bundle.order); + + newPubRings[key] = publicKeyRing; + + newOrder.Add(key); + + return new PgpPublicKeyRingBundle(newPubRings, newOrder); + } + + /// + /// Return a new bundle containing the contents of the passed in bundle with + /// the passed in public key ring removed. + /// + /// The PgpPublicKeyRingBundle the key ring is to be removed from. + /// The key ring to be removed. + /// A new PgpPublicKeyRingBundle not containing the passed in key ring. + /// If the keyId for the passed in key ring is not present. + public static PgpPublicKeyRingBundle RemovePublicKeyRing( + PgpPublicKeyRingBundle bundle, + PgpPublicKeyRing publicKeyRing) + { + long key = publicKeyRing.GetPublicKey().KeyId; + + if (!bundle.pubRings.Contains(key)) + { + throw new ArgumentException("Bundle does not contain a key with a keyId for the passed in ring."); + } + + IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings); + IList newOrder = Platform.CreateArrayList(bundle.order); + + newPubRings.Remove(key); + newOrder.Remove(key); + + return new PgpPublicKeyRingBundle(newPubRings, newOrder); + } + } +} diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs new file mode 100644 index 000000000..9d87f49c8 --- /dev/null +++ b/crypto/src/openpgp/PgpSecretKey.cs @@ -0,0 +1,666 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// General class to handle a PGP secret key object. + public class PgpSecretKey + { + private readonly SecretKeyPacket secret; + private readonly PgpPublicKey pub; + + internal PgpSecretKey( + SecretKeyPacket secret, + PgpPublicKey pub) + { + this.secret = secret; + this.pub = pub; + } + + internal PgpSecretKey( + PgpPrivateKey privKey, + PgpPublicKey pubKey, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + bool useSha1, + SecureRandom rand) + : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false) + { + } + + internal PgpSecretKey( + PgpPrivateKey privKey, + PgpPublicKey pubKey, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + bool useSha1, + SecureRandom rand, + bool isMasterKey) + { + BcpgObject secKey; + + this.pub = pubKey; + + switch (pubKey.Algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaSign: + case PublicKeyAlgorithmTag.RsaGeneral: + RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) privKey.Key; + secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q); + break; + case PublicKeyAlgorithmTag.Dsa: + DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key; + secKey = new DsaSecretBcpgKey(dsK.X); + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key; + secKey = new ElGamalSecretBcpgKey(esK.X); + break; + default: + throw new PgpException("unknown key class"); + } + + try + { + MemoryStream bOut = new MemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pOut.WriteObject(secKey); + + byte[] keyData = bOut.ToArray(); + byte[] checksumBytes = Checksum(useSha1, keyData, keyData.Length); + + pOut.Write(checksumBytes); + + byte[] bOutData = bOut.ToArray(); + + if (encAlgorithm == SymmetricKeyAlgorithmTag.Null) + { + if (isMasterKey) + { + this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); + } + else + { + this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); + } + } + else + { + S2k s2k; + byte[] iv; + byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv); + + int s2kUsage = useSha1 + ? SecretKeyPacket.UsageSha1 + : SecretKeyPacket.UsageChecksum; + + if (isMasterKey) + { + this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); + } + else + { + this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); + } + } + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception encrypting key", e); + } + } + + public PgpSecretKey( + int certificationLevel, + PgpKeyPair keyPair, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + : this(certificationLevel, keyPair, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand) + { + } + + public PgpSecretKey( + int certificationLevel, + PgpKeyPair keyPair, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + bool useSha1, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + : this(keyPair.PrivateKey, certifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true) + { + } + + private static PgpPublicKey certifiedPublicKey( + int certificationLevel, + PgpKeyPair keyPair, + string id, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets) + { + PgpSignatureGenerator sGen; + try + { + sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + } + catch (Exception e) + { + throw new PgpException("Creating signature generator: " + e.Message, e); + } + + // + // Generate the certification + // + sGen.InitSign(certificationLevel, keyPair.PrivateKey); + + sGen.SetHashedSubpackets(hashedPackets); + sGen.SetUnhashedSubpackets(unhashedPackets); + + try + { + PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey); + return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification); + } + catch (Exception e) + { + throw new PgpException("Exception doing certification: " + e.Message, e); + } + } + + public PgpSecretKey( + int certificationLevel, + PublicKeyAlgorithmTag algorithm, + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey, + DateTime time, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + : this(certificationLevel, + new PgpKeyPair(algorithm, pubKey, privKey, time), + id, encAlgorithm, passPhrase, hashedPackets, unhashedPackets, rand) + { + } + + public PgpSecretKey( + int certificationLevel, + PublicKeyAlgorithmTag algorithm, + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey, + DateTime time, + string id, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + bool useSha1, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + SecureRandom rand) + : this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand) + { + } + + /// + /// Check if this key has an algorithm type that makes it suitable to use for signing. + /// + /// + /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for + /// determining the preferred use of the key. + /// + /// + /// true if this key algorithm is suitable for use with signing. + /// + public bool IsSigningKey + { + get + { + switch (pub.Algorithm) + { + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + case PublicKeyAlgorithmTag.Dsa: + case PublicKeyAlgorithmTag.ECDsa: + case PublicKeyAlgorithmTag.ElGamalGeneral: + return true; + default: + return false; + } + } + } + + /// True, if this is a master key. + public bool IsMasterKey + { + get { return pub.IsMasterKey; } + } + + /// The algorithm the key is encrypted with. + public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm + { + get { return secret.EncAlgorithm; } + } + + /// The key ID of the public key associated with this key. + public long KeyId + { + get { return pub.KeyId; } + } + + /// The public key associated with this key. + public PgpPublicKey PublicKey + { + get { return pub; } + } + + /// Allows enumeration of any user IDs associated with the key. + /// An IEnumerable of string objects. + public IEnumerable UserIds + { + get { return pub.GetUserIds(); } + } + + /// Allows enumeration of any user attribute vectors associated with the key. + /// An IEnumerable of string objects. + public IEnumerable UserAttributes + { + get { return pub.GetUserAttributes(); } + } + + private byte[] ExtractKeyData( + char[] passPhrase) + { + SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm; + byte[] encData = secret.GetSecretKeyData(); + + if (alg == SymmetricKeyAlgorithmTag.Null) + return encData; + + byte[] data; + IBufferedCipher c = null; + try + { + string cName = PgpUtilities.GetSymmetricCipherName(alg); + c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); + } + catch (Exception e) + { + throw new PgpException("Exception creating cipher", e); + } + + // TODO Factor this block out as 'encryptData' + try + { + KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase); + byte[] iv = secret.GetIV(); + + if (secret.PublicKeyPacket.Version == 4) + { + c.Init(false, new ParametersWithIV(key, iv)); + + data = c.DoFinal(encData); + + bool useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1; + byte[] check = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2); + + for (int i = 0; i != check.Length; i++) + { + if (check[i] != data[data.Length - check.Length + i]) + { + throw new PgpException("Checksum mismatch at " + i + " of " + check.Length); + } + } + } + else // version 2 or 3, RSA only. + { + data = new byte[encData.Length]; + + // + // read in the four numbers + // + int pos = 0; + + for (int i = 0; i != 4; i++) + { + c.Init(false, new ParametersWithIV(key, iv)); + + int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8; + + data[pos] = encData[pos]; + data[pos + 1] = encData[pos + 1]; + pos += 2; + + c.DoFinal(encData, pos, encLen, data, pos); + pos += encLen; + + if (i != 3) + { + Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length); + } + } + + // + // verify Checksum + // + int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff); + int calcCs = 0; + for (int j=0; j < data.Length-2; j++) + { + calcCs += data[j] & 0xff; + } + + calcCs &= 0xffff; + if (calcCs != cs) + { + throw new PgpException("Checksum mismatch: passphrase wrong, expected " + + cs.ToString("X") + + " found " + calcCs.ToString("X")); + } + } + + return data; + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception decrypting key", e); + } + } + + /// Extract a PgpPrivateKey from this secret key's encrypted contents. + public PgpPrivateKey ExtractPrivateKey( + char[] passPhrase) + { + byte[] secKeyData = secret.GetSecretKeyData(); + if (secKeyData == null || secKeyData.Length < 1) + return null; + + PublicKeyPacket pubPk = secret.PublicKeyPacket; + try + { + byte[] data = ExtractKeyData(passPhrase); + BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(data, false)); + AsymmetricKeyParameter privateKey; + switch (pubPk.Algorithm) + { + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + RsaPublicBcpgKey rsaPub = (RsaPublicBcpgKey)pubPk.Key; + RsaSecretBcpgKey rsaPriv = new RsaSecretBcpgKey(bcpgIn); + RsaPrivateCrtKeyParameters rsaPrivSpec = new RsaPrivateCrtKeyParameters( + rsaPriv.Modulus, + rsaPub.PublicExponent, + rsaPriv.PrivateExponent, + rsaPriv.PrimeP, + rsaPriv.PrimeQ, + rsaPriv.PrimeExponentP, + rsaPriv.PrimeExponentQ, + rsaPriv.CrtCoefficient); + privateKey = rsaPrivSpec; + break; + case PublicKeyAlgorithmTag.Dsa: + DsaPublicBcpgKey dsaPub = (DsaPublicBcpgKey)pubPk.Key; + DsaSecretBcpgKey dsaPriv = new DsaSecretBcpgKey(bcpgIn); + DsaParameters dsaParams = new DsaParameters(dsaPub.P, dsaPub.Q, dsaPub.G); + privateKey = new DsaPrivateKeyParameters(dsaPriv.X, dsaParams); + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + ElGamalPublicBcpgKey elPub = (ElGamalPublicBcpgKey)pubPk.Key; + ElGamalSecretBcpgKey elPriv = new ElGamalSecretBcpgKey(bcpgIn); + ElGamalParameters elParams = new ElGamalParameters(elPub.P, elPub.G); + privateKey = new ElGamalPrivateKeyParameters(elPriv.X, elParams); + break; + default: + throw new PgpException("unknown public key algorithm encountered"); + } + + return new PgpPrivateKey(privateKey, KeyId); + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception constructing key", e); + } + } + + private static byte[] Checksum( + bool useSha1, + byte[] bytes, + int length) + { + if (useSha1) + { + try + { + IDigest dig = DigestUtilities.GetDigest("SHA1"); + dig.BlockUpdate(bytes, 0, length); + return DigestUtilities.DoFinal(dig); + } + //catch (NoSuchAlgorithmException e) + catch (Exception e) + { + throw new PgpException("Can't find SHA-1", e); + } + } + else + { + int Checksum = 0; + for (int i = 0; i != length; i++) + { + Checksum += bytes[i]; + } + + return new byte[] { (byte)(Checksum >> 8), (byte)Checksum }; + } + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + Encode(bOut); + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr); + + bcpgOut.WritePacket(secret); + if (pub.trustPk != null) + { + bcpgOut.WritePacket(pub.trustPk); + } + + if (pub.subSigs == null) // is not a sub key + { + foreach (PgpSignature keySig in pub.keySigs) + { + keySig.Encode(bcpgOut); + } + + for (int i = 0; i != pub.ids.Count; i++) + { + object pubID = pub.ids[i]; + if (pubID is string) + { + string id = (string) pubID; + bcpgOut.WritePacket(new UserIdPacket(id)); + } + else + { + PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector) pubID; + bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray())); + } + + if (pub.idTrusts[i] != null) + { + bcpgOut.WritePacket((ContainedPacket)pub.idTrusts[i]); + } + + foreach (PgpSignature sig in (IList) pub.idSigs[i]) + { + sig.Encode(bcpgOut); + } + } + } + else + { + foreach (PgpSignature subSig in pub.subSigs) + { + subSig.Encode(bcpgOut); + } + } + + // TODO Check that this is right/necessary + //bcpgOut.Finish(); + } + + /// + /// Return a copy of the passed in secret key, encrypted using a new password + /// and the passed in algorithm. + /// + /// The PgpSecretKey to be copied. + /// The current password for the key. + /// The new password for the key. + /// The algorithm to be used for the encryption. + /// Source of randomness. + public static PgpSecretKey CopyWithNewPassword( + PgpSecretKey key, + char[] oldPassPhrase, + char[] newPassPhrase, + SymmetricKeyAlgorithmTag newEncAlgorithm, + SecureRandom rand) + { + byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase); + int s2kUsage = key.secret.S2kUsage; + byte[] iv = null; + S2k s2k = null; + byte[] keyData; + + if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null) + { + s2kUsage = SecretKeyPacket.UsageNone; + if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum + { + keyData = new byte[rawKeyData.Length - 18]; + + Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); + + byte[] check = Checksum(false, keyData, keyData.Length - 2); + + keyData[keyData.Length - 2] = check[0]; + keyData[keyData.Length - 1] = check[1]; + } + else + { + keyData = rawKeyData; + } + } + else + { + try + { + keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv); + } + catch (PgpException e) + { + throw e; + } + catch (Exception e) + { + throw new PgpException("Exception encrypting key", e); + } + } + + SecretKeyPacket secret; + if (key.secret is SecretSubkeyPacket) + { + secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, + newEncAlgorithm, s2kUsage, s2k, iv, keyData); + } + else + { + secret = new SecretKeyPacket(key.secret.PublicKeyPacket, + newEncAlgorithm, s2kUsage, s2k, iv, keyData); + } + + return new PgpSecretKey(secret, key.pub); + } + + /// Replace the passed the public key on the passed in secret key. + /// Secret key to change. + /// New public key. + /// A new secret key. + /// If KeyId's do not match. + public static PgpSecretKey ReplacePublicKey( + PgpSecretKey secretKey, + PgpPublicKey publicKey) + { + if (publicKey.KeyId != secretKey.KeyId) + throw new ArgumentException("KeyId's do not match"); + + return new PgpSecretKey(secretKey.secret, publicKey); + } + + private static byte[] EncryptKeyData( + byte[] rawKeyData, + SymmetricKeyAlgorithmTag encAlgorithm, + char[] passPhrase, + SecureRandom random, + out S2k s2k, + out byte[] iv) + { + IBufferedCipher c; + try + { + string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); + c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); + } + catch (Exception e) + { + throw new PgpException("Exception creating cipher", e); + } + + byte[] s2kIV = new byte[8]; + random.NextBytes(s2kIV); + s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60); + + KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase); + + iv = new byte[c.GetBlockSize()]; + random.NextBytes(iv); + + c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random)); + + return c.DoFinal(rawKeyData); + } + } +} diff --git a/crypto/src/openpgp/PgpSecretKeyRing.cs b/crypto/src/openpgp/PgpSecretKeyRing.cs new file mode 100644 index 000000000..3e646eaa1 --- /dev/null +++ b/crypto/src/openpgp/PgpSecretKeyRing.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Class to hold a single master secret key and its subkeys. + ///

    + /// Often PGP keyring files consist of multiple master keys, if you are trying to process + /// or construct one of these you should use the PgpSecretKeyRingBundle class. + ///

    + ///
    + public class PgpSecretKeyRing + : PgpKeyRing + { + private readonly IList keys; + private readonly IList extraPubKeys; + + internal PgpSecretKeyRing( + IList keys) + : this(keys, Platform.CreateArrayList()) + { + } + + private PgpSecretKeyRing( + IList keys, + IList extraPubKeys) + { + this.keys = keys; + this.extraPubKeys = extraPubKeys; + } + + public PgpSecretKeyRing( + byte[] encoding) + : this(new MemoryStream(encoding)) + { + } + + public PgpSecretKeyRing( + Stream inputStream) + { + this.keys = Platform.CreateArrayList(); + this.extraPubKeys = Platform.CreateArrayList(); + + BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream); + + PacketTag initialTag = bcpgInput.NextPacketTag(); + if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey) + { + throw new IOException("secret key ring doesn't start with secret key tag: " + + "tag 0x" + ((int)initialTag).ToString("X")); + } + + SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket(); + + // + // ignore GPG comment packets if found. + // + while (bcpgInput.NextPacketTag() == PacketTag.Experimental2) + { + bcpgInput.ReadPacket(); + } + + TrustPacket trust = ReadOptionalTrustPacket(bcpgInput); + + // revocation and direct signatures + IList keySigs = ReadSignaturesAndTrust(bcpgInput); + + IList ids, idTrusts, idSigs; + ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs); + + keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs))); + + + // Read subkeys + while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey + || bcpgInput.NextPacketTag() == PacketTag.PublicSubkey) + { + if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey) + { + SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket(); + + // + // ignore GPG comment packets if found. + // + while (bcpgInput.NextPacketTag() == PacketTag.Experimental2) + { + bcpgInput.ReadPacket(); + } + + TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); + IList sigList = ReadSignaturesAndTrust(bcpgInput); + + keys.Add(new PgpSecretKey(sub, new PgpPublicKey(sub.PublicKeyPacket, subTrust, sigList))); + } + else + { + PublicSubkeyPacket sub = (PublicSubkeyPacket) bcpgInput.ReadPacket(); + + TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); + IList sigList = ReadSignaturesAndTrust(bcpgInput); + + extraPubKeys.Add(new PgpPublicKey(sub, subTrust, sigList)); + } + } + } + + /// Return the public key for the master key. + public PgpPublicKey GetPublicKey() + { + return ((PgpSecretKey) keys[0]).PublicKey; + } + + /// Return the master private key. + public PgpSecretKey GetSecretKey() + { + return (PgpSecretKey) keys[0]; + } + + /// Allows enumeration of the secret keys. + /// An IEnumerable of PgpSecretKey objects. + public IEnumerable GetSecretKeys() + { + return new EnumerableProxy(keys); + } + + public PgpSecretKey GetSecretKey( + long keyId) + { + foreach (PgpSecretKey k in keys) + { + if (keyId == k.KeyId) + { + return k; + } + } + + return null; + } + + /// + /// Return an iterator of the public keys in the secret key ring that + /// have no matching private key. At the moment only personal certificate data + /// appears in this fashion. + /// + /// An IEnumerable of unattached, or extra, public keys. + public IEnumerable GetExtraPublicKeys() + { + return new EnumerableProxy(extraPubKeys); + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + if (outStr == null) + throw new ArgumentNullException("outStr"); + + foreach (PgpSecretKey key in keys) + { + key.Encode(outStr); + } + foreach (PgpPublicKey extraPubKey in extraPubKeys) + { + extraPubKey.Encode(outStr); + } + } + + /// + /// Replace the public key set on the secret ring with the corresponding key off the public ring. + /// + /// Secret ring to be changed. + /// Public ring containing the new public key set. + public static PgpSecretKeyRing ReplacePublicKeys( + PgpSecretKeyRing secretRing, + PgpPublicKeyRing publicRing) + { + IList newList = Platform.CreateArrayList(secretRing.keys.Count); + + foreach (PgpSecretKey sk in secretRing.keys) + { + PgpPublicKey pk = publicRing.GetPublicKey(sk.KeyId); + + newList.Add(PgpSecretKey.ReplacePublicKey(sk, pk)); + } + + return new PgpSecretKeyRing(newList); + } + + /// + /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted + /// using a new password and the passed in algorithm. + /// + /// The PgpSecretKeyRing to be copied. + /// The current password for key. + /// The new password for the key. + /// The algorithm to be used for the encryption. + /// Source of randomness. + public static PgpSecretKeyRing CopyWithNewPassword( + PgpSecretKeyRing ring, + char[] oldPassPhrase, + char[] newPassPhrase, + SymmetricKeyAlgorithmTag newEncAlgorithm, + SecureRandom rand) + { + IList newKeys = Platform.CreateArrayList(ring.keys.Count); + foreach (PgpSecretKey secretKey in ring.GetSecretKeys()) + { + newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand)); + } + + return new PgpSecretKeyRing(newKeys, ring.extraPubKeys); + } + + /// + /// Returns a new key ring with the secret key passed in either added or + /// replacing an existing one with the same key ID. + /// + /// The secret key ring to be modified. + /// The secret key to be inserted. + /// A new PgpSecretKeyRing + public static PgpSecretKeyRing InsertSecretKey( + PgpSecretKeyRing secRing, + PgpSecretKey secKey) + { + IList keys = Platform.CreateArrayList(secRing.keys); + bool found = false; + bool masterFound = false; + + for (int i = 0; i != keys.Count; i++) + { + PgpSecretKey key = (PgpSecretKey) keys[i]; + + if (key.KeyId == secKey.KeyId) + { + found = true; + keys[i] = secKey; + } + if (key.IsMasterKey) + { + masterFound = true; + } + } + + if (!found) + { + if (secKey.IsMasterKey) + { + if (masterFound) + throw new ArgumentException("cannot add a master key to a ring that already has one"); + + keys.Insert(0, secKey); + } + else + { + keys.Add(secKey); + } + } + + return new PgpSecretKeyRing(keys, secRing.extraPubKeys); + } + + /// Returns a new key ring with the secret key passed in removed from the key ring. + /// The secret key ring to be modified. + /// The secret key to be removed. + /// A new PgpSecretKeyRing, or null if secKey is not found. + public static PgpSecretKeyRing RemoveSecretKey( + PgpSecretKeyRing secRing, + PgpSecretKey secKey) + { + IList keys = Platform.CreateArrayList(secRing.keys); + bool found = false; + + for (int i = 0; i < keys.Count; i++) + { + PgpSecretKey key = (PgpSecretKey)keys[i]; + + if (key.KeyId == secKey.KeyId) + { + found = true; + keys.RemoveAt(i); + } + } + + return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null; + } + } +} diff --git a/crypto/src/openpgp/PgpSecretKeyRingBundle.cs b/crypto/src/openpgp/PgpSecretKeyRingBundle.cs new file mode 100644 index 000000000..12c7c098c --- /dev/null +++ b/crypto/src/openpgp/PgpSecretKeyRingBundle.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections; +using System.Globalization; +using System.IO; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// + /// Often a PGP key ring file is made up of a succession of master/sub-key key rings. + /// If you want to read an entire secret key file in one hit this is the class for you. + /// + public class PgpSecretKeyRingBundle + { + private readonly IDictionary secretRings; + private readonly IList order; + + private PgpSecretKeyRingBundle( + IDictionary secretRings, + IList order) + { + this.secretRings = secretRings; + this.order = order; + } + + public PgpSecretKeyRingBundle( + byte[] encoding) + : this(new MemoryStream(encoding, false)) + { + } + + /// Build a PgpSecretKeyRingBundle from the passed in input stream. + /// Input stream containing data. + /// If a problem parsing the stream occurs. + /// If an object is encountered which isn't a PgpSecretKeyRing. + public PgpSecretKeyRingBundle( + Stream inputStream) + : this(new PgpObjectFactory(inputStream).AllPgpObjects()) + { + } + + public PgpSecretKeyRingBundle( + IEnumerable e) + { + this.secretRings = Platform.CreateHashtable(); + this.order = Platform.CreateArrayList(); + + foreach (object obj in e) + { + PgpSecretKeyRing pgpSecret = obj as PgpSecretKeyRing; + + if (pgpSecret == null) + { + throw new PgpException(obj.GetType().FullName + " found where PgpSecretKeyRing expected"); + } + + long key = pgpSecret.GetPublicKey().KeyId; + secretRings.Add(key, pgpSecret); + order.Add(key); + } + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return order.Count; } + } + + /// Return the number of rings in this collection. + public int Count + { + get { return order.Count; } + } + + /// Allow enumeration of the secret key rings making up this collection. + public IEnumerable GetKeyRings() + { + return new EnumerableProxy(secretRings.Values); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId) + { + return GetKeyRings(userId, false, false); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// If true, userId need only be a substring of an actual ID string to match. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId, + bool matchPartial) + { + return GetKeyRings(userId, matchPartial, false); + } + + /// Allow enumeration of the key rings associated with the passed in userId. + /// The user ID to be matched. + /// If true, userId need only be a substring of an actual ID string to match. + /// If true, case is ignored in user ID comparisons. + /// An IEnumerable of key rings which matched (possibly none). + public IEnumerable GetKeyRings( + string userId, + bool matchPartial, + bool ignoreCase) + { + IList rings = Platform.CreateArrayList(); + + if (ignoreCase) + { + userId = Platform.ToLowerInvariant(userId); + } + + foreach (PgpSecretKeyRing secRing in GetKeyRings()) + { + foreach (string nextUserID in secRing.GetSecretKey().UserIds) + { + string next = nextUserID; + if (ignoreCase) + { + next = Platform.ToLowerInvariant(next); + } + + if (matchPartial) + { + if (next.IndexOf(userId) > -1) + { + rings.Add(secRing); + } + } + else + { + if (next.Equals(userId)) + { + rings.Add(secRing); + } + } + } + } + + return new EnumerableProxy(rings); + } + + /// Return the PGP secret key associated with the given key id. + /// The ID of the secret key to return. + public PgpSecretKey GetSecretKey( + long keyId) + { + foreach (PgpSecretKeyRing secRing in GetKeyRings()) + { + PgpSecretKey sec = secRing.GetSecretKey(keyId); + + if (sec != null) + { + return sec; + } + } + + return null; + } + + /// Return the secret key ring which contains the key referred to by keyId + /// The ID of the secret key + public PgpSecretKeyRing GetSecretKeyRing( + long keyId) + { + long id = keyId; + + if (secretRings.Contains(id)) + { + return (PgpSecretKeyRing) secretRings[id]; + } + + foreach (PgpSecretKeyRing secretRing in GetKeyRings()) + { + PgpSecretKey secret = secretRing.GetSecretKey(keyId); + + if (secret != null) + { + return secretRing; + } + } + + return null; + } + + /// + /// Return true if a key matching the passed in key ID is present, false otherwise. + /// + /// key ID to look for. + public bool Contains( + long keyID) + { + return GetSecretKey(keyID) != null; + } + + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStr) + { + BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr); + + foreach (long key in order) + { + PgpSecretKeyRing pub = (PgpSecretKeyRing) secretRings[key]; + + pub.Encode(bcpgOut); + } + } + + /// + /// Return a new bundle containing the contents of the passed in bundle and + /// the passed in secret key ring. + /// + /// The PgpSecretKeyRingBundle the key ring is to be added to. + /// The key ring to be added. + /// A new PgpSecretKeyRingBundle merging the current one with the passed in key ring. + /// If the keyId for the passed in key ring is already present. + public static PgpSecretKeyRingBundle AddSecretKeyRing( + PgpSecretKeyRingBundle bundle, + PgpSecretKeyRing secretKeyRing) + { + long key = secretKeyRing.GetPublicKey().KeyId; + + if (bundle.secretRings.Contains(key)) + { + throw new ArgumentException("Collection already contains a key with a keyId for the passed in ring."); + } + + IDictionary newSecretRings = Platform.CreateHashtable(bundle.secretRings); + IList newOrder = Platform.CreateArrayList(bundle.order); + + newSecretRings[key] = secretKeyRing; + newOrder.Add(key); + + return new PgpSecretKeyRingBundle(newSecretRings, newOrder); + } + + /// + /// Return a new bundle containing the contents of the passed in bundle with + /// the passed in secret key ring removed. + /// + /// The PgpSecretKeyRingBundle the key ring is to be removed from. + /// The key ring to be removed. + /// A new PgpSecretKeyRingBundle not containing the passed in key ring. + /// If the keyId for the passed in key ring is not present. + public static PgpSecretKeyRingBundle RemoveSecretKeyRing( + PgpSecretKeyRingBundle bundle, + PgpSecretKeyRing secretKeyRing) + { + long key = secretKeyRing.GetPublicKey().KeyId; + + if (!bundle.secretRings.Contains(key)) + { + throw new ArgumentException("Collection does not contain a key with a keyId for the passed in ring."); + } + + IDictionary newSecretRings = Platform.CreateHashtable(bundle.secretRings); + IList newOrder = Platform.CreateArrayList(bundle.order); + + newSecretRings.Remove(key); + newOrder.Remove(key); + + return new PgpSecretKeyRingBundle(newSecretRings, newOrder); + } + } +} diff --git a/crypto/src/openpgp/PgpSignature.cs b/crypto/src/openpgp/PgpSignature.cs new file mode 100644 index 000000000..3bb6f2f0e --- /dev/null +++ b/crypto/src/openpgp/PgpSignature.cs @@ -0,0 +1,422 @@ +using System; +using System.IO; +using Org.BouncyCastle.Asn1; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A PGP signature object. + public class PgpSignature + { + public const int BinaryDocument = 0x00; + public const int CanonicalTextDocument = 0x01; + public const int StandAlone = 0x02; + + public const int DefaultCertification = 0x10; + public const int NoCertification = 0x11; + public const int CasualCertification = 0x12; + public const int PositiveCertification = 0x13; + + public const int SubkeyBinding = 0x18; + public const int PrimaryKeyBinding = 0x19; + public const int DirectKey = 0x1f; + public const int KeyRevocation = 0x20; + public const int SubkeyRevocation = 0x28; + public const int CertificationRevocation = 0x30; + public const int Timestamp = 0x40; + + private readonly SignaturePacket sigPck; + private readonly int signatureType; + private readonly TrustPacket trustPck; + + private ISigner sig; + private byte lastb; // Initial value anything but '\r' + + internal PgpSignature( + BcpgInputStream bcpgInput) + : this((SignaturePacket)bcpgInput.ReadPacket()) + { + } + + internal PgpSignature( + SignaturePacket sigPacket) + : this(sigPacket, null) + { + } + + internal PgpSignature( + SignaturePacket sigPacket, + TrustPacket trustPacket) + { + if (sigPacket == null) + throw new ArgumentNullException("sigPacket"); + + this.sigPck = sigPacket; + this.signatureType = sigPck.SignatureType; + this.trustPck = trustPacket; + } + + private void GetSig() + { + this.sig = SignerUtilities.GetSigner( + PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm)); + } + + /// The OpenPGP version number for this signature. + public int Version + { + get { return sigPck.Version; } + } + + /// The key algorithm associated with this signature. + public PublicKeyAlgorithmTag KeyAlgorithm + { + get { return sigPck.KeyAlgorithm; } + } + + /// The hash algorithm associated with this signature. + public HashAlgorithmTag HashAlgorithm + { + get { return sigPck.HashAlgorithm; } + } + + public void InitVerify( + PgpPublicKey pubKey) + { + lastb = 0; + if (sig == null) + { + GetSig(); + } + try + { + sig.Init(false, pubKey.GetKey()); + } + catch (InvalidKeyException e) + { + throw new PgpException("invalid key.", e); + } + } + + public void Update( + byte b) + { + if (signatureType == CanonicalTextDocument) + { + doCanonicalUpdateByte(b); + } + else + { + sig.Update(b); + } + } + + private void doCanonicalUpdateByte( + byte b) + { + if (b == '\r') + { + doUpdateCRLF(); + } + else if (b == '\n') + { + if (lastb != '\r') + { + doUpdateCRLF(); + } + } + else + { + sig.Update(b); + } + + lastb = b; + } + + private void doUpdateCRLF() + { + sig.Update((byte)'\r'); + sig.Update((byte)'\n'); + } + + public void Update( + params byte[] bytes) + { + Update(bytes, 0, bytes.Length); + } + + public void Update( + byte[] bytes, + int off, + int length) + { + if (signatureType == CanonicalTextDocument) + { + int finish = off + length; + + for (int i = off; i != finish; i++) + { + doCanonicalUpdateByte(bytes[i]); + } + } + else + { + sig.BlockUpdate(bytes, off, length); + } + } + + public bool Verify() + { + byte[] trailer = GetSignatureTrailer(); + sig.BlockUpdate(trailer, 0, trailer.Length); + + return sig.VerifySignature(GetSignature()); + } + + private void UpdateWithIdData( + int header, + byte[] idBytes) + { + this.Update( + (byte) header, + (byte)(idBytes.Length >> 24), + (byte)(idBytes.Length >> 16), + (byte)(idBytes.Length >> 8), + (byte)(idBytes.Length)); + this.Update(idBytes); + } + + private void UpdateWithPublicKey( + PgpPublicKey key) + { + byte[] keyBytes = GetEncodedPublicKey(key); + + this.Update( + (byte) 0x99, + (byte)(keyBytes.Length >> 8), + (byte)(keyBytes.Length)); + this.Update(keyBytes); + } + + /// + /// Verify the signature as certifying the passed in public key as associated + /// with the passed in user attributes. + /// + /// User attributes the key was stored under. + /// The key to be verified. + /// True, if the signature matches, false otherwise. + public bool VerifyCertification( + PgpUserAttributeSubpacketVector userAttributes, + PgpPublicKey key) + { + UpdateWithPublicKey(key); + + // + // hash in the userAttributes + // + try + { + MemoryStream bOut = new MemoryStream(); + foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray()) + { + packet.Encode(bOut); + } + UpdateWithIdData(0xd1, bOut.ToArray()); + } + catch (IOException e) + { + throw new PgpException("cannot encode subpacket array", e); + } + + this.Update(sigPck.GetSignatureTrailer()); + + return sig.VerifySignature(this.GetSignature()); + } + + /// + /// Verify the signature as certifying the passed in public key as associated + /// with the passed in ID. + /// + /// ID the key was stored under. + /// The key to be verified. + /// True, if the signature matches, false otherwise. + public bool VerifyCertification( + string id, + PgpPublicKey key) + { + UpdateWithPublicKey(key); + + // + // hash in the id + // + UpdateWithIdData(0xb4, Strings.ToUtf8ByteArray(id)); + + Update(sigPck.GetSignatureTrailer()); + + return sig.VerifySignature(GetSignature()); + } + + /// Verify a certification for the passed in key against the passed in master key. + /// The key we are verifying against. + /// The key we are verifying. + /// True, if the certification is valid, false otherwise. + public bool VerifyCertification( + PgpPublicKey masterKey, + PgpPublicKey pubKey) + { + UpdateWithPublicKey(masterKey); + UpdateWithPublicKey(pubKey); + + Update(sigPck.GetSignatureTrailer()); + + return sig.VerifySignature(GetSignature()); + } + + /// Verify a key certification, such as revocation, for the passed in key. + /// The key we are checking. + /// True, if the certification is valid, false otherwise. + public bool VerifyCertification( + PgpPublicKey pubKey) + { + if (SignatureType != KeyRevocation + && SignatureType != SubkeyRevocation) + { + throw new InvalidOperationException("signature is not a key signature"); + } + + UpdateWithPublicKey(pubKey); + + Update(sigPck.GetSignatureTrailer()); + + return sig.VerifySignature(GetSignature()); + } + + public int SignatureType + { + get { return sigPck.SignatureType; } + } + + /// The ID of the key that created the signature. + public long KeyId + { + get { return sigPck.KeyId; } + } + + [Obsolete("Use 'CreationTime' property instead")] + public DateTime GetCreationTime() + { + return CreationTime; + } + + /// The creation time of this signature. + public DateTime CreationTime + { + get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); } + } + + public byte[] GetSignatureTrailer() + { + return sigPck.GetSignatureTrailer(); + } + + /// + /// Return true if the signature has either hashed or unhashed subpackets. + /// + public bool HasSubpackets + { + get + { + return sigPck.GetHashedSubPackets() != null + || sigPck.GetUnhashedSubPackets() != null; + } + } + + public PgpSignatureSubpacketVector GetHashedSubPackets() + { + return createSubpacketVector(sigPck.GetHashedSubPackets()); + } + + public PgpSignatureSubpacketVector GetUnhashedSubPackets() + { + return createSubpacketVector(sigPck.GetUnhashedSubPackets()); + } + + private PgpSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] pcks) + { + return pcks == null ? null : new PgpSignatureSubpacketVector(pcks); + } + + public byte[] GetSignature() + { + MPInteger[] sigValues = sigPck.GetSignature(); + byte[] signature; + + if (sigValues != null) + { + if (sigValues.Length == 1) // an RSA signature + { + signature = sigValues[0].Value.ToByteArrayUnsigned(); + } + else + { + try + { + signature = new DerSequence( + new DerInteger(sigValues[0].Value), + new DerInteger(sigValues[1].Value)).GetEncoded(); + } + catch (IOException e) + { + throw new PgpException("exception encoding DSA sig.", e); + } + } + } + else + { + signature = sigPck.GetSignatureBytes(); + } + + return signature; + } + + // TODO Handle the encoding stuff by subclassing BcpgObject? + public byte[] GetEncoded() + { + MemoryStream bOut = new MemoryStream(); + + Encode(bOut); + + return bOut.ToArray(); + } + + public void Encode( + Stream outStream) + { + BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStream); + + bcpgOut.WritePacket(sigPck); + + if (trustPck != null) + { + bcpgOut.WritePacket(trustPck); + } + } + + private byte[] GetEncodedPublicKey( + PgpPublicKey pubKey) + { + try + { + return pubKey.publicPk.GetEncodedContents(); + } + catch (IOException e) + { + throw new PgpException("exception preparing key.", e); + } + } + } +} diff --git a/crypto/src/openpgp/PgpSignatureGenerator.cs b/crypto/src/openpgp/PgpSignatureGenerator.cs new file mode 100644 index 000000000..c5309689f --- /dev/null +++ b/crypto/src/openpgp/PgpSignatureGenerator.cs @@ -0,0 +1,393 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Generator for PGP signatures. + // TODO Should be able to implement ISigner? + public class PgpSignatureGenerator + { + private static readonly SignatureSubpacket[] EmptySignatureSubpackets = new SignatureSubpacket[0]; + + private PublicKeyAlgorithmTag keyAlgorithm; + private HashAlgorithmTag hashAlgorithm; + private PgpPrivateKey privKey; + private ISigner sig; + private IDigest dig; + private int signatureType; + private byte lastb; + + private SignatureSubpacket[] unhashed = EmptySignatureSubpackets; + private SignatureSubpacket[] hashed = EmptySignatureSubpackets; + + /// Create a generator for the passed in keyAlgorithm and hashAlgorithm codes. + public PgpSignatureGenerator( + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm) + { + this.keyAlgorithm = keyAlgorithm; + this.hashAlgorithm = hashAlgorithm; + + dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm)); + sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm)); + } + + /// Initialise the generator for signing. + public void InitSign( + int sigType, + PgpPrivateKey key) + { + InitSign(sigType, key, null); + } + + /// Initialise the generator for signing. + public void InitSign( + int sigType, + PgpPrivateKey key, + SecureRandom random) + { + this.privKey = key; + this.signatureType = sigType; + + try + { + ICipherParameters cp = key.Key; + if (random != null) + { + cp = new ParametersWithRandom(key.Key, random); + } + + sig.Init(true, cp); + } + catch (InvalidKeyException e) + { + throw new PgpException("invalid key.", e); + } + + dig.Reset(); + lastb = 0; + } + + public void Update( + byte b) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + doCanonicalUpdateByte(b); + } + else + { + doUpdateByte(b); + } + } + + private void doCanonicalUpdateByte( + byte b) + { + if (b == '\r') + { + doUpdateCRLF(); + } + else if (b == '\n') + { + if (lastb != '\r') + { + doUpdateCRLF(); + } + } + else + { + doUpdateByte(b); + } + + lastb = b; + } + + private void doUpdateCRLF() + { + doUpdateByte((byte)'\r'); + doUpdateByte((byte)'\n'); + } + + private void doUpdateByte( + byte b) + { + sig.Update(b); + dig.Update(b); + } + + public void Update( + params byte[] b) + { + Update(b, 0, b.Length); + } + + public void Update( + byte[] b, + int off, + int len) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + int finish = off + len; + + for (int i = off; i != finish; i++) + { + doCanonicalUpdateByte(b[i]); + } + } + else + { + sig.BlockUpdate(b, off, len); + dig.BlockUpdate(b, off, len); + } + } + + public void SetHashedSubpackets( + PgpSignatureSubpacketVector hashedPackets) + { + hashed = hashedPackets == null + ? EmptySignatureSubpackets + : hashedPackets.ToSubpacketArray(); + } + + public void SetUnhashedSubpackets( + PgpSignatureSubpacketVector unhashedPackets) + { + unhashed = unhashedPackets == null + ? EmptySignatureSubpackets + : unhashedPackets.ToSubpacketArray(); + } + + /// Return the one pass header associated with the current signature. + public PgpOnePassSignature GenerateOnePassVersion( + bool isNested) + { + return new PgpOnePassSignature( + new OnePassSignaturePacket( + signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested)); + } + + /// Return a signature object containing the current signature state. + public PgpSignature Generate() + { + SignatureSubpacket[] hPkts = hashed, unhPkts = unhashed; + + if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime)) + { + hPkts = insertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow)); + } + + if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) + && !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId)) + { + unhPkts = insertSubpacket(unhPkts, new IssuerKeyId(false, privKey.KeyId)); + } + + int version = 4; + byte[] hData; + + try + { + MemoryStream hOut = new MemoryStream(); + + for (int i = 0; i != hPkts.Length; i++) + { + hPkts[i].Encode(hOut); + } + + byte[] data = hOut.ToArray(); + + MemoryStream sOut = new MemoryStream(data.Length + 6); + sOut.WriteByte((byte)version); + sOut.WriteByte((byte)signatureType); + sOut.WriteByte((byte)keyAlgorithm); + sOut.WriteByte((byte)hashAlgorithm); + sOut.WriteByte((byte)(data.Length >> 8)); + sOut.WriteByte((byte)data.Length); + sOut.Write(data, 0, data.Length); + + hData = sOut.ToArray(); + } + catch (IOException e) + { + throw new PgpException("exception encoding hashed data.", e); + } + + sig.BlockUpdate(hData, 0, hData.Length); + dig.BlockUpdate(hData, 0, hData.Length); + + hData = new byte[] + { + (byte) version, + 0xff, + (byte)(hData.Length >> 24), + (byte)(hData.Length >> 16), + (byte)(hData.Length >> 8), + (byte) hData.Length + }; + + sig.BlockUpdate(hData, 0, hData.Length); + dig.BlockUpdate(hData, 0, hData.Length); + + byte[] sigBytes = sig.GenerateSignature(); + byte[] digest = DigestUtilities.DoFinal(dig); + byte[] fingerPrint = new byte[] { digest[0], digest[1] }; + + // an RSA signature + bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign + || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral; + + MPInteger[] sigValues = isRsa + ? PgpUtilities.RsaSigToMpi(sigBytes) + : PgpUtilities.DsaSigToMpi(sigBytes); + + return new PgpSignature( + new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm, + hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues)); + } + + /// Generate a certification for the passed in ID and key. + /// The ID we are certifying against the public key. + /// The key we are certifying against the ID. + /// The certification. + public PgpSignature GenerateCertification( + string id, + PgpPublicKey pubKey) + { + UpdateWithPublicKey(pubKey); + + // + // hash in the id + // + UpdateWithIdData(0xb4, Strings.ToUtf8ByteArray(id)); + + return Generate(); + } + + /// Generate a certification for the passed in userAttributes. + /// The ID we are certifying against the public key. + /// The key we are certifying against the ID. + /// The certification. + public PgpSignature GenerateCertification( + PgpUserAttributeSubpacketVector userAttributes, + PgpPublicKey pubKey) + { + UpdateWithPublicKey(pubKey); + + // + // hash in the attributes + // + try + { + MemoryStream bOut = new MemoryStream(); + foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray()) + { + packet.Encode(bOut); + } + UpdateWithIdData(0xd1, bOut.ToArray()); + } + catch (IOException e) + { + throw new PgpException("cannot encode subpacket array", e); + } + + return this.Generate(); + } + + /// Generate a certification for the passed in key against the passed in master key. + /// The key we are certifying against. + /// The key we are certifying. + /// The certification. + public PgpSignature GenerateCertification( + PgpPublicKey masterKey, + PgpPublicKey pubKey) + { + UpdateWithPublicKey(masterKey); + UpdateWithPublicKey(pubKey); + + return Generate(); + } + + /// Generate a certification, such as a revocation, for the passed in key. + /// The key we are certifying. + /// The certification. + public PgpSignature GenerateCertification( + PgpPublicKey pubKey) + { + UpdateWithPublicKey(pubKey); + + return Generate(); + } + + private byte[] GetEncodedPublicKey( + PgpPublicKey pubKey) + { + try + { + return pubKey.publicPk.GetEncodedContents(); + } + catch (IOException e) + { + throw new PgpException("exception preparing key.", e); + } + } + + private bool packetPresent( + SignatureSubpacket[] packets, + SignatureSubpacketTag type) + { + for (int i = 0; i != packets.Length; i++) + { + if (packets[i].SubpacketType == type) + { + return true; + } + } + + return false; + } + + private SignatureSubpacket[] insertSubpacket( + SignatureSubpacket[] packets, + SignatureSubpacket subpacket) + { + SignatureSubpacket[] tmp = new SignatureSubpacket[packets.Length + 1]; + tmp[0] = subpacket; + packets.CopyTo(tmp, 1); + return tmp; + } + + private void UpdateWithIdData( + int header, + byte[] idBytes) + { + this.Update( + (byte) header, + (byte)(idBytes.Length >> 24), + (byte)(idBytes.Length >> 16), + (byte)(idBytes.Length >> 8), + (byte)(idBytes.Length)); + this.Update(idBytes); + } + + private void UpdateWithPublicKey( + PgpPublicKey key) + { + byte[] keyBytes = GetEncodedPublicKey(key); + + this.Update( + (byte) 0x99, + (byte)(keyBytes.Length >> 8), + (byte)(keyBytes.Length)); + this.Update(keyBytes); + } + } +} diff --git a/crypto/src/openpgp/PgpSignatureList.cs b/crypto/src/openpgp/PgpSignatureList.cs new file mode 100644 index 000000000..61976fc4f --- /dev/null +++ b/crypto/src/openpgp/PgpSignatureList.cs @@ -0,0 +1,51 @@ +using System; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// A list of PGP signatures - normally in the signature block after literal data. + public class PgpSignatureList + : PgpObject + { + private PgpSignature[] sigs; + + public PgpSignatureList( + PgpSignature[] sigs) + { + this.sigs = (PgpSignature[]) sigs.Clone(); + } + + public PgpSignatureList( + PgpSignature sig) + { + this.sigs = new PgpSignature[]{ sig }; + } + + public PgpSignature this[int index] + { + get { return sigs[index]; } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public PgpSignature Get( + int index) + { + return this[index]; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return sigs.Length; } + } + + public int Count + { + get { return sigs.Length; } + } + + public bool IsEmpty + { + get { return (sigs.Length == 0); } + } + } +} diff --git a/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs new file mode 100644 index 000000000..4adf64012 --- /dev/null +++ b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Generator for signature subpackets. + public class PgpSignatureSubpacketGenerator + { + private IList list = Platform.CreateArrayList(); + + public void SetRevocable( + bool isCritical, + bool isRevocable) + { + list.Add(new Revocable(isCritical, isRevocable)); + } + + public void SetExportable( + bool isCritical, + bool isExportable) + { + list.Add(new Exportable(isCritical, isExportable)); + } + + /// + /// Add a TrustSignature packet to the signature. The values for depth and trust are largely + /// installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13. + /// + /// true if the packet is critical. + /// depth level. + /// trust amount. + public void SetTrust( + bool isCritical, + int depth, + int trustAmount) + { + list.Add(new TrustSignature(isCritical, depth, trustAmount)); + } + + /// + /// Set the number of seconds a key is valid for after the time of its creation. + /// A value of zero means the key never expires. + /// + /// True, if should be treated as critical, false otherwise. + /// The number of seconds the key is valid, or zero if no expiry. + public void SetKeyExpirationTime( + bool isCritical, + long seconds) + { + list.Add(new KeyExpirationTime(isCritical, seconds)); + } + + /// + /// Set the number of seconds a signature is valid for after the time of its creation. + /// A value of zero means the signature never expires. + /// + /// True, if should be treated as critical, false otherwise. + /// The number of seconds the signature is valid, or zero if no expiry. + public void SetSignatureExpirationTime( + bool isCritical, + long seconds) + { + list.Add(new SignatureExpirationTime(isCritical, seconds)); + } + + /// + /// Set the creation time for the signature. + ///

    + /// Note: this overrides the generation of a creation time when the signature + /// is generated.

    + ///
    + public void SetSignatureCreationTime( + bool isCritical, + DateTime date) + { + list.Add(new SignatureCreationTime(isCritical, date)); + } + + public void SetPreferredHashAlgorithms( + bool isCritical, + int[] algorithms) + { + list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredHashAlgorithms, isCritical, algorithms)); + } + + public void SetPreferredSymmetricAlgorithms( + bool isCritical, + int[] algorithms) + { + list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredSymmetricAlgorithms, isCritical, algorithms)); + } + + public void SetPreferredCompressionAlgorithms( + bool isCritical, + int[] algorithms) + { + list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredCompressionAlgorithms, isCritical, algorithms)); + } + + public void SetKeyFlags( + bool isCritical, + int flags) + { + list.Add(new KeyFlags(isCritical, flags)); + } + + public void SetSignerUserId( + bool isCritical, + string userId) + { + if (userId == null) + throw new ArgumentNullException("userId"); + + list.Add(new SignerUserId(isCritical, userId)); + } + + public void SetEmbeddedSignature( + bool isCritical, + PgpSignature pgpSignature) + { + byte[] sig = pgpSignature.GetEncoded(); + byte[] data; + + // TODO Should be >= ? + if (sig.Length - 1 > 256) + { + data = new byte[sig.Length - 3]; + } + else + { + data = new byte[sig.Length - 2]; + } + + Array.Copy(sig, sig.Length - data.Length, data, 0, data.Length); + + list.Add(new EmbeddedSignature(isCritical, data)); + } + + public void SetPrimaryUserId( + bool isCritical, + bool isPrimaryUserId) + { + list.Add(new PrimaryUserId(isCritical, isPrimaryUserId)); + } + + public void SetNotationData( + bool isCritical, + bool isHumanReadable, + string notationName, + string notationValue) + { + list.Add(new NotationData(isCritical, isHumanReadable, notationName, notationValue)); + } + + /// + /// Sets revocation reason sub packet + /// + public void SetRevocationReason(bool isCritical, RevocationReasonTag reason, + string description) + { + list.Add(new RevocationReason(isCritical, reason, description)); + } + + /// + /// Sets revocation key sub packet + /// + public void SetRevocationKey(bool isCritical, PublicKeyAlgorithmTag keyAlgorithm, byte[] fingerprint) + { + list.Add(new RevocationKey(isCritical, RevocationKeyTag.ClassDefault, keyAlgorithm, fingerprint)); + } + + /// + /// Sets issuer key sub packet + /// + public void SetIssuerKeyID(bool isCritical, long keyID) + { + list.Add(new IssuerKeyId(isCritical, keyID)); + } + + public PgpSignatureSubpacketVector Generate() + { + SignatureSubpacket[] a = new SignatureSubpacket[list.Count]; + for (int i = 0; i < list.Count; ++i) + { + a[i] = (SignatureSubpacket)list[i]; + } + return new PgpSignatureSubpacketVector(a); + } + } +} diff --git a/crypto/src/openpgp/PgpSignatureSubpacketVector.cs b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs new file mode 100644 index 000000000..68fe4b594 --- /dev/null +++ b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Container for a list of signature subpackets. + public class PgpSignatureSubpacketVector + { + private readonly SignatureSubpacket[] packets; + + internal PgpSignatureSubpacketVector( + SignatureSubpacket[] packets) + { + this.packets = packets; + } + + public SignatureSubpacket GetSubpacket( + SignatureSubpacketTag type) + { + for (int i = 0; i != packets.Length; i++) + { + if (packets[i].SubpacketType == type) + { + return packets[i]; + } + } + + return null; + } + + /** + * Return true if a particular subpacket type exists. + * + * @param type type to look for. + * @return true if present, false otherwise. + */ + public bool HasSubpacket( + SignatureSubpacketTag type) + { + return GetSubpacket(type) != null; + } + + /** + * Return all signature subpackets of the passed in type. + * @param type subpacket type code + * @return an array of zero or more matching subpackets. + */ + public SignatureSubpacket[] GetSubpackets( + SignatureSubpacketTag type) + { + int count = 0; + for (int i = 0; i < packets.Length; ++i) + { + if (packets[i].SubpacketType == type) + { + ++count; + } + } + + SignatureSubpacket[] result = new SignatureSubpacket[count]; + + int pos = 0; + for (int i = 0; i < packets.Length; ++i) + { + if (packets[i].SubpacketType == type) + { + result[pos++] = packets[i]; + } + } + + return result; + } + + public NotationData[] GetNotationDataOccurences() + { + SignatureSubpacket[] notations = GetSubpackets(SignatureSubpacketTag.NotationData); + NotationData[] vals = new NotationData[notations.Length]; + + for (int i = 0; i < notations.Length; i++) + { + vals[i] = (NotationData) notations[i]; + } + + return vals; + } + + public long GetIssuerKeyId() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.IssuerKeyId); + + return p == null ? 0 : ((IssuerKeyId) p).KeyId; + } + + public bool HasSignatureCreationTime() + { + return GetSubpacket(SignatureSubpacketTag.CreationTime) != null; + } + + public DateTime GetSignatureCreationTime() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.CreationTime); + + if (p == null) + { + throw new PgpException("SignatureCreationTime not available"); + } + + return ((SignatureCreationTime)p).GetTime(); + } + + /// + /// Return the number of seconds a signature is valid for after its creation date. + /// A value of zero means the signature never expires. + /// + /// Seconds a signature is valid for. + public long GetSignatureExpirationTime() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.ExpireTime); + + return p == null ? 0 : ((SignatureExpirationTime) p).Time; + } + + /// + /// Return the number of seconds a key is valid for after its creation date. + /// A value of zero means the key never expires. + /// + /// Seconds a signature is valid for. + public long GetKeyExpirationTime() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.KeyExpireTime); + + return p == null ? 0 : ((KeyExpirationTime) p).Time; + } + + public int[] GetPreferredHashAlgorithms() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredHashAlgorithms); + + return p == null ? null : ((PreferredAlgorithms) p).GetPreferences(); + } + + public int[] GetPreferredSymmetricAlgorithms() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredSymmetricAlgorithms); + + return p == null ? null : ((PreferredAlgorithms) p).GetPreferences(); + } + + public int[] GetPreferredCompressionAlgorithms() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredCompressionAlgorithms); + + return p == null ? null : ((PreferredAlgorithms) p).GetPreferences(); + } + + public int GetKeyFlags() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.KeyFlags); + + return p == null ? 0 : ((KeyFlags) p).Flags; + } + + public string GetSignerUserId() + { + SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.SignerUserId); + + return p == null ? null : ((SignerUserId) p).GetId(); + } + + public bool IsPrimaryUserId() + { + PrimaryUserId primaryId = (PrimaryUserId) + this.GetSubpacket(SignatureSubpacketTag.PrimaryUserId); + + if (primaryId != null) + { + return primaryId.IsPrimaryUserId(); + } + + return false; + } + + public SignatureSubpacketTag[] GetCriticalTags() + { + int count = 0; + for (int i = 0; i != packets.Length; i++) + { + if (packets[i].IsCritical()) + { + count++; + } + } + + SignatureSubpacketTag[] list = new SignatureSubpacketTag[count]; + + count = 0; + + for (int i = 0; i != packets.Length; i++) + { + if (packets[i].IsCritical()) + { + list[count++] = packets[i].SubpacketType; + } + } + + return list; + } + + [Obsolete("Use 'Count' property instead")] + public int Size + { + get { return packets.Length; } + } + + /// Return the number of packets this vector contains. + public int Count + { + get { return packets.Length; } + } + + internal SignatureSubpacket[] ToSubpacketArray() + { + return packets; + } + } +} diff --git a/crypto/src/openpgp/PgpUserAttributeSubpacketVector.cs b/crypto/src/openpgp/PgpUserAttributeSubpacketVector.cs new file mode 100644 index 000000000..4cdbeda54 --- /dev/null +++ b/crypto/src/openpgp/PgpUserAttributeSubpacketVector.cs @@ -0,0 +1,81 @@ +using Org.BouncyCastle.Bcpg.Attr; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Container for a list of user attribute subpackets. + public class PgpUserAttributeSubpacketVector + { + private readonly UserAttributeSubpacket[] packets; + + internal PgpUserAttributeSubpacketVector( + UserAttributeSubpacket[] packets) + { + this.packets = packets; + } + + public UserAttributeSubpacket GetSubpacket( + UserAttributeSubpacketTag type) + { + for (int i = 0; i != packets.Length; i++) + { + if (packets[i].SubpacketType == type) + { + return packets[i]; + } + } + + return null; + } + + public ImageAttrib GetImageAttribute() + { + UserAttributeSubpacket p = GetSubpacket(UserAttributeSubpacketTag.ImageAttribute); + + return p == null ? null : (ImageAttrib) p; + } + + internal UserAttributeSubpacket[] ToSubpacketArray() + { + return packets; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + PgpUserAttributeSubpacketVector other = obj as PgpUserAttributeSubpacketVector; + + if (other == null) + return false; + + if (other.packets.Length != packets.Length) + { + return false; + } + + for (int i = 0; i != packets.Length; i++) + { + if (!other.packets[i].Equals(packets[i])) + { + return false; + } + } + + return true; + } + + public override int GetHashCode() + { + int code = 0; + + foreach (object o in packets) + { + code ^= o.GetHashCode(); + } + + return code; + } + } +} diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs new file mode 100644 index 000000000..7cd3dfc4f --- /dev/null +++ b/crypto/src/openpgp/PgpUtilities.cs @@ -0,0 +1,426 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Basic utility class. + public sealed class PgpUtilities + { + private PgpUtilities() + { + } + + public static MPInteger[] DsaSigToMpi( + byte[] encoding) + { + DerInteger i1, i2; + + try + { + Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + + i1 = (DerInteger) s[0]; + i2 = (DerInteger) s[1]; + } + catch (IOException e) + { + throw new PgpException("exception encoding signature", e); + } + + return new MPInteger[]{ new MPInteger(i1.Value), new MPInteger(i2.Value) }; + } + + public static MPInteger[] RsaSigToMpi( + byte[] encoding) + { + return new MPInteger[]{ new MPInteger(new BigInteger(1, encoding)) }; + } + + public static string GetDigestName( + HashAlgorithmTag hashAlgorithm) + { + switch (hashAlgorithm) + { + case HashAlgorithmTag.Sha1: + return "SHA1"; + case HashAlgorithmTag.MD2: + return "MD2"; + case HashAlgorithmTag.MD5: + return "MD5"; + case HashAlgorithmTag.RipeMD160: + return "RIPEMD160"; + case HashAlgorithmTag.Sha224: + return "SHA224"; + case HashAlgorithmTag.Sha256: + return "SHA256"; + case HashAlgorithmTag.Sha384: + return "SHA384"; + case HashAlgorithmTag.Sha512: + return "SHA512"; + default: + throw new PgpException("unknown hash algorithm tag in GetDigestName: " + hashAlgorithm); + } + } + + public static string GetSignatureName( + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm) + { + string encAlg; + switch (keyAlgorithm) + { + case PublicKeyAlgorithmTag.RsaGeneral: + case PublicKeyAlgorithmTag.RsaSign: + encAlg = "RSA"; + break; + case PublicKeyAlgorithmTag.Dsa: + encAlg = "DSA"; + break; + case PublicKeyAlgorithmTag.ElGamalEncrypt: // in some malformed cases. + case PublicKeyAlgorithmTag.ElGamalGeneral: + encAlg = "ElGamal"; + break; + default: + throw new PgpException("unknown algorithm tag in signature:" + keyAlgorithm); + } + + return GetDigestName(hashAlgorithm) + "with" + encAlg; + } + + public static string GetSymmetricCipherName( + SymmetricKeyAlgorithmTag algorithm) + { + switch (algorithm) + { + case SymmetricKeyAlgorithmTag.Null: + return null; + case SymmetricKeyAlgorithmTag.TripleDes: + return "DESEDE"; + case SymmetricKeyAlgorithmTag.Idea: + return "IDEA"; + case SymmetricKeyAlgorithmTag.Cast5: + return "CAST5"; + case SymmetricKeyAlgorithmTag.Blowfish: + return "Blowfish"; + case SymmetricKeyAlgorithmTag.Safer: + return "SAFER"; + case SymmetricKeyAlgorithmTag.Des: + return "DES"; + case SymmetricKeyAlgorithmTag.Aes128: + return "AES"; + case SymmetricKeyAlgorithmTag.Aes192: + return "AES"; + case SymmetricKeyAlgorithmTag.Aes256: + return "AES"; + case SymmetricKeyAlgorithmTag.Twofish: + return "Twofish"; + default: + throw new PgpException("unknown symmetric algorithm: " + algorithm); + } + } + + public static int GetKeySize(SymmetricKeyAlgorithmTag algorithm) + { + int keySize; + switch (algorithm) + { + case SymmetricKeyAlgorithmTag.Des: + keySize = 64; + break; + case SymmetricKeyAlgorithmTag.Idea: + case SymmetricKeyAlgorithmTag.Cast5: + case SymmetricKeyAlgorithmTag.Blowfish: + case SymmetricKeyAlgorithmTag.Safer: + case SymmetricKeyAlgorithmTag.Aes128: + keySize = 128; + break; + case SymmetricKeyAlgorithmTag.TripleDes: + case SymmetricKeyAlgorithmTag.Aes192: + keySize = 192; + break; + case SymmetricKeyAlgorithmTag.Aes256: + case SymmetricKeyAlgorithmTag.Twofish: + keySize = 256; + break; + default: + throw new PgpException("unknown symmetric algorithm: " + algorithm); + } + + return keySize; + } + + public static KeyParameter MakeKey( + SymmetricKeyAlgorithmTag algorithm, + byte[] keyBytes) + { + string algName = GetSymmetricCipherName(algorithm); + + return ParameterUtilities.CreateKeyParameter(algName, keyBytes); + } + + public static KeyParameter MakeRandomKey( + SymmetricKeyAlgorithmTag algorithm, + SecureRandom random) + { + int keySize = GetKeySize(algorithm); + byte[] keyBytes = new byte[(keySize + 7) / 8]; + random.NextBytes(keyBytes); + return MakeKey(algorithm, keyBytes); + } + + public static KeyParameter MakeKeyFromPassPhrase( + SymmetricKeyAlgorithmTag algorithm, + S2k s2k, + char[] passPhrase) + { + int keySize = GetKeySize(algorithm); + byte[] pBytes = Strings.ToByteArray(new string(passPhrase)); + byte[] keyBytes = new byte[(keySize + 7) / 8]; + + int generatedBytes = 0; + int loopCount = 0; + + while (generatedBytes < keyBytes.Length) + { + IDigest digest; + if (s2k != null) + { + string digestName = GetDigestName(s2k.HashAlgorithm); + + try + { + digest = DigestUtilities.GetDigest(digestName); + } + catch (Exception e) + { + throw new PgpException("can't find S2k digest", e); + } + + for (int i = 0; i != loopCount; i++) + { + digest.Update(0); + } + + byte[] iv = s2k.GetIV(); + + switch (s2k.Type) + { + case S2k.Simple: + digest.BlockUpdate(pBytes, 0, pBytes.Length); + break; + case S2k.Salted: + digest.BlockUpdate(iv, 0, iv.Length); + digest.BlockUpdate(pBytes, 0, pBytes.Length); + break; + case S2k.SaltedAndIterated: + long count = s2k.IterationCount; + digest.BlockUpdate(iv, 0, iv.Length); + digest.BlockUpdate(pBytes, 0, pBytes.Length); + + count -= iv.Length + pBytes.Length; + + while (count > 0) + { + if (count < iv.Length) + { + digest.BlockUpdate(iv, 0, (int)count); + break; + } + else + { + digest.BlockUpdate(iv, 0, iv.Length); + count -= iv.Length; + } + + if (count < pBytes.Length) + { + digest.BlockUpdate(pBytes, 0, (int)count); + count = 0; + } + else + { + digest.BlockUpdate(pBytes, 0, pBytes.Length); + count -= pBytes.Length; + } + } + break; + default: + throw new PgpException("unknown S2k type: " + s2k.Type); + } + } + else + { + try + { + digest = DigestUtilities.GetDigest("MD5"); + + for (int i = 0; i != loopCount; i++) + { + digest.Update(0); + } + + digest.BlockUpdate(pBytes, 0, pBytes.Length); + } + catch (Exception e) + { + throw new PgpException("can't find MD5 digest", e); + } + } + + byte[] dig = DigestUtilities.DoFinal(digest); + + if (dig.Length > (keyBytes.Length - generatedBytes)) + { + Array.Copy(dig, 0, keyBytes, generatedBytes, keyBytes.Length - generatedBytes); + } + else + { + Array.Copy(dig, 0, keyBytes, generatedBytes, dig.Length); + } + + generatedBytes += dig.Length; + + loopCount++; + } + + Array.Clear(pBytes, 0, pBytes.Length); + + return MakeKey(algorithm, keyBytes); + } + + /// Write out the passed in file as a literal data packet. + public static void WriteFileToLiteralData( + Stream output, + char fileType, + FileInfo file) + { + PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); + Stream pOut = lData.Open(output, fileType, file.Name, file.Length, file.LastWriteTime); + PipeFileContents(file, pOut, 4096); + } + + /// Write out the passed in file as a literal data packet in partial packet format. + public static void WriteFileToLiteralData( + Stream output, + char fileType, + FileInfo file, + byte[] buffer) + { + PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); + Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, buffer); + PipeFileContents(file, pOut, buffer.Length); + } + + private static void PipeFileContents(FileInfo file, Stream pOut, int bufSize) + { + FileStream inputStream = file.OpenRead(); + byte[] buf = new byte[bufSize]; + + int len; + while ((len = inputStream.Read(buf, 0, buf.Length)) > 0) + { + pOut.Write(buf, 0, len); + } + + pOut.Close(); + inputStream.Close(); + } + + private const int ReadAhead = 60; + + private static bool IsPossiblyBase64( + int ch) + { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') + || (ch >= '0' && ch <= '9') || (ch == '+') || (ch == '/') + || (ch == '\r') || (ch == '\n'); + } + + /// + /// Return either an ArmoredInputStream or a BcpgInputStream based on whether + /// the initial characters of the stream are binary PGP encodings or not. + /// + public static Stream GetDecoderStream( + Stream inputStream) + { + // TODO Remove this restriction? + if (!inputStream.CanSeek) + throw new ArgumentException("inputStream must be seek-able", "inputStream"); + + long markedPos = inputStream.Position; + + int ch = inputStream.ReadByte(); + if ((ch & 0x80) != 0) + { + inputStream.Position = markedPos; + + return inputStream; + } + else + { + if (!IsPossiblyBase64(ch)) + { + inputStream.Position = markedPos; + + return new ArmoredInputStream(inputStream); + } + + byte[] buf = new byte[ReadAhead]; + int count = 1; + int index = 1; + + buf[0] = (byte)ch; + while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0) + { + if (!IsPossiblyBase64(ch)) + { + inputStream.Position = markedPos; + + return new ArmoredInputStream(inputStream); + } + + if (ch != '\n' && ch != '\r') + { + buf[index++] = (byte)ch; + } + + count++; + } + + inputStream.Position = markedPos; + + // + // nothing but new lines, little else, assume regular armoring + // + if (count < 4) + { + return new ArmoredInputStream(inputStream); + } + + // + // test our non-blank data + // + byte[] firstBlock = new byte[8]; + Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length); + byte[] decoded = Base64.Decode(firstBlock); + + // + // it's a base64 PGP block. + // + bool hasHeaders = (decoded[0] & 0x80) == 0; + + return new ArmoredInputStream(inputStream, hasHeaders); + } + } + } +} diff --git a/crypto/src/openpgp/PgpV3SignatureGenerator.cs b/crypto/src/openpgp/PgpV3SignatureGenerator.cs new file mode 100644 index 000000000..fc8b42df2 --- /dev/null +++ b/crypto/src/openpgp/PgpV3SignatureGenerator.cs @@ -0,0 +1,199 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// Generator for old style PGP V3 Signatures. + // TODO Should be able to implement ISigner? + public class PgpV3SignatureGenerator + { + private PublicKeyAlgorithmTag keyAlgorithm; + private HashAlgorithmTag hashAlgorithm; + private PgpPrivateKey privKey; + private ISigner sig; + private IDigest dig; + private int signatureType; + private byte lastb; + + /// Create a generator for the passed in keyAlgorithm and hashAlgorithm codes. + public PgpV3SignatureGenerator( + PublicKeyAlgorithmTag keyAlgorithm, + HashAlgorithmTag hashAlgorithm) + { + this.keyAlgorithm = keyAlgorithm; + this.hashAlgorithm = hashAlgorithm; + + dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm)); + sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm)); + } + + /// Initialise the generator for signing. + public void InitSign( + int sigType, + PgpPrivateKey key) + { + InitSign(sigType, key, null); + } + + /// Initialise the generator for signing. + public void InitSign( + int sigType, + PgpPrivateKey key, + SecureRandom random) + { + this.privKey = key; + this.signatureType = sigType; + + try + { + ICipherParameters cp = key.Key; + if (random != null) + { + cp = new ParametersWithRandom(key.Key, random); + } + + sig.Init(true, cp); + } + catch (InvalidKeyException e) + { + throw new PgpException("invalid key.", e); + } + + dig.Reset(); + lastb = 0; + } + + public void Update( + byte b) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + doCanonicalUpdateByte(b); + } + else + { + doUpdateByte(b); + } + } + + private void doCanonicalUpdateByte( + byte b) + { + if (b == '\r') + { + doUpdateCRLF(); + } + else if (b == '\n') + { + if (lastb != '\r') + { + doUpdateCRLF(); + } + } + else + { + doUpdateByte(b); + } + + lastb = b; + } + + private void doUpdateCRLF() + { + doUpdateByte((byte)'\r'); + doUpdateByte((byte)'\n'); + } + + private void doUpdateByte( + byte b) + { + sig.Update(b); + dig.Update(b); + } + + public void Update( + byte[] b) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + for (int i = 0; i != b.Length; i++) + { + doCanonicalUpdateByte(b[i]); + } + } + else + { + sig.BlockUpdate(b, 0, b.Length); + dig.BlockUpdate(b, 0, b.Length); + } + } + + public void Update( + byte[] b, + int off, + int len) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + int finish = off + len; + + for (int i = off; i != finish; i++) + { + doCanonicalUpdateByte(b[i]); + } + } + else + { + sig.BlockUpdate(b, off, len); + dig.BlockUpdate(b, off, len); + } + } + + /// Return the one pass header associated with the current signature. + public PgpOnePassSignature GenerateOnePassVersion( + bool isNested) + { + return new PgpOnePassSignature( + new OnePassSignaturePacket(signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested)); + } + + /// Return a V3 signature object containing the current signature state. + public PgpSignature Generate() + { + long creationTime = DateTimeUtilities.CurrentUnixMs() / 1000L; + + byte[] hData = new byte[] + { + (byte) signatureType, + (byte)(creationTime >> 24), + (byte)(creationTime >> 16), + (byte)(creationTime >> 8), + (byte) creationTime + }; + + sig.BlockUpdate(hData, 0, hData.Length); + dig.BlockUpdate(hData, 0, hData.Length); + + byte[] sigBytes = sig.GenerateSignature(); + byte[] digest = DigestUtilities.DoFinal(dig); + byte[] fingerPrint = new byte[]{ digest[0], digest[1] }; + + // an RSA signature + bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign + || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral; + + MPInteger[] sigValues = isRsa + ? PgpUtilities.RsaSigToMpi(sigBytes) + : PgpUtilities.DsaSigToMpi(sigBytes); + + return new PgpSignature( + new SignaturePacket(3, signatureType, privKey.KeyId, keyAlgorithm, + hashAlgorithm, creationTime * 1000L, fingerPrint, sigValues)); + } + } +} diff --git a/crypto/src/openpgp/WrappedGeneratorStream.cs b/crypto/src/openpgp/WrappedGeneratorStream.cs new file mode 100644 index 000000000..6fc7329af --- /dev/null +++ b/crypto/src/openpgp/WrappedGeneratorStream.cs @@ -0,0 +1,25 @@ +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + public class WrappedGeneratorStream + : FilterStream + { + private readonly IStreamGenerator gen; + + public WrappedGeneratorStream( + IStreamGenerator gen, + Stream str) + : base(str) + { + this.gen = gen; + } + + public override void Close() + { + gen.Close(); + } + } +} diff --git a/crypto/src/openssl/EncryptionException.cs b/crypto/src/openssl/EncryptionException.cs new file mode 100644 index 000000000..c4a6ec02f --- /dev/null +++ b/crypto/src/openssl/EncryptionException.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class EncryptionException + : IOException + { + public EncryptionException( + string message) + : base(message) + { + } + + public EncryptionException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/openssl/IPasswordFinder.cs b/crypto/src/openssl/IPasswordFinder.cs new file mode 100644 index 000000000..4fcef1bd7 --- /dev/null +++ b/crypto/src/openssl/IPasswordFinder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.OpenSsl +{ + public interface IPasswordFinder + { + char[] GetPassword(); + } +} diff --git a/crypto/src/openssl/MiscPemGenerator.cs b/crypto/src/openssl/MiscPemGenerator.cs new file mode 100644 index 000000000..c4c537904 --- /dev/null +++ b/crypto/src/openssl/MiscPemGenerator.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO.Pem; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.OpenSsl +{ + /** + * PEM generator for the original set of PEM objects used in Open SSL. + */ + public class MiscPemGenerator + : PemObjectGenerator + { + private object obj; + private string algorithm; + private char[] password; + private SecureRandom random; + + public MiscPemGenerator(object obj) + { + this.obj = obj; + } + + public MiscPemGenerator( + object obj, + string algorithm, + char[] password, + SecureRandom random) + { + this.obj = obj; + this.algorithm = algorithm; + this.password = password; + this.random = random; + } + + private static PemObject CreatePemObject(object obj) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + if (obj is AsymmetricCipherKeyPair) + { + return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private); + } + + string type; + byte[] encoding; + + if (obj is PemObject) + return (PemObject)obj; + + if (obj is PemObjectGenerator) + return ((PemObjectGenerator)obj).Generate(); + + if (obj is X509Certificate) + { + // TODO Should we prefer "X509 CERTIFICATE" here? + type = "CERTIFICATE"; + try + { + encoding = ((X509Certificate)obj).GetEncoded(); + } + catch (CertificateEncodingException e) + { + throw new IOException("Cannot Encode object: " + e.ToString()); + } + } + else if (obj is X509Crl) + { + type = "X509 CRL"; + try + { + encoding = ((X509Crl)obj).GetEncoded(); + } + catch (CrlException e) + { + throw new IOException("Cannot Encode object: " + e.ToString()); + } + } + else if (obj is AsymmetricKeyParameter) + { + AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; + if (akp.IsPrivate) + { + string keyType; + encoding = EncodePrivateKey(akp, out keyType); + + type = keyType + " PRIVATE KEY"; + } + else + { + type = "PUBLIC KEY"; + + encoding = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(akp).GetDerEncoded(); + } + } + else if (obj is IX509AttributeCertificate) + { + type = "ATTRIBUTE CERTIFICATE"; + encoding = ((X509V2AttributeCertificate)obj).GetEncoded(); + } + else if (obj is Pkcs10CertificationRequest) + { + type = "CERTIFICATE REQUEST"; + encoding = ((Pkcs10CertificationRequest)obj).GetEncoded(); + } + else if (obj is Asn1.Cms.ContentInfo) + { + type = "PKCS7"; + encoding = ((Asn1.Cms.ContentInfo)obj).GetEncoded(); + } + else + { + throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); + } + + return new PemObject(type, encoding); + } + +// private string GetHexEncoded(byte[] bytes) +// { +// bytes = Hex.Encode(bytes); +// +// char[] chars = new char[bytes.Length]; +// +// for (int i = 0; i != bytes.Length; i++) +// { +// chars[i] = (char)bytes[i]; +// } +// +// return new string(chars); +// } + + private static PemObject CreatePemObject( + object obj, + string algorithm, + char[] password, + SecureRandom random) + { + if (obj == null) + throw new ArgumentNullException("obj"); + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (password == null) + throw new ArgumentNullException("password"); + if (random == null) + throw new ArgumentNullException("random"); + + if (obj is AsymmetricCipherKeyPair) + { + return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random); + } + + string type = null; + byte[] keyData = null; + + if (obj is AsymmetricKeyParameter) + { + AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; + if (akp.IsPrivate) + { + string keyType; + keyData = EncodePrivateKey(akp, out keyType); + + type = keyType + " PRIVATE KEY"; + } + } + + if (type == null || keyData == null) + { + // TODO Support other types? + throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); + } + + + string dekAlgName = Platform.ToUpperInvariant(algorithm); + + // Note: For backward compatibility + if (dekAlgName == "DESEDE") + { + dekAlgName = "DES-EDE3-CBC"; + } + + int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8; + + byte[] iv = new byte[ivLength]; + random.NextBytes(iv); + + byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv); + + IList headers = Platform.CreateArrayList(2); + + headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED")); + headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv))); + + return new PemObject(type, headers, encData); + } + + private static byte[] EncodePrivateKey( + AsymmetricKeyParameter akp, + out string keyType) + { + PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp); + + DerObjectIdentifier oid = info.AlgorithmID.ObjectID; + + if (oid.Equals(X9ObjectIdentifiers.IdDsa)) + { + keyType = "DSA"; + + DsaParameter p = DsaParameter.GetInstance(info.AlgorithmID.Parameters); + + BigInteger x = ((DsaPrivateKeyParameters) akp).X; + BigInteger y = p.G.ModPow(x, p.P); + + // TODO Create an ASN1 object somewhere for this? + return new DerSequence( + new DerInteger(0), + new DerInteger(p.P), + new DerInteger(p.Q), + new DerInteger(p.G), + new DerInteger(y), + new DerInteger(x)).GetEncoded(); + } + + if (oid.Equals(PkcsObjectIdentifiers.RsaEncryption)) + { + keyType = "RSA"; + } + else if (oid.Equals(CryptoProObjectIdentifiers.GostR3410x2001) + || oid.Equals(X9ObjectIdentifiers.IdECPublicKey)) + { + keyType = "EC"; + } + else + { + throw new ArgumentException("Cannot handle private key of type: " + akp.GetType().FullName, "akp"); + } + + return info.PrivateKey.GetEncoded(); + } + + public PemObject Generate() + { + try + { + if (algorithm != null) + { + return CreatePemObject(obj, algorithm, password, random); + } + + return CreatePemObject(obj); + } + catch (IOException e) + { + throw new PemGenerationException("encoding exception", e); + } + } + } +} diff --git a/crypto/src/openssl/PEMException.cs b/crypto/src/openssl/PEMException.cs new file mode 100644 index 000000000..4d33a2a1f --- /dev/null +++ b/crypto/src/openssl/PEMException.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.OpenSsl +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PemException + : IOException + { + public PemException( + string message) + : base(message) + { + } + + public PemException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs new file mode 100644 index 000000000..a2fedab96 --- /dev/null +++ b/crypto/src/openssl/PEMReader.cs @@ -0,0 +1,407 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO.Pem; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.OpenSsl +{ + /** + * Class for reading OpenSSL PEM encoded streams containing + * X509 certificates, PKCS8 encoded keys and PKCS7 objects. + *

    + * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and + * Certificates will be returned using the appropriate java.security type.

    + */ + public class PemReader + : Org.BouncyCastle.Utilities.IO.Pem.PemReader + { +// private static readonly IDictionary parsers = new Hashtable(); + + static PemReader() + { +// parsers.Add("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); +// parsers.Add("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); +// parsers.Add("CERTIFICATE", new X509CertificateParser(provider)); +// parsers.Add("X509 CERTIFICATE", new X509CertificateParser(provider)); +// parsers.Add("X509 CRL", new X509CRLParser(provider)); +// parsers.Add("PKCS7", new PKCS7Parser()); +// parsers.Add("ATTRIBUTE CERTIFICATE", new X509AttributeCertificateParser()); +// parsers.Add("EC PARAMETERS", new ECNamedCurveSpecParser()); +// parsers.Add("PUBLIC KEY", new PublicKeyParser(provider)); +// parsers.Add("RSA PUBLIC KEY", new RSAPublicKeyParser(provider)); +// parsers.Add("RSA PRIVATE KEY", new RSAKeyPairParser(provider)); +// parsers.Add("DSA PRIVATE KEY", new DSAKeyPairParser(provider)); +// parsers.Add("EC PRIVATE KEY", new ECDSAKeyPairParser(provider)); +// parsers.Add("ENCRYPTED PRIVATE KEY", new EncryptedPrivateKeyParser(provider)); +// parsers.Add("PRIVATE KEY", new PrivateKeyParser(provider)); + } + + private readonly IPasswordFinder pFinder; + + /** + * Create a new PemReader + * + * @param reader the Reader + */ + public PemReader( + TextReader reader) + : this(reader, null) + { + } + + /** + * Create a new PemReader with a password finder + * + * @param reader the Reader + * @param pFinder the password finder + */ + public PemReader( + TextReader reader, + IPasswordFinder pFinder) + : base(reader) + { + this.pFinder = pFinder; + } + + public object ReadObject() + { + PemObject obj = ReadPemObject(); + + if (obj == null) + return null; + + // TODO Follow Java build and map to parser objects? +// if (parsers.Contains(obj.Type)) +// return ((PemObjectParser)parsers[obj.Type]).ParseObject(obj); + + if (obj.Type.EndsWith("PRIVATE KEY")) + return ReadPrivateKey(obj); + + switch (obj.Type) + { + case "PUBLIC KEY": + return ReadPublicKey(obj); + case "RSA PUBLIC KEY": + return ReadRsaPublicKey(obj); + case "CERTIFICATE REQUEST": + case "NEW CERTIFICATE REQUEST": + return ReadCertificateRequest(obj); + case "CERTIFICATE": + case "X509 CERTIFICATE": + return ReadCertificate(obj); + case "PKCS7": + return ReadPkcs7(obj); + case "X509 CRL": + return ReadCrl(obj); + case "ATTRIBUTE CERTIFICATE": + return ReadAttributeCertificate(obj); + // TODO Add back in when tests done, and return type issue resolved + //case "EC PARAMETERS": + // return ReadECParameters(obj); + default: + throw new IOException("unrecognised object: " + obj.Type); + } + } + + private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject) + { + RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance( + Asn1Object.FromByteArray(pemObject.Content)); + + return new RsaKeyParameters( + false, // not private + rsaPubStructure.Modulus, + rsaPubStructure.PublicExponent); + } + + private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject) + { + return PublicKeyFactory.CreateKey(pemObject.Content); + } + + /** + * Reads in a X509Certificate. + * + * @return the X509Certificate + * @throws IOException if an I/O error occured + */ + private X509Certificate ReadCertificate(PemObject pemObject) + { + try + { + return new X509CertificateParser().ReadCertificate(pemObject.Content); + } + catch (Exception e) + { + throw new PemException("problem parsing cert: " + e.ToString()); + } + } + + /** + * Reads in a X509CRL. + * + * @return the X509Certificate + * @throws IOException if an I/O error occured + */ + private X509Crl ReadCrl(PemObject pemObject) + { + try + { + return new X509CrlParser().ReadCrl(pemObject.Content); + } + catch (Exception e) + { + throw new PemException("problem parsing cert: " + e.ToString()); + } + } + + /** + * Reads in a PKCS10 certification request. + * + * @return the certificate request. + * @throws IOException if an I/O error occured + */ + private Pkcs10CertificationRequest ReadCertificateRequest(PemObject pemObject) + { + try + { + return new Pkcs10CertificationRequest(pemObject.Content); + } + catch (Exception e) + { + throw new PemException("problem parsing cert: " + e.ToString()); + } + } + + /** + * Reads in a X509 Attribute Certificate. + * + * @return the X509 Attribute Certificate + * @throws IOException if an I/O error occured + */ + private IX509AttributeCertificate ReadAttributeCertificate(PemObject pemObject) + { + return new X509V2AttributeCertificate(pemObject.Content); + } + + /** + * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS + * API. + * + * @return the X509Certificate + * @throws IOException if an I/O error occured + */ + // TODO Consider returning Asn1.Pkcs.ContentInfo + private Asn1.Cms.ContentInfo ReadPkcs7(PemObject pemObject) + { + try + { + return Asn1.Cms.ContentInfo.GetInstance( + Asn1Object.FromByteArray(pemObject.Content)); + } + catch (Exception e) + { + throw new PemException("problem parsing PKCS7 object: " + e.ToString()); + } + } + + /** + * Read a Key Pair + */ + private object ReadPrivateKey(PemObject pemObject) + { + // + // extract the key + // + Debug.Assert(pemObject.Type.EndsWith("PRIVATE KEY")); + + string type = pemObject.Type.Substring(0, pemObject.Type.Length - "PRIVATE KEY".Length).Trim(); + byte[] keyBytes = pemObject.Content; + + IDictionary fields = Platform.CreateHashtable(); + foreach (PemHeader header in pemObject.Headers) + { + fields[header.Name] = header.Value; + } + + string procType = (string) fields["Proc-Type"]; + + if (procType == "4,ENCRYPTED") + { + if (pFinder == null) + throw new PasswordException("No password finder specified, but a password is required"); + + char[] password = pFinder.GetPassword(); + + if (password == null) + throw new PasswordException("Password is null, but a password is required"); + + string dekInfo = (string) fields["DEK-Info"]; + string[] tknz = dekInfo.Split(','); + + string dekAlgName = tknz[0].Trim(); + byte[] iv = Hex.Decode(tknz[1].Trim()); + + keyBytes = PemUtilities.Crypt(false, keyBytes, password, dekAlgName, iv); + } + + try + { + AsymmetricKeyParameter pubSpec, privSpec; + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(keyBytes); + + switch (type) + { + case "RSA": + { + if (seq.Count != 9) + throw new PemException("malformed sequence in RSA private key"); + + RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq); + + pubSpec = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent); + privSpec = new RsaPrivateCrtKeyParameters( + rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, + rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, + rsa.Coefficient); + + break; + } + + case "DSA": + { + if (seq.Count != 6) + throw new PemException("malformed sequence in DSA private key"); + + // TODO Create an ASN1 object somewhere for this? + //DerInteger v = (DerInteger)seq[0]; + DerInteger p = (DerInteger)seq[1]; + DerInteger q = (DerInteger)seq[2]; + DerInteger g = (DerInteger)seq[3]; + DerInteger y = (DerInteger)seq[4]; + DerInteger x = (DerInteger)seq[5]; + + DsaParameters parameters = new DsaParameters(p.Value, q.Value, g.Value); + + privSpec = new DsaPrivateKeyParameters(x.Value, parameters); + pubSpec = new DsaPublicKeyParameters(y.Value, parameters); + + break; + } + + case "EC": + { + ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq); + AlgorithmIdentifier algId = new AlgorithmIdentifier( + X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters()); + + PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object()); + + // TODO Are the keys returned here ECDSA, as Java version forces? + privSpec = PrivateKeyFactory.CreateKey(privInfo); + + DerBitString pubKey = pKey.GetPublicKey(); + if (pubKey != null) + { + SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes()); + + // TODO Are the keys returned here ECDSA, as Java version forces? + pubSpec = PublicKeyFactory.CreateKey(pubInfo); + } + else + { + pubSpec = ECKeyPairGenerator.GetCorrespondingPublicKey( + (ECPrivateKeyParameters)privSpec); + } + + break; + } + + case "ENCRYPTED": + { + char[] password = pFinder.GetPassword(); + + if (password == null) + throw new PasswordException("Password is null, but a password is required"); + + return PrivateKeyFactory.DecryptKey(password, EncryptedPrivateKeyInfo.GetInstance(seq)); + } + + case "": + { + return PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(seq)); + } + + default: + throw new ArgumentException("Unknown key type: " + type, "type"); + } + + return new AsymmetricCipherKeyPair(pubSpec, privSpec); + } + catch (IOException e) + { + throw e; + } + catch (Exception e) + { + throw new PemException( + "problem creating " + type + " private key: " + e.ToString()); + } + } + + // TODO Add an equivalent class for ECNamedCurveParameterSpec? + //private ECNamedCurveParameterSpec ReadECParameters( +// private X9ECParameters ReadECParameters(PemObject pemObject) +// { +// DerObjectIdentifier oid = (DerObjectIdentifier)Asn1Object.FromByteArray(pemObject.Content); +// +// //return ECNamedCurveTable.getParameterSpec(oid.Id); +// return GetCurveParameters(oid.Id); +// } + + //private static ECDomainParameters GetCurveParameters( + private static X9ECParameters GetCurveParameters( + string name) + { + // TODO ECGost3410NamedCurves support (returns ECDomainParameters though) + X9ECParameters ecP = X962NamedCurves.GetByName(name); + + if (ecP == null) + { + ecP = SecNamedCurves.GetByName(name); + if (ecP == null) + { + ecP = NistNamedCurves.GetByName(name); + if (ecP == null) + { + ecP = TeleTrusTNamedCurves.GetByName(name); + + if (ecP == null) + throw new Exception("unknown curve name: " + name); + } + } + } + + //return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed()); + return ecP; + } + } +} diff --git a/crypto/src/openssl/PEMUtilities.cs b/crypto/src/openssl/PEMUtilities.cs new file mode 100644 index 000000000..b58e5e765 --- /dev/null +++ b/crypto/src/openssl/PEMUtilities.cs @@ -0,0 +1,158 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.OpenSsl +{ + internal sealed class PemUtilities + { + private enum PemBaseAlg { AES_128, AES_192, AES_256, BF, DES, DES_EDE, DES_EDE3, RC2, RC2_40, RC2_64 }; + private enum PemMode { CBC, CFB, ECB, OFB }; + + static PemUtilities() + { + // Signal to obfuscation tools not to change enum constants + ((PemBaseAlg)Enums.GetArbitraryValue(typeof(PemBaseAlg))).ToString(); + ((PemMode)Enums.GetArbitraryValue(typeof(PemMode))).ToString(); + } + + private static void ParseDekAlgName( + string dekAlgName, + out PemBaseAlg baseAlg, + out PemMode mode) + { + try + { + mode = PemMode.ECB; + + if (dekAlgName == "DES-EDE" || dekAlgName == "DES-EDE3") + { + baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName); + return; + } + + int pos = dekAlgName.LastIndexOf('-'); + if (pos >= 0) + { + baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName.Substring(0, pos)); + mode = (PemMode)Enums.GetEnumValue(typeof(PemMode), dekAlgName.Substring(pos + 1)); + return; + } + } + catch (ArgumentException) + { + } + + throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); + } + + internal static byte[] Crypt( + bool encrypt, + byte[] bytes, + char[] password, + string dekAlgName, + byte[] iv) + { + PemBaseAlg baseAlg; + PemMode mode; + ParseDekAlgName(dekAlgName, out baseAlg, out mode); + + string padding; + switch (mode) + { + case PemMode.CBC: + case PemMode.ECB: + padding = "PKCS5Padding"; + break; + case PemMode.CFB: + case PemMode.OFB: + padding = "NoPadding"; + break; + default: + throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); + } + + string algorithm; + + byte[] salt = iv; + switch (baseAlg) + { + case PemBaseAlg.AES_128: + case PemBaseAlg.AES_192: + case PemBaseAlg.AES_256: + algorithm = "AES"; + if (salt.Length > 8) + { + salt = new byte[8]; + Array.Copy(iv, 0, salt, 0, salt.Length); + } + break; + case PemBaseAlg.BF: + algorithm = "BLOWFISH"; + break; + case PemBaseAlg.DES: + algorithm = "DES"; + break; + case PemBaseAlg.DES_EDE: + case PemBaseAlg.DES_EDE3: + algorithm = "DESede"; + break; + case PemBaseAlg.RC2: + case PemBaseAlg.RC2_40: + case PemBaseAlg.RC2_64: + algorithm = "RC2"; + break; + default: + throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); + } + + string cipherName = algorithm + "/" + mode + "/" + padding; + IBufferedCipher cipher = CipherUtilities.GetCipher(cipherName); + + ICipherParameters cParams = GetCipherParameters(password, baseAlg, salt); + + if (mode != PemMode.ECB) + { + cParams = new ParametersWithIV(cParams, iv); + } + + cipher.Init(encrypt, cParams); + + return cipher.DoFinal(bytes); + } + + private static ICipherParameters GetCipherParameters( + char[] password, + PemBaseAlg baseAlg, + byte[] salt) + { + string algorithm; + int keyBits; + switch (baseAlg) + { + case PemBaseAlg.AES_128: keyBits = 128; algorithm = "AES128"; break; + case PemBaseAlg.AES_192: keyBits = 192; algorithm = "AES192"; break; + case PemBaseAlg.AES_256: keyBits = 256; algorithm = "AES256"; break; + case PemBaseAlg.BF: keyBits = 128; algorithm = "BLOWFISH"; break; + case PemBaseAlg.DES: keyBits = 64; algorithm = "DES"; break; + case PemBaseAlg.DES_EDE: keyBits = 128; algorithm = "DESEDE"; break; + case PemBaseAlg.DES_EDE3: keyBits = 192; algorithm = "DESEDE3"; break; + case PemBaseAlg.RC2: keyBits = 128; algorithm = "RC2"; break; + case PemBaseAlg.RC2_40: keyBits = 40; algorithm = "RC2"; break; + case PemBaseAlg.RC2_64: keyBits = 64; algorithm = "RC2"; break; + default: + return null; + } + + OpenSslPbeParametersGenerator pGen = new OpenSslPbeParametersGenerator(); + + pGen.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt); + + return pGen.GenerateDerivedParameters(algorithm, keyBits); + } + } +} diff --git a/crypto/src/openssl/PEMWriter.cs b/crypto/src/openssl/PEMWriter.cs new file mode 100644 index 000000000..aefb018f3 --- /dev/null +++ b/crypto/src/openssl/PEMWriter.cs @@ -0,0 +1,61 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO.Pem; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.OpenSsl +{ + /// General purpose writer for OpenSSL PEM objects. + public class PemWriter + : Org.BouncyCastle.Utilities.IO.Pem.PemWriter + { + /// The TextWriter object to write the output to. + public PemWriter( + TextWriter writer) + : base(writer) + { + } + + public void WriteObject( + object obj) + { + try + { + base.WriteObject(new MiscPemGenerator(obj)); + } + catch (PemGenerationException e) + { + if (e.InnerException is IOException) + throw (IOException)e.InnerException; + + throw e; + } + } + + public void WriteObject( + object obj, + string algorithm, + char[] password, + SecureRandom random) + { + base.WriteObject(new MiscPemGenerator(obj, algorithm, password, random)); + } + } +} diff --git a/crypto/src/openssl/PasswordException.cs b/crypto/src/openssl/PasswordException.cs new file mode 100644 index 000000000..fba958aa0 --- /dev/null +++ b/crypto/src/openssl/PasswordException.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PasswordException + : IOException + { + public PasswordException( + string message) + : base(message) + { + } + + public PasswordException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/openssl/Pkcs8Generator.cs b/crypto/src/openssl/Pkcs8Generator.cs new file mode 100644 index 000000000..d03ea08d2 --- /dev/null +++ b/crypto/src/openssl/Pkcs8Generator.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO.Pem; + +namespace Org.BouncyCastle.OpenSsl +{ + public class Pkcs8Generator + : PemObjectGenerator + { + // FIXME See PbeUtilities static constructor +// public static readonly string Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc.Id; +// public static readonly string Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc.Id; +// public static readonly string Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc.Id; +// +// public static readonly string Des3Cbc = PkcsObjectIdentifiers.DesEde3Cbc.Id; + + public static readonly string PbeSha1_RC4_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id; + public static readonly string PbeSha1_RC4_40 = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id; + public static readonly string PbeSha1_3DES = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id; + public static readonly string PbeSha1_2DES = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id; + public static readonly string PbeSha1_RC2_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id; + public static readonly string PbeSha1_RC2_40 = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id; + + private char[] password; + private string algorithm; + private int iterationCount; + private AsymmetricKeyParameter privKey; + private SecureRandom random; + + /** + * Constructor for an unencrypted private key PEM object. + * + * @param key private key to be encoded. + */ + public Pkcs8Generator(AsymmetricKeyParameter privKey) + { + this.privKey = privKey; + } + + /** + * Constructor for an encrypted private key PEM object. + * + * @param key private key to be encoded + * @param algorithm encryption algorithm to use + * @param provider provider to use + * @throws NoSuchAlgorithmException if algorithm/mode cannot be found + */ + public Pkcs8Generator(AsymmetricKeyParameter privKey, string algorithm) + { + // TODO Check privKey.IsPrivate + this.privKey = privKey; + this.algorithm = algorithm; + this.iterationCount = 2048; + } + + public SecureRandom SecureRandom + { + set { this.random = value; } + } + + public char[] Password + { + set { this.password = value; } + } + + public int IterationCount + { + set { this.iterationCount = value; } + } + + public PemObject Generate() + { + if (algorithm == null) + { + PrivateKeyInfo pki = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privKey); + + return new PemObject("PRIVATE KEY", pki.GetEncoded()); + } + + // TODO Theoretically, the amount of salt needed depends on the algorithm + byte[] salt = new byte[20]; + if (random == null) + { + random = new SecureRandom(); + } + random.NextBytes(salt); + + try + { + EncryptedPrivateKeyInfo epki = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + algorithm, password, salt, iterationCount, privKey); + + return new PemObject("ENCRYPTED PRIVATE KEY", epki.GetEncoded()); + } + catch (Exception e) + { + throw new PemGenerationException("Couldn't encrypt private key", e); + } + } + } +} diff --git a/crypto/src/pkcs/AsymmetricKeyEntry.cs b/crypto/src/pkcs/AsymmetricKeyEntry.cs new file mode 100644 index 000000000..1c37631d5 --- /dev/null +++ b/crypto/src/pkcs/AsymmetricKeyEntry.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Pkcs +{ + public class AsymmetricKeyEntry + : Pkcs12Entry + { + private readonly AsymmetricKeyParameter key; + + public AsymmetricKeyEntry( + AsymmetricKeyParameter key) + : base(Platform.CreateHashtable()) + { + this.key = key; + } + +#if !SILVERLIGHT + [Obsolete] + public AsymmetricKeyEntry( + AsymmetricKeyParameter key, + Hashtable attributes) + : base(attributes) + { + this.key = key; + } +#endif + + public AsymmetricKeyEntry( + AsymmetricKeyParameter key, + IDictionary attributes) + : base(attributes) + { + this.key = key; + } + + public AsymmetricKeyParameter Key + { + get { return this.key; } + } + + public override bool Equals(object obj) + { + AsymmetricKeyEntry other = obj as AsymmetricKeyEntry; + + if (other == null) + return false; + + return key.Equals(other.key); + } + + public override int GetHashCode() + { + return ~key.GetHashCode(); + } + } +} diff --git a/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs b/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs new file mode 100644 index 000000000..b6b7bac65 --- /dev/null +++ b/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs @@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Pkcs +{ + public sealed class EncryptedPrivateKeyInfoFactory + { + private EncryptedPrivateKeyInfoFactory() + { + } + + public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo( + DerObjectIdentifier algorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + AsymmetricKeyParameter key) + { + return CreateEncryptedPrivateKeyInfo( + algorithm.Id, passPhrase, salt, iterationCount, + PrivateKeyInfoFactory.CreatePrivateKeyInfo(key)); + } + + public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo( + string algorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + AsymmetricKeyParameter key) + { + return CreateEncryptedPrivateKeyInfo( + algorithm, passPhrase, salt, iterationCount, + PrivateKeyInfoFactory.CreatePrivateKeyInfo(key)); + } + + public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo( + string algorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + PrivateKeyInfo keyInfo) + { + IBufferedCipher cipher = PbeUtilities.CreateEngine(algorithm) as IBufferedCipher; + if (cipher == null) + throw new Exception("Unknown encryption algorithm: " + algorithm); + + Asn1Encodable pbeParameters = PbeUtilities.GenerateAlgorithmParameters( + algorithm, salt, iterationCount); + ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters( + algorithm, passPhrase, pbeParameters); + cipher.Init(true, cipherParameters); + byte[] encoding = cipher.DoFinal(keyInfo.GetEncoded()); + + DerObjectIdentifier oid = PbeUtilities.GetObjectIdentifier(algorithm); + AlgorithmIdentifier algID = new AlgorithmIdentifier(oid, pbeParameters); + return new EncryptedPrivateKeyInfo(algID, encoding); + } + } +} diff --git a/crypto/src/pkcs/PKCS12StoreBuilder.cs b/crypto/src/pkcs/PKCS12StoreBuilder.cs new file mode 100644 index 000000000..c8fa0f603 --- /dev/null +++ b/crypto/src/pkcs/PKCS12StoreBuilder.cs @@ -0,0 +1,41 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; + +namespace Org.BouncyCastle.Pkcs +{ + public class Pkcs12StoreBuilder + { + private DerObjectIdentifier keyAlgorithm = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc; + private DerObjectIdentifier certAlgorithm = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc; + private bool useDerEncoding = false; + + public Pkcs12StoreBuilder() + { + } + + public Pkcs12Store Build() + { + return new Pkcs12Store(keyAlgorithm, certAlgorithm, useDerEncoding); + } + + public Pkcs12StoreBuilder SetCertAlgorithm(DerObjectIdentifier certAlgorithm) + { + this.certAlgorithm = certAlgorithm; + return this; + } + + public Pkcs12StoreBuilder SetKeyAlgorithm(DerObjectIdentifier keyAlgorithm) + { + this.keyAlgorithm = keyAlgorithm; + return this; + } + + public Pkcs12StoreBuilder SetUseDerEncoding(bool useDerEncoding) + { + this.useDerEncoding = useDerEncoding; + return this; + } + } +} diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs new file mode 100644 index 000000000..9f24eb18a --- /dev/null +++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkcs +{ + /// + /// A class for verifying and creating Pkcs10 Certification requests. + /// + /// + /// CertificationRequest ::= Sequence { + /// certificationRequestInfo CertificationRequestInfo, + /// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, + /// signature BIT STRING + /// } + /// + /// CertificationRequestInfo ::= Sequence { + /// version Integer { v1(0) } (v1,...), + /// subject Name, + /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, + /// attributes [0] Attributes{{ CRIAttributes }} + /// } + /// + /// Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }} + /// + /// Attr { ATTRIBUTE:IOSet } ::= Sequence { + /// type ATTRIBUTE.&id({IOSet}), + /// values Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type}) + /// } + /// + /// see + public class Pkcs10CertificationRequest + : CertificationRequest + { + protected static readonly IDictionary algorithms = Platform.CreateHashtable(); + protected static readonly IDictionary exParams = Platform.CreateHashtable(); + protected static readonly IDictionary keyAlgorithms = Platform.CreateHashtable(); + protected static readonly IDictionary oids = Platform.CreateHashtable(); + protected static readonly ISet noParams = new HashSet(); + + static Pkcs10CertificationRequest() + { + algorithms.Add("MD2WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.Add("MD2WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.Add("MD5WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.Add("MD5WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.Add("RSAWITHMD5", new DerObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.Add("SHA1WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.Add("SHA1WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("RSAWITHSHA1", new DerObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("SHA1WITHDSA", new DerObjectIdentifier("1.2.840.10040.4.3")); + algorithms.Add("DSAWITHSHA1", new DerObjectIdentifier("1.2.840.10040.4.3")); + algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224); + algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256); + algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384); + algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512); + algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + algorithms.Add("GOST3410WITHGOST3411", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + + // + // reverse mappings + // + oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384WITHRSA"); + oids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512WITHRSA"); + oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411WITHGOST3410"); + oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, "GOST3411WITHECGOST3410"); + + oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); + oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); + oids.Add(new DerObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384WITHECDSA"); + oids.Add(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512WITHECDSA"); + oids.Add(OiwObjectIdentifiers.Sha1WithRsa, "SHA1WITHRSA"); + oids.Add(OiwObjectIdentifiers.DsaWithSha1, "SHA1WITHDSA"); + oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA"); + oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA"); + + // + // key types + // + keyAlgorithms.Add(PkcsObjectIdentifiers.RsaEncryption, "RSA"); + keyAlgorithms.Add(X9ObjectIdentifiers.IdDsa, "DSA"); + + // + // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. + // The parameters field SHALL be NULL for RSA based signature algorithms. + // + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512); + noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1); + noParams.Add(NistObjectIdentifiers.DsaWithSha224); + noParams.Add(NistObjectIdentifiers.DsaWithSha256); + + // + // RFC 4491 + // + noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + + // + // explicit params + // + AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); + exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20)); + + AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance); + exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28)); + + AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance); + exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32)); + + AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance); + exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48)); + + AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance); + exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64)); + } + + private static RsassaPssParameters CreatePssParams( + AlgorithmIdentifier hashAlgId, + int saltSize) + { + return new RsassaPssParameters( + hashAlgId, + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId), + new DerInteger(saltSize), + new DerInteger(1)); + } + + protected Pkcs10CertificationRequest() + { + } + + public Pkcs10CertificationRequest( + byte[] encoded) + : base((Asn1Sequence) Asn1Object.FromByteArray(encoded)) + { + } + + public Pkcs10CertificationRequest( + Asn1Sequence seq) + : base(seq) + { + } + + public Pkcs10CertificationRequest( + Stream input) + : base((Asn1Sequence) Asn1Object.FromStream(input)) + { + } + + /// + /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials. + /// + ///Name of Sig Alg. + /// X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" + /// Public Key to be included in cert reqest. + /// ASN1Set of Attributes. + /// Matching Private key for nominated (above) public key to be used to sign the request. + public Pkcs10CertificationRequest( + string signatureAlgorithm, + X509Name subject, + AsymmetricKeyParameter publicKey, + Asn1Set attributes, + AsymmetricKeyParameter signingKey) + { + if (signatureAlgorithm == null) + throw new ArgumentNullException("signatureAlgorithm"); + if (subject == null) + throw new ArgumentNullException("subject"); + if (publicKey == null) + throw new ArgumentNullException("publicKey"); + if (publicKey.IsPrivate) + throw new ArgumentException("expected public key", "publicKey"); + if (!signingKey.IsPrivate) + throw new ArgumentException("key for signing must be private", "signingKey"); + +// DerObjectIdentifier sigOid = SignerUtilities.GetObjectIdentifier(signatureAlgorithm); + string algorithmName = Platform.ToUpperInvariant(signatureAlgorithm); + DerObjectIdentifier sigOid = (DerObjectIdentifier) algorithms[algorithmName]; + + if (sigOid == null) + { + try + { + sigOid = new DerObjectIdentifier(algorithmName); + } + catch (Exception e) + { + throw new ArgumentException("Unknown signature type requested", e); + } + } + + if (noParams.Contains(sigOid)) + { + this.sigAlgId = new AlgorithmIdentifier(sigOid); + } + else if (exParams.Contains(algorithmName)) + { + this.sigAlgId = new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]); + } + else + { + this.sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance); + } + + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); + + this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes); + + ISigner sig = SignerUtilities.GetSigner(signatureAlgorithm); + + sig.Init(true, signingKey); + + try + { + // Encode. + byte[] b = reqInfo.GetDerEncoded(); + sig.BlockUpdate(b, 0, b.Length); + } + catch (Exception e) + { + throw new ArgumentException("exception encoding TBS cert request", e); + } + + // Generate Signature. + sigBits = new DerBitString(sig.GenerateSignature()); + } + +// internal Pkcs10CertificationRequest( +// Asn1InputStream seqStream) +// { +// Asn1Sequence seq = (Asn1Sequence) seqStream.ReadObject(); +// try +// { +// this.reqInfo = CertificationRequestInfo.GetInstance(seq[0]); +// this.sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]); +// this.sigBits = (DerBitString) seq[2]; +// } +// catch (Exception ex) +// { +// throw new ArgumentException("Create From Asn1Sequence: " + ex.Message); +// } +// } + + /// + /// Get the public key. + /// + /// The public key. + public AsymmetricKeyParameter GetPublicKey() + { + return PublicKeyFactory.CreateKey(reqInfo.SubjectPublicKeyInfo); + } + + /// + /// Verify Pkcs10 Cert Request is valid. + /// + /// true = valid. + public bool Verify() + { + return Verify(this.GetPublicKey()); + } + + public bool Verify( + AsymmetricKeyParameter publicKey) + { + ISigner sig; + + try + { + sig = SignerUtilities.GetSigner(GetSignatureName(sigAlgId)); + } + catch (Exception e) + { + // try an alternate + string alt = (string) oids[sigAlgId.ObjectID]; + + if (alt != null) + { + sig = SignerUtilities.GetSigner(alt); + } + else + { + throw e; + } + } + + SetSignatureParameters(sig, sigAlgId.Parameters); + + sig.Init(false, publicKey); + + try + { + byte[] b = reqInfo.GetDerEncoded(); + sig.BlockUpdate(b, 0, b.Length); + } + catch (Exception e) + { + throw new SignatureException("exception encoding TBS cert request", e); + } + + return sig.VerifySignature(sigBits.GetBytes()); + } + +// /// +// /// Get the Der Encoded Pkcs10 Certification Request. +// /// +// /// A byte array. +// public byte[] GetEncoded() +// { +// return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded(); +// } + + // TODO Figure out how to set parameters on an ISigner + private void SetSignatureParameters( + ISigner signature, + Asn1Encodable asn1Params) + { + if (asn1Params != null && !(asn1Params is Asn1Null)) + { +// AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm()); +// +// try +// { +// sigParams.init(asn1Params.ToAsn1Object().GetDerEncoded()); +// } +// catch (IOException e) +// { +// throw new SignatureException("IOException decoding parameters: " + e.Message); +// } + + if (signature.AlgorithmName.EndsWith("MGF1")) + { + throw Platform.CreateNotImplementedException("signature algorithm with MGF1"); + +// try +// { +// signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class)); +// } +// catch (GeneralSecurityException e) +// { +// throw new SignatureException("Exception extracting parameters: " + e.getMessage()); +// } + } + } + } + + internal static string GetSignatureName( + AlgorithmIdentifier sigAlgId) + { + Asn1Encodable asn1Params = sigAlgId.Parameters; + + if (asn1Params != null && !(asn1Params is Asn1Null)) + { + if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss)) + { + RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(asn1Params); + return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1"; + } + } + + return sigAlgId.ObjectID.Id; + } + + private static string GetDigestAlgName( + DerObjectIdentifier digestAlgOID) + { + if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID)) + { + return "MD5"; + } + else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID)) + { + return "SHA1"; + } + else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID)) + { + return "SHA224"; + } + else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID)) + { + return "SHA256"; + } + else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID)) + { + return "SHA384"; + } + else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID)) + { + return "SHA512"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID)) + { + return "RIPEMD128"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID)) + { + return "RIPEMD160"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID)) + { + return "RIPEMD256"; + } + else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID)) + { + return "GOST3411"; + } + else + { + return digestAlgOID.Id; + } + } + } +} diff --git a/crypto/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs b/crypto/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs new file mode 100644 index 000000000..ecbb4ab62 --- /dev/null +++ b/crypto/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections; +using System.Globalization; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkcs +{ + /// + /// A class for creating and verifying Pkcs10 Certification requests (this is an extension on ). + /// The requests are made using delay signing. This is useful for situations where + /// the private key is in another environment and not directly accessible (e.g. HSM) + /// So the first step creates the request, then the signing is done outside this + /// object and the signature is then used to complete the request. + /// + /// + /// CertificationRequest ::= Sequence { + /// certificationRequestInfo CertificationRequestInfo, + /// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, + /// signature BIT STRING + /// } + /// + /// CertificationRequestInfo ::= Sequence { + /// version Integer { v1(0) } (v1,...), + /// subject Name, + /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, + /// attributes [0] Attributes{{ CRIAttributes }} + /// } + /// + /// Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }} + /// + /// Attr { ATTRIBUTE:IOSet } ::= Sequence { + /// type ATTRIBUTE.&id({IOSet}), + /// values Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type}) + /// } + /// + /// see + public class Pkcs10CertificationRequestDelaySigned : Pkcs10CertificationRequest + { + protected Pkcs10CertificationRequestDelaySigned() + : base() + { + } + public Pkcs10CertificationRequestDelaySigned( + byte[] encoded) + : base(encoded) + { + } + public Pkcs10CertificationRequestDelaySigned( + Asn1Sequence seq) + : base(seq) + { + } + public Pkcs10CertificationRequestDelaySigned( + Stream input) + : base(input) + { + } + public Pkcs10CertificationRequestDelaySigned( + string signatureAlgorithm, + X509Name subject, + AsymmetricKeyParameter publicKey, + Asn1Set attributes, + AsymmetricKeyParameter signingKey) + : base(signatureAlgorithm, subject, publicKey, attributes, signingKey) + { + } + /// + /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials. + /// + /// Name of Sig Alg. + /// X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" + /// Public Key to be included in cert reqest. + /// ASN1Set of Attributes. + /// + /// After the object is constructed use the and finally the + /// SignRequest methods to finalize the request. + /// + public Pkcs10CertificationRequestDelaySigned( + string signatureAlgorithm, + X509Name subject, + AsymmetricKeyParameter publicKey, + Asn1Set attributes) + { + if (signatureAlgorithm == null) + throw new ArgumentNullException("signatureAlgorithm"); + if (subject == null) + throw new ArgumentNullException("subject"); + if (publicKey == null) + throw new ArgumentNullException("publicKey"); + if (publicKey.IsPrivate) + throw new ArgumentException("expected public key", "publicKey"); +// DerObjectIdentifier sigOid = SignerUtilities.GetObjectIdentifier(signatureAlgorithm); + string algorithmName = Platform.ToUpperInvariant(signatureAlgorithm); + DerObjectIdentifier sigOid = (DerObjectIdentifier) algorithms[algorithmName]; + if (sigOid == null) + { + try + { + sigOid = new DerObjectIdentifier(algorithmName); + } + catch (Exception e) + { + throw new ArgumentException("Unknown signature type requested", e); + } + } + if (noParams.Contains(sigOid)) + { + this.sigAlgId = new AlgorithmIdentifier(sigOid); + } + else if (exParams.Contains(algorithmName)) + { + this.sigAlgId = new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]); + } + else + { + this.sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance); + } + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); + this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes); + } + public byte[] GetDataToSign() + { + return reqInfo.GetDerEncoded(); + } + public void SignRequest(byte[] signedData) + { + //build the signature from the signed data + sigBits = new DerBitString(signedData); + } + public void SignRequest(DerBitString signedData) + { + //build the signature from the signed data + sigBits = signedData; + } + } +} diff --git a/crypto/src/pkcs/Pkcs12Entry.cs b/crypto/src/pkcs/Pkcs12Entry.cs new file mode 100644 index 000000000..5dcc94e88 --- /dev/null +++ b/crypto/src/pkcs/Pkcs12Entry.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Pkcs +{ + public abstract class Pkcs12Entry + { + private readonly IDictionary attributes; + + protected internal Pkcs12Entry( + IDictionary attributes) + { + this.attributes = attributes; + + foreach (DictionaryEntry entry in attributes) + { + if (!(entry.Key is string)) + throw new ArgumentException("Attribute keys must be of type: " + typeof(string).FullName, "attributes"); + if (!(entry.Value is Asn1Encodable)) + throw new ArgumentException("Attribute values must be of type: " + typeof(Asn1Encodable).FullName, "attributes"); + } + } + + [Obsolete("Use 'object[index]' syntax instead")] + public Asn1Encodable GetBagAttribute( + DerObjectIdentifier oid) + { + return (Asn1Encodable)this.attributes[oid.Id]; + } + + [Obsolete("Use 'object[index]' syntax instead")] + public Asn1Encodable GetBagAttribute( + string oid) + { + return (Asn1Encodable)this.attributes[oid]; + } + + [Obsolete("Use 'BagAttributeKeys' property")] + public IEnumerator GetBagAttributeKeys() + { + return this.attributes.Keys.GetEnumerator(); + } + + public Asn1Encodable this[ + DerObjectIdentifier oid] + { + get { return (Asn1Encodable) this.attributes[oid.Id]; } + } + + public Asn1Encodable this[ + string oid] + { + get { return (Asn1Encodable) this.attributes[oid]; } + } + + public IEnumerable BagAttributeKeys + { + get { return new EnumerableProxy(this.attributes.Keys); } + } + } +} diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs new file mode 100644 index 000000000..6718aea10 --- /dev/null +++ b/crypto/src/pkcs/Pkcs12Store.cs @@ -0,0 +1,1228 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkcs +{ + public class Pkcs12Store + { + private readonly IgnoresCaseHashtable keys = new IgnoresCaseHashtable(); + private readonly IDictionary localIds = Platform.CreateHashtable(); + private readonly IgnoresCaseHashtable certs = new IgnoresCaseHashtable(); + private readonly IDictionary chainCerts = Platform.CreateHashtable(); + private readonly IDictionary keyCerts = Platform.CreateHashtable(); + private readonly DerObjectIdentifier keyAlgorithm; + private readonly DerObjectIdentifier certAlgorithm; + private readonly bool useDerEncoding; + + private const int MinIterations = 1024; + private const int SaltSize = 20; + + private static SubjectKeyIdentifier CreateSubjectKeyID( + AsymmetricKeyParameter pubKey) + { + return new SubjectKeyIdentifier( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey)); + } + + internal class CertId + { + private readonly byte[] id; + + internal CertId( + AsymmetricKeyParameter pubKey) + { + this.id = CreateSubjectKeyID(pubKey).GetKeyIdentifier(); + } + + internal CertId( + byte[] id) + { + this.id = id; + } + + internal byte[] Id + { + get { return id; } + } + + public override int GetHashCode() + { + return Arrays.GetHashCode(id); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + CertId other = obj as CertId; + + if (other == null) + return false; + + return Arrays.AreEqual(id, other.id); + } + } + + internal Pkcs12Store( + DerObjectIdentifier keyAlgorithm, + DerObjectIdentifier certAlgorithm, + bool useDerEncoding) + { + this.keyAlgorithm = keyAlgorithm; + this.certAlgorithm = certAlgorithm; + this.useDerEncoding = useDerEncoding; + } + + // TODO Consider making obsolete +// [Obsolete("Use 'Pkcs12StoreBuilder' instead")] + public Pkcs12Store() + : this(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, + PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc, false) + { + } + + // TODO Consider making obsolete +// [Obsolete("Use 'Pkcs12StoreBuilder' and 'Load' method instead")] + public Pkcs12Store( + Stream input, + char[] password) + : this() + { + Load(input, password); + } + + public void Load( + Stream input, + char[] password) + { + if (input == null) + throw new ArgumentNullException("input"); + if (password == null) + throw new ArgumentNullException("password"); + + Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromStream(input); + Pfx bag = new Pfx(obj); + ContentInfo info = bag.AuthSafe; + bool unmarkedKey = false; + bool wrongPkcs12Zero = false; + + if (bag.MacData != null) // check the mac code + { + MacData mData = bag.MacData; + DigestInfo dInfo = mData.Mac; + AlgorithmIdentifier algId = dInfo.AlgorithmID; + byte[] salt = mData.GetSalt(); + int itCount = mData.IterationCount.IntValue; + + byte[] data = ((Asn1OctetString) info.Content).GetOctets(); + + byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data); + byte[] dig = dInfo.GetDigest(); + + if (!Arrays.ConstantTimeAreEqual(mac, dig)) + { + if (password.Length > 0) + throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file."); + + // Try with incorrect zero length password + mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data); + + if (!Arrays.ConstantTimeAreEqual(mac, dig)) + throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file."); + + wrongPkcs12Zero = true; + } + } + + keys.Clear(); + localIds.Clear(); + + IList chain = Platform.CreateArrayList(); + + if (info.ContentType.Equals(PkcsObjectIdentifiers.Data)) + { + byte[] octs = ((Asn1OctetString)info.Content).GetOctets(); + AuthenticatedSafe authSafe = new AuthenticatedSafe( + (Asn1Sequence) Asn1OctetString.FromByteArray(octs)); + ContentInfo[] cis = authSafe.GetContentInfo(); + + foreach (ContentInfo ci in cis) + { + DerObjectIdentifier oid = ci.ContentType; + + if (oid.Equals(PkcsObjectIdentifiers.Data)) + { + byte[] octets = ((Asn1OctetString)ci.Content).GetOctets(); + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); + + foreach (Asn1Sequence subSeq in seq) + { + SafeBag b = new SafeBag(subSeq); + + if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) + { + EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue); + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo( + password, wrongPkcs12Zero, eIn); + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo); + + // + // set the attributes on the key + // + IDictionary attributes = Platform.CreateHashtable(); + AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); + string alias = null; + Asn1OctetString localId = null; + + if (b.BagAttributes != null) + { + foreach (Asn1Sequence sq in b.BagAttributes) + { + DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0]; + Asn1Set attrSet = (Asn1Set) sq[1]; + Asn1Encodable attr = null; + + if (attrSet.Count > 0) + { + // TODO We should be adding all attributes in the set + attr = attrSet[0]; + + // TODO We might want to "merge" attribute sets with + // the same OID - currently, differing values give an error + if (attributes.Contains(aOid.Id)) + { + // OK, but the value has to be the same + if (!attributes[aOid.Id].Equals(attr)) + { + throw new IOException("attempt to add existing attribute with different value"); + } + } + else + { + attributes.Add(aOid.Id, attr); + } + + if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) + { + alias = ((DerBmpString)attr).GetString(); + // TODO Do these in a separate loop, just collect aliases here + keys[alias] = pkcs12Key; + } + else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) + { + localId = (Asn1OctetString)attr; + } + } + } + } + + if (localId != null) + { + string name = Hex.ToHexString(localId.GetOctets()); + + if (alias == null) + { + keys[name] = pkcs12Key; + } + else + { + // TODO There may have been more than one alias + localIds[alias] = name; + } + } + else + { + unmarkedKey = true; + keys["unmarked"] = pkcs12Key; + } + } + else if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag)) + { + chain.Add(b); + } + else + { + Console.WriteLine("extra " + b.BagID); + Console.WriteLine("extra " + Asn1Dump.DumpAsString(b)); + } + } + } + else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData)) + { + EncryptedData d = EncryptedData.GetInstance(ci.Content); + byte[] octets = CryptPbeData(false, d.EncryptionAlgorithm, + password, wrongPkcs12Zero, d.Content.GetOctets()); + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); + + foreach (Asn1Sequence subSeq in seq) + { + SafeBag b = new SafeBag(subSeq); + + if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag)) + { + chain.Add(b); + } + else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) + { + EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue); + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo( + password, wrongPkcs12Zero, eIn); + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo); + + // + // set the attributes on the key + // + IDictionary attributes = Platform.CreateHashtable(); + AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); + string alias = null; + Asn1OctetString localId = null; + + foreach (Asn1Sequence sq in b.BagAttributes) + { + DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0]; + Asn1Set attrSet = (Asn1Set) sq[1]; + Asn1Encodable attr = null; + + if (attrSet.Count > 0) + { + // TODO We should be adding all attributes in the set + attr = attrSet[0]; + + // TODO We might want to "merge" attribute sets with + // the same OID - currently, differing values give an error + if (attributes.Contains(aOid.Id)) + { + // OK, but the value has to be the same + if (!attributes[aOid.Id].Equals(attr)) + { + throw new IOException("attempt to add existing attribute with different value"); + } + } + else + { + attributes.Add(aOid.Id, attr); + } + + if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) + { + alias = ((DerBmpString)attr).GetString(); + // TODO Do these in a separate loop, just collect aliases here + keys[alias] = pkcs12Key; + } + else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) + { + localId = (Asn1OctetString)attr; + } + } + } + + // TODO Should we be checking localIds != null here + // as for PkcsObjectIdentifiers.Data version above? + + string name = Hex.ToHexString(localId.GetOctets()); + + if (alias == null) + { + keys[name] = pkcs12Key; + } + else + { + // TODO There may have been more than one alias + localIds[alias] = name; + } + } + else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag)) + { + PrivateKeyInfo privKeyInfo = PrivateKeyInfo.GetInstance(b.BagValue); + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyInfo); + + // + // set the attributes on the key + // + string alias = null; + Asn1OctetString localId = null; + IDictionary attributes = Platform.CreateHashtable(); + AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); + + foreach (Asn1Sequence sq in b.BagAttributes) + { + DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0]; + Asn1Set attrSet = (Asn1Set) sq[1]; + Asn1Encodable attr = null; + + if (attrSet.Count > 0) + { + // TODO We should be adding all attributes in the set + attr = attrSet[0]; + + // TODO We might want to "merge" attribute sets with + // the same OID - currently, differing values give an error + if (attributes.Contains(aOid.Id)) + { + // OK, but the value has to be the same + if (!attributes[aOid.Id].Equals(attr)) + { + throw new IOException("attempt to add existing attribute with different value"); + } + } + else + { + attributes.Add(aOid.Id, attr); + } + + if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) + { + alias = ((DerBmpString)attr).GetString(); + // TODO Do these in a separate loop, just collect aliases here + keys[alias] = pkcs12Key; + } + else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) + { + localId = (Asn1OctetString)attr; + } + } + } + + // TODO Should we be checking localIds != null here + // as for PkcsObjectIdentifiers.Data version above? + + string name = Hex.ToHexString(localId.GetOctets()); + + if (alias == null) + { + keys[name] = pkcs12Key; + } + else + { + // TODO There may have been more than one alias + localIds[alias] = name; + } + } + else + { + Console.WriteLine("extra " + b.BagID); + Console.WriteLine("extra " + Asn1Dump.DumpAsString(b)); + } + } + } + else + { + Console.WriteLine("extra " + oid); + Console.WriteLine("extra " + Asn1Dump.DumpAsString(ci.Content)); + } + } + } + + certs.Clear(); + chainCerts.Clear(); + keyCerts.Clear(); + + foreach (SafeBag b in chain) + { + CertBag cb = new CertBag((Asn1Sequence)b.BagValue); + byte[] octets = ((Asn1OctetString) cb.CertValue).GetOctets(); + X509Certificate cert = new X509CertificateParser().ReadCertificate(octets); + + // + // set the attributes + // + IDictionary attributes = Platform.CreateHashtable(); + Asn1OctetString localId = null; + string alias = null; + + if (b.BagAttributes != null) + { + foreach (Asn1Sequence sq in b.BagAttributes) + { + DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0]; + Asn1Set attrSet = (Asn1Set) sq[1]; + + if (attrSet.Count > 0) + { + // TODO We should be adding all attributes in the set + Asn1Encodable attr = attrSet[0]; + + // TODO We might want to "merge" attribute sets with + // the same OID - currently, differing values give an error + if (attributes.Contains(aOid.Id)) + { + // OK, but the value has to be the same + if (!attributes[aOid.Id].Equals(attr)) + { + throw new IOException("attempt to add existing attribute with different value"); + } + } + else + { + attributes.Add(aOid.Id, attr); + } + + if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) + { + alias = ((DerBmpString)attr).GetString(); + } + else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) + { + localId = (Asn1OctetString)attr; + } + } + } + } + + CertId certId = new CertId(cert.GetPublicKey()); + X509CertificateEntry pkcs12Cert = new X509CertificateEntry(cert, attributes); + + chainCerts[certId] = pkcs12Cert; + + if (unmarkedKey) + { + if (keyCerts.Count == 0) + { + string name = Hex.ToHexString(certId.Id); + + keyCerts[name] = pkcs12Cert; + + object temp = keys["unmarked"]; + keys.Remove("unmarked"); + keys[name] = temp; + } + } + else + { + if (localId != null) + { + string name = Hex.ToHexString(localId.GetOctets()); + + keyCerts[name] = pkcs12Cert; + } + + if (alias != null) + { + // TODO There may have been more than one alias + certs[alias] = pkcs12Cert; + } + } + } + } + + public AsymmetricKeyEntry GetKey( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + return (AsymmetricKeyEntry)keys[alias]; + } + + public bool IsCertificateEntry( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + return (certs[alias] != null && keys[alias] == null); + } + + public bool IsKeyEntry( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + return (keys[alias] != null); + } + + private IDictionary GetAliasesTable() + { + IDictionary tab = Platform.CreateHashtable(); + + foreach (string key in certs.Keys) + { + tab[key] = "cert"; + } + + foreach (string a in keys.Keys) + { + if (tab[a] == null) + { + tab[a] = "key"; + } + } + + return tab; + } + + public IEnumerable Aliases + { + get { return new EnumerableProxy(GetAliasesTable().Keys); } + } + + public bool ContainsAlias( + string alias) + { + return certs[alias] != null || keys[alias] != null; + } + + /** + * simply return the cert entry for the private key + */ + public X509CertificateEntry GetCertificate( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + X509CertificateEntry c = (X509CertificateEntry) certs[alias]; + + // + // look up the key table - and try the local key id + // + if (c == null) + { + string id = (string)localIds[alias]; + if (id != null) + { + c = (X509CertificateEntry)keyCerts[id]; + } + else + { + c = (X509CertificateEntry)keyCerts[alias]; + } + } + + return c; + } + + public string GetCertificateAlias( + X509Certificate cert) + { + if (cert == null) + throw new ArgumentNullException("cert"); + + foreach (DictionaryEntry entry in certs) + { + X509CertificateEntry entryValue = (X509CertificateEntry) entry.Value; + if (entryValue.Certificate.Equals(cert)) + { + return (string) entry.Key; + } + } + + foreach (DictionaryEntry entry in keyCerts) + { + X509CertificateEntry entryValue = (X509CertificateEntry) entry.Value; + if (entryValue.Certificate.Equals(cert)) + { + return (string) entry.Key; + } + } + + return null; + } + + public X509CertificateEntry[] GetCertificateChain( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + if (!IsKeyEntry(alias)) + { + return null; + } + + X509CertificateEntry c = GetCertificate(alias); + + if (c != null) + { + IList cs = Platform.CreateArrayList(); + + while (c != null) + { + X509Certificate x509c = c.Certificate; + X509CertificateEntry nextC = null; + + Asn1OctetString ext = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); + if (ext != null) + { + AuthorityKeyIdentifier id = AuthorityKeyIdentifier.GetInstance( + Asn1Object.FromByteArray(ext.GetOctets())); + + if (id.GetKeyIdentifier() != null) + { + nextC = (X509CertificateEntry) chainCerts[new CertId(id.GetKeyIdentifier())]; + } + } + + if (nextC == null) + { + // + // no authority key id, try the Issuer DN + // + X509Name i = x509c.IssuerDN; + X509Name s = x509c.SubjectDN; + + if (!i.Equivalent(s)) + { + foreach (CertId certId in chainCerts.Keys) + { + X509CertificateEntry x509CertEntry = (X509CertificateEntry) chainCerts[certId]; + + X509Certificate crt = x509CertEntry.Certificate; + + X509Name sub = crt.SubjectDN; + if (sub.Equivalent(i)) + { + try + { + x509c.Verify(crt.GetPublicKey()); + + nextC = x509CertEntry; + break; + } + catch (InvalidKeyException) + { + // TODO What if it doesn't verify? + } + } + } + } + } + + cs.Add(c); + if (nextC != c) // self signed - end of the chain + { + c = nextC; + } + else + { + c = null; + } + } + + X509CertificateEntry[] result = new X509CertificateEntry[cs.Count]; + for (int i = 0; i < cs.Count; ++i) + { + result[i] = (X509CertificateEntry)cs[i]; + } + return result; + } + + return null; + } + + public void SetCertificateEntry( + string alias, + X509CertificateEntry certEntry) + { + if (alias == null) + throw new ArgumentNullException("alias"); + if (certEntry == null) + throw new ArgumentNullException("certEntry"); + if (keys[alias] != null) + throw new ArgumentException("There is a key entry with the name " + alias + "."); + + certs[alias] = certEntry; + chainCerts[new CertId(certEntry.Certificate.GetPublicKey())] = certEntry; + } + + public void SetKeyEntry( + string alias, + AsymmetricKeyEntry keyEntry, + X509CertificateEntry[] chain) + { + if (alias == null) + throw new ArgumentNullException("alias"); + if (keyEntry == null) + throw new ArgumentNullException("keyEntry"); + if (keyEntry.Key.IsPrivate && (chain == null)) + throw new ArgumentException("No certificate chain for private key"); + + if (keys[alias] != null) + { + DeleteEntry(alias); + } + + keys[alias] = keyEntry; + certs[alias] = chain[0]; + + for (int i = 0; i != chain.Length; i++) + { + chainCerts[new CertId(chain[i].Certificate.GetPublicKey())] = chain[i]; + } + } + + public void DeleteEntry( + string alias) + { + if (alias == null) + throw new ArgumentNullException("alias"); + + AsymmetricKeyEntry k = (AsymmetricKeyEntry)keys[alias]; + if (k != null) + { + keys.Remove(alias); + } + + X509CertificateEntry c = (X509CertificateEntry)certs[alias]; + + if (c != null) + { + certs.Remove(alias); + chainCerts.Remove(new CertId(c.Certificate.GetPublicKey())); + } + + if (k != null) + { + string id = (string)localIds[alias]; + if (id != null) + { + localIds.Remove(alias); + c = (X509CertificateEntry)keyCerts[id]; + } + if (c != null) + { + keyCerts.Remove(id); + chainCerts.Remove(new CertId(c.Certificate.GetPublicKey())); + } + } + + if (c == null && k == null) + { + throw new ArgumentException("no such entry as " + alias); + } + } + + public bool IsEntryOfType( + string alias, + Type entryType) + { + if (entryType == typeof(X509CertificateEntry)) + return IsCertificateEntry(alias); + + if (entryType == typeof(AsymmetricKeyEntry)) + return IsKeyEntry(alias) && GetCertificate(alias) != null; + + return false; + } + + [Obsolete("Use 'Count' property instead")] + public int Size() + { + return Count; + } + + public int Count + { + // TODO Seems a little inefficient + get { return GetAliasesTable().Count; } + } + + public void Save( + Stream stream, + char[] password, + SecureRandom random) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (password == null) + throw new ArgumentNullException("password"); + if (random == null) + throw new ArgumentNullException("random"); + + // + // handle the key + // + Asn1EncodableVector keyS = new Asn1EncodableVector(); + foreach (string name in keys.Keys) + { + byte[] kSalt = new byte[SaltSize]; + random.NextBytes(kSalt); + + AsymmetricKeyEntry privKey = (AsymmetricKeyEntry) keys[name]; + EncryptedPrivateKeyInfo kInfo = + EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + keyAlgorithm, password, kSalt, MinIterations, privKey.Key); + + Asn1EncodableVector kName = new Asn1EncodableVector(); + + foreach (string oid in privKey.BagAttributeKeys) + { + Asn1Encodable entry = privKey[oid]; + + // NB: Ignore any existing FriendlyName + if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) + continue; + + kName.Add( + new DerSequence( + new DerObjectIdentifier(oid), + new DerSet(entry))); + } + + // + // make sure we are using the local alias on store + // + // NB: We always set the FriendlyName based on 'name' + //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) + { + kName.Add( + new DerSequence( + PkcsObjectIdentifiers.Pkcs9AtFriendlyName, + new DerSet(new DerBmpString(name)))); + } + + // + // make sure we have a local key-id + // + if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) + { + X509CertificateEntry ct = GetCertificate(name); + AsymmetricKeyParameter pubKey = ct.Certificate.GetPublicKey(); + SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey); + + kName.Add( + new DerSequence( + PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, + new DerSet(subjectKeyID))); + } + + SafeBag kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName)); + keyS.Add(kBag); + } + + byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded(); + + BerOctetString keyString = new BerOctetString(derEncodedBytes); + + // + // certificate processing + // + byte[] cSalt = new byte[SaltSize]; + + random.NextBytes(cSalt); + + Asn1EncodableVector certSeq = new Asn1EncodableVector(); + Pkcs12PbeParams cParams = new Pkcs12PbeParams(cSalt, MinIterations); + AlgorithmIdentifier cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.ToAsn1Object()); + ISet doneCerts = new HashSet(); + + foreach (string name in keys.Keys) + { + X509CertificateEntry certEntry = GetCertificate(name); + CertBag cBag = new CertBag( + PkcsObjectIdentifiers.X509Certificate, + new DerOctetString(certEntry.Certificate.GetEncoded())); + + Asn1EncodableVector fName = new Asn1EncodableVector(); + + foreach (string oid in certEntry.BagAttributeKeys) + { + Asn1Encodable entry = certEntry[oid]; + + // NB: Ignore any existing FriendlyName + if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) + continue; + + fName.Add( + new DerSequence( + new DerObjectIdentifier(oid), + new DerSet(entry))); + } + + // + // make sure we are using the local alias on store + // + // NB: We always set the FriendlyName based on 'name' + //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) + { + fName.Add( + new DerSequence( + PkcsObjectIdentifiers.Pkcs9AtFriendlyName, + new DerSet(new DerBmpString(name)))); + } + + // + // make sure we have a local key-id + // + if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) + { + AsymmetricKeyParameter pubKey = certEntry.Certificate.GetPublicKey(); + SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey); + + fName.Add( + new DerSequence( + PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, + new DerSet(subjectKeyID))); + } + + SafeBag sBag = new SafeBag( + PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); + + certSeq.Add(sBag); + + doneCerts.Add(certEntry.Certificate); + } + + foreach (string certId in certs.Keys) + { + X509CertificateEntry cert = (X509CertificateEntry)certs[certId]; + + if (keys[certId] != null) + continue; + + CertBag cBag = new CertBag( + PkcsObjectIdentifiers.X509Certificate, + new DerOctetString(cert.Certificate.GetEncoded())); + + Asn1EncodableVector fName = new Asn1EncodableVector(); + + foreach (string oid in cert.BagAttributeKeys) + { + // a certificate not immediately linked to a key doesn't require + // a localKeyID and will confuse some PKCS12 implementations. + // + // If we find one, we'll prune it out. + if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id)) + continue; + + Asn1Encodable entry = cert[oid]; + + // NB: Ignore any existing FriendlyName + if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) + continue; + + fName.Add( + new DerSequence( + new DerObjectIdentifier(oid), + new DerSet(entry))); + } + + // + // make sure we are using the local alias on store + // + // NB: We always set the FriendlyName based on 'certId' + //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) + { + fName.Add( + new DerSequence( + PkcsObjectIdentifiers.Pkcs9AtFriendlyName, + new DerSet(new DerBmpString(certId)))); + } + + SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, + cBag.ToAsn1Object(), new DerSet(fName)); + + certSeq.Add(sBag); + + doneCerts.Add(cert.Certificate); + } + + foreach (CertId certId in chainCerts.Keys) + { + X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId]; + + if (doneCerts.Contains(cert.Certificate)) + continue; + + CertBag cBag = new CertBag( + PkcsObjectIdentifiers.X509Certificate, + new DerOctetString(cert.Certificate.GetEncoded())); + + Asn1EncodableVector fName = new Asn1EncodableVector(); + + foreach (string oid in cert.BagAttributeKeys) + { + // a certificate not immediately linked to a key doesn't require + // a localKeyID and will confuse some PKCS12 implementations. + // + // If we find one, we'll prune it out. + if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id)) + continue; + + fName.Add( + new DerSequence( + new DerObjectIdentifier(oid), + new DerSet(cert[oid]))); + } + + SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); + + certSeq.Add(sBag); + } + + derEncodedBytes = new DerSequence(certSeq).GetDerEncoded(); + + byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes); + + EncryptedData cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes)); + + ContentInfo[] info = new ContentInfo[] + { + new ContentInfo(PkcsObjectIdentifiers.Data, keyString), + new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object()) + }; + + byte[] data = new AuthenticatedSafe(info).GetEncoded( + useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber); + + ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data)); + + // + // create the mac + // + byte[] mSalt = new byte[20]; + random.NextBytes(mSalt); + + byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1, + mSalt, MinIterations, password, false, data); + + AlgorithmIdentifier algId = new AlgorithmIdentifier( + OiwObjectIdentifiers.IdSha1, DerNull.Instance); + DigestInfo dInfo = new DigestInfo(algId, mac); + + MacData mData = new MacData(dInfo, mSalt, MinIterations); + + // + // output the Pfx + // + Pfx pfx = new Pfx(mainInfo, mData); + + DerOutputStream derOut; + if (useDerEncoding) + { + derOut = new DerOutputStream(stream); + } + else + { + derOut = new BerOutputStream(stream); + } + + derOut.WriteObject(pfx); + } + + internal static byte[] CalculatePbeMac( + DerObjectIdentifier oid, + byte[] salt, + int itCount, + char[] password, + bool wrongPkcs12Zero, + byte[] data) + { + Asn1Encodable asn1Params = PbeUtilities.GenerateAlgorithmParameters( + oid, salt, itCount); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + oid, password, wrongPkcs12Zero, asn1Params); + + IMac mac = (IMac) PbeUtilities.CreateEngine(oid); + mac.Init(cipherParams); + mac.BlockUpdate(data, 0, data.Length); + return MacUtilities.DoFinal(mac); + } + + private static byte[] CryptPbeData( + bool forEncryption, + AlgorithmIdentifier algId, + char[] password, + bool wrongPkcs12Zero, + byte[] data) + { + IBufferedCipher cipher = PbeUtilities.CreateEngine(algId.ObjectID) as IBufferedCipher; + + if (cipher == null) + throw new Exception("Unknown encryption algorithm: " + algId.ObjectID); + + Pkcs12PbeParams pbeParameters = Pkcs12PbeParams.GetInstance(algId.Parameters); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + algId.ObjectID, password, wrongPkcs12Zero, pbeParameters); + cipher.Init(forEncryption, cipherParams); + return cipher.DoFinal(data); + } + + private class IgnoresCaseHashtable + : IEnumerable + { + private readonly IDictionary orig = Platform.CreateHashtable(); + private readonly IDictionary keys = Platform.CreateHashtable(); + + public void Clear() + { + orig.Clear(); + keys.Clear(); + } + + public IEnumerator GetEnumerator() + { + return orig.GetEnumerator(); + } + + public ICollection Keys + { + get { return orig.Keys; } + } + + public object Remove( + string alias) + { + string lower = Platform.ToLowerInvariant(alias); + string k = (string) keys[lower]; + + if (k == null) + return null; + + keys.Remove(lower); + + object o = orig[k]; + orig.Remove(k); + return o; + } + + public object this[ + string alias] + { + get + { + string lower = Platform.ToLowerInvariant(alias); + string k = (string)keys[lower]; + + if (k == null) + return null; + + return orig[k]; + } + set + { + string lower = Platform.ToLowerInvariant(alias); + string k = (string)keys[lower]; + if (k != null) + { + orig.Remove(k); + } + keys[lower] = alias; + orig[alias] = value; + } + } + + public ICollection Values + { + get { return orig.Values; } + } + } + } +} diff --git a/crypto/src/pkcs/Pkcs12Utilities.cs b/crypto/src/pkcs/Pkcs12Utilities.cs new file mode 100644 index 000000000..d35c8b6a2 --- /dev/null +++ b/crypto/src/pkcs/Pkcs12Utilities.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Pkcs +{ + /** + * Utility class for reencoding PKCS#12 files to definite length. + */ + public class Pkcs12Utilities + { + /** + * Just re-encode the outer layer of the PKCS#12 file to definite length encoding. + * + * @param berPKCS12File - original PKCS#12 file + * @return a byte array representing the DER encoding of the PFX structure + * @throws IOException + */ + public static byte[] ConvertToDefiniteLength( + byte[] berPkcs12File) + { + Pfx pfx = new Pfx(Asn1Sequence.GetInstance(Asn1Object.FromByteArray(berPkcs12File))); + + return pfx.GetEncoded(Asn1Encodable.Der); + } + + /** + * Re-encode the PKCS#12 structure to definite length encoding at the inner layer + * as well, recomputing the MAC accordingly. + * + * @param berPKCS12File - original PKCS12 file. + * @param provider - provider to use for MAC calculation. + * @return a byte array representing the DER encoding of the PFX structure. + * @throws IOException on parsing, encoding errors. + */ + public static byte[] ConvertToDefiniteLength( + byte[] berPkcs12File, + char[] passwd) + { + Pfx pfx = new Pfx(Asn1Sequence.GetInstance(Asn1Object.FromByteArray(berPkcs12File))); + + ContentInfo info = pfx.AuthSafe; + + Asn1OctetString content = Asn1OctetString.GetInstance(info.Content); + Asn1Object obj = Asn1Object.FromByteArray(content.GetOctets()); + + info = new ContentInfo(info.ContentType, new DerOctetString(obj.GetEncoded(Asn1Encodable.Der))); + + MacData mData = pfx.MacData; + + try + { + int itCount = mData.IterationCount.IntValue; + byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets(); + byte[] res = Pkcs12Store.CalculatePbeMac( + mData.Mac.AlgorithmID.ObjectID, mData.GetSalt(), itCount, passwd, false, data); + + AlgorithmIdentifier algId = new AlgorithmIdentifier( + mData.Mac.AlgorithmID.ObjectID, DerNull.Instance); + DigestInfo dInfo = new DigestInfo(algId, res); + + mData = new MacData(dInfo, mData.GetSalt(), itCount); + } + catch (Exception e) + { + throw new IOException("error constructing MAC: " + e.ToString()); + } + + pfx = new Pfx(info, mData); + + return pfx.GetEncoded(Asn1Encodable.Der); + } + } +} \ No newline at end of file diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs new file mode 100644 index 000000000..723d50f08 --- /dev/null +++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs @@ -0,0 +1,208 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Pkcs +{ + public sealed class PrivateKeyInfoFactory + { + private PrivateKeyInfoFactory() + { + } + + public static PrivateKeyInfo CreatePrivateKeyInfo( + AsymmetricKeyParameter key) + { + if (key == null) + throw new ArgumentNullException("key"); + if (!key.IsPrivate) + throw new ArgumentException("Public key passed - private key expected", "key"); + + if (key is ElGamalPrivateKeyParameters) + { + ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)key; + return new PrivateKeyInfo( + new AlgorithmIdentifier( + OiwObjectIdentifiers.ElGamalAlgorithm, + new ElGamalParameter( + _key.Parameters.P, + _key.Parameters.G).ToAsn1Object()), + new DerInteger(_key.X)); + } + + if (key is DsaPrivateKeyParameters) + { + DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)key; + return new PrivateKeyInfo( + new AlgorithmIdentifier( + X9ObjectIdentifiers.IdDsa, + new DsaParameter( + _key.Parameters.P, + _key.Parameters.Q, + _key.Parameters.G).ToAsn1Object()), + new DerInteger(_key.X)); + } + + if (key is DHPrivateKeyParameters) + { + DHPrivateKeyParameters _key = (DHPrivateKeyParameters)key; + + DHParameter p = new DHParameter( + _key.Parameters.P, _key.Parameters.G, _key.Parameters.L); + + return new PrivateKeyInfo( + new AlgorithmIdentifier(_key.AlgorithmOid, p.ToAsn1Object()), + new DerInteger(_key.X)); + } + + if (key is RsaKeyParameters) + { + AlgorithmIdentifier algID = new AlgorithmIdentifier( + PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance); + + RsaPrivateKeyStructure keyStruct; + if (key is RsaPrivateCrtKeyParameters) + { + RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)key; + + keyStruct = new RsaPrivateKeyStructure( + _key.Modulus, + _key.PublicExponent, + _key.Exponent, + _key.P, + _key.Q, + _key.DP, + _key.DQ, + _key.QInv); + } + else + { + RsaKeyParameters _key = (RsaKeyParameters) key; + + keyStruct = new RsaPrivateKeyStructure( + _key.Modulus, + BigInteger.Zero, + _key.Exponent, + BigInteger.Zero, + BigInteger.Zero, + BigInteger.Zero, + BigInteger.Zero, + BigInteger.Zero); + } + + return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object()); + } + + if (key is ECPrivateKeyParameters) + { + ECPrivateKeyParameters _key = (ECPrivateKeyParameters)key; + AlgorithmIdentifier algID; + ECPrivateKeyStructure ec; + + if (_key.AlgorithmName == "ECGOST3410") + { + if (_key.PublicKeyParamSet == null) + throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); + + Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( + _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); + + algID = new AlgorithmIdentifier( + CryptoProObjectIdentifiers.GostR3410x2001, + gostParams.ToAsn1Object()); + + // TODO Do we need to pass any parameters here? + ec = new ECPrivateKeyStructure(_key.D); + } + else + { + X962Parameters x962; + if (_key.PublicKeyParamSet == null) + { + ECDomainParameters kp = _key.Parameters; + X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed()); + + x962 = new X962Parameters(ecP); + } + else + { + x962 = new X962Parameters(_key.PublicKeyParamSet); + } + + Asn1Object x962Object = x962.ToAsn1Object(); + + // TODO Possible to pass the publicKey bitstring here? + ec = new ECPrivateKeyStructure(_key.D, x962Object); + + algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962Object); + } + + return new PrivateKeyInfo(algID, ec.ToAsn1Object()); + } + + if (key is Gost3410PrivateKeyParameters) + { + Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)key; + + if (_key.PublicKeyParamSet == null) + throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); + + byte[] keyEnc = _key.X.ToByteArrayUnsigned(); + byte[] keyBytes = new byte[keyEnc.Length]; + + for (int i = 0; i != keyBytes.Length; i++) + { + keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian + } + + Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters( + _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet, null); + + AlgorithmIdentifier algID = new AlgorithmIdentifier( + CryptoProObjectIdentifiers.GostR3410x94, + algParams.ToAsn1Object()); + + return new PrivateKeyInfo(algID, new DerOctetString(keyBytes)); + } + + throw new ArgumentException("Class provided is not convertible: " + key.GetType().FullName); + } + + public static PrivateKeyInfo CreatePrivateKeyInfo( + char[] passPhrase, + EncryptedPrivateKeyInfo encInfo) + { + return CreatePrivateKeyInfo(passPhrase, false, encInfo); + } + + public static PrivateKeyInfo CreatePrivateKeyInfo( + char[] passPhrase, + bool wrongPkcs12Zero, + EncryptedPrivateKeyInfo encInfo) + { + AlgorithmIdentifier algID = encInfo.EncryptionAlgorithm; + + IBufferedCipher cipher = PbeUtilities.CreateEngine(algID) as IBufferedCipher; + if (cipher == null) + throw new Exception("Unknown encryption algorithm: " + algID.ObjectID); + + ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters( + algID, passPhrase, wrongPkcs12Zero); + cipher.Init(false, cipherParameters); + byte[] keyBytes = cipher.DoFinal(encInfo.GetEncryptedData()); + + return PrivateKeyInfo.GetInstance(keyBytes); + } + } +} diff --git a/crypto/src/pkcs/X509CertificateEntry.cs b/crypto/src/pkcs/X509CertificateEntry.cs new file mode 100644 index 000000000..a621619fb --- /dev/null +++ b/crypto/src/pkcs/X509CertificateEntry.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkcs +{ + public class X509CertificateEntry + : Pkcs12Entry + { + private readonly X509Certificate cert; + + public X509CertificateEntry( + X509Certificate cert) + : base(Platform.CreateHashtable()) + { + this.cert = cert; + } + +#if !SILVERLIGHT + [Obsolete] + public X509CertificateEntry( + X509Certificate cert, + Hashtable attributes) + : base(attributes) + { + this.cert = cert; + } +#endif + + public X509CertificateEntry( + X509Certificate cert, + IDictionary attributes) + : base(attributes) + { + this.cert = cert; + } + + public X509Certificate Certificate + { + get { return this.cert; } + } + + public override bool Equals(object obj) + { + X509CertificateEntry other = obj as X509CertificateEntry; + + if (other == null) + return false; + + return cert.Equals(other.cert); + } + + public override int GetHashCode() + { + return ~cert.GetHashCode(); + } + } +} diff --git a/crypto/src/pkix/CertStatus.cs b/crypto/src/pkix/CertStatus.cs new file mode 100644 index 000000000..4f40b7bc6 --- /dev/null +++ b/crypto/src/pkix/CertStatus.cs @@ -0,0 +1,35 @@ +using System; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Pkix +{ + public class CertStatus + { + public const int Unrevoked = 11; + + public const int Undetermined = 12; + + private int status = Unrevoked; + + DateTimeObject revocationDate = null; + + /// + /// Returns the revocationDate. + /// + public DateTimeObject RevocationDate + { + get { return revocationDate; } + set { this.revocationDate = value; } + } + + /// + /// Returns the certStatus. + /// + public int Status + { + get { return status; } + set { this.status = value; } + } + } +} diff --git a/crypto/src/pkix/PkixAttrCertChecker.cs b/crypto/src/pkix/PkixAttrCertChecker.cs new file mode 100644 index 000000000..a6eab8480 --- /dev/null +++ b/crypto/src/pkix/PkixAttrCertChecker.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkix +{ + public abstract class PkixAttrCertChecker + { + /** + * Returns an immutable Set of X.509 attribute certificate + * extensions that this PkixAttrCertChecker supports or + * null if no extensions are supported. + *

    + * Each element of the set is a String representing the + * Object Identifier (OID) of the X.509 extension that is supported. + *

    + *

    + * All X.509 attribute certificate extensions that a + * PkixAttrCertChecker might possibly be able to process + * should be included in the set. + *

    + * + * @return an immutable Set of X.509 extension OIDs (in + * String format) supported by this + * PkixAttrCertChecker, or null if no + * extensions are supported + */ + public abstract ISet GetSupportedExtensions(); + + /** + * Performs checks on the specified attribute certificate. Every handled + * extension is rmeoved from the unresolvedCritExts + * collection. + * + * @param attrCert The attribute certificate to be checked. + * @param certPath The certificate path which belongs to the attribute + * certificate issuer public key certificate. + * @param holderCertPath The certificate path which belongs to the holder + * certificate. + * @param unresolvedCritExts a Collection of OID strings + * representing the current set of unresolved critical extensions + * @throws CertPathValidatorException if the specified attribute certificate + * does not pass the check. + */ + public abstract void Check(IX509AttributeCertificate attrCert, PkixCertPath certPath, + PkixCertPath holderCertPath, ICollection unresolvedCritExts); + + /** + * Returns a clone of this object. + * + * @return a copy of this PkixAttrCertChecker + */ + public abstract PkixAttrCertChecker Clone(); + } +} diff --git a/crypto/src/pkix/PkixAttrCertPathBuilder.cs b/crypto/src/pkix/PkixAttrCertPathBuilder.cs new file mode 100644 index 000000000..646cc5db5 --- /dev/null +++ b/crypto/src/pkix/PkixAttrCertPathBuilder.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + public class PkixAttrCertPathBuilder + { + /** + * Build and validate a CertPath using the given parameter. + * + * @param params PKIXBuilderParameters object containing all information to + * build the CertPath + */ + public virtual PkixCertPathBuilderResult Build( + PkixBuilderParameters pkixParams) + { + // search target certificates + + IX509Selector certSelect = pkixParams.GetTargetConstraints(); + if (!(certSelect is X509AttrCertStoreSelector)) + { + throw new PkixCertPathBuilderException( + "TargetConstraints must be an instance of " + + typeof(X509AttrCertStoreSelector).FullName + + " for " + + typeof(PkixAttrCertPathBuilder).FullName + " class."); + } + + ICollection targets; + try + { + targets = PkixCertPathValidatorUtilities.FindCertificates( + (X509AttrCertStoreSelector)certSelect, pkixParams.GetStores()); + } + catch (Exception e) + { + throw new PkixCertPathBuilderException("Error finding target attribute certificate.", e); + } + + if (targets.Count == 0) + { + throw new PkixCertPathBuilderException( + "No attribute certificate found matching targetContraints."); + } + + PkixCertPathBuilderResult result = null; + + // check all potential target certificates + foreach (IX509AttributeCertificate cert in targets) + { + X509CertStoreSelector selector = new X509CertStoreSelector(); + X509Name[] principals = cert.Issuer.GetPrincipals(); + ISet issuers = new HashSet(); + for (int i = 0; i < principals.Length; i++) + { + try + { + selector.Subject = principals[i]; + + issuers.AddAll(PkixCertPathValidatorUtilities.FindCertificates(selector, pkixParams.GetStores())); + } + catch (Exception e) + { + throw new PkixCertPathBuilderException( + "Public key certificate for attribute certificate cannot be searched.", + e); + } + } + + if (issuers.IsEmpty) + throw new PkixCertPathBuilderException("Public key certificate for attribute certificate cannot be found."); + + IList certPathList = Platform.CreateArrayList(); + + foreach (X509Certificate issuer in issuers) + { + result = Build(cert, issuer, pkixParams, certPathList); + + if (result != null) + break; + } + + if (result != null) + break; + } + + if (result == null && certPathException != null) + { + throw new PkixCertPathBuilderException( + "Possible certificate chain could not be validated.", + certPathException); + } + + if (result == null && certPathException == null) + { + throw new PkixCertPathBuilderException( + "Unable to find certificate chain."); + } + + return result; + } + + private Exception certPathException; + + private PkixCertPathBuilderResult Build( + IX509AttributeCertificate attrCert, + X509Certificate tbvCert, + PkixBuilderParameters pkixParams, + IList tbvPath) + { + // If tbvCert is readily present in tbvPath, it indicates having run + // into a cycle in the + // PKI graph. + if (tbvPath.Contains(tbvCert)) + return null; + + // step out, the certificate is not allowed to appear in a certification + // chain + if (pkixParams.GetExcludedCerts().Contains(tbvCert)) + return null; + + // test if certificate path exceeds maximum length + if (pkixParams.MaxPathLength != -1) + { + if (tbvPath.Count - 1 > pkixParams.MaxPathLength) + return null; + } + + tbvPath.Add(tbvCert); + + PkixCertPathBuilderResult builderResult = null; + +// X509CertificateParser certParser = new X509CertificateParser(); + PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator(); + + try + { + // check whether the issuer of is a TrustAnchor + if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null) + { + PkixCertPath certPath = new PkixCertPath(tbvPath); + PkixCertPathValidatorResult result; + + try + { + result = validator.Validate(certPath, pkixParams); + } + catch (Exception e) + { + throw new Exception("Certification path could not be validated.", e); + } + + return new PkixCertPathBuilderResult(certPath, result.TrustAnchor, + result.PolicyTree, result.SubjectPublicKey); + } + else + { + // add additional X.509 stores from locations in certificate + try + { + PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams); + } + catch (CertificateParsingException e) + { + throw new Exception("No additional X.509 stores can be added from certificate locations.", e); + } + + // try to get the issuer certificate from one of the stores + ISet issuers = new HashSet(); + try + { + issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams)); + } + catch (Exception e) + { + throw new Exception("Cannot find issuer certificate for certificate in certification path.", e); + } + + if (issuers.IsEmpty) + throw new Exception("No issuer certificate for certificate in certification path found."); + + foreach (X509Certificate issuer in issuers) + { + // if untrusted self signed certificate continue + if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer)) + continue; + + builderResult = Build(attrCert, issuer, pkixParams, tbvPath); + + if (builderResult != null) + break; + } + } + } + catch (Exception e) + { + certPathException = new Exception("No valid certification path could be build.", e); + } + + if (builderResult == null) + { + tbvPath.Remove(tbvCert); + } + + return builderResult; + } + } +} diff --git a/crypto/src/pkix/PkixAttrCertPathValidator.cs b/crypto/src/pkix/PkixAttrCertPathValidator.cs new file mode 100644 index 000000000..5f53bcde6 --- /dev/null +++ b/crypto/src/pkix/PkixAttrCertPathValidator.cs @@ -0,0 +1,76 @@ +using System; + +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + /** + * CertPathValidatorSpi implementation for X.509 Attribute Certificates la RFC 3281. + * + * @see org.bouncycastle.x509.ExtendedPkixParameters + */ + public class PkixAttrCertPathValidator + // extends CertPathValidatorSpi + { + /** + * Validates an attribute certificate with the given certificate path. + * + *

    + * params must be an instance of + * ExtendedPkixParameters. + *

    + * The target constraints in the params must be an + * X509AttrCertStoreSelector with at least the attribute + * certificate criterion set. Obey that also target informations may be + * necessary to correctly validate this attribute certificate. + *

    + * The attribute certificate issuer must be added to the trusted attribute + * issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}. + *

    + * @param certPath The certificate path which belongs to the attribute + * certificate issuer public key certificate. + * @param params The PKIX parameters. + * @return A PKIXCertPathValidatorResult of the result of + * validating the certPath. + * @throws InvalidAlgorithmParameterException if params is + * inappropriate for this validator. + * @throws CertPathValidatorException if the verification fails. + */ + public virtual PkixCertPathValidatorResult Validate( + PkixCertPath certPath, + PkixParameters pkixParams) + { + IX509Selector certSelect = pkixParams.GetTargetConstraints(); + if (!(certSelect is X509AttrCertStoreSelector)) + { + throw new ArgumentException( + "TargetConstraints must be an instance of " + typeof(X509AttrCertStoreSelector).FullName, + "pkixParams"); + } + IX509AttributeCertificate attrCert = ((X509AttrCertStoreSelector) certSelect).AttributeCert; + + PkixCertPath holderCertPath = Rfc3281CertPathUtilities.ProcessAttrCert1(attrCert, pkixParams); + PkixCertPathValidatorResult result = Rfc3281CertPathUtilities.ProcessAttrCert2(certPath, pkixParams); + X509Certificate issuerCert = (X509Certificate)certPath.Certificates[0]; + Rfc3281CertPathUtilities.ProcessAttrCert3(issuerCert, pkixParams); + Rfc3281CertPathUtilities.ProcessAttrCert4(issuerCert, pkixParams); + Rfc3281CertPathUtilities.ProcessAttrCert5(attrCert, pkixParams); + // 6 already done in X509AttrCertStoreSelector + Rfc3281CertPathUtilities.ProcessAttrCert7(attrCert, certPath, holderCertPath, pkixParams); + Rfc3281CertPathUtilities.AdditionalChecks(attrCert, pkixParams); + DateTime date; + try + { + date = PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(pkixParams, null, -1); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Could not get validity date from attribute certificate.", e); + } + Rfc3281CertPathUtilities.CheckCrls(attrCert, pkixParams, issuerCert, date, certPath.Certificates); + return result; + } + } +} diff --git a/crypto/src/pkix/PkixBuilderParameters.cs b/crypto/src/pkix/PkixBuilderParameters.cs new file mode 100644 index 000000000..32fc04360 --- /dev/null +++ b/crypto/src/pkix/PkixBuilderParameters.cs @@ -0,0 +1,140 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509.Store; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixBuilderParameters. + /// + public class PkixBuilderParameters + : PkixParameters + { + private int maxPathLength = 5; + + private ISet excludedCerts = new HashSet(); + + /** + * Returns an instance of PkixBuilderParameters. + *

    + * This method can be used to get a copy from other + * PKIXBuilderParameters, PKIXParameters, + * and ExtendedPKIXParameters instances. + *

    + * + * @param pkixParams The PKIX parameters to create a copy of. + * @return An PkixBuilderParameters instance. + */ + public static PkixBuilderParameters GetInstance( + PkixParameters pkixParams) + { + PkixBuilderParameters parameters = new PkixBuilderParameters( + pkixParams.GetTrustAnchors(), + new X509CertStoreSelector(pkixParams.GetTargetCertConstraints())); + parameters.SetParams(pkixParams); + return parameters; + } + + public PkixBuilderParameters( + ISet trustAnchors, + IX509Selector targetConstraints) + : base(trustAnchors) + { + SetTargetCertConstraints(targetConstraints); + } + + public virtual int MaxPathLength + { + get { return maxPathLength; } + set + { + if (value < -1) + { + throw new InvalidParameterException( + "The maximum path length parameter can not be less than -1."); + } + this.maxPathLength = value; + } + } + + /// + /// Excluded certificates are not used for building a certification path. + /// + /// the excluded certificates. + public virtual ISet GetExcludedCerts() + { + return new HashSet(excludedCerts); + } + + /// + /// Sets the excluded certificates which are not used for building a + /// certification path. If the ISet is null an + /// empty set is assumed. + /// + /// + /// The given set is cloned to protect it against subsequent modifications. + /// + /// The excluded certificates to set. + public virtual void SetExcludedCerts( + ISet excludedCerts) + { + if (excludedCerts == null) + { + excludedCerts = new HashSet(); + } + else + { + this.excludedCerts = new HashSet(excludedCerts); + } + } + + /** + * Can alse handle ExtendedPKIXBuilderParameters and + * PKIXBuilderParameters. + * + * @param params Parameters to set. + * @see org.bouncycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters) + */ + protected override void SetParams( + PkixParameters parameters) + { + base.SetParams(parameters); + if (parameters is PkixBuilderParameters) + { + PkixBuilderParameters _params = (PkixBuilderParameters) parameters; + maxPathLength = _params.maxPathLength; + excludedCerts = new HashSet(_params.excludedCerts); + } + } + + /** + * Makes a copy of this PKIXParameters object. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this PKIXParameters object + */ + public override object Clone() + { + PkixBuilderParameters parameters = new PkixBuilderParameters( + GetTrustAnchors(), GetTargetCertConstraints()); + parameters.SetParams(this); + return parameters; + } + + public override string ToString() + { + string nl = Platform.NewLine; + StringBuilder s = new StringBuilder(); + s.Append("PkixBuilderParameters [" + nl); + s.Append(base.ToString()); + s.Append(" Maximum Path Length: "); + s.Append(MaxPathLength); + s.Append(nl + "]" + nl); + return s.ToString(); + } + } +} diff --git a/crypto/src/pkix/PkixCertPath.cs b/crypto/src/pkix/PkixCertPath.cs new file mode 100644 index 000000000..e3d3ea7fe --- /dev/null +++ b/crypto/src/pkix/PkixCertPath.cs @@ -0,0 +1,460 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Pkix +{ + /** + * An immutable sequence of certificates (a certification path).
    + *
    + * This is an abstract class that defines the methods common to all CertPaths. + * Subclasses can handle different kinds of certificates (X.509, PGP, etc.).
    + *
    + * All CertPath objects have a type, a list of Certificates, and one or more + * supported encodings. Because the CertPath class is immutable, a CertPath + * cannot change in any externally visible way after being constructed. This + * stipulation applies to all public fields and methods of this class and any + * added or overridden by subclasses.
    + *
    + * The type is a string that identifies the type of Certificates in the + * certification path. For each certificate cert in a certification path + * certPath, cert.getType().equals(certPath.getType()) must be true.
    + *
    + * The list of Certificates is an ordered List of zero or more Certificates. + * This List and all of the Certificates contained in it must be immutable.
    + *
    + * Each CertPath object must support one or more encodings so that the object + * can be translated into a byte array for storage or transmission to other + * parties. Preferably, these encodings should be well-documented standards + * (such as PKCS#7). One of the encodings supported by a CertPath is considered + * the default encoding. This encoding is used if no encoding is explicitly + * requested (for the {@link #getEncoded()} method, for instance).
    + *
    + * All CertPath objects are also Serializable. CertPath objects are resolved + * into an alternate {@link CertPathRep} object during serialization. This + * allows a CertPath object to be serialized into an equivalent representation + * regardless of its underlying implementation.
    + *
    + * CertPath objects can be created with a CertificateFactory or they can be + * returned by other classes, such as a CertPathBuilder.
    + *
    + * By convention, X.509 CertPaths (consisting of X509Certificates), are ordered + * starting with the target certificate and ending with a certificate issued by + * the trust anchor. That is, the issuer of one certificate is the subject of + * the following one. The certificate representing the + * {@link TrustAnchor TrustAnchor} should not be included in the certification + * path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX + * CertPathValidators will detect any departure from these conventions that + * cause the certification path to be invalid and throw a + * CertPathValidatorException.
    + *
    + * Concurrent Access
    + *
    + * All CertPath objects must be thread-safe. That is, multiple threads may + * concurrently invoke the methods defined in this class on a single CertPath + * object (or more than one) with no ill effects. This is also true for the List + * returned by CertPath.getCertificates.
    + *
    + * Requiring CertPath objects to be immutable and thread-safe allows them to be + * passed around to various pieces of code without worrying about coordinating + * access. Providing this thread-safety is generally not difficult, since the + * CertPath and List objects in question are immutable. + * + * @see CertificateFactory + * @see CertPathBuilder + */ + /// + /// CertPath implementation for X.509 certificates. + /// + public class PkixCertPath +// : CertPath + { + internal static readonly IList certPathEncodings; + + static PkixCertPath() + { + IList encodings = Platform.CreateArrayList(); + encodings.Add("PkiPath"); + encodings.Add("PEM"); + encodings.Add("PKCS7"); + certPathEncodings = CollectionUtilities.ReadOnly(encodings); + } + + private readonly IList certificates; + + /** + * @param certs + */ + private static IList SortCerts( + IList certs) + { + if (certs.Count < 2) + return certs; + + X509Name issuer = ((X509Certificate)certs[0]).IssuerDN; + bool okay = true; + + for (int i = 1; i != certs.Count; i++) + { + X509Certificate cert = (X509Certificate)certs[i]; + + if (issuer.Equivalent(cert.SubjectDN, true)) + { + issuer = ((X509Certificate)certs[i]).IssuerDN; + } + else + { + okay = false; + break; + } + } + + if (okay) + return certs; + + // find end-entity cert + IList retList = Platform.CreateArrayList(certs.Count); + IList orig = Platform.CreateArrayList(certs); + + for (int i = 0; i < certs.Count; i++) + { + X509Certificate cert = (X509Certificate)certs[i]; + bool found = false; + + X509Name subject = cert.SubjectDN; + foreach (X509Certificate c in certs) + { + if (c.IssuerDN.Equivalent(subject, true)) + { + found = true; + break; + } + } + + if (!found) + { + retList.Add(cert); + certs.RemoveAt(i); + } + } + + // can only have one end entity cert - something's wrong, give up. + if (retList.Count > 1) + return orig; + + for (int i = 0; i != retList.Count; i++) + { + issuer = ((X509Certificate)retList[i]).IssuerDN; + + for (int j = 0; j < certs.Count; j++) + { + X509Certificate c = (X509Certificate)certs[j]; + if (issuer.Equivalent(c.SubjectDN, true)) + { + retList.Add(c); + certs.RemoveAt(j); + break; + } + } + } + + // make sure all certificates are accounted for. + if (certs.Count > 0) + return orig; + + return retList; + } + + /** + * Creates a CertPath of the specified type. + * This constructor is protected because most users should use + * a CertificateFactory to create CertPaths. + * @param type the standard name of the type of Certificatesin this path + **/ + public PkixCertPath( + ICollection certificates) +// : base("X.509") + { + this.certificates = SortCerts(Platform.CreateArrayList(certificates)); + } + + public PkixCertPath( + Stream inStream) + : this(inStream, "PkiPath") + { + } + + /** + * Creates a CertPath of the specified type. + * This constructor is protected because most users should use + * a CertificateFactory to create CertPaths. + * + * @param type the standard name of the type of Certificatesin this path + **/ + public PkixCertPath( + Stream inStream, + string encoding) +// : base("X.509") + { + string upper = encoding.ToUpper(); + + IList certs; + try + { + if (upper.Equals("PkiPath".ToUpper())) + { + Asn1InputStream derInStream = new Asn1InputStream(inStream); + Asn1Object derObject = derInStream.ReadObject(); + if (!(derObject is Asn1Sequence)) + { + throw new CertificateException( + "input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath"); + } + + certs = Platform.CreateArrayList(); + + foreach (Asn1Encodable ae in (Asn1Sequence)derObject) + { + byte[] derBytes = ae.GetEncoded(Asn1Encodable.Der); + Stream certInStream = new MemoryStream(derBytes, false); + + // TODO Is inserting at the front important (list will be sorted later anyway)? + certs.Insert(0, new X509CertificateParser().ReadCertificate(certInStream)); + } + } + else if (upper.Equals("PKCS7") || upper.Equals("PEM")) + { + certs = Platform.CreateArrayList(new X509CertificateParser().ReadCertificates(inStream)); + } + else + { + throw new CertificateException("unsupported encoding: " + encoding); + } + } + catch (IOException ex) + { + throw new CertificateException( + "IOException throw while decoding CertPath:\n" + + ex.ToString()); + } + + this.certificates = SortCerts(certs); + } + + /** + * Returns an iteration of the encodings supported by this + * certification path, with the default encoding + * first. Attempts to modify the returned Iterator via its + * remove method result in an UnsupportedOperationException. + * + * @return an Iterator over the names of the supported encodings (as Strings) + **/ + public virtual IEnumerable Encodings + { + get { return new EnumerableProxy(certPathEncodings); } + } + + /** + * Compares this certification path for equality with the specified object. + * Two CertPaths are equal if and only if their types are equal and their + * certificate Lists (and by implication the Certificates in those Lists) + * are equal. A CertPath is never equal to an object that is not a CertPath.
    + *
    + * This algorithm is implemented by this method. If it is overridden, the + * behavior specified here must be maintained. + * + * @param other + * the object to test for equality with this certification path + * + * @return true if the specified object is equal to this certification path, + * false otherwise + * + * @see Object#hashCode() Object.hashCode() + */ + public override bool Equals( + object obj) + { + if (this == obj) + return true; + + PkixCertPath other = obj as PkixCertPath; + if (other == null) + return false; + +// if (!this.Type.Equals(other.Type)) +// return false; + + //return this.Certificates.Equals(other.Certificates); + + // TODO Extract this to a utility class + IList thisCerts = this.Certificates; + IList otherCerts = other.Certificates; + + if (thisCerts.Count != otherCerts.Count) + return false; + + IEnumerator e1 = thisCerts.GetEnumerator(); + IEnumerator e2 = thisCerts.GetEnumerator(); + + while (e1.MoveNext()) + { + e2.MoveNext(); + + if (!Platform.Equals(e1.Current, e2.Current)) + return false; + } + + return true; + } + + public override int GetHashCode() + { + // FIXME? + return this.Certificates.GetHashCode(); + } + + /** + * Returns the encoded form of this certification path, using + * the default encoding. + * + * @return the encoded bytes + * @exception CertificateEncodingException if an encoding error occurs + **/ + public virtual byte[] GetEncoded() + { + foreach (object enc in Encodings) + { + if (enc is string) + { + return GetEncoded((string)enc); + } + } + return null; + } + + /** + * Returns the encoded form of this certification path, using + * the specified encoding. + * + * @param encoding the name of the encoding to use + * @return the encoded bytes + * @exception CertificateEncodingException if an encoding error + * occurs or the encoding requested is not supported + * + */ + public virtual byte[] GetEncoded( + string encoding) + { + if (Platform.CompareIgnoreCase(encoding, "PkiPath") == 0) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + for (int i = certificates.Count - 1; i >= 0; i--) + { + v.Add(ToAsn1Object((X509Certificate) certificates[i])); + } + + return ToDerEncoded(new DerSequence(v)); + } + else if (Platform.CompareIgnoreCase(encoding, "PKCS7") == 0) + { + Asn1.Pkcs.ContentInfo encInfo = new Asn1.Pkcs.ContentInfo( + PkcsObjectIdentifiers.Data, null); + + Asn1EncodableVector v = new Asn1EncodableVector(); + for (int i = 0; i != certificates.Count; i++) + { + v.Add(ToAsn1Object((X509Certificate)certificates[i])); + } + + Asn1.Pkcs.SignedData sd = new Asn1.Pkcs.SignedData( + new DerInteger(1), + new DerSet(), + encInfo, + new DerSet(v), + null, + new DerSet()); + + return ToDerEncoded(new Asn1.Pkcs.ContentInfo(PkcsObjectIdentifiers.SignedData, sd)); + } + else if (Platform.CompareIgnoreCase(encoding, "PEM") == 0) + { + MemoryStream bOut = new MemoryStream(); + PemWriter pWrt = new PemWriter(new StreamWriter(bOut)); + + try + { + for (int i = 0; i != certificates.Count; i++) + { + pWrt.WriteObject(certificates[i]); + } + + pWrt.Writer.Close(); + } + catch (Exception) + { + throw new CertificateEncodingException("can't encode certificate for PEM encoded path"); + } + + return bOut.ToArray(); + } + else + { + throw new CertificateEncodingException("unsupported encoding: " + encoding); + } + } + + /// + /// Returns the list of certificates in this certification + /// path. + /// + public virtual IList Certificates + { + get { return CollectionUtilities.ReadOnly(certificates); } + } + + /** + * Return a DERObject containing the encoded certificate. + * + * @param cert the X509Certificate object to be encoded + * + * @return the DERObject + **/ + private Asn1Object ToAsn1Object( + X509Certificate cert) + { + try + { + return Asn1Object.FromByteArray(cert.GetEncoded()); + } + catch (Exception e) + { + throw new CertificateEncodingException("Exception while encoding certificate", e); + } + } + + private byte[] ToDerEncoded(Asn1Encodable obj) + { + try + { + return obj.GetEncoded(Asn1Encodable.Der); + } + catch (IOException e) + { + throw new CertificateEncodingException("Exception thrown", e); + } + } + } +} diff --git a/crypto/src/pkix/PkixCertPathBuilder.cs b/crypto/src/pkix/PkixCertPathBuilder.cs new file mode 100644 index 000000000..7082fe409 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathBuilder.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Asn1.IsisMtt; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + /** + * Implements the PKIX CertPathBuilding algorithm for BouncyCastle. + * + * @see CertPathBuilderSpi + */ + public class PkixCertPathBuilder + // : CertPathBuilderSpi + { + /** + * Build and validate a CertPath using the given parameter. + * + * @param params PKIXBuilderParameters object containing all information to + * build the CertPath + */ + public virtual PkixCertPathBuilderResult Build( + PkixBuilderParameters pkixParams) + { + // search target certificates + + IX509Selector certSelect = pkixParams.GetTargetCertConstraints(); + if (!(certSelect is X509CertStoreSelector)) + { + throw new PkixCertPathBuilderException( + "TargetConstraints must be an instance of " + + typeof(X509CertStoreSelector).FullName + " for " + + this.GetType() + " class."); + } + + ISet targets = new HashSet(); + try + { + targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetStores())); + // TODO Should this include an entry for pkixParams.GetAdditionalStores() too? + } + catch (Exception e) + { + throw new PkixCertPathBuilderException( + "Error finding target certificate.", e); + } + + if (targets.IsEmpty) + throw new PkixCertPathBuilderException("No certificate found matching targetContraints."); + + PkixCertPathBuilderResult result = null; + IList certPathList = Platform.CreateArrayList(); + + // check all potential target certificates + foreach (X509Certificate cert in targets) + { + result = Build(cert, pkixParams, certPathList); + + if (result != null) + break; + } + + if (result == null && certPathException != null) + { + throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException); + } + + if (result == null && certPathException == null) + { + throw new PkixCertPathBuilderException("Unable to find certificate chain."); + } + + return result; + } + + private Exception certPathException; + + protected virtual PkixCertPathBuilderResult Build( + X509Certificate tbvCert, + PkixBuilderParameters pkixParams, + IList tbvPath) + { + // If tbvCert is readily present in tbvPath, it indicates having run + // into a cycle in the PKI graph. + if (tbvPath.Contains(tbvCert)) + return null; + + // step out, the certificate is not allowed to appear in a certification + // chain. + if (pkixParams.GetExcludedCerts().Contains(tbvCert)) + return null; + + // test if certificate path exceeds maximum length + if (pkixParams.MaxPathLength != -1) + { + if (tbvPath.Count - 1 > pkixParams.MaxPathLength) + return null; + } + + tbvPath.Add(tbvCert); + +// X509CertificateParser certParser = new X509CertificateParser(); + PkixCertPathBuilderResult builderResult = null; + PkixCertPathValidator validator = new PkixCertPathValidator(); + + try + { + // check whether the issuer of is a TrustAnchor + if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null) + { + // exception message from possibly later tried certification + // chains + PkixCertPath certPath = null; + try + { + certPath = new PkixCertPath(tbvPath); + } + catch (Exception e) + { + throw new Exception( + "Certification path could not be constructed from certificate list.", + e); + } + + PkixCertPathValidatorResult result = null; + try + { + result = (PkixCertPathValidatorResult)validator.Validate( + certPath, pkixParams); + } + catch (Exception e) + { + throw new Exception( + "Certification path could not be validated.", e); + } + + return new PkixCertPathBuilderResult(certPath, result.TrustAnchor, + result.PolicyTree, result.SubjectPublicKey); + } + else + { + // add additional X.509 stores from locations in certificate + try + { + PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames( + tbvCert, pkixParams); + } + catch (CertificateParsingException e) + { + throw new Exception( + "No additiontal X.509 stores can be added from certificate locations.", + e); + } + + // try to get the issuer certificate from one of the stores + HashSet issuers = new HashSet(); + try + { + issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams)); + } + catch (Exception e) + { + throw new Exception( + "Cannot find issuer certificate for certificate in certification path.", + e); + } + + if (issuers.IsEmpty) + throw new Exception("No issuer certificate for certificate in certification path found."); + + foreach (X509Certificate issuer in issuers) + { + builderResult = Build(issuer, pkixParams, tbvPath); + + if (builderResult != null) + break; + } + } + } + catch (Exception e) + { + certPathException = e; + } + + if (builderResult == null) + { + tbvPath.Remove(tbvCert); + } + + return builderResult; + } + } +} diff --git a/crypto/src/pkix/PkixCertPathBuilderException.cs b/crypto/src/pkix/PkixCertPathBuilderException.cs new file mode 100644 index 000000000..5a4944dd8 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathBuilderException.cs @@ -0,0 +1,22 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixCertPathBuilderException. + /// +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PkixCertPathBuilderException : GeneralSecurityException + { + public PkixCertPathBuilderException() : base() { } + + public PkixCertPathBuilderException(string message) : base(message) { } + + public PkixCertPathBuilderException(string message, Exception exception) : base(message, exception) { } + + } +} diff --git a/crypto/src/pkix/PkixCertPathBuilderResult.cs b/crypto/src/pkix/PkixCertPathBuilderResult.cs new file mode 100644 index 000000000..f8003032f --- /dev/null +++ b/crypto/src/pkix/PkixCertPathBuilderResult.cs @@ -0,0 +1,45 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkix; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixCertPathBuilderResult. + /// + public class PkixCertPathBuilderResult + : PkixCertPathValidatorResult//, ICertPathBuilderResult + { + private PkixCertPath certPath; + + public PkixCertPathBuilderResult( + PkixCertPath certPath, + TrustAnchor trustAnchor, + PkixPolicyNode policyTree, + AsymmetricKeyParameter subjectPublicKey) + : base(trustAnchor, policyTree, subjectPublicKey) + { + if (certPath == null) + throw new ArgumentNullException("certPath"); + + this.certPath = certPath; + } + + public PkixCertPath CertPath + { + get { return certPath; } + } + + public override string ToString() + { + StringBuilder s = new StringBuilder(); + s.Append("SimplePKIXCertPathBuilderResult: [\n"); + s.Append(" Certification Path: ").Append(CertPath).Append('\n'); + s.Append(" Trust Anchor: ").Append(this.TrustAnchor.TrustedCert.IssuerDN.ToString()).Append('\n'); + s.Append(" Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]"); + return s.ToString(); + } + } +} diff --git a/crypto/src/pkix/PkixCertPathChecker.cs b/crypto/src/pkix/PkixCertPathChecker.cs new file mode 100644 index 000000000..f22738d89 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathChecker.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkix +{ + public abstract class PkixCertPathChecker + { + protected PkixCertPathChecker() + { + } + + /** + * Initializes the internal state of this PKIXCertPathChecker. + *

    + * The forward flag specifies the order that certificates + * will be passed to the {@link #check check} method (forward or reverse). A + * PKIXCertPathChecker must support reverse checking + * and may support forward checking. + *

    + * + * @param forward + * the order that certificates are presented to the + * check method. If true, + * certificates are presented from target to most-trusted CA + * (forward); if false, from most-trusted CA to + * target (reverse). + * @exception CertPathValidatorException + * if this PKIXCertPathChecker is unable to + * check certificates in the specified order; it should never + * be thrown if the forward flag is false since reverse + * checking must be supported + */ + public abstract void Init(bool forward); + //throws CertPathValidatorException; + + /** + * Indicates if forward checking is supported. Forward checking refers to + * the ability of the PKIXCertPathChecker to perform its + * checks when certificates are presented to the check method + * in the forward direction (from target to most-trusted CA). + * + * @return true if forward checking is supported, + * false otherwise + */ + public abstract bool IsForwardCheckingSupported(); + + /** + * Returns an immutable Set of X.509 certificate extensions + * that this PKIXCertPathChecker supports (i.e. recognizes, + * is able to process), or null if no extensions are + * supported. + *

    + * Each element of the set is a String representing the + * Object Identifier (OID) of the X.509 extension that is supported. The OID + * is represented by a set of nonnegative integers separated by periods. + *

    + * All X.509 certificate extensions that a PKIXCertPathChecker + * might possibly be able to process should be included in the set. + *

    + * + * @return an immutable Set of X.509 extension OIDs (in + * String format) supported by this + * PKIXCertPathChecker, or null if no + * extensions are supported + */ + public abstract ISet GetSupportedExtensions(); + + /** + * Performs the check(s) on the specified certificate using its internal + * state and removes any critical extensions that it processes from the + * specified collection of OID strings that represent the unresolved + * critical extensions. The certificates are presented in the order + * specified by the init method. + * + * @param cert + * the Certificate to be checked + * @param unresolvedCritExts + * a Collection of OID strings representing the + * current set of unresolved critical extensions + * @exception CertPathValidatorException + * if the specified certificate does not pass the check + */ + public abstract void Check(X509Certificate cert, ICollection unresolvedCritExts); + //throws CertPathValidatorException; + + /** + * Returns a clone of this object. Calls the Object.clone() + * method. All subclasses which maintain state must support and override + * this method, if necessary. + * + * @return a copy of this PKIXCertPathChecker + */ + public virtual object Clone() + { + // TODO Check this + return base.MemberwiseClone(); + } + } +} diff --git a/crypto/src/pkix/PkixCertPathValidator.cs b/crypto/src/pkix/PkixCertPathValidator.cs new file mode 100644 index 000000000..7eb838886 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathValidator.cs @@ -0,0 +1,420 @@ +using System; +using System.Collections; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + /** + * The Service Provider Interface (SPI) + * for the {@link CertPathValidator CertPathValidator} class. All + * CertPathValidator implementations must include a class (the + * SPI class) that extends this class (CertPathValidatorSpi) + * and implements all of its methods. In general, instances of this class + * should only be accessed through the CertPathValidator class. + * For details, see the Java Cryptography Architecture.
    + *
    + * Concurrent Access
    + *
    + * Instances of this class need not be protected against concurrent + * access from multiple threads. Threads that need to access a single + * CertPathValidatorSpi instance concurrently should synchronize + * amongst themselves and provide the necessary locking before calling the + * wrapping CertPathValidator object.
    + *
    + * However, implementations of CertPathValidatorSpi may still + * encounter concurrency issues, since multiple threads each + * manipulating a different CertPathValidatorSpi instance need not + * synchronize. + */ + /// + /// CertPathValidatorSpi implementation for X.509 Certificate validation a la RFC + /// 3280. + /// + public class PkixCertPathValidator + { + public virtual PkixCertPathValidatorResult Validate( + PkixCertPath certPath, + PkixParameters paramsPkix) + { + if (paramsPkix.GetTrustAnchors() == null) + { + throw new ArgumentException( + "trustAnchors is null, this is not allowed for certification path validation.", + "parameters"); + } + + // + // 6.1.1 - inputs + // + + // + // (a) + // + IList certs = certPath.Certificates; + int n = certs.Count; + + if (certs.Count == 0) + throw new PkixCertPathValidatorException("Certification path is empty.", null, certPath, 0); + + // + // (b) + // + // DateTime validDate = PkixCertPathValidatorUtilities.GetValidDate(paramsPkix); + + // + // (c) + // + ISet userInitialPolicySet = paramsPkix.GetInitialPolicies(); + + // + // (d) + // + TrustAnchor trust; + try + { + trust = PkixCertPathValidatorUtilities.FindTrustAnchor( + (X509Certificate)certs[certs.Count - 1], + paramsPkix.GetTrustAnchors()); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException(e.Message, e, certPath, certs.Count - 1); + } + + if (trust == null) + throw new PkixCertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1); + + // + // (e), (f), (g) are part of the paramsPkix object. + // + IEnumerator certIter; + int index = 0; + int i; + // Certificate for each interation of the validation loop + // Signature information for each iteration of the validation loop + // + // 6.1.2 - setup + // + + // + // (a) + // + IList[] policyNodes = new IList[n + 1]; + for (int j = 0; j < policyNodes.Length; j++) + { + policyNodes[j] = Platform.CreateArrayList(); + } + + ISet policySet = new HashSet(); + + policySet.Add(Rfc3280CertPathUtilities.ANY_POLICY); + + PkixPolicyNode validPolicyTree = new PkixPolicyNode(Platform.CreateArrayList(), 0, policySet, null, new HashSet(), + Rfc3280CertPathUtilities.ANY_POLICY, false); + + policyNodes[0].Add(validPolicyTree); + + // + // (b) and (c) + // + PkixNameConstraintValidator nameConstraintValidator = new PkixNameConstraintValidator(); + + // (d) + // + int explicitPolicy; + ISet acceptablePolicies = new HashSet(); + + if (paramsPkix.IsExplicitPolicyRequired) + { + explicitPolicy = 0; + } + else + { + explicitPolicy = n + 1; + } + + // + // (e) + // + int inhibitAnyPolicy; + + if (paramsPkix.IsAnyPolicyInhibited) + { + inhibitAnyPolicy = 0; + } + else + { + inhibitAnyPolicy = n + 1; + } + + // + // (f) + // + int policyMapping; + + if (paramsPkix.IsPolicyMappingInhibited) + { + policyMapping = 0; + } + else + { + policyMapping = n + 1; + } + + // + // (g), (h), (i), (j) + // + AsymmetricKeyParameter workingPublicKey; + X509Name workingIssuerName; + + X509Certificate sign = trust.TrustedCert; + try + { + if (sign != null) + { + workingIssuerName = sign.SubjectDN; + workingPublicKey = sign.GetPublicKey(); + } + else + { + workingIssuerName = new X509Name(trust.CAName); + workingPublicKey = trust.CAPublicKey; + } + } + catch (ArgumentException ex) + { + throw new PkixCertPathValidatorException("Subject of trust anchor could not be (re)encoded.", ex, certPath, + -1); + } + + AlgorithmIdentifier workingAlgId = null; + try + { + workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey); + } + catch (PkixCertPathValidatorException e) + { + throw new PkixCertPathValidatorException( + "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1); + } + +// DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.ObjectID; +// Asn1Encodable workingPublicKeyParameters = workingAlgId.Parameters; + + // + // (k) + // + int maxPathLength = n; + + // + // 6.1.3 + // + + X509CertStoreSelector certConstraints = paramsPkix.GetTargetCertConstraints(); + if (certConstraints != null && !certConstraints.Match((X509Certificate)certs[0])) + { + throw new PkixCertPathValidatorException( + "Target certificate in certification path does not match targetConstraints.", null, certPath, 0); + } + + // + // initialize CertPathChecker's + // + IList pathCheckers = paramsPkix.GetCertPathCheckers(); + certIter = pathCheckers.GetEnumerator(); + + while (certIter.MoveNext()) + { + ((PkixCertPathChecker)certIter.Current).Init(false); + } + + X509Certificate cert = null; + + for (index = certs.Count - 1; index >= 0; index--) + { + // try + // { + // + // i as defined in the algorithm description + // + i = n - index; + + // + // set certificate to be checked in this round + // sign and workingPublicKey and workingIssuerName are set + // at the end of the for loop and initialized the + // first time from the TrustAnchor + // + cert = (X509Certificate)certs[index]; + + // + // 6.1.3 + // + + Rfc3280CertPathUtilities.ProcessCertA(certPath, paramsPkix, index, workingPublicKey, + workingIssuerName, sign); + + Rfc3280CertPathUtilities.ProcessCertBC(certPath, index, nameConstraintValidator); + + validPolicyTree = Rfc3280CertPathUtilities.ProcessCertD(certPath, index, + acceptablePolicies, validPolicyTree, policyNodes, inhibitAnyPolicy); + + validPolicyTree = Rfc3280CertPathUtilities.ProcessCertE(certPath, index, validPolicyTree); + + Rfc3280CertPathUtilities.ProcessCertF(certPath, index, validPolicyTree, explicitPolicy); + + // + // 6.1.4 + // + + if (i != n) + { + if (cert != null && cert.Version == 1) + { + throw new PkixCertPathValidatorException( + "Version 1 certificates can't be used as CA ones.", null, certPath, index); + } + + Rfc3280CertPathUtilities.PrepareNextCertA(certPath, index); + + validPolicyTree = Rfc3280CertPathUtilities.PrepareCertB(certPath, index, policyNodes, + validPolicyTree, policyMapping); + + Rfc3280CertPathUtilities.PrepareNextCertG(certPath, index, nameConstraintValidator); + + // (h) + explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertH1(certPath, index, explicitPolicy); + policyMapping = Rfc3280CertPathUtilities.PrepareNextCertH2(certPath, index, policyMapping); + inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertH3(certPath, index, inhibitAnyPolicy); + + // + // (i) + // + explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertI1(certPath, index, explicitPolicy); + policyMapping = Rfc3280CertPathUtilities.PrepareNextCertI2(certPath, index, policyMapping); + + // (j) + inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertJ(certPath, index, inhibitAnyPolicy); + + // (k) + Rfc3280CertPathUtilities.PrepareNextCertK(certPath, index); + + // (l) + maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertL(certPath, index, maxPathLength); + + // (m) + maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertM(certPath, index, maxPathLength); + + // (n) + Rfc3280CertPathUtilities.PrepareNextCertN(certPath, index); + + ISet criticalExtensions1 = cert.GetCriticalExtensionOids(); + + if (criticalExtensions1 != null) + { + criticalExtensions1 = new HashSet(criticalExtensions1); + + // these extensions are handled by the algorithm + criticalExtensions1.Remove(X509Extensions.KeyUsage.Id); + criticalExtensions1.Remove(X509Extensions.CertificatePolicies.Id); + criticalExtensions1.Remove(X509Extensions.PolicyMappings.Id); + criticalExtensions1.Remove(X509Extensions.InhibitAnyPolicy.Id); + criticalExtensions1.Remove(X509Extensions.IssuingDistributionPoint.Id); + criticalExtensions1.Remove(X509Extensions.DeltaCrlIndicator.Id); + criticalExtensions1.Remove(X509Extensions.PolicyConstraints.Id); + criticalExtensions1.Remove(X509Extensions.BasicConstraints.Id); + criticalExtensions1.Remove(X509Extensions.SubjectAlternativeName.Id); + criticalExtensions1.Remove(X509Extensions.NameConstraints.Id); + } + else + { + criticalExtensions1 = new HashSet(); + } + + // (o) + Rfc3280CertPathUtilities.PrepareNextCertO(certPath, index, criticalExtensions1, pathCheckers); + + // set signing certificate for next round + sign = cert; + + // (c) + workingIssuerName = sign.SubjectDN; + + // (d) + try + { + workingPublicKey = PkixCertPathValidatorUtilities.GetNextWorkingKey(certPath.Certificates, index); + } + catch (PkixCertPathValidatorException e) + { + throw new PkixCertPathValidatorException("Next working key could not be retrieved.", e, certPath, index); + } + + workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey); + // (f) +// workingPublicKeyAlgorithm = workingAlgId.ObjectID; + // (e) +// workingPublicKeyParameters = workingAlgId.Parameters; + } + } + + // + // 6.1.5 Wrap-up procedure + // + + explicitPolicy = Rfc3280CertPathUtilities.WrapupCertA(explicitPolicy, cert); + + explicitPolicy = Rfc3280CertPathUtilities.WrapupCertB(certPath, index + 1, explicitPolicy); + + // + // (c) (d) and (e) are already done + // + + // + // (f) + // + ISet criticalExtensions = cert.GetCriticalExtensionOids(); + + if (criticalExtensions != null) + { + criticalExtensions = new HashSet(criticalExtensions); + + // Requires .Id + // these extensions are handled by the algorithm + criticalExtensions.Remove(X509Extensions.KeyUsage.Id); + criticalExtensions.Remove(X509Extensions.CertificatePolicies.Id); + criticalExtensions.Remove(X509Extensions.PolicyMappings.Id); + criticalExtensions.Remove(X509Extensions.InhibitAnyPolicy.Id); + criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id); + criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id); + criticalExtensions.Remove(X509Extensions.PolicyConstraints.Id); + criticalExtensions.Remove(X509Extensions.BasicConstraints.Id); + criticalExtensions.Remove(X509Extensions.SubjectAlternativeName.Id); + criticalExtensions.Remove(X509Extensions.NameConstraints.Id); + criticalExtensions.Remove(X509Extensions.CrlDistributionPoints.Id); + } + else + { + criticalExtensions = new HashSet(); + } + + Rfc3280CertPathUtilities.WrapupCertF(certPath, index + 1, pathCheckers, criticalExtensions); + + PkixPolicyNode intersection = Rfc3280CertPathUtilities.WrapupCertG(certPath, paramsPkix, userInitialPolicySet, + index + 1, policyNodes, validPolicyTree, acceptablePolicies); + + if ((explicitPolicy > 0) || (intersection != null)) + { + return new PkixCertPathValidatorResult(trust, intersection, cert.GetPublicKey()); + } + + throw new PkixCertPathValidatorException("Path processing failed on policy.", null, certPath, index); + } + } +} diff --git a/crypto/src/pkix/PkixCertPathValidatorException.cs b/crypto/src/pkix/PkixCertPathValidatorException.cs new file mode 100644 index 000000000..35522c6f8 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathValidatorException.cs @@ -0,0 +1,221 @@ +using System; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Pkix +{ + /** + * An exception indicating one of a variety of problems encountered when + * validating a certification path.
    + *
    + * A CertPathValidatorException provides support for wrapping + * exceptions. The {@link #getCause getCause} method returns the throwable, + * if any, that caused this exception to be thrown.
    + *
    + * A CertPathValidatorException may also include the + * certification path that was being validated when the exception was thrown + * and the index of the certificate in the certification path that caused the + * exception to be thrown. Use the {@link #getCertPath getCertPath} and + * {@link #getIndex getIndex} methods to retrieve this information.
    + *
    + * Concurrent Access
    + *
    + * Unless otherwise specified, the methods defined in this class are not + * thread-safe. Multiple threads that need to access a single + * object concurrently should synchronize amongst themselves and + * provide the necessary locking. Multiple threads each manipulating + * separate objects need not synchronize. + * + * @see CertPathValidator + **/ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PkixCertPathValidatorException + : GeneralSecurityException + { + private Exception cause; + private PkixCertPath certPath; + private int index = -1; + + public PkixCertPathValidatorException() : base() { } + + /// + /// Creates a PkixCertPathValidatorException with the given detail + /// message. A detail message is a String that describes this + /// particular exception. + /// + /// the detail message + public PkixCertPathValidatorException(string message) : base(message) { } + + /// + /// Creates a PkixCertPathValidatorException with the specified + /// detail message and cause. + /// + /// the detail message + /// the cause (which is saved for later retrieval by the + /// {@link #getCause getCause()} method). (A null + /// value is permitted, and indicates that the cause is + /// nonexistent or unknown.) + public PkixCertPathValidatorException(string message, Exception cause) : base(message) + { + this.cause = cause; + } + + /// + /// Creates a PkixCertPathValidatorException with the specified + /// detail message, cause, certification path, and index. + /// + /// the detail message (or null if none) + /// the cause (or null if none) + /// the certification path that was in the process of being + /// validated when the error was encountered + /// the index of the certificate in the certification path that * + public PkixCertPathValidatorException( + string message, + Exception cause, + PkixCertPath certPath, + int index) + : base(message) + { + if (certPath == null && index != -1) + { + throw new ArgumentNullException( + "certPath = null and index != -1"); + } + if (index < -1 + || (certPath != null && index >= certPath.Certificates.Count)) + { + throw new IndexOutOfRangeException( + " index < -1 or out of bound of certPath.getCertificates()"); + } + + this.cause = cause; + this.certPath = certPath; + this.index = index; + } + + // + // Prints a stack trace to a PrintWriter, including the + // backtrace of the cause, if any. + // + // @param pw + // the PrintWriter to use for output + // + // public void printStackTrace(PrintWriter pw) + // { + // super.printStackTrace(pw); + // if (getCause() != null) + // { + // getCause().printStackTrace(pw); + // } + // } + //} + + + // /** + // * Creates a CertPathValidatorException that wraps the + // * specified throwable. This allows any exception to be converted into a + // * CertPathValidatorException, while retaining information + // * about the wrapped exception, which may be useful for debugging. The + // * detail message is set to (cause==null ? null : cause.toString() + // * ) + // * (which typically contains the class and detail message of cause). + // * + // * @param cause + // * the cause (which is saved for later retrieval by the + // * {@link #getCause getCause()} method). (A null + // * value is permitted, and indicates that the cause is + // * nonexistent or unknown.) + // */ + // public PkixCertPathValidatorException(Throwable cause) + // { + // this.cause = cause; + // } + // + + /// + /// Returns the detail message for this CertPathValidatorException. + /// + /// the detail message, or null if neither the message nor cause were specified + public override string Message + { + get + { + string message = base.Message; + + if (message != null) + { + return message; + } + + if (cause != null) + { + return cause.Message; + } + + return null; + } + } + + /** + * Returns the certification path that was being validated when the + * exception was thrown. + * + * @return the CertPath that was being validated when the + * exception was thrown (or null if not specified) + */ + public PkixCertPath CertPath + { + get { return certPath; } + } + + /** + * Returns the index of the certificate in the certification path that + * caused the exception to be thrown. Note that the list of certificates in + * a CertPath is zero based. If no index has been set, -1 is + * returned. + * + * @return the index that has been set, or -1 if none has been set + */ + public int Index + { + get { return index; } + } + +// /** +// * Returns the cause of this CertPathValidatorException or +// * null if the cause is nonexistent or unknown. +// * +// * @return the cause of this throwable or null if the cause +// * is nonexistent or unknown. +// */ +// public Throwable getCause() +// { +// return cause; +// } +// +// /** +// * Returns a string describing this exception, including a description of +// * the internal (wrapped) cause if there is one. +// * +// * @return a string representation of this +// * CertPathValidatorException +// */ +// public String toString() +// { +// StringBuffer sb = new StringBuffer(); +// String s = getMessage(); +// if (s != null) +// { +// sb.append(s); +// } +// if (getIndex() >= 0) +// { +// sb.append("index in certpath: ").append(getIndex()).append('\n'); +// sb.append(getCertPath()); +// } +// return sb.toString(); +// } + + } +} diff --git a/crypto/src/pkix/PkixCertPathValidatorResult.cs b/crypto/src/pkix/PkixCertPathValidatorResult.cs new file mode 100644 index 000000000..c7d81c7f5 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathValidatorResult.cs @@ -0,0 +1,69 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixCertPathValidatorResult. + /// + public class PkixCertPathValidatorResult + //: ICertPathValidatorResult + { + private TrustAnchor trustAnchor; + private PkixPolicyNode policyTree; + private AsymmetricKeyParameter subjectPublicKey; + + public PkixPolicyNode PolicyTree + { + get { return this.policyTree; } + } + + public TrustAnchor TrustAnchor + { + get { return this.trustAnchor; } + } + + public AsymmetricKeyParameter SubjectPublicKey + { + get { return this.subjectPublicKey; } + } + + public PkixCertPathValidatorResult( + TrustAnchor trustAnchor, + PkixPolicyNode policyTree, + AsymmetricKeyParameter subjectPublicKey) + { + if (subjectPublicKey == null) + { + throw new NullReferenceException("subjectPublicKey must be non-null"); + } + if (trustAnchor == null) + { + throw new NullReferenceException("trustAnchor must be non-null"); + } + + this.trustAnchor = trustAnchor; + this.policyTree = policyTree; + this.subjectPublicKey = subjectPublicKey; + } + + public object Clone() + { + return new PkixCertPathValidatorResult(this.TrustAnchor, this.PolicyTree, this.SubjectPublicKey); + } + + public override String ToString() + { + StringBuilder sB = new StringBuilder(); + sB.Append("PKIXCertPathValidatorResult: [ \n"); + sB.Append(" Trust Anchor: ").Append(this.TrustAnchor).Append('\n'); + sB.Append(" Policy Tree: ").Append(this.PolicyTree).Append('\n'); + sB.Append(" Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]"); + return sB.ToString(); + } + + } +} diff --git a/crypto/src/pkix/PkixCertPathValidatorUtilities.cs b/crypto/src/pkix/PkixCertPathValidatorUtilities.cs new file mode 100644 index 000000000..305b2de35 --- /dev/null +++ b/crypto/src/pkix/PkixCertPathValidatorUtilities.cs @@ -0,0 +1,1194 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.IsisMtt; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixCertPathValidatorUtilities. + /// + public class PkixCertPathValidatorUtilities + { + private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities(); + + internal static readonly string ANY_POLICY = "2.5.29.32.0"; + + internal static readonly string CRL_NUMBER = X509Extensions.CrlNumber.Id; + + /// + /// key usage bits + /// + internal static readonly int KEY_CERT_SIGN = 5; + internal static readonly int CRL_SIGN = 6; + + internal static readonly string[] crlReasons = new string[] + { + "unspecified", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "unknown", + "removeFromCRL", + "privilegeWithdrawn", + "aACompromise" + }; + + /// + /// Search the given Set of TrustAnchor's for one that is the + /// issuer of the given X509 certificate. + /// + /// the X509 certificate + /// a Set of TrustAnchor's + /// the TrustAnchor object if found or + /// null if not. + /// + /// @exception + internal static TrustAnchor FindTrustAnchor( + X509Certificate cert, + ISet trustAnchors) + { + IEnumerator iter = trustAnchors.GetEnumerator(); + TrustAnchor trust = null; + AsymmetricKeyParameter trustPublicKey = null; + Exception invalidKeyEx = null; + + X509CertStoreSelector certSelectX509 = new X509CertStoreSelector(); + + try + { + certSelectX509.Subject = GetIssuerPrincipal(cert); + } + catch (IOException ex) + { + throw new Exception("Cannot set subject search criteria for trust anchor.", ex); + } + + while (iter.MoveNext() && trust == null) + { + trust = (TrustAnchor) iter.Current; + if (trust.TrustedCert != null) + { + if (certSelectX509.Match(trust.TrustedCert)) + { + trustPublicKey = trust.TrustedCert.GetPublicKey(); + } + else + { + trust = null; + } + } + else if (trust.CAName != null && trust.CAPublicKey != null) + { + try + { + X509Name certIssuer = GetIssuerPrincipal(cert); + X509Name caName = new X509Name(trust.CAName); + + if (certIssuer.Equivalent(caName, true)) + { + trustPublicKey = trust.CAPublicKey; + } + else + { + trust = null; + } + } + catch (InvalidParameterException) + { + trust = null; + } + } + else + { + trust = null; + } + + if (trustPublicKey != null) + { + try + { + cert.Verify(trustPublicKey); + } + catch (Exception ex) + { + invalidKeyEx = ex; + trust = null; + } + } + } + + if (trust == null && invalidKeyEx != null) + { + throw new Exception("TrustAnchor found but certificate validation failed.", invalidKeyEx); + } + + return trust; + } + + internal static void AddAdditionalStoresFromAltNames( + X509Certificate cert, + PkixParameters pkixParams) + { + // if in the IssuerAltName extension an URI + // is given, add an additinal X.509 store + if (cert.GetIssuerAlternativeNames() != null) + { + IEnumerator it = cert.GetIssuerAlternativeNames().GetEnumerator(); + while (it.MoveNext()) + { + // look for URI + IList list = (IList)it.Current; + //if (list[0].Equals(new Integer(GeneralName.UniformResourceIdentifier))) + if (list[0].Equals(GeneralName.UniformResourceIdentifier)) + { + // found + string temp = (string)list[1]; + PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation(temp, pkixParams); + } + } + } + } + + internal static DateTime GetValidDate(PkixParameters paramsPKIX) + { + DateTimeObject validDate = paramsPKIX.Date; + + if (validDate == null) + return DateTime.UtcNow; + + return validDate.Value; + } + + /// + /// Returns the issuer of an attribute certificate or certificate. + /// + /// The attribute certificate or certificate. + /// The issuer as X500Principal. + internal static X509Name GetIssuerPrincipal( + object cert) + { + if (cert is X509Certificate) + { + return ((X509Certificate)cert).IssuerDN; + } + else + { + return ((IX509AttributeCertificate)cert).Issuer.GetPrincipals()[0]; + } + } + + internal static bool IsSelfIssued( + X509Certificate cert) + { + return cert.SubjectDN.Equivalent(cert.IssuerDN, true); + } + + internal static AlgorithmIdentifier GetAlgorithmIdentifier( + AsymmetricKeyParameter key) + { + try + { + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key); + + return info.AlgorithmID; + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Subject public key cannot be decoded.", e); + } + } + + internal static bool IsAnyPolicy( + ISet policySet) + { + return policySet == null || policySet.Contains(ANY_POLICY) || policySet.Count == 0; + } + + internal static void AddAdditionalStoreFromLocation( + string location, + PkixParameters pkixParams) + { + if (pkixParams.IsAdditionalLocationsEnabled) + { + try + { + if (location.StartsWith("ldap://")) + { + // ldap://directory.d-trust.net/CN=D-TRUST + // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE + // skip "ldap://" + location = location.Substring(7); + // after first / baseDN starts + string url;//, baseDN; + int slashPos = location.IndexOf('/'); + if (slashPos != -1) + { + url = "ldap://" + location.Substring(0, slashPos); +// baseDN = location.Substring(slashPos); + } + else + { + url = "ldap://" + location; +// baseDN = nsull; + } + + throw Platform.CreateNotImplementedException("LDAP cert/CRL stores"); + + // use all purpose parameters + //X509LDAPCertStoreParameters ldapParams = new X509LDAPCertStoreParameters.Builder( + // url, baseDN).build(); + //pkixParams.AddAdditionalStore(X509Store.getInstance( + // "CERTIFICATE/LDAP", ldapParams)); + //pkixParams.AddAdditionalStore(X509Store.getInstance( + // "CRL/LDAP", ldapParams)); + //pkixParams.AddAdditionalStore(X509Store.getInstance( + // "ATTRIBUTECERTIFICATE/LDAP", ldapParams)); + //pkixParams.AddAdditionalStore(X509Store.getInstance( + // "CERTIFICATEPAIR/LDAP", ldapParams)); + } + } + catch (Exception) + { + // cannot happen + throw new Exception("Exception adding X.509 stores."); + } + } + } + + private static BigInteger GetSerialNumber( + object cert) + { + if (cert is X509Certificate) + { + return ((X509Certificate)cert).SerialNumber; + } + else + { + return ((X509V2AttributeCertificate)cert).SerialNumber; + } + } + + // + // policy checking + // + + internal static ISet GetQualifierSet(Asn1Sequence qualifiers) + { + ISet pq = new HashSet(); + + if (qualifiers == null) + { + return pq; + } + + foreach (Asn1Encodable ae in qualifiers) + { + try + { +// pq.Add(PolicyQualifierInfo.GetInstance(Asn1Object.FromByteArray(ae.GetEncoded()))); + pq.Add(PolicyQualifierInfo.GetInstance(ae.ToAsn1Object())); + } + catch (IOException ex) + { + throw new PkixCertPathValidatorException("Policy qualifier info cannot be decoded.", ex); + } + } + + return pq; + } + + internal static PkixPolicyNode RemovePolicyNode( + PkixPolicyNode validPolicyTree, + IList[] policyNodes, + PkixPolicyNode _node) + { + PkixPolicyNode _parent = (PkixPolicyNode)_node.Parent; + + if (validPolicyTree == null) + { + return null; + } + + if (_parent == null) + { + for (int j = 0; j < policyNodes.Length; j++) + { + policyNodes[j] = Platform.CreateArrayList(); + } + + return null; + } + else + { + _parent.RemoveChild(_node); + RemovePolicyNodeRecurse(policyNodes, _node); + + return validPolicyTree; + } + } + + private static void RemovePolicyNodeRecurse(IList[] policyNodes, PkixPolicyNode _node) + { + policyNodes[_node.Depth].Remove(_node); + + if (_node.HasChildren) + { + foreach (PkixPolicyNode _child in _node.Children) + { + RemovePolicyNodeRecurse(policyNodes, _child); + } + } + } + + internal static void PrepareNextCertB1( + int i, + IList[] policyNodes, + string id_p, + IDictionary m_idp, + X509Certificate cert) + { + bool idp_found = false; + IEnumerator nodes_i = policyNodes[i].GetEnumerator(); + while (nodes_i.MoveNext()) + { + PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current; + if (node.ValidPolicy.Equals(id_p)) + { + idp_found = true; + node.ExpectedPolicies = (ISet)m_idp[id_p]; + break; + } + } + + if (!idp_found) + { + nodes_i = policyNodes[i].GetEnumerator(); + while (nodes_i.MoveNext()) + { + PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current; + if (ANY_POLICY.Equals(node.ValidPolicy)) + { + ISet pq = null; + Asn1Sequence policies = null; + try + { + policies = DerSequence.GetInstance(GetExtensionValue(cert, X509Extensions.CertificatePolicies)); + } + catch (Exception e) + { + throw new Exception("Certificate policies cannot be decoded.", e); + } + + IEnumerator enm = policies.GetEnumerator(); + while (enm.MoveNext()) + { + PolicyInformation pinfo = null; + + try + { + pinfo = PolicyInformation.GetInstance(enm.Current); + } + catch (Exception ex) + { + throw new Exception("Policy information cannot be decoded.", ex); + } + + if (ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id)) + { + try + { + pq = GetQualifierSet(pinfo.PolicyQualifiers); + } + catch (PkixCertPathValidatorException ex) + { + throw new PkixCertPathValidatorException( + "Policy qualifier info set could not be built.", ex); + } + break; + } + } + bool ci = false; + ISet critExtOids = cert.GetCriticalExtensionOids(); + if (critExtOids != null) + { + ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id); + } + + PkixPolicyNode p_node = (PkixPolicyNode)node.Parent; + if (ANY_POLICY.Equals(p_node.ValidPolicy)) + { + PkixPolicyNode c_node = new PkixPolicyNode( + Platform.CreateArrayList(), i, + (ISet)m_idp[id_p], + p_node, pq, id_p, ci); + p_node.AddChild(c_node); + policyNodes[i].Add(c_node); + } + break; + } + } + } + } + + internal static PkixPolicyNode PrepareNextCertB2( + int i, + IList[] policyNodes, + string id_p, + PkixPolicyNode validPolicyTree) + { + int pos = 0; + + // Copy to avoid RemoveAt calls interfering with enumeration + foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i])) + { + if (node.ValidPolicy.Equals(id_p)) + { + PkixPolicyNode p_node = (PkixPolicyNode)node.Parent; + p_node.RemoveChild(node); + + // Removal of element at current iterator position not supported in C# + //nodes_i.remove(); + policyNodes[i].RemoveAt(pos); + + for (int k = (i - 1); k >= 0; k--) + { + IList nodes = policyNodes[k]; + for (int l = 0; l < nodes.Count; l++) + { + PkixPolicyNode node2 = (PkixPolicyNode)nodes[l]; + if (!node2.HasChildren) + { + validPolicyTree = RemovePolicyNode(validPolicyTree, policyNodes, node2); + if (validPolicyTree == null) + break; + } + } + } + } + else + { + ++pos; + } + } + return validPolicyTree; + } + + internal static void GetCertStatus( + DateTime validDate, + X509Crl crl, + Object cert, + CertStatus certStatus) + { + X509Crl bcCRL = null; + + try + { + bcCRL = new X509Crl(CertificateList.GetInstance((Asn1Sequence)Asn1Sequence.FromByteArray(crl.GetEncoded()))); + } + catch (Exception exception) + { + throw new Exception("Bouncy Castle X509Crl could not be created.", exception); + } + + X509CrlEntry crl_entry = (X509CrlEntry)bcCRL.GetRevokedCertificate(GetSerialNumber(cert)); + + if (crl_entry == null) + return; + + X509Name issuer = GetIssuerPrincipal(cert); + + if (issuer.Equivalent(crl_entry.GetCertificateIssuer(), true) + || issuer.Equivalent(crl.IssuerDN, true)) + { + DerEnumerated reasonCode = null; + if (crl_entry.HasExtensions) + { + try + { + reasonCode = DerEnumerated.GetInstance( + GetExtensionValue(crl_entry, X509Extensions.ReasonCode)); + } + catch (Exception e) + { + new Exception( + "Reason code CRL entry extension could not be decoded.", + e); + } + } + + // for reason keyCompromise, caCompromise, aACompromise or + // unspecified + if (!(validDate.Ticks < crl_entry.RevocationDate.Ticks) + || reasonCode == null + || reasonCode.Value.TestBit(0) + || reasonCode.Value.TestBit(1) + || reasonCode.Value.TestBit(2) + || reasonCode.Value.TestBit(8)) + { + if (reasonCode != null) // (i) or (j) (1) + { + certStatus.Status = reasonCode.Value.SignValue; + } + else // (i) or (j) (2) + { + certStatus.Status = CrlReason.Unspecified; + } + certStatus.RevocationDate = new DateTimeObject(crl_entry.RevocationDate); + } + } + } + + /** + * Return the next working key inheriting DSA parameters if necessary. + *

    + * This methods inherits DSA parameters from the indexed certificate or + * previous certificates in the certificate chain to the returned + * PublicKey. The list is searched upwards, meaning the end + * certificate is at position 0 and previous certificates are following. + *

    + *

    + * If the indexed certificate does not contain a DSA key this method simply + * returns the public key. If the DSA key already contains DSA parameters + * the key is also only returned. + *

    + * + * @param certs The certification path. + * @param index The index of the certificate which contains the public key + * which should be extended with DSA parameters. + * @return The public key of the certificate in list position + * index extended with DSA parameters if applicable. + * @throws Exception if DSA parameters cannot be inherited. + */ + internal static AsymmetricKeyParameter GetNextWorkingKey( + IList certs, + int index) + { + //Only X509Certificate + X509Certificate cert = (X509Certificate)certs[index]; + + AsymmetricKeyParameter pubKey = cert.GetPublicKey(); + + if (!(pubKey is DsaPublicKeyParameters)) + return pubKey; + + DsaPublicKeyParameters dsaPubKey = (DsaPublicKeyParameters)pubKey; + + if (dsaPubKey.Parameters != null) + return dsaPubKey; + + for (int i = index + 1; i < certs.Count; i++) + { + X509Certificate parentCert = (X509Certificate)certs[i]; + pubKey = parentCert.GetPublicKey(); + + if (!(pubKey is DsaPublicKeyParameters)) + { + throw new PkixCertPathValidatorException( + "DSA parameters cannot be inherited from previous certificate."); + } + + DsaPublicKeyParameters prevDSAPubKey = (DsaPublicKeyParameters)pubKey; + + if (prevDSAPubKey.Parameters == null) + continue; + + DsaParameters dsaParams = prevDSAPubKey.Parameters; + + try + { + return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams); + } + catch (Exception exception) + { + throw new Exception(exception.Message); + } + } + + throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate."); + } + + internal static DateTime GetValidCertDateFromValidityModel( + PkixParameters paramsPkix, + PkixCertPath certPath, + int index) + { + if (paramsPkix.ValidityModel != PkixParameters.ChainValidityModel) + { + return GetValidDate(paramsPkix); + } + + // if end cert use given signing/encryption/... time + if (index <= 0) + { + return PkixCertPathValidatorUtilities.GetValidDate(paramsPkix); + // else use time when previous cert was created + } + + if (index - 1 == 0) + { + DerGeneralizedTime dateOfCertgen = null; + try + { + X509Certificate cert = (X509Certificate)certPath.Certificates[index - 1]; + Asn1OctetString extVal = cert.GetExtensionValue( + IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen); + dateOfCertgen = DerGeneralizedTime.GetInstance(extVal); + } + catch (ArgumentException) + { + throw new Exception( + "Date of cert gen extension could not be read."); + } + if (dateOfCertgen != null) + { + try + { + return dateOfCertgen.ToDateTime(); + } + catch (ArgumentException e) + { + throw new Exception( + "Date from date of cert gen extension could not be parsed.", + e); + } + } + } + + return ((X509Certificate)certPath.Certificates[index - 1]).NotBefore; + } + + /// + /// Return a Collection of all certificates or attribute certificates found + /// in the X509Store's that are matching the certSelect criteriums. + /// + /// a {@link Selector} object that will be used to select + /// the certificates + /// a List containing only X509Store objects. These + /// are used to search for certificates. + /// a Collection of all found or + /// org.bouncycastle.x509.X509AttributeCertificate objects. + /// May be empty but never null. + /// + internal static ICollection FindCertificates( + X509CertStoreSelector certSelect, + IList certStores) + { + ISet certs = new HashSet(); + + foreach (IX509Store certStore in certStores) + { + try + { +// certs.AddAll(certStore.GetMatches(certSelect)); + foreach (X509Certificate c in certStore.GetMatches(certSelect)) + { + certs.Add(c); + } + } + catch (Exception e) + { + throw new Exception("Problem while picking certificates from X.509 store.", e); + } + } + + return certs; + } + + /** + * Add the CRL issuers from the cRLIssuer field of the distribution point or + * from the certificate if not given to the issuer criterion of the + * selector. + *

    + * The issuerPrincipals are a collection with a single + * X500Principal for X509Certificates. For + * {@link X509AttributeCertificate}s the issuer may contain more than one + * X500Principal. + *

    + * + * @param dp The distribution point. + * @param issuerPrincipals The issuers of the certificate or attribute + * certificate which contains the distribution point. + * @param selector The CRL selector. + * @param pkixParams The PKIX parameters containing the cert stores. + * @throws Exception if an exception occurs while processing. + * @throws ClassCastException if issuerPrincipals does not + * contain only X500Principals. + */ + internal static void GetCrlIssuersFromDistributionPoint( + DistributionPoint dp, + ICollection issuerPrincipals, + X509CrlStoreSelector selector, + PkixParameters pkixParams) + { + IList issuers = Platform.CreateArrayList(); + // indirect CRL + if (dp.CrlIssuer != null) + { + GeneralName[] genNames = dp.CrlIssuer.GetNames(); + // look for a DN + for (int j = 0; j < genNames.Length; j++) + { + if (genNames[j].TagNo == GeneralName.DirectoryName) + { + try + { + issuers.Add(X509Name.GetInstance(genNames[j].Name.ToAsn1Object())); + } + catch (IOException e) + { + throw new Exception( + "CRL issuer information from distribution point cannot be decoded.", + e); + } + } + } + } + else + { + /* + * certificate issuer is CRL issuer, distributionPoint field MUST be + * present. + */ + if (dp.DistributionPointName == null) + { + throw new Exception( + "CRL issuer is omitted from distribution point but no distributionPoint field present."); + } + + // add and check issuer principals + for (IEnumerator it = issuerPrincipals.GetEnumerator(); it.MoveNext(); ) + { + issuers.Add((X509Name)it.Current); + } + } + // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid + // distributionPoint + // if (dp.getDistributionPoint() != null) + // { + // // look for nameRelativeToCRLIssuer + // if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER) + // { + // // append fragment to issuer, only one + // // issuer can be there, if this is given + // if (issuers.size() != 1) + // { + // throw new AnnotatedException( + // "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given."); + // } + // DEREncodable relName = dp.getDistributionPoint().getName(); + // Iterator it = issuers.iterator(); + // List issuersTemp = new ArrayList(issuers.size()); + // while (it.hasNext()) + // { + // Enumeration e = null; + // try + // { + // e = ASN1Sequence.getInstance( + // new ASN1InputStream(((X500Principal) it.next()) + // .getEncoded()).readObject()).getObjects(); + // } + // catch (IOException ex) + // { + // throw new AnnotatedException( + // "Cannot decode CRL issuer information.", ex); + // } + // ASN1EncodableVector v = new ASN1EncodableVector(); + // while (e.hasMoreElements()) + // { + // v.add((DEREncodable) e.nextElement()); + // } + // v.add(relName); + // issuersTemp.add(new X500Principal(new DERSequence(v) + // .getDEREncoded())); + // } + // issuers.clear(); + // issuers.addAll(issuersTemp); + // } + // } + + selector.Issuers = issuers; + } + + /** + * Fetches complete CRLs according to RFC 3280. + * + * @param dp The distribution point for which the complete CRL + * @param cert The X509Certificate or + * {@link org.bouncycastle.x509.X509AttributeCertificate} for + * which the CRL should be searched. + * @param currentDate The date for which the delta CRLs must be valid. + * @param paramsPKIX The extended PKIX parameters. + * @return A Set of X509CRLs with complete + * CRLs. + * @throws Exception if an exception occurs while picking the CRLs + * or no CRLs are found. + */ + internal static ISet GetCompleteCrls( + DistributionPoint dp, + object cert, + DateTime currentDate, + PkixParameters paramsPKIX) + { + X509CrlStoreSelector crlselect = new X509CrlStoreSelector(); + try + { + ISet issuers = new HashSet(); + if (cert is X509V2AttributeCertificate) + { + issuers.Add(((X509V2AttributeCertificate)cert) + .Issuer.GetPrincipals()[0]); + } + else + { + issuers.Add(GetIssuerPrincipal(cert)); + } + PkixCertPathValidatorUtilities.GetCrlIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX); + } + catch (Exception e) + { + new Exception("Could not get issuer information from distribution point.", e); + } + + if (cert is X509Certificate) + { + crlselect.CertificateChecking = (X509Certificate)cert; + } + else if (cert is X509V2AttributeCertificate) + { + crlselect.AttrCertChecking = (IX509AttributeCertificate)cert; + } + + crlselect.CompleteCrlEnabled = true; + ISet crls = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate); + + if (crls.IsEmpty) + { + if (cert is IX509AttributeCertificate) + { + IX509AttributeCertificate aCert = (IX509AttributeCertificate)cert; + + throw new Exception("No CRLs found for issuer \"" + aCert.Issuer.GetPrincipals()[0] + "\""); + } + else + { + X509Certificate xCert = (X509Certificate)cert; + + throw new Exception("No CRLs found for issuer \"" + xCert.IssuerDN + "\""); + } + } + + return crls; + } + + /** + * Fetches delta CRLs according to RFC 3280 section 5.2.4. + * + * @param currentDate The date for which the delta CRLs must be valid. + * @param paramsPKIX The extended PKIX parameters. + * @param completeCRL The complete CRL the delta CRL is for. + * @return A Set of X509CRLs with delta CRLs. + * @throws Exception if an exception occurs while picking the delta + * CRLs. + */ + internal static ISet GetDeltaCrls( + DateTime currentDate, + PkixParameters paramsPKIX, + X509Crl completeCRL) + { + X509CrlStoreSelector deltaSelect = new X509CrlStoreSelector(); + + // 5.2.4 (a) + try + { + IList deltaSelectIssuer = Platform.CreateArrayList(); + deltaSelectIssuer.Add(completeCRL.IssuerDN); + deltaSelect.Issuers = deltaSelectIssuer; + } + catch (IOException e) + { + new Exception("Cannot extract issuer from CRL.", e); + } + + BigInteger completeCRLNumber = null; + try + { + Asn1Object asn1Object = GetExtensionValue(completeCRL, X509Extensions.CrlNumber); + if (asn1Object != null) + { + completeCRLNumber = CrlNumber.GetInstance(asn1Object).PositiveValue; + } + } + catch (Exception e) + { + throw new Exception( + "CRL number extension could not be extracted from CRL.", e); + } + + // 5.2.4 (b) + byte[] idp = null; + + try + { + Asn1Object obj = GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint); + if (obj != null) + { + idp = obj.GetDerEncoded(); + } + } + catch (Exception e) + { + throw new Exception( + "Issuing distribution point extension value could not be read.", + e); + } + + // 5.2.4 (d) + + deltaSelect.MinCrlNumber = (completeCRLNumber == null) + ? null + : completeCRLNumber.Add(BigInteger.One); + + deltaSelect.IssuingDistributionPoint = idp; + deltaSelect.IssuingDistributionPointEnabled = true; + + // 5.2.4 (c) + deltaSelect.MaxBaseCrlNumber = completeCRLNumber; + + // find delta CRLs + ISet temp = CrlUtilities.FindCrls(deltaSelect, paramsPKIX, currentDate); + + ISet result = new HashSet(); + + foreach (X509Crl crl in temp) + { + if (isDeltaCrl(crl)) + { + result.Add(crl); + } + } + + return result; + } + + private static bool isDeltaCrl( + X509Crl crl) + { + ISet critical = crl.GetCriticalExtensionOids(); + + return critical.Contains(X509Extensions.DeltaCrlIndicator.Id); + } + + internal static ICollection FindCertificates( + X509AttrCertStoreSelector certSelect, + IList certStores) + { + ISet certs = new HashSet(); + + foreach (IX509Store certStore in certStores) + { + try + { +// certs.AddAll(certStore.GetMatches(certSelect)); + foreach (X509V2AttributeCertificate ac in certStore.GetMatches(certSelect)) + { + certs.Add(ac); + } + } + catch (Exception e) + { + throw new Exception( + "Problem while picking certificates from X.509 store.", e); + } + } + + return certs; + } + + internal static void AddAdditionalStoresFromCrlDistributionPoint( + CrlDistPoint crldp, + PkixParameters pkixParams) + { + if (crldp != null) + { + DistributionPoint[] dps = null; + try + { + dps = crldp.GetDistributionPoints(); + } + catch (Exception e) + { + throw new Exception( + "Distribution points could not be read.", e); + } + for (int i = 0; i < dps.Length; i++) + { + DistributionPointName dpn = dps[i].DistributionPointName; + // look for URIs in fullName + if (dpn != null) + { + if (dpn.PointType == DistributionPointName.FullName) + { + GeneralName[] genNames = GeneralNames.GetInstance( + dpn.Name).GetNames(); + // look for an URI + for (int j = 0; j < genNames.Length; j++) + { + if (genNames[j].TagNo == GeneralName.UniformResourceIdentifier) + { + string location = DerIA5String.GetInstance( + genNames[j].Name).GetString(); + PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation( + location, pkixParams); + } + } + } + } + } + } + } + + internal static bool ProcessCertD1i( + int index, + IList[] policyNodes, + DerObjectIdentifier pOid, + ISet pq) + { + IList policyNodeVec = policyNodes[index - 1]; + + for (int j = 0; j < policyNodeVec.Count; j++) + { + PkixPolicyNode node = (PkixPolicyNode)policyNodeVec[j]; + ISet expectedPolicies = node.ExpectedPolicies; + + if (expectedPolicies.Contains(pOid.Id)) + { + ISet childExpectedPolicies = new HashSet(); + childExpectedPolicies.Add(pOid.Id); + + PkixPolicyNode child = new PkixPolicyNode(Platform.CreateArrayList(), + index, + childExpectedPolicies, + node, + pq, + pOid.Id, + false); + node.AddChild(child); + policyNodes[index].Add(child); + + return true; + } + } + + return false; + } + + internal static void ProcessCertD1ii( + int index, + IList[] policyNodes, + DerObjectIdentifier _poid, + ISet _pq) + { + IList policyNodeVec = policyNodes[index - 1]; + + for (int j = 0; j < policyNodeVec.Count; j++) + { + PkixPolicyNode _node = (PkixPolicyNode)policyNodeVec[j]; + + if (ANY_POLICY.Equals(_node.ValidPolicy)) + { + ISet _childExpectedPolicies = new HashSet(); + _childExpectedPolicies.Add(_poid.Id); + + PkixPolicyNode _child = new PkixPolicyNode(Platform.CreateArrayList(), + index, + _childExpectedPolicies, + _node, + _pq, + _poid.Id, + false); + _node.AddChild(_child); + policyNodes[index].Add(_child); + return; + } + } + } + + /** + * Find the issuer certificates of a given certificate. + * + * @param cert + * The certificate for which an issuer should be found. + * @param pkixParams + * @return A Collection object containing the issuer + * X509Certificates. Never null. + * + * @exception Exception + * if an error occurs. + */ + internal static ICollection FindIssuerCerts( + X509Certificate cert, + PkixBuilderParameters pkixParams) + { + X509CertStoreSelector certSelect = new X509CertStoreSelector(); + ISet certs = new HashSet(); + try + { + certSelect.Subject = cert.IssuerDN; + } + catch (IOException ex) + { + throw new Exception( + "Subject criteria for certificate selector to find issuer certificate could not be set.", ex); + } + + try + { + certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetStores())); + certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetAdditionalStores())); + } + catch (Exception e) + { + throw new Exception("Issuer certificate cannot be searched.", e); + } + + return certs; + } + + /// + /// Extract the value of the given extension, if it exists. + /// + /// The extension object. + /// The object identifier to obtain. + /// Asn1Object + /// if the extension cannot be read. + internal static Asn1Object GetExtensionValue( + IX509Extension ext, + DerObjectIdentifier oid) + { + Asn1OctetString bytes = ext.GetExtensionValue(oid); + + if (bytes == null) + return null; + + return X509ExtensionUtilities.FromExtensionValue(bytes); + } + } +} diff --git a/crypto/src/pkix/PkixCrlUtilities.cs b/crypto/src/pkix/PkixCrlUtilities.cs new file mode 100644 index 000000000..c386b8a05 --- /dev/null +++ b/crypto/src/pkix/PkixCrlUtilities.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + public class PkixCrlUtilities + { + public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix, DateTime currentDate) + { + ISet initialSet = new HashSet(); + + // get complete CRL(s) + try + { + initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetAdditionalStores())); + initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores())); + } + catch (Exception e) + { + throw new Exception("Exception obtaining complete CRLs.", e); + } + + ISet finalSet = new HashSet(); + DateTime validityDate = currentDate; + + if (paramsPkix.Date != null) + { + validityDate = paramsPkix.Date.Value; + } + + // based on RFC 5280 6.3.3 + foreach (X509Crl crl in initialSet) + { + if (crl.NextUpdate.Value.CompareTo(validityDate) > 0) + { + X509Certificate cert = crlselect.CertificateChecking; + + if (cert != null) + { + if (crl.ThisUpdate.CompareTo(cert.NotAfter) < 0) + { + finalSet.Add(crl); + } + } + else + { + finalSet.Add(crl); + } + } + } + + return finalSet; + } + + public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix) + { + ISet completeSet = new HashSet(); + + // get complete CRL(s) + try + { + completeSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores())); + } + catch (Exception e) + { + throw new Exception("Exception obtaining complete CRLs.", e); + } + + return completeSet; + } + + /// + /// crl checking + /// Return a Collection of all CRLs found in the X509Store's that are + /// matching the crlSelect criteriums. + /// + /// a {@link X509CRLStoreSelector} object that will be used + /// to select the CRLs + /// a List containing only {@link org.bouncycastle.x509.X509Store + /// X509Store} objects. These are used to search for CRLs + /// a Collection of all found {@link X509CRL X509CRL} objects. May be + /// empty but never null. + /// + private ICollection FindCrls(X509CrlStoreSelector crlSelect, IList crlStores) + { + ISet crls = new HashSet(); + + Exception lastException = null; + bool foundValidStore = false; + + foreach (IX509Store store in crlStores) + { + try + { + crls.AddAll(store.GetMatches(crlSelect)); + foundValidStore = true; + } + catch (X509StoreException e) + { + lastException = new Exception("Exception searching in X.509 CRL store.", e); + } + } + + if (!foundValidStore && lastException != null) + throw lastException; + + return crls; + } + } +} diff --git a/crypto/src/pkix/PkixNameConstraintValidator.cs b/crypto/src/pkix/PkixNameConstraintValidator.cs new file mode 100644 index 000000000..535f95174 --- /dev/null +++ b/crypto/src/pkix/PkixNameConstraintValidator.cs @@ -0,0 +1,1937 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Pkix +{ + public class PkixNameConstraintValidator + { + private ISet excludedSubtreesDN = new HashSet(); + + private ISet excludedSubtreesDNS = new HashSet(); + + private ISet excludedSubtreesEmail = new HashSet(); + + private ISet excludedSubtreesURI = new HashSet(); + + private ISet excludedSubtreesIP = new HashSet(); + + private ISet permittedSubtreesDN; + + private ISet permittedSubtreesDNS; + + private ISet permittedSubtreesEmail; + + private ISet permittedSubtreesURI; + + private ISet permittedSubtreesIP; + + public PkixNameConstraintValidator() + { + } + + private static bool WithinDNSubtree( + Asn1Sequence dns, + Asn1Sequence subtree) + { + if (subtree.Count < 1) + { + return false; + } + + if (subtree.Count > dns.Count) + { + return false; + } + + for (int j = subtree.Count - 1; j >= 0; j--) + { + if (!(subtree[j].Equals(dns[j]))) + { + return false; + } + } + + return true; + } + + public void CheckPermittedDN(Asn1Sequence dns) + //throws PkixNameConstraintValidatorException + { + CheckPermittedDN(permittedSubtreesDN, dns); + } + + public void CheckExcludedDN(Asn1Sequence dns) + //throws PkixNameConstraintValidatorException + { + CheckExcludedDN(excludedSubtreesDN, dns); + } + + private void CheckPermittedDN(ISet permitted, Asn1Sequence dns) + //throws PkixNameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + if ((permitted.Count == 0) && dns.Count == 0) + { + return; + } + + IEnumerator it = permitted.GetEnumerator(); + + while (it.MoveNext()) + { + Asn1Sequence subtree = (Asn1Sequence)it.Current; + + if (WithinDNSubtree(dns, subtree)) + { + return; + } + } + + throw new PkixNameConstraintValidatorException( + "Subject distinguished name is not from a permitted subtree"); + } + + private void CheckExcludedDN(ISet excluded, Asn1Sequence dns) + //throws PkixNameConstraintValidatorException + { + if (excluded.IsEmpty) + { + return; + } + + IEnumerator it = excluded.GetEnumerator(); + + while (it.MoveNext()) + { + Asn1Sequence subtree = (Asn1Sequence)it.Current; + + if (WithinDNSubtree(dns, subtree)) + { + throw new PkixNameConstraintValidatorException( + "Subject distinguished name is from an excluded subtree"); + } + } + } + + private ISet IntersectDN(ISet permitted, ISet dns) + { + ISet intersect = new HashSet(); + for (IEnumerator it = dns.GetEnumerator(); it.MoveNext(); ) + { + Asn1Sequence dn = Asn1Sequence.GetInstance(((GeneralSubtree)it + .Current).Base.Name.ToAsn1Object()); + if (permitted == null) + { + if (dn != null) + { + intersect.Add(dn); + } + } + else + { + IEnumerator _iter = permitted.GetEnumerator(); + while (_iter.MoveNext()) + { + Asn1Sequence subtree = (Asn1Sequence)_iter.Current; + + if (WithinDNSubtree(dn, subtree)) + { + intersect.Add(dn); + } + else if (WithinDNSubtree(subtree, dn)) + { + intersect.Add(subtree); + } + } + } + } + return intersect; + } + + private ISet UnionDN(ISet excluded, Asn1Sequence dn) + { + if (excluded.IsEmpty) + { + if (dn == null) + { + return excluded; + } + excluded.Add(dn); + + return excluded; + } + else + { + ISet intersect = new HashSet(); + + IEnumerator it = excluded.GetEnumerator(); + while (it.MoveNext()) + { + Asn1Sequence subtree = (Asn1Sequence)it.Current; + + if (WithinDNSubtree(dn, subtree)) + { + intersect.Add(subtree); + } + else if (WithinDNSubtree(subtree, dn)) + { + intersect.Add(dn); + } + else + { + intersect.Add(subtree); + intersect.Add(dn); + } + } + + return intersect; + } + } + + private ISet IntersectEmail(ISet permitted, ISet emails) + { + ISet intersect = new HashSet(); + for (IEnumerator it = emails.GetEnumerator(); it.MoveNext(); ) + { + String email = ExtractNameAsString(((GeneralSubtree)it.Current) + .Base); + + if (permitted == null) + { + if (email != null) + { + intersect.Add(email); + } + } + else + { + IEnumerator it2 = permitted.GetEnumerator(); + while (it2.MoveNext()) + { + String _permitted = (String)it2.Current; + + intersectEmail(email, _permitted, intersect); + } + } + } + return intersect; + } + + private ISet UnionEmail(ISet excluded, String email) + { + if (excluded.IsEmpty) + { + if (email == null) + { + return excluded; + } + excluded.Add(email); + return excluded; + } + else + { + ISet union = new HashSet(); + + IEnumerator it = excluded.GetEnumerator(); + while (it.MoveNext()) + { + String _excluded = (String)it.Current; + + unionEmail(_excluded, email, union); + } + + return union; + } + } + + /** + * Returns the intersection of the permitted IP ranges in + * permitted with ip. + * + * @param permitted A Set of permitted IP addresses with + * their subnet mask as byte arrays. + * @param ips The IP address with its subnet mask. + * @return The Set of permitted IP ranges intersected with + * ip. + */ + private ISet IntersectIP(ISet permitted, ISet ips) + { + ISet intersect = new HashSet(); + for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); ) + { + byte[] ip = Asn1OctetString.GetInstance( + ((GeneralSubtree)it.Current).Base.Name).GetOctets(); + if (permitted == null) + { + if (ip != null) + { + intersect.Add(ip); + } + } + else + { + IEnumerator it2 = permitted.GetEnumerator(); + while (it2.MoveNext()) + { + byte[] _permitted = (byte[])it2.Current; + intersect.AddAll(IntersectIPRange(_permitted, ip)); + } + } + } + return intersect; + } + + /** + * Returns the union of the excluded IP ranges in excluded + * with ip. + * + * @param excluded A Set of excluded IP addresses with their + * subnet mask as byte arrays. + * @param ip The IP address with its subnet mask. + * @return The Set of excluded IP ranges unified with + * ip as byte arrays. + */ + private ISet UnionIP(ISet excluded, byte[] ip) + { + if (excluded.IsEmpty) + { + if (ip == null) + { + return excluded; + } + excluded.Add(ip); + + return excluded; + } + else + { + ISet union = new HashSet(); + + IEnumerator it = excluded.GetEnumerator(); + while (it.MoveNext()) + { + byte[] _excluded = (byte[])it.Current; + union.AddAll(UnionIPRange(_excluded, ip)); + } + + return union; + } + } + + /** + * Calculates the union if two IP ranges. + * + * @param ipWithSubmask1 The first IP address with its subnet mask. + * @param ipWithSubmask2 The second IP address with its subnet mask. + * @return A Set with the union of both addresses. + */ + private ISet UnionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2) + { + ISet set = new HashSet(); + + // difficult, adding always all IPs is not wrong + if (Org.BouncyCastle.Utilities.Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2)) + { + set.Add(ipWithSubmask1); + } + else + { + set.Add(ipWithSubmask1); + set.Add(ipWithSubmask2); + } + return set; + } + + /** + * Calculates the interesction if two IP ranges. + * + * @param ipWithSubmask1 The first IP address with its subnet mask. + * @param ipWithSubmask2 The second IP address with its subnet mask. + * @return A Set with the single IP address with its subnet + * mask as a byte array or an empty Set. + */ + private ISet IntersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2) + { + if (ipWithSubmask1.Length != ipWithSubmask2.Length) + { + //Collections.EMPTY_SET; + return new HashSet(); + } + + byte[][] temp = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2); + byte[] ip1 = temp[0]; + byte[] subnetmask1 = temp[1]; + byte[] ip2 = temp[2]; + byte[] subnetmask2 = temp[3]; + + byte[][] minMax = MinMaxIPs(ip1, subnetmask1, ip2, subnetmask2); + byte[] min; + byte[] max; + max = Min(minMax[1], minMax[3]); + min = Max(minMax[0], minMax[2]); + + // minimum IP address must be bigger than max + if (CompareTo(min, max) == 1) + { + //return Collections.EMPTY_SET; + return new HashSet(); + } + // OR keeps all significant bits + byte[] ip = Or(minMax[0], minMax[2]); + byte[] subnetmask = Or(subnetmask1, subnetmask2); + + //return new HashSet( ICollectionsingleton(IpWithSubnetMask(ip, subnetmask)); + ISet hs = new HashSet(); + hs.Add(IpWithSubnetMask(ip, subnetmask)); + + return hs; + } + + /** + * Concatenates the IP address with its subnet mask. + * + * @param ip The IP address. + * @param subnetMask Its subnet mask. + * @return The concatenated IP address with its subnet mask. + */ + private byte[] IpWithSubnetMask(byte[] ip, byte[] subnetMask) + { + int ipLength = ip.Length; + byte[] temp = new byte[ipLength * 2]; + Array.Copy(ip, 0, temp, 0, ipLength); + Array.Copy(subnetMask, 0, temp, ipLength, ipLength); + return temp; + } + + /** + * Splits the IP addresses and their subnet mask. + * + * @param ipWithSubmask1 The first IP address with the subnet mask. + * @param ipWithSubmask2 The second IP address with the subnet mask. + * @return An array with two elements. Each element contains the IP address + * and the subnet mask in this order. + */ + private byte[][] ExtractIPsAndSubnetMasks( + byte[] ipWithSubmask1, + byte[] ipWithSubmask2) + { + int ipLength = ipWithSubmask1.Length / 2; + byte[] ip1 = new byte[ipLength]; + byte[] subnetmask1 = new byte[ipLength]; + Array.Copy(ipWithSubmask1, 0, ip1, 0, ipLength); + Array.Copy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength); + + byte[] ip2 = new byte[ipLength]; + byte[] subnetmask2 = new byte[ipLength]; + Array.Copy(ipWithSubmask2, 0, ip2, 0, ipLength); + Array.Copy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength); + return new byte[][] + {ip1, subnetmask1, ip2, subnetmask2}; + } + + /** + * Based on the two IP addresses and their subnet masks the IP range is + * computed for each IP address - subnet mask pair and returned as the + * minimum IP address and the maximum address of the range. + * + * @param ip1 The first IP address. + * @param subnetmask1 The subnet mask of the first IP address. + * @param ip2 The second IP address. + * @param subnetmask2 The subnet mask of the second IP address. + * @return A array with two elements. The first/second element contains the + * min and max IP address of the first/second IP address and its + * subnet mask. + */ + private byte[][] MinMaxIPs( + byte[] ip1, + byte[] subnetmask1, + byte[] ip2, + byte[] subnetmask2) + { + int ipLength = ip1.Length; + byte[] min1 = new byte[ipLength]; + byte[] max1 = new byte[ipLength]; + + byte[] min2 = new byte[ipLength]; + byte[] max2 = new byte[ipLength]; + + for (int i = 0; i < ipLength; i++) + { + min1[i] = (byte)(ip1[i] & subnetmask1[i]); + max1[i] = (byte)(ip1[i] & subnetmask1[i] | ~subnetmask1[i]); + + min2[i] = (byte)(ip2[i] & subnetmask2[i]); + max2[i] = (byte)(ip2[i] & subnetmask2[i] | ~subnetmask2[i]); + } + + return new byte[][] { min1, max1, min2, max2 }; + } + + private void CheckPermittedEmail(ISet permitted, String email) + //throws PkixNameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + IEnumerator it = permitted.GetEnumerator(); + + while (it.MoveNext()) + { + String str = ((String)it.Current); + + if (EmailIsConstrained(email, str)) + { + return; + } + } + + if (email.Length == 0 && permitted.Count == 0) + { + return; + } + + throw new PkixNameConstraintValidatorException( + "Subject email address is not from a permitted subtree."); + } + + private void CheckExcludedEmail(ISet excluded, String email) + //throws PkixNameConstraintValidatorException + { + if (excluded.IsEmpty) + { + return; + } + + IEnumerator it = excluded.GetEnumerator(); + + while (it.MoveNext()) + { + String str = (String)it.Current; + + if (EmailIsConstrained(email, str)) + { + throw new PkixNameConstraintValidatorException( + "Email address is from an excluded subtree."); + } + } + } + + /** + * Checks if the IP ip is included in the permitted ISet + * permitted. + * + * @param permitted A Set of permitted IP addresses with + * their subnet mask as byte arrays. + * @param ip The IP address. + * @throws PkixNameConstraintValidatorException + * if the IP is not permitted. + */ + private void CheckPermittedIP(ISet permitted, byte[] ip) + //throws PkixNameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + IEnumerator it = permitted.GetEnumerator(); + + while (it.MoveNext()) + { + byte[] ipWithSubnet = (byte[])it.Current; + + if (IsIPConstrained(ip, ipWithSubnet)) + { + return; + } + } + if (ip.Length == 0 && permitted.Count == 0) + { + return; + } + throw new PkixNameConstraintValidatorException( + "IP is not from a permitted subtree."); + } + + /** + * Checks if the IP ip is included in the excluded ISet + * excluded. + * + * @param excluded A Set of excluded IP addresses with their + * subnet mask as byte arrays. + * @param ip The IP address. + * @throws PkixNameConstraintValidatorException + * if the IP is excluded. + */ + private void checkExcludedIP(ISet excluded, byte[] ip) + //throws PkixNameConstraintValidatorException + { + if (excluded.IsEmpty) + { + return; + } + + IEnumerator it = excluded.GetEnumerator(); + + while (it.MoveNext()) + { + byte[] ipWithSubnet = (byte[])it.Current; + + if (IsIPConstrained(ip, ipWithSubnet)) + { + throw new PkixNameConstraintValidatorException( + "IP is from an excluded subtree."); + } + } + } + + /** + * Checks if the IP address ip is constrained by + * constraint. + * + * @param ip The IP address. + * @param constraint The constraint. This is an IP address concatenated with + * its subnetmask. + * @return true if constrained, false + * otherwise. + */ + private bool IsIPConstrained(byte[] ip, byte[] constraint) + { + int ipLength = ip.Length; + + if (ipLength != (constraint.Length / 2)) + { + return false; + } + + byte[] subnetMask = new byte[ipLength]; + Array.Copy(constraint, ipLength, subnetMask, 0, ipLength); + + byte[] permittedSubnetAddress = new byte[ipLength]; + + byte[] ipSubnetAddress = new byte[ipLength]; + + // the resulting IP address by applying the subnet mask + for (int i = 0; i < ipLength; i++) + { + permittedSubnetAddress[i] = (byte)(constraint[i] & subnetMask[i]); + ipSubnetAddress[i] = (byte)(ip[i] & subnetMask[i]); + } + + return Org.BouncyCastle.Utilities.Arrays.AreEqual(permittedSubnetAddress, ipSubnetAddress); + } + + private bool EmailIsConstrained(String email, String constraint) + { + String sub = email.Substring(email.IndexOf('@') + 1); + // a particular mailbox + if (constraint.IndexOf('@') != -1) + { + if (email.ToUpper().Equals(constraint.ToUpper())) + { + return true; + } + } + // on particular host + else if (!(constraint[0].Equals('.'))) + { + if (sub.ToUpper().Equals(constraint.ToUpper())) + { + return true; + } + } + // address in sub domain + else if (WithinDomain(sub, constraint)) + { + return true; + } + return false; + } + + private bool WithinDomain(String testDomain, String domain) + { + String tempDomain = domain; + if (tempDomain.StartsWith(".")) + { + tempDomain = tempDomain.Substring(1); + } + String[] domainParts = tempDomain.Split('.'); // Strings.split(tempDomain, '.'); + String[] testDomainParts = testDomain.Split('.'); // Strings.split(testDomain, '.'); + + // must have at least one subdomain + if (testDomainParts.Length <= domainParts.Length) + { + return false; + } + + int d = testDomainParts.Length - domainParts.Length; + for (int i = -1; i < domainParts.Length; i++) + { + if (i == -1) + { + if (testDomainParts[i + d].Equals("")) + { + return false; + } + } + else if (!(Platform.CompareIgnoreCase(testDomainParts[i + d], domainParts[i]) == 0)) + { + return false; + } + } + return true; + } + + private void CheckPermittedDNS(ISet permitted, String dns) + //throws PkixNameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + IEnumerator it = permitted.GetEnumerator(); + + while (it.MoveNext()) + { + String str = ((String)it.Current); + + // is sub domain + if (WithinDomain(dns, str) || dns.ToUpper().Equals(str.ToUpper())) + { + return; + } + } + if (dns.Length == 0 && permitted.Count == 0) + { + return; + } + throw new PkixNameConstraintValidatorException( + "DNS is not from a permitted subtree."); + } + + private void checkExcludedDNS(ISet excluded, String dns) + // throws PkixNameConstraintValidatorException + { + if (excluded.IsEmpty) + { + return; + } + + IEnumerator it = excluded.GetEnumerator(); + + while (it.MoveNext()) + { + String str = ((String)it.Current); + + // is sub domain or the same + if (WithinDomain(dns, str) || (Platform.CompareIgnoreCase(dns, str) == 0)) + { + throw new PkixNameConstraintValidatorException( + "DNS is from an excluded subtree."); + } + } + } + + /** + * The common part of email1 and email2 is + * added to the union union. If email1 and + * email2 have nothing in common they are added both. + * + * @param email1 Email address constraint 1. + * @param email2 Email address constraint 2. + * @param union The union. + */ + private void unionEmail(String email1, String email2, ISet union) + { + // email1 is a particular address + if (email1.IndexOf('@') != -1) + { + String _sub = email1.Substring(email1.IndexOf('@') + 1); + // both are a particular mailbox + if (email2.IndexOf('@') != -1) + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(_sub, email2)) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(_sub, email2) == 0) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + } + // email1 specifies a domain + else if (email1.StartsWith(".")) + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (WithinDomain(_sub, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2) || Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email2); + } + else if (WithinDomain(email2, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + else + { + if (WithinDomain(email2, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + } + // email specifies a host + else + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (Platform.CompareIgnoreCase(_sub, email1) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2)) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + } + } + + private void unionURI(String email1, String email2, ISet union) + { + // email1 is a particular address + if (email1.IndexOf('@') != -1) + { + String _sub = email1.Substring(email1.IndexOf('@') + 1); + // both are a particular mailbox + if (email2.IndexOf('@') != -1) + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(_sub, email2)) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(_sub, email2) == 0) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + + } + } + } + // email1 specifies a domain + else if (email1.StartsWith(".")) + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (WithinDomain(_sub, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2) || Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email2); + } + else if (WithinDomain(email2, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + else + { + if (WithinDomain(email2, email1)) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + } + // email specifies a host + else + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (Platform.CompareIgnoreCase(_sub, email1) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2)) + { + union.Add(email2); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + union.Add(email1); + } + else + { + union.Add(email1); + union.Add(email2); + } + } + } + } + + private ISet intersectDNS(ISet permitted, ISet dnss) + { + ISet intersect = new HashSet(); + for (IEnumerator it = dnss.GetEnumerator(); it.MoveNext(); ) + { + String dns = ExtractNameAsString(((GeneralSubtree)it.Current) + .Base); + if (permitted == null) + { + if (dns != null) + { + intersect.Add(dns); + } + } + else + { + IEnumerator _iter = permitted.GetEnumerator(); + while (_iter.MoveNext()) + { + String _permitted = (String)_iter.Current; + + if (WithinDomain(_permitted, dns)) + { + intersect.Add(_permitted); + } + else if (WithinDomain(dns, _permitted)) + { + intersect.Add(dns); + } + } + } + } + + return intersect; + } + + protected ISet unionDNS(ISet excluded, String dns) + { + if (excluded.IsEmpty) + { + if (dns == null) + { + return excluded; + } + excluded.Add(dns); + + return excluded; + } + else + { + ISet union = new HashSet(); + + IEnumerator _iter = excluded.GetEnumerator(); + while (_iter.MoveNext()) + { + String _permitted = (String)_iter.Current; + + if (WithinDomain(_permitted, dns)) + { + union.Add(dns); + } + else if (WithinDomain(dns, _permitted)) + { + union.Add(_permitted); + } + else + { + union.Add(_permitted); + union.Add(dns); + } + } + + return union; + } + } + + /** + * The most restricting part from email1 and + * email2 is added to the intersection intersect. + * + * @param email1 Email address constraint 1. + * @param email2 Email address constraint 2. + * @param intersect The intersection. + */ + private void intersectEmail(String email1, String email2, ISet intersect) + { + // email1 is a particular address + if (email1.IndexOf('@') != -1) + { + String _sub = email1.Substring(email1.IndexOf('@') + 1); + // both are a particular mailbox + if (email2.IndexOf('@') != -1) + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + intersect.Add(email1); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(_sub, email2)) + { + intersect.Add(email1); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(_sub, email2) == 0) + { + intersect.Add(email1); + } + } + } + // email specifies a domain + else if (email1.StartsWith(".")) + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (WithinDomain(_sub, email1)) + { + intersect.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2) || (Platform.CompareIgnoreCase(email1, email2) == 0)) + { + intersect.Add(email1); + } + else if (WithinDomain(email2, email1)) + { + intersect.Add(email2); + } + } + else + { + if (WithinDomain(email2, email1)) + { + intersect.Add(email2); + } + } + } + // email1 specifies a host + else + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email2.IndexOf('@') + 1); + if (Platform.CompareIgnoreCase(_sub, email1) == 0) + { + intersect.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2)) + { + intersect.Add(email1); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + intersect.Add(email1); + } + } + } + } + + private void checkExcludedURI(ISet excluded, String uri) + // throws PkixNameConstraintValidatorException + { + if (excluded.IsEmpty) + { + return; + } + + IEnumerator it = excluded.GetEnumerator(); + + while (it.MoveNext()) + { + String str = ((String)it.Current); + + if (IsUriConstrained(uri, str)) + { + throw new PkixNameConstraintValidatorException( + "URI is from an excluded subtree."); + } + } + } + + private ISet intersectURI(ISet permitted, ISet uris) + { + ISet intersect = new HashSet(); + for (IEnumerator it = uris.GetEnumerator(); it.MoveNext(); ) + { + String uri = ExtractNameAsString(((GeneralSubtree)it.Current) + .Base); + if (permitted == null) + { + if (uri != null) + { + intersect.Add(uri); + } + } + else + { + IEnumerator _iter = permitted.GetEnumerator(); + while (_iter.MoveNext()) + { + String _permitted = (String)_iter.Current; + intersectURI(_permitted, uri, intersect); + } + } + } + return intersect; + } + + private ISet unionURI(ISet excluded, String uri) + { + if (excluded.IsEmpty) + { + if (uri == null) + { + return excluded; + } + excluded.Add(uri); + + return excluded; + } + else + { + ISet union = new HashSet(); + + IEnumerator _iter = excluded.GetEnumerator(); + while (_iter.MoveNext()) + { + String _excluded = (String)_iter.Current; + + unionURI(_excluded, uri, union); + } + + return union; + } + } + + private void intersectURI(String email1, String email2, ISet intersect) + { + // email1 is a particular address + if (email1.IndexOf('@') != -1) + { + String _sub = email1.Substring(email1.IndexOf('@') + 1); + // both are a particular mailbox + if (email2.IndexOf('@') != -1) + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + intersect.Add(email1); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(_sub, email2)) + { + intersect.Add(email1); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(_sub, email2) == 0) + { + intersect.Add(email1); + } + } + } + // email specifies a domain + else if (email1.StartsWith(".")) + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email1.IndexOf('@') + 1); + if (WithinDomain(_sub, email1)) + { + intersect.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2) || (Platform.CompareIgnoreCase(email1, email2) == 0)) + { + intersect.Add(email1); + } + else if (WithinDomain(email2, email1)) + { + intersect.Add(email2); + } + } + else + { + if (WithinDomain(email2, email1)) + { + intersect.Add(email2); + } + } + } + // email1 specifies a host + else + { + if (email2.IndexOf('@') != -1) + { + String _sub = email2.Substring(email2.IndexOf('@') + 1); + if (Platform.CompareIgnoreCase(_sub, email1) == 0) + { + intersect.Add(email2); + } + } + // email2 specifies a domain + else if (email2.StartsWith(".")) + { + if (WithinDomain(email1, email2)) + { + intersect.Add(email1); + } + } + // email2 specifies a particular host + else + { + if (Platform.CompareIgnoreCase(email1, email2) == 0) + { + intersect.Add(email1); + } + } + } + } + + private void CheckPermittedURI(ISet permitted, String uri) + // throws PkixNameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + IEnumerator it = permitted.GetEnumerator(); + + while (it.MoveNext()) + { + String str = ((String)it.Current); + + if (IsUriConstrained(uri, str)) + { + return; + } + } + if (uri.Length == 0 && permitted.Count == 0) + { + return; + } + throw new PkixNameConstraintValidatorException( + "URI is not from a permitted subtree."); + } + + private bool IsUriConstrained(String uri, String constraint) + { + String host = ExtractHostFromURL(uri); + // a host + if (!constraint.StartsWith(".")) + { + if (Platform.CompareIgnoreCase(host, constraint) == 0) + { + return true; + } + } + + // in sub domain or domain + else if (WithinDomain(host, constraint)) + { + return true; + } + + return false; + } + + private static String ExtractHostFromURL(String url) + { + // see RFC 1738 + // remove ':' after protocol, e.g. http: + String sub = url.Substring(url.IndexOf(':') + 1); + // extract host from Common Internet Scheme Syntax, e.g. http:// + if (sub.IndexOf("//") != -1) + { + sub = sub.Substring(sub.IndexOf("//") + 2); + } + // first remove port, e.g. http://test.com:21 + if (sub.LastIndexOf(':') != -1) + { + sub = sub.Substring(0, sub.LastIndexOf(':')); + } + // remove user and password, e.g. http://john:password@test.com + sub = sub.Substring(sub.IndexOf(':') + 1); + sub = sub.Substring(sub.IndexOf('@') + 1); + // remove local parts, e.g. http://test.com/bla + if (sub.IndexOf('/') != -1) + { + sub = sub.Substring(0, sub.IndexOf('/')); + } + return sub; + } + + /** + * Checks if the given GeneralName is in the permitted ISet. + * + * @param name The GeneralName + * @throws PkixNameConstraintValidatorException + * If the name + */ + public void checkPermitted(GeneralName name) + // throws PkixNameConstraintValidatorException + { + switch (name.TagNo) + { + case 1: + CheckPermittedEmail(permittedSubtreesEmail, + ExtractNameAsString(name)); + break; + case 2: + CheckPermittedDNS(permittedSubtreesDNS, DerIA5String.GetInstance( + name.Name).GetString()); + break; + case 4: + CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object())); + break; + case 6: + CheckPermittedURI(permittedSubtreesURI, DerIA5String.GetInstance( + name.Name).GetString()); + break; + case 7: + byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets(); + + CheckPermittedIP(permittedSubtreesIP, ip); + break; + } + } + + /** + * Check if the given GeneralName is contained in the excluded ISet. + * + * @param name The GeneralName. + * @throws PkixNameConstraintValidatorException + * If the name is + * excluded. + */ + public void checkExcluded(GeneralName name) + // throws PkixNameConstraintValidatorException + { + switch (name.TagNo) + { + case 1: + CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name)); + break; + case 2: + checkExcludedDNS(excludedSubtreesDNS, DerIA5String.GetInstance( + name.Name).GetString()); + break; + case 4: + CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object())); + break; + case 6: + checkExcludedURI(excludedSubtreesURI, DerIA5String.GetInstance( + name.Name).GetString()); + break; + case 7: + byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets(); + + checkExcludedIP(excludedSubtreesIP, ip); + break; + } + } + + /** + * Updates the permitted ISet of these name constraints with the intersection + * with the given subtree. + * + * @param permitted The permitted subtrees + */ + + public void IntersectPermittedSubtree(Asn1Sequence permitted) + { + IDictionary subtreesMap = Platform.CreateHashtable(); + + // group in ISets in a map ordered by tag no. + for (IEnumerator e = permitted.GetEnumerator(); e.MoveNext(); ) + { + GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current); + + int tagNo = subtree.Base.TagNo; + if (subtreesMap[tagNo] == null) + { + subtreesMap[tagNo] = new HashSet(); + } + + ((ISet)subtreesMap[tagNo]).Add(subtree); + } + + for (IEnumerator it = subtreesMap.GetEnumerator(); it.MoveNext(); ) + { + DictionaryEntry entry = (DictionaryEntry)it.Current; + + // go through all subtree groups + switch ((int)entry.Key ) + { + case 1: + permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail, + (ISet)entry.Value); + break; + case 2: + permittedSubtreesDNS = intersectDNS(permittedSubtreesDNS, + (ISet)entry.Value); + break; + case 4: + permittedSubtreesDN = IntersectDN(permittedSubtreesDN, + (ISet)entry.Value); + break; + case 6: + permittedSubtreesURI = intersectURI(permittedSubtreesURI, + (ISet)entry.Value); + break; + case 7: + permittedSubtreesIP = IntersectIP(permittedSubtreesIP, + (ISet)entry.Value); + break; + } + } + } + + private String ExtractNameAsString(GeneralName name) + { + return DerIA5String.GetInstance(name.Name).GetString(); + } + + public void IntersectEmptyPermittedSubtree(int nameType) + { + switch (nameType) + { + case 1: + permittedSubtreesEmail = new HashSet(); + break; + case 2: + permittedSubtreesDNS = new HashSet(); + break; + case 4: + permittedSubtreesDN = new HashSet(); + break; + case 6: + permittedSubtreesURI = new HashSet(); + break; + case 7: + permittedSubtreesIP = new HashSet(); + break; + } + } + + /** + * Adds a subtree to the excluded ISet of these name constraints. + * + * @param subtree A subtree with an excluded GeneralName. + */ + public void AddExcludedSubtree(GeneralSubtree subtree) + { + GeneralName subTreeBase = subtree.Base; + + switch (subTreeBase.TagNo) + { + case 1: + excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail, + ExtractNameAsString(subTreeBase)); + break; + case 2: + excludedSubtreesDNS = unionDNS(excludedSubtreesDNS, + ExtractNameAsString(subTreeBase)); + break; + case 4: + excludedSubtreesDN = UnionDN(excludedSubtreesDN, + (Asn1Sequence)subTreeBase.Name.ToAsn1Object()); + break; + case 6: + excludedSubtreesURI = unionURI(excludedSubtreesURI, + ExtractNameAsString(subTreeBase)); + break; + case 7: + excludedSubtreesIP = UnionIP(excludedSubtreesIP, Asn1OctetString + .GetInstance(subTreeBase.Name).GetOctets()); + break; + } + } + + /** + * Returns the maximum IP address. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The maximum IP address. + */ + private static byte[] Max(byte[] ip1, byte[] ip2) + { + for (int i = 0; i < ip1.Length; i++) + { + if ((ip1[i] & 0xFFFF) > (ip2[i] & 0xFFFF)) + { + return ip1; + } + } + return ip2; + } + + /** + * Returns the minimum IP address. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The minimum IP address. + */ + private static byte[] Min(byte[] ip1, byte[] ip2) + { + for (int i = 0; i < ip1.Length; i++) + { + if ((ip1[i] & 0xFFFF) < (ip2[i] & 0xFFFF)) + { + return ip1; + } + } + return ip2; + } + + /** + * Compares IP address ip1 with ip2. If ip1 + * is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1 + * otherwise. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise. + */ + private static int CompareTo(byte[] ip1, byte[] ip2) + { + if (Org.BouncyCastle.Utilities.Arrays.AreEqual(ip1, ip2)) + { + return 0; + } + if (Org.BouncyCastle.Utilities.Arrays.AreEqual(Max(ip1, ip2), ip1)) + { + return 1; + } + return -1; + } + + /** + * Returns the logical OR of the IP addresses ip1 and + * ip2. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The OR of ip1 and ip2. + */ + private static byte[] Or(byte[] ip1, byte[] ip2) + { + byte[] temp = new byte[ip1.Length]; + for (int i = 0; i < ip1.Length; i++) + { + temp[i] = (byte)(ip1[i] | ip2[i]); + } + return temp; + } + + [Obsolete("Use GetHashCode instead")] + public int HashCode() + { + return GetHashCode(); + } + + public override int GetHashCode() + { + return HashCollection(excludedSubtreesDN) + + HashCollection(excludedSubtreesDNS) + + HashCollection(excludedSubtreesEmail) + + HashCollection(excludedSubtreesIP) + + HashCollection(excludedSubtreesURI) + + HashCollection(permittedSubtreesDN) + + HashCollection(permittedSubtreesDNS) + + HashCollection(permittedSubtreesEmail) + + HashCollection(permittedSubtreesIP) + + HashCollection(permittedSubtreesURI); + } + + private int HashCollection(ICollection coll) + { + if (coll == null) + { + return 0; + } + int hash = 0; + IEnumerator it1 = coll.GetEnumerator(); + while (it1.MoveNext()) + { + Object o = it1.Current; + if (o is byte[]) + { + hash += Org.BouncyCastle.Utilities.Arrays.GetHashCode((byte[])o); + } + else + { + hash += o.GetHashCode(); + } + } + return hash; + } + + public override bool Equals(Object o) + { + if (!(o is PkixNameConstraintValidator)) + return false; + + PkixNameConstraintValidator constraintValidator = (PkixNameConstraintValidator)o; + + return CollectionsAreEqual(constraintValidator.excludedSubtreesDN, excludedSubtreesDN) + && CollectionsAreEqual(constraintValidator.excludedSubtreesDNS, excludedSubtreesDNS) + && CollectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail) + && CollectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP) + && CollectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI) + && CollectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN) + && CollectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS) + && CollectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail) + && CollectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP) + && CollectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI); + } + + private bool CollectionsAreEqual(ICollection coll1, ICollection coll2) + { + if (coll1 == coll2) + { + return true; + } + if (coll1 == null || coll2 == null) + { + return false; + } + if (coll1.Count != coll2.Count) + { + return false; + } + IEnumerator it1 = coll1.GetEnumerator(); + + while (it1.MoveNext()) + { + Object a = it1.Current; + IEnumerator it2 = coll2.GetEnumerator(); + bool found = false; + while (it2.MoveNext()) + { + Object b = it2.Current; + if (SpecialEquals(a, b)) + { + found = true; + break; + } + } + if (!found) + { + return false; + } + } + return true; + } + + private bool SpecialEquals(Object o1, Object o2) + { + if (o1 == o2) + { + return true; + } + if (o1 == null || o2 == null) + { + return false; + } + if ((o1 is byte[]) && (o2 is byte[])) + { + return Org.BouncyCastle.Utilities.Arrays.AreEqual((byte[])o1, (byte[])o2); + } + else + { + return o1.Equals(o2); + } + } + + /** + * Stringifies an IPv4 or v6 address with subnet mask. + * + * @param ip The IP with subnet mask. + * @return The stringified IP address. + */ + private String StringifyIP(byte[] ip) + { + String temp = ""; + for (int i = 0; i < ip.Length / 2; i++) + { + //temp += Integer.toString(ip[i] & 0x00FF) + "."; + temp += (ip[i] & 0x00FF) + "."; + } + temp = temp.Substring(0, temp.Length - 1); + temp += "/"; + for (int i = ip.Length / 2; i < ip.Length; i++) + { + //temp += Integer.toString(ip[i] & 0x00FF) + "."; + temp += (ip[i] & 0x00FF) + "."; + } + temp = temp.Substring(0, temp.Length - 1); + return temp; + } + + private String StringifyIPCollection(ISet ips) + { + String temp = ""; + temp += "["; + for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); ) + { + temp += StringifyIP((byte[])it.Current) + ","; + } + if (temp.Length > 1) + { + temp = temp.Substring(0, temp.Length - 1); + } + temp += "]"; + + return temp; + } + + public override String ToString() + { + String temp = ""; + + temp += "permitted:\n"; + if (permittedSubtreesDN != null) + { + temp += "DN:\n"; + temp += permittedSubtreesDN.ToString() + "\n"; + } + if (permittedSubtreesDNS != null) + { + temp += "DNS:\n"; + temp += permittedSubtreesDNS.ToString() + "\n"; + } + if (permittedSubtreesEmail != null) + { + temp += "Email:\n"; + temp += permittedSubtreesEmail.ToString() + "\n"; + } + if (permittedSubtreesURI != null) + { + temp += "URI:\n"; + temp += permittedSubtreesURI.ToString() + "\n"; + } + if (permittedSubtreesIP != null) + { + temp += "IP:\n"; + temp += StringifyIPCollection(permittedSubtreesIP) + "\n"; + } + temp += "excluded:\n"; + if (!(excludedSubtreesDN.IsEmpty)) + { + temp += "DN:\n"; + temp += excludedSubtreesDN.ToString() + "\n"; + } + if (!excludedSubtreesDNS.IsEmpty) + { + temp += "DNS:\n"; + temp += excludedSubtreesDNS.ToString() + "\n"; + } + if (!excludedSubtreesEmail.IsEmpty) + { + temp += "Email:\n"; + temp += excludedSubtreesEmail.ToString() + "\n"; + } + if (!excludedSubtreesURI.IsEmpty) + { + temp += "URI:\n"; + temp += excludedSubtreesURI.ToString() + "\n"; + } + if (!excludedSubtreesIP.IsEmpty) + { + temp += "IP:\n"; + temp += StringifyIPCollection(excludedSubtreesIP) + "\n"; + } + return temp; + } + + } +} diff --git a/crypto/src/pkix/PkixNameConstraintValidatorException.cs b/crypto/src/pkix/PkixNameConstraintValidatorException.cs new file mode 100644 index 000000000..432d7bd6b --- /dev/null +++ b/crypto/src/pkix/PkixNameConstraintValidatorException.cs @@ -0,0 +1,16 @@ +using System; + +namespace Org.BouncyCastle.Pkix +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PkixNameConstraintValidatorException + : Exception + { + public PkixNameConstraintValidatorException(String msg) + : base(msg) + { + } + } +} diff --git a/crypto/src/pkix/PkixParameters.cs b/crypto/src/pkix/PkixParameters.cs new file mode 100644 index 000000000..6df1b646f --- /dev/null +++ b/crypto/src/pkix/PkixParameters.cs @@ -0,0 +1,893 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixParameters. + /// + public class PkixParameters +// : ICertPathParameters + { + /** + * This is the default PKIX validity model. Actually there are two variants + * of this: The PKIX model and the modified PKIX model. The PKIX model + * verifies that all involved certificates must have been valid at the + * current time. The modified PKIX model verifies that all involved + * certificates were valid at the signing time. Both are indirectly choosen + * with the {@link PKIXParameters#setDate(java.util.Date)} method, so this + * methods sets the Date when all certificates must have been + * valid. + */ + public const int PkixValidityModel = 0; + + /** + * This model uses the following validity model. Each certificate must have + * been valid at the moment where is was used. That means the end + * certificate must have been valid at the time the signature was done. The + * CA certificate which signed the end certificate must have been valid, + * when the end certificate was signed. The CA (or Root CA) certificate must + * have been valid, when the CA certificate was signed and so on. So the + * {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when + * the end certificate must have been valid.

    It is used e.g. + * in the German signature law. + */ + public const int ChainValidityModel = 1; + + private ISet trustAnchors; + private DateTimeObject date; + private IList certPathCheckers; + private bool revocationEnabled = true; + private ISet initialPolicies; + //private bool checkOnlyEECertificateCrl = false; + private bool explicitPolicyRequired = false; + private bool anyPolicyInhibited = false; + private bool policyMappingInhibited = false; + private bool policyQualifiersRejected = true; + private IX509Selector certSelector; + private IList stores; + private IX509Selector selector; + private bool additionalLocationsEnabled; + private IList additionalStores; + private ISet trustedACIssuers; + private ISet necessaryACAttributes; + private ISet prohibitedACAttributes; + private ISet attrCertCheckers; + private int validityModel = PkixValidityModel; + private bool useDeltas = false; + + /** + * Creates an instance of PKIXParameters with the specified Set of + * most-trusted CAs. Each element of the set is a TrustAnchor.
    + *
    + * Note that the Set is copied to protect against subsequent modifications. + * + * @param trustAnchors + * a Set of TrustAnchors + * + * @exception InvalidAlgorithmParameterException + * if the specified Set is empty + * (trustAnchors.isEmpty() == true) + * @exception NullPointerException + * if the specified Set is null + * @exception ClassCastException + * if any of the elements in the Set are not of type + * java.security.cert.TrustAnchor + */ + public PkixParameters( + ISet trustAnchors) + { + SetTrustAnchors(trustAnchors); + + this.initialPolicies = new HashSet(); + this.certPathCheckers = Platform.CreateArrayList(); + this.stores = Platform.CreateArrayList(); + this.additionalStores = Platform.CreateArrayList(); + this.trustedACIssuers = new HashSet(); + this.necessaryACAttributes = new HashSet(); + this.prohibitedACAttributes = new HashSet(); + this.attrCertCheckers = new HashSet(); + } + +// // TODO implement for other keystores (see Java build)? +// /** +// * Creates an instance of PKIXParameters that +// * populates the set of most-trusted CAs from the trusted +// * certificate entries contained in the specified KeyStore. +// * Only keystore entries that contain trusted X509Certificates +// * are considered; all other certificate types are ignored. +// * +// * @param keystore a KeyStore from which the set of +// * most-trusted CAs will be populated +// * @throws KeyStoreException if the keystore has not been initialized +// * @throws InvalidAlgorithmParameterException if the keystore does +// * not contain at least one trusted certificate entry +// * @throws NullPointerException if the keystore is null +// */ +// public PkixParameters( +// Pkcs12Store keystore) +//// throws KeyStoreException, InvalidAlgorithmParameterException +// { +// if (keystore == null) +// throw new ArgumentNullException("keystore"); +// ISet trustAnchors = new HashSet(); +// foreach (string alias in keystore.Aliases) +// { +// if (keystore.IsCertificateEntry(alias)) +// { +// X509CertificateEntry x509Entry = keystore.GetCertificate(alias); +// trustAnchors.Add(new TrustAnchor(x509Entry.Certificate, null)); +// } +// } +// SetTrustAnchors(trustAnchors); +// +// this.initialPolicies = new HashSet(); +// this.certPathCheckers = new ArrayList(); +// this.stores = new ArrayList(); +// this.additionalStores = new ArrayList(); +// this.trustedACIssuers = new HashSet(); +// this.necessaryACAttributes = new HashSet(); +// this.prohibitedACAttributes = new HashSet(); +// this.attrCertCheckers = new HashSet(); +// } + + public virtual bool IsRevocationEnabled + { + get { return revocationEnabled; } + set { revocationEnabled = value; } + } + + public virtual bool IsExplicitPolicyRequired + { + get { return explicitPolicyRequired; } + set { this.explicitPolicyRequired = value; } + } + + public virtual bool IsAnyPolicyInhibited + { + get { return anyPolicyInhibited; } + set { this.anyPolicyInhibited = value; } + } + + public virtual bool IsPolicyMappingInhibited + { + get { return policyMappingInhibited; } + set { this.policyMappingInhibited = value; } + } + + public virtual bool IsPolicyQualifiersRejected + { + get { return policyQualifiersRejected; } + set { this.policyQualifiersRejected = value; } + } + + //public bool IsCheckOnlyEECertificateCrl + //{ + // get { return this.checkOnlyEECertificateCrl; } + // set { this.checkOnlyEECertificateCrl = value; } + //} + + public virtual DateTimeObject Date + { + get { return this.date; } + set { this.date = value; } + } + + // Returns a Set of the most-trusted CAs. + public virtual ISet GetTrustAnchors() + { + return new HashSet(this.trustAnchors); + } + + // Sets the set of most-trusted CAs. + // Set is copied to protect against subsequent modifications. + public virtual void SetTrustAnchors( + ISet tas) + { + if (tas == null) + throw new ArgumentNullException("value"); + if (tas.IsEmpty) + throw new ArgumentException("non-empty set required", "value"); + + // Explicit copy to enforce type-safety + this.trustAnchors = new HashSet(); + foreach (TrustAnchor ta in tas) + { + if (ta != null) + { + trustAnchors.Add(ta); + } + } + } + + /** + * Returns the required constraints on the target certificate. The + * constraints are returned as an instance of CertSelector. If + * null, no constraints are defined.
    + *
    + * Note that the CertSelector returned is cloned to protect against + * subsequent modifications. + * + * @return a CertSelector specifying the constraints on the target + * certificate (or null) + * + * @see #setTargetCertConstraints(CertSelector) + */ + public virtual X509CertStoreSelector GetTargetCertConstraints() + { + if (certSelector == null) + { + return null; + } + + return (X509CertStoreSelector)certSelector.Clone(); + } + + /** + * Sets the required constraints on the target certificate. The constraints + * are specified as an instance of CertSelector. If null, no constraints are + * defined.
    + *
    + * Note that the CertSelector specified is cloned to protect against + * subsequent modifications. + * + * @param selector + * a CertSelector specifying the constraints on the target + * certificate (or null) + * + * @see #getTargetCertConstraints() + */ + public virtual void SetTargetCertConstraints( + IX509Selector selector) + { + if (selector == null) + { + certSelector = null; + } + else + { + certSelector = (IX509Selector)selector.Clone(); + } + } + + /** + * Returns an immutable Set of initial policy identifiers (OID strings), + * indicating that any one of these policies would be acceptable to the + * certificate user for the purposes of certification path processing. The + * default return value is an empty Set, which is + * interpreted as meaning that any policy would be acceptable. + * + * @return an immutable Set of initial policy OIDs in String + * format, or an empty Set (implying any policy is + * acceptable). Never returns null. + * + * @see #setInitialPolicies(java.util.Set) + */ + public virtual ISet GetInitialPolicies() + { + ISet returnSet = initialPolicies; + + // TODO Can it really be null? + if (initialPolicies == null) + { + returnSet = new HashSet(); + } + + return new HashSet(returnSet); + } + + /** + * Sets the Set of initial policy identifiers (OID strings), + * indicating that any one of these policies would be acceptable to the + * certificate user for the purposes of certification path processing. By + * default, any policy is acceptable (i.e. all policies), so a user that + * wants to allow any policy as acceptable does not need to call this + * method, or can call it with an empty Set (or + * null).
    + *
    + * Note that the Set is copied to protect against subsequent modifications.
    + *
    + * + * @param initialPolicies + * a Set of initial policy OIDs in String format (or + * null) + * + * @exception ClassCastException + * if any of the elements in the set are not of type String + * + * @see #getInitialPolicies() + */ + public virtual void SetInitialPolicies( + ISet initialPolicies) + { + this.initialPolicies = new HashSet(); + if (initialPolicies != null) + { + foreach (string obj in initialPolicies) + { + if (obj != null) + { + this.initialPolicies.Add(obj); + } + } + } + } + + /** + * Sets a List of additional certification path checkers. If + * the specified List contains an object that is not a PKIXCertPathChecker, + * it is ignored.
    + *
    + * Each PKIXCertPathChecker specified implements additional + * checks on a certificate. Typically, these are checks to process and + * verify private extensions contained in certificates. Each + * PKIXCertPathChecker should be instantiated with any + * initialization parameters needed to execute the check.
    + *
    + * This method allows sophisticated applications to extend a PKIX + * CertPathValidator or CertPathBuilder. Each + * of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX + * CertPathValidator or CertPathBuilder for + * each certificate processed or validated.
    + *
    + * Regardless of whether these additional PKIXCertPathCheckers are set, a + * PKIX CertPathValidator or CertPathBuilder + * must perform all of the required PKIX checks on each certificate. The one + * exception to this rule is if the RevocationEnabled flag is set to false + * (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled} + * method).
    + *
    + * Note that the List supplied here is copied and each PKIXCertPathChecker + * in the list is cloned to protect against subsequent modifications. + * + * @param checkers + * a List of PKIXCertPathCheckers. May be null, in which case no + * additional checkers will be used. + * @exception ClassCastException + * if any of the elements in the list are not of type + * java.security.cert.PKIXCertPathChecker + * @see #getCertPathCheckers() + */ + public virtual void SetCertPathCheckers(IList checkers) + { + certPathCheckers = Platform.CreateArrayList(); + if (checkers != null) + { + foreach (PkixCertPathChecker obj in checkers) + { + certPathCheckers.Add(obj.Clone()); + } + } + } + + /** + * Returns the List of certification path checkers. Each PKIXCertPathChecker + * in the returned IList is cloned to protect against subsequent modifications. + * + * @return an immutable List of PKIXCertPathCheckers (may be empty, but not + * null) + * + * @see #setCertPathCheckers(java.util.List) + */ + public virtual IList GetCertPathCheckers() + { + IList checkers = Platform.CreateArrayList(); + foreach (PkixCertPathChecker obj in certPathCheckers) + { + checkers.Add(obj.Clone()); + } + return checkers; + } + + /** + * Adds a PKIXCertPathChecker to the list of certification + * path checkers. See the {@link #setCertPathCheckers setCertPathCheckers} + * method for more details. + *

    + * Note that the PKIXCertPathChecker is cloned to protect + * against subsequent modifications.

    + * + * @param checker a PKIXCertPathChecker to add to the list of + * checks. If null, the checker is ignored (not added to list). + */ + public virtual void AddCertPathChecker( + PkixCertPathChecker checker) + { + if (checker != null) + { + certPathCheckers.Add(checker.Clone()); + } + } + + public virtual object Clone() + { + // FIXME Check this whole method against the Java implementation! + + PkixParameters parameters = new PkixParameters(GetTrustAnchors()); + parameters.SetParams(this); + return parameters; + + +// PkixParameters obj = new PkixParameters(new HashSet()); +//// (PkixParameters) this.MemberwiseClone(); +// obj.x509Stores = new ArrayList(x509Stores); +// obj.certPathCheckers = new ArrayList(certPathCheckers); +// +// //Iterator iter = certPathCheckers.iterator(); +// //obj.certPathCheckers = new ArrayList(); +// //while (iter.hasNext()) +// //{ +// // obj.certPathCheckers.add(((PKIXCertPathChecker)iter.next()) +// // .clone()); +// //} +// //if (initialPolicies != null) +// //{ +// // obj.initialPolicies = new HashSet(initialPolicies); +// //} +//// if (trustAnchors != null) +//// { +//// obj.trustAnchors = new HashSet(trustAnchors); +//// } +//// if (certSelector != null) +//// { +//// obj.certSelector = (X509CertStoreSelector) certSelector.Clone(); +//// } +// return obj; + } + + /** + * Method to support Clone() under J2ME. + * super.Clone() does not exist and fields are not copied. + * + * @param params Parameters to set. If this are + * ExtendedPkixParameters they are copied to. + */ + protected virtual void SetParams( + PkixParameters parameters) + { + Date = parameters.Date; + SetCertPathCheckers(parameters.GetCertPathCheckers()); + IsAnyPolicyInhibited = parameters.IsAnyPolicyInhibited; + IsExplicitPolicyRequired = parameters.IsExplicitPolicyRequired; + IsPolicyMappingInhibited = parameters.IsPolicyMappingInhibited; + IsRevocationEnabled = parameters.IsRevocationEnabled; + SetInitialPolicies(parameters.GetInitialPolicies()); + IsPolicyQualifiersRejected = parameters.IsPolicyQualifiersRejected; + SetTargetCertConstraints(parameters.GetTargetCertConstraints()); + SetTrustAnchors(parameters.GetTrustAnchors()); + + validityModel = parameters.validityModel; + useDeltas = parameters.useDeltas; + additionalLocationsEnabled = parameters.additionalLocationsEnabled; + selector = parameters.selector == null ? null + : (IX509Selector) parameters.selector.Clone(); + stores = Platform.CreateArrayList(parameters.stores); + additionalStores = Platform.CreateArrayList(parameters.additionalStores); + trustedACIssuers = new HashSet(parameters.trustedACIssuers); + prohibitedACAttributes = new HashSet(parameters.prohibitedACAttributes); + necessaryACAttributes = new HashSet(parameters.necessaryACAttributes); + attrCertCheckers = new HashSet(parameters.attrCertCheckers); + } + + /** + * Whether delta CRLs should be used for checking the revocation status. + * Defaults to false. + */ + public virtual bool IsUseDeltasEnabled + { + get { return useDeltas; } + set { useDeltas = value; } + } + + /** + * The validity model. + * @see #CHAIN_VALIDITY_MODEL + * @see #PKIX_VALIDITY_MODEL + */ + public virtual int ValidityModel + { + get { return validityModel; } + set { validityModel = value; } + } + + /** + * Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute + * certificates or cross certificates. + *

    + * The IList is cloned. + *

    + * + * @param stores A list of stores to use. + * @see #getStores + * @throws ClassCastException if an element of stores is not + * a {@link Store}. + */ + public virtual void SetStores( + IList stores) + { + if (stores == null) + { + this.stores = Platform.CreateArrayList(); + } + else + { + foreach (object obj in stores) + { + if (!(obj is IX509Store)) + { + throw new InvalidCastException( + "All elements of list must be of type " + typeof(IX509Store).FullName); + } + } + this.stores = Platform.CreateArrayList(stores); + } + } + + /** + * Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute + * certificates or cross certificates. + *

    + * This method should be used to add local stores, like collection based + * X.509 stores, if available. Local stores should be considered first, + * before trying to use additional (remote) locations, because they do not + * need possible additional network traffic. + *

    + * If store is null it is ignored. + *

    + * + * @param store The store to add. + * @see #getStores + */ + public virtual void AddStore( + IX509Store store) + { + if (store != null) + { + stores.Add(store); + } + } + + /** + * Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates, + * attribute certificates or cross certificates. + *

    + * You should not use this method. This method is used for adding additional + * X.509 stores, which are used to add (remote) locations, e.g. LDAP, found + * during X.509 object processing, e.g. in certificates or CRLs. This method + * is used in PKIX certification path processing. + *

    + * If store is null it is ignored. + *

    + * + * @param store The store to add. + * @see #getStores() + */ + public virtual void AddAdditionalStore( + IX509Store store) + { + if (store != null) + { + additionalStores.Add(store); + } + } + + /** + * Returns an IList of additional Bouncy Castle + * Stores used for finding CRLs, certificates, attribute + * certificates or cross certificates. + * + * @return an immutable IList of additional Bouncy Castle + * Stores. Never null. + * + * @see #addAddionalStore(Store) + */ + public virtual IList GetAdditionalStores() + { + return Platform.CreateArrayList(additionalStores); + } + + /** + * Returns an IList of Bouncy Castle + * Stores used for finding CRLs, certificates, attribute + * certificates or cross certificates. + * + * @return an immutable IList of Bouncy Castle + * Stores. Never null. + * + * @see #setStores(IList) + */ + public virtual IList GetStores() + { + return Platform.CreateArrayList(stores); + } + + /** + * Returns if additional {@link X509Store}s for locations like LDAP found + * in certificates or CRLs should be used. + * + * @return Returns true if additional stores are used. + */ + public virtual bool IsAdditionalLocationsEnabled + { + get { return additionalLocationsEnabled; } + } + + /** + * Sets if additional {@link X509Store}s for locations like LDAP found in + * certificates or CRLs should be used. + * + * @param enabled true if additional stores are used. + */ + public virtual void SetAdditionalLocationsEnabled( + bool enabled) + { + additionalLocationsEnabled = enabled; + } + + /** + * Returns the required constraints on the target certificate or attribute + * certificate. The constraints are returned as an instance of + * IX509Selector. If null, no constraints are + * defined. + * + *

    + * The target certificate in a PKIX path may be a certificate or an + * attribute certificate. + *

    + * Note that the IX509Selector returned is cloned to protect + * against subsequent modifications. + *

    + * @return a IX509Selector specifying the constraints on the + * target certificate or attribute certificate (or null) + * @see #setTargetConstraints + * @see X509CertStoreSelector + * @see X509AttributeCertStoreSelector + */ + public virtual IX509Selector GetTargetConstraints() + { + if (selector != null) + { + return (IX509Selector) selector.Clone(); + } + else + { + return null; + } + } + + /** + * Sets the required constraints on the target certificate or attribute + * certificate. The constraints are specified as an instance of + * IX509Selector. If null, no constraints are + * defined. + *

    + * The target certificate in a PKIX path may be a certificate or an + * attribute certificate. + *

    + * Note that the IX509Selector specified is cloned to protect + * against subsequent modifications. + *

    + * + * @param selector a IX509Selector specifying the constraints on + * the target certificate or attribute certificate (or + * null) + * @see #getTargetConstraints + * @see X509CertStoreSelector + * @see X509AttributeCertStoreSelector + */ + public virtual void SetTargetConstraints(IX509Selector selector) + { + if (selector != null) + { + this.selector = (IX509Selector) selector.Clone(); + } + else + { + this.selector = null; + } + } + + /** + * Returns the trusted attribute certificate issuers. If attribute + * certificates is verified the trusted AC issuers must be set. + *

    + * The returned ISet consists of TrustAnchors. + *

    + * The returned ISet is immutable. Never null + *

    + * + * @return Returns an immutable set of the trusted AC issuers. + */ + public virtual ISet GetTrustedACIssuers() + { + return new HashSet(trustedACIssuers); + } + + /** + * Sets the trusted attribute certificate issuers. If attribute certificates + * is verified the trusted AC issuers must be set. + *

    + * The trustedACIssuers must be a ISet of + * TrustAnchor + *

    + * The given set is cloned. + *

    + * + * @param trustedACIssuers The trusted AC issuers to set. Is never + * null. + * @throws ClassCastException if an element of stores is not + * a TrustAnchor. + */ + public virtual void SetTrustedACIssuers( + ISet trustedACIssuers) + { + if (trustedACIssuers == null) + { + this.trustedACIssuers = new HashSet(); + } + else + { + foreach (object obj in trustedACIssuers) + { + if (!(obj is TrustAnchor)) + { + throw new InvalidCastException("All elements of set must be " + + "of type " + typeof(TrustAnchor).Name + "."); + } + } + this.trustedACIssuers = new HashSet(trustedACIssuers); + } + } + + /** + * Returns the neccessary attributes which must be contained in an attribute + * certificate. + *

    + * The returned ISet is immutable and contains + * Strings with the OIDs. + *

    + * + * @return Returns the necessary AC attributes. + */ + public virtual ISet GetNecessaryACAttributes() + { + return new HashSet(necessaryACAttributes); + } + + /** + * Sets the neccessary which must be contained in an attribute certificate. + *

    + * The ISet must contain Strings with the + * OIDs. + *

    + * The set is cloned. + *

    + * + * @param necessaryACAttributes The necessary AC attributes to set. + * @throws ClassCastException if an element of + * necessaryACAttributes is not a + * String. + */ + public virtual void SetNecessaryACAttributes( + ISet necessaryACAttributes) + { + if (necessaryACAttributes == null) + { + this.necessaryACAttributes = new HashSet(); + } + else + { + foreach (object obj in necessaryACAttributes) + { + if (!(obj is string)) + { + throw new InvalidCastException("All elements of set must be " + + "of type string."); + } + } + this.necessaryACAttributes = new HashSet(necessaryACAttributes); + } + } + + /** + * Returns the attribute certificates which are not allowed. + *

    + * The returned ISet is immutable and contains + * Strings with the OIDs. + *

    + * + * @return Returns the prohibited AC attributes. Is never null. + */ + public virtual ISet GetProhibitedACAttributes() + { + return new HashSet(prohibitedACAttributes); + } + + /** + * Sets the attribute certificates which are not allowed. + *

    + * The ISet must contain Strings with the + * OIDs. + *

    + * The set is cloned. + *

    + * + * @param prohibitedACAttributes The prohibited AC attributes to set. + * @throws ClassCastException if an element of + * prohibitedACAttributes is not a + * String. + */ + public virtual void SetProhibitedACAttributes( + ISet prohibitedACAttributes) + { + if (prohibitedACAttributes == null) + { + this.prohibitedACAttributes = new HashSet(); + } + else + { + foreach (object obj in prohibitedACAttributes) + { + if (!(obj is String)) + { + throw new InvalidCastException("All elements of set must be " + + "of type string."); + } + } + this.prohibitedACAttributes = new HashSet(prohibitedACAttributes); + } + } + + /** + * Returns the attribute certificate checker. The returned set contains + * {@link PKIXAttrCertChecker}s and is immutable. + * + * @return Returns the attribute certificate checker. Is never + * null. + */ + public virtual ISet GetAttrCertCheckers() + { + return new HashSet(attrCertCheckers); + } + + /** + * Sets the attribute certificate checkers. + *

    + * All elements in the ISet must a {@link PKIXAttrCertChecker}. + *

    + *

    + * The given set is cloned. + *

    + * + * @param attrCertCheckers The attribute certificate checkers to set. Is + * never null. + * @throws ClassCastException if an element of attrCertCheckers + * is not a PKIXAttrCertChecker. + */ + public virtual void SetAttrCertCheckers( + ISet attrCertCheckers) + { + if (attrCertCheckers == null) + { + this.attrCertCheckers = new HashSet(); + } + else + { + foreach (object obj in attrCertCheckers) + { + if (!(obj is PkixAttrCertChecker)) + { + throw new InvalidCastException("All elements of set must be " + + "of type " + typeof(PkixAttrCertChecker).FullName + "."); + } + } + this.attrCertCheckers = new HashSet(attrCertCheckers); + } + } + } +} diff --git a/crypto/src/pkix/PkixPolicyNode.cs b/crypto/src/pkix/PkixPolicyNode.cs new file mode 100644 index 000000000..fc5b82f6f --- /dev/null +++ b/crypto/src/pkix/PkixPolicyNode.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// Summary description for PkixPolicyNode. + /// + public class PkixPolicyNode +// : IPolicyNode + { + protected IList mChildren; + protected int mDepth; + protected ISet mExpectedPolicies; + protected PkixPolicyNode mParent; + protected ISet mPolicyQualifiers; + protected string mValidPolicy; + protected bool mCritical; + + public virtual int Depth + { + get { return this.mDepth; } + } + + public virtual IEnumerable Children + { + get { return new EnumerableProxy(mChildren); } + } + + public virtual bool IsCritical + { + get { return this.mCritical; } + set { this.mCritical = value; } + } + + public virtual ISet PolicyQualifiers + { + get { return new HashSet(this.mPolicyQualifiers); } + } + + public virtual string ValidPolicy + { + get { return this.mValidPolicy; } + } + + public virtual bool HasChildren + { + get { return mChildren.Count != 0; } + } + + public virtual ISet ExpectedPolicies + { + get { return new HashSet(this.mExpectedPolicies); } + set { this.mExpectedPolicies = new HashSet(value); } + } + + public virtual PkixPolicyNode Parent + { + get { return this.mParent; } + set { this.mParent = value; } + } + + /// Constructors + public PkixPolicyNode( + IList children, + int depth, + ISet expectedPolicies, + PkixPolicyNode parent, + ISet policyQualifiers, + string validPolicy, + bool critical) + { + if (children == null) + { + this.mChildren = Platform.CreateArrayList(); + } + else + { + this.mChildren = Platform.CreateArrayList(children); + } + + this.mDepth = depth; + this.mExpectedPolicies = expectedPolicies; + this.mParent = parent; + this.mPolicyQualifiers = policyQualifiers; + this.mValidPolicy = validPolicy; + this.mCritical = critical; + } + + public virtual void AddChild( + PkixPolicyNode child) + { + child.Parent = this; + mChildren.Add(child); + } + + public virtual void RemoveChild( + PkixPolicyNode child) + { + mChildren.Remove(child); + } + + public override string ToString() + { + return ToString(""); + } + + public virtual string ToString( + string indent) + { + StringBuilder buf = new StringBuilder(); + buf.Append(indent); + buf.Append(mValidPolicy); + buf.Append(" {"); + buf.Append(Platform.NewLine); + + foreach (PkixPolicyNode child in mChildren) + { + buf.Append(child.ToString(indent + " ")); + } + + buf.Append(indent); + buf.Append("}"); + buf.Append(Platform.NewLine); + return buf.ToString(); + } + + public virtual object Clone() + { + return Copy(); + } + + public virtual PkixPolicyNode Copy() + { + PkixPolicyNode node = new PkixPolicyNode( + Platform.CreateArrayList(), + mDepth, + new HashSet(mExpectedPolicies), + null, + new HashSet(mPolicyQualifiers), + mValidPolicy, + mCritical); + + foreach (PkixPolicyNode child in mChildren) + { + PkixPolicyNode copy = child.Copy(); + copy.Parent = node; + node.AddChild(copy); + } + + return node; + } + } +} diff --git a/crypto/src/pkix/ReasonsMask.cs b/crypto/src/pkix/ReasonsMask.cs new file mode 100644 index 000000000..e389bfe11 --- /dev/null +++ b/crypto/src/pkix/ReasonsMask.cs @@ -0,0 +1,96 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// This class helps to handle CRL revocation reasons mask. Each CRL handles a + /// certain set of revocation reasons. + /// + internal class ReasonsMask + { + private int _reasons; + + /// + /// Constructs are reason mask with the reasons. + /// + /// The reasons. + internal ReasonsMask( + int reasons) + { + _reasons = reasons; + } + + /// + /// A reason mask with no reason. + /// + internal ReasonsMask() + : this(0) + { + } + + /// + /// A mask with all revocation reasons. + /// + internal static readonly ReasonsMask AllReasons = new ReasonsMask( + ReasonFlags.AACompromise | ReasonFlags.AffiliationChanged | ReasonFlags.CACompromise + | ReasonFlags.CertificateHold | ReasonFlags.CessationOfOperation + | ReasonFlags.KeyCompromise | ReasonFlags.PrivilegeWithdrawn | ReasonFlags.Unused + | ReasonFlags.Superseded); + + /** + * Adds all reasons from the reasons mask to this mask. + * + * @param mask The reasons mask to add. + */ + internal void AddReasons( + ReasonsMask mask) + { + _reasons = _reasons | mask.Reasons.IntValue; + } + + /// + /// Returns true if this reasons mask contains all possible + /// reasons. + /// + /// true if this reasons mask contains all possible reasons. + /// + internal bool IsAllReasons + { + get { return _reasons == AllReasons._reasons; } + } + + /// + /// Intersects this mask with the given reasons mask. + /// + /// mask The mask to intersect with. + /// The intersection of this and teh given mask. + internal ReasonsMask Intersect( + ReasonsMask mask) + { + ReasonsMask _mask = new ReasonsMask(); + _mask.AddReasons(new ReasonsMask(_reasons & mask.Reasons.IntValue)); + return _mask; + } + + /// + /// Returns true if the passed reasons mask has new reasons. + /// + /// The reasons mask which should be tested for new reasons. + /// true if the passed reasons mask has new reasons. + internal bool HasNewReasons( + ReasonsMask mask) + { + return ((_reasons | mask.Reasons.IntValue ^ _reasons) != 0); + } + + /// + /// Returns the reasons in this mask. + /// + public ReasonFlags Reasons + { + get { return new ReasonFlags(_reasons); } + } + } +} diff --git a/crypto/src/pkix/Rfc3280CertPathUtilities.cs b/crypto/src/pkix/Rfc3280CertPathUtilities.cs new file mode 100644 index 000000000..bae657d90 --- /dev/null +++ b/crypto/src/pkix/Rfc3280CertPathUtilities.cs @@ -0,0 +1,2448 @@ +using System; +using System.Collections; +using System.Globalization; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + public class Rfc3280CertPathUtilities + { + private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities(); + + internal static readonly string ANY_POLICY = "2.5.29.32.0"; + + // key usage bits + internal static readonly int KEY_CERT_SIGN = 5; + internal static readonly int CRL_SIGN = 6; + + /** + * If the complete CRL includes an issuing distribution point (IDP) CRL + * extension check the following: + *

    + * (i) If the distribution point name is present in the IDP CRL extension + * and the distribution field is present in the DP, then verify that one of + * the names in the IDP matches one of the names in the DP. If the + * distribution point name is present in the IDP CRL extension and the + * distribution field is omitted from the DP, then verify that one of the + * names in the IDP matches one of the names in the cRLIssuer field of the + * DP. + *

    + *

    + * (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL + * extension, verify that the certificate does not include the basic + * constraints extension with the cA boolean asserted. + *

    + *

    + * (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL + * extension, verify that the certificate includes the basic constraints + * extension with the cA boolean asserted. + *

    + *

    + * (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted. + *

    + * + * @param dp The distribution point. + * @param cert The certificate. + * @param crl The CRL. + * @throws AnnotatedException if one of the conditions is not met or an error occurs. + */ + internal static void ProcessCrlB2( + DistributionPoint dp, + object cert, + X509Crl crl) + { + IssuingDistributionPoint idp = null; + try + { + idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint)); + } + catch (Exception e) + { + throw new Exception("0 Issuing distribution point extension could not be decoded.", e); + } + // (b) (2) (i) + // distribution point name is present + if (idp != null) + { + if (idp.DistributionPoint != null) + { + // make list of names + DistributionPointName dpName = IssuingDistributionPoint.GetInstance(idp).DistributionPoint; + IList names = Platform.CreateArrayList(); + + if (dpName.PointType == DistributionPointName.FullName) + { + GeneralName[] genNames = GeneralNames.GetInstance(dpName.Name).GetNames(); + for (int j = 0; j < genNames.Length; j++) + { + names.Add(genNames[j]); + } + } + if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer) + { + Asn1EncodableVector vec = new Asn1EncodableVector(); + try + { + IEnumerator e = Asn1Sequence.GetInstance( + Asn1Sequence.FromByteArray(crl.IssuerDN.GetEncoded())).GetEnumerator(); + while (e.MoveNext()) + { + vec.Add((Asn1Encodable)e.Current); + } + } + catch (IOException e) + { + throw new Exception("Could not read CRL issuer.", e); + } + vec.Add(dpName.Name); + names.Add(new GeneralName(X509Name.GetInstance(new DerSequence(vec)))); + } + bool matches = false; + // verify that one of the names in the IDP matches one + // of the names in the DP. + if (dp.DistributionPointName != null) + { + dpName = dp.DistributionPointName; + GeneralName[] genNames = null; + if (dpName.PointType == DistributionPointName.FullName) + { + genNames = GeneralNames.GetInstance(dpName.Name).GetNames(); + } + if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer) + { + if (dp.CrlIssuer != null) + { + genNames = dp.CrlIssuer.GetNames(); + } + else + { + genNames = new GeneralName[1]; + try + { + genNames[0] = new GeneralName( + PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert)); + } + catch (IOException e) + { + throw new Exception("Could not read certificate issuer.", e); + } + } + for (int j = 0; j < genNames.Length; j++) + { + IEnumerator e = Asn1Sequence.GetInstance(genNames[j].Name.ToAsn1Object()).GetEnumerator(); + Asn1EncodableVector vec = new Asn1EncodableVector(); + while (e.MoveNext()) + { + vec.Add((Asn1Encodable)e.Current); + } + vec.Add(dpName.Name); + genNames[j] = new GeneralName(X509Name.GetInstance(new DerSequence(vec))); + } + } + if (genNames != null) + { + for (int j = 0; j < genNames.Length; j++) + { + if (names.Contains(genNames[j])) + { + matches = true; + break; + } + } + } + if (!matches) + { + throw new Exception( + "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); + } + } + // verify that one of the names in + // the IDP matches one of the names in the cRLIssuer field of + // the DP + else + { + if (dp.CrlIssuer == null) + { + throw new Exception("Either the cRLIssuer or the distributionPoint field must " + + "be contained in DistributionPoint."); + } + GeneralName[] genNames = dp.CrlIssuer.GetNames(); + for (int j = 0; j < genNames.Length; j++) + { + if (names.Contains(genNames[j])) + { + matches = true; + break; + } + } + if (!matches) + { + throw new Exception( + "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); + } + } + } + BasicConstraints bc = null; + try + { + bc = BasicConstraints.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue( + (IX509Extension)cert, X509Extensions.BasicConstraints)); + } + catch (Exception e) + { + throw new Exception("Basic constraints extension could not be decoded.", e); + } + + //if (cert is X509Certificate) + { + // (b) (2) (ii) + if (idp.OnlyContainsUserCerts && ((bc != null) && bc.IsCA())) + { + throw new Exception("CA Cert CRL only contains user certificates."); + } + + // (b) (2) (iii) + if (idp.OnlyContainsCACerts && (bc == null || !bc.IsCA())) + { + throw new Exception("End CRL only contains CA certificates."); + } + } + + // (b) (2) (iv) + if (idp.OnlyContainsAttributeCerts) + { + throw new Exception("onlyContainsAttributeCerts boolean is asserted."); + } + } + } + + internal static void ProcessCertBC( + PkixCertPath certPath, + int index, + PkixNameConstraintValidator nameConstraintValidator) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + int n = certs.Count; + // i as defined in the algorithm description + int i = n - index; + // + // (b), (c) permitted and excluded subtree checking. + // + if (!(PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (i < n))) + { + X509Name principal = cert.SubjectDN; + Asn1InputStream aIn = new Asn1InputStream(principal.GetEncoded()); + Asn1Sequence dns; + + try + { + dns = DerSequence.GetInstance(aIn.ReadObject()); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Exception extracting subject name when checking subtrees.", e, certPath, index); + } + + try + { + nameConstraintValidator.CheckPermittedDN(dns); + nameConstraintValidator.CheckExcludedDN(dns); + } + catch (PkixNameConstraintValidatorException e) + { + throw new PkixCertPathValidatorException( + "Subtree check for certificate subject failed.", e, certPath, index); + } + + GeneralNames altName = null; + try + { + altName = GeneralNames.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.SubjectAlternativeName)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Subject alternative name extension could not be decoded.", e, certPath, index); + } + + IList emails = X509Name.GetInstance(dns).GetValueList(X509Name.EmailAddress); + foreach (string email in emails) + { + GeneralName emailAsGeneralName = new GeneralName(GeneralName.Rfc822Name, email); + try + { + nameConstraintValidator.checkPermitted(emailAsGeneralName); + nameConstraintValidator.checkExcluded(emailAsGeneralName); + } + catch (PkixNameConstraintValidatorException ex) + { + throw new PkixCertPathValidatorException( + "Subtree check for certificate subject alternative email failed.", ex, certPath, index); + } + } + if (altName != null) + { + GeneralName[] genNames = null; + try + { + genNames = altName.GetNames(); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Subject alternative name contents could not be decoded.", e, certPath, index); + } + foreach (GeneralName genName in genNames) + { + try + { + nameConstraintValidator.checkPermitted(genName); + nameConstraintValidator.checkExcluded(genName); + } + catch (PkixNameConstraintValidatorException e) + { + throw new PkixCertPathValidatorException( + "Subtree check for certificate subject alternative name failed.", e, certPath, index); + } + } + } + } + } + + internal static void PrepareNextCertA( + PkixCertPath certPath, + int index) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + // + // + // (a) check the policy mappings + // + Asn1Sequence pm = null; + try + { + pm = Asn1Sequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings)); + } + catch (Exception ex) + { + throw new PkixCertPathValidatorException( + "Policy mappings extension could not be decoded.", ex, certPath, index); + } + if (pm != null) + { + Asn1Sequence mappings = pm; + + for (int j = 0; j < mappings.Count; j++) + { + DerObjectIdentifier issuerDomainPolicy = null; + DerObjectIdentifier subjectDomainPolicy = null; + try + { + Asn1Sequence mapping = DerSequence.GetInstance(mappings[j]); + + issuerDomainPolicy = DerObjectIdentifier.GetInstance(mapping[0]); + subjectDomainPolicy = DerObjectIdentifier.GetInstance(mapping[1]); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Policy mappings extension contents could not be decoded.", e, certPath, index); + } + + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(issuerDomainPolicy.Id)) + throw new PkixCertPathValidatorException( + "IssuerDomainPolicy is anyPolicy", null, certPath, index); + + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(subjectDomainPolicy.Id)) + throw new PkixCertPathValidatorException( + "SubjectDomainPolicy is anyPolicy,", null, certPath, index); + } + } + } + + internal static PkixPolicyNode ProcessCertD( + PkixCertPath certPath, + int index, + ISet acceptablePolicies, + PkixPolicyNode validPolicyTree, + IList[] policyNodes, + int inhibitAnyPolicy) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + int n = certs.Count; + // i as defined in the algorithm description + int i = n - index; + // + // (d) policy Information checking against initial policy and + // policy mapping + // + Asn1Sequence certPolicies = null; + try + { + certPolicies = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Could not read certificate policies extension from certificate.", e, certPath, index); + } + if (certPolicies != null && validPolicyTree != null) + { + // + // (d) (1) + // + ISet pols = new HashSet(); + + foreach (Asn1Encodable ae in certPolicies) + { + PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object()); + DerObjectIdentifier pOid = pInfo.PolicyIdentifier; + + pols.Add(pOid.Id); + + if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(pOid.Id)) + { + ISet pq = null; + try + { + pq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers); + } + catch (PkixCertPathValidatorException ex) + { + throw new PkixCertPathValidatorException( + "Policy qualifier info set could not be build.", ex, certPath, index); + } + + bool match = PkixCertPathValidatorUtilities.ProcessCertD1i(i, policyNodes, pOid, pq); + + if (!match) + { + PkixCertPathValidatorUtilities.ProcessCertD1ii(i, policyNodes, pOid, pq); + } + } + } + + if (acceptablePolicies.IsEmpty || acceptablePolicies.Contains(Rfc3280CertPathUtilities.ANY_POLICY)) + { + acceptablePolicies.Clear(); + acceptablePolicies.AddAll(pols); + } + else + { + ISet t1 = new HashSet(); + + foreach (object o in acceptablePolicies) + { + if (pols.Contains(o)) + { + t1.Add(o); + } + } + acceptablePolicies.Clear(); + acceptablePolicies.AddAll(t1); + } + + // + // (d) (2) + // + if ((inhibitAnyPolicy > 0) || ((i < n) && PkixCertPathValidatorUtilities.IsSelfIssued(cert))) + { + foreach (Asn1Encodable ae in certPolicies) + { + PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object()); + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pInfo.PolicyIdentifier.Id)) + { + ISet _apq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers); + IList _nodes = policyNodes[i - 1]; + + for (int k = 0; k < _nodes.Count; k++) + { + PkixPolicyNode _node = (PkixPolicyNode)_nodes[k]; + + IEnumerator _policySetIter = _node.ExpectedPolicies.GetEnumerator(); + while (_policySetIter.MoveNext()) + { + object _tmp = _policySetIter.Current; + + string _policy; + if (_tmp is string) + { + _policy = (string)_tmp; + } + else if (_tmp is DerObjectIdentifier) + { + _policy = ((DerObjectIdentifier)_tmp).Id; + } + else + { + continue; + } + + bool _found = false; + + foreach (PkixPolicyNode _child in _node.Children) + { + if (_policy.Equals(_child.ValidPolicy)) + { + _found = true; + } + } + + if (!_found) + { + ISet _newChildExpectedPolicies = new HashSet(); + _newChildExpectedPolicies.Add(_policy); + + PkixPolicyNode _newChild = new PkixPolicyNode(Platform.CreateArrayList(), i, + _newChildExpectedPolicies, _node, _apq, _policy, false); + _node.AddChild(_newChild); + policyNodes[i].Add(_newChild); + } + } + } + break; + } + } + } + + PkixPolicyNode _validPolicyTree = validPolicyTree; + // + // (d) (3) + // + for (int j = (i - 1); j >= 0; j--) + { + IList nodes = policyNodes[j]; + + for (int k = 0; k < nodes.Count; k++) + { + PkixPolicyNode node = (PkixPolicyNode)nodes[k]; + if (!node.HasChildren) + { + _validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(_validPolicyTree, policyNodes, + node); + if (_validPolicyTree == null) + { + break; + } + } + } + } + + // + // d (4) + // + ISet criticalExtensionOids = cert.GetCriticalExtensionOids(); + + if (criticalExtensionOids != null) + { + bool critical = criticalExtensionOids.Contains(X509Extensions.CertificatePolicies.Id); + + IList nodes = policyNodes[i]; + for (int j = 0; j < nodes.Count; j++) + { + PkixPolicyNode node = (PkixPolicyNode)nodes[j]; + node.IsCritical = critical; + } + } + return _validPolicyTree; + } + return null; + } + + /** + * If the DP includes cRLIssuer, then verify that the issuer field in the + * complete CRL matches cRLIssuer in the DP and that the complete CRL + * contains an + * g distribution point extension with the indirectCRL + * boolean asserted. Otherwise, verify that the CRL issuer matches the + * certificate issuer. + * + * @param dp The distribution point. + * @param cert The certificate ot attribute certificate. + * @param crl The CRL for cert. + * @throws AnnotatedException if one of the above conditions does not apply or an error + * occurs. + */ + internal static void ProcessCrlB1( + DistributionPoint dp, + object cert, + X509Crl crl) + { + Asn1Object idp = PkixCertPathValidatorUtilities.GetExtensionValue( + crl, X509Extensions.IssuingDistributionPoint); + + bool isIndirect = false; + if (idp != null) + { + if (IssuingDistributionPoint.GetInstance(idp).IsIndirectCrl) + { + isIndirect = true; + } + } + byte[] issuerBytes = crl.IssuerDN.GetEncoded(); + + bool matchIssuer = false; + if (dp.CrlIssuer != null) + { + GeneralName[] genNames = dp.CrlIssuer.GetNames(); + for (int j = 0; j < genNames.Length; j++) + { + if (genNames[j].TagNo == GeneralName.DirectoryName) + { + try + { + if (Org.BouncyCastle.Utilities.Arrays.AreEqual(genNames[j].Name.ToAsn1Object().GetEncoded(), issuerBytes)) + { + matchIssuer = true; + } + } + catch (IOException e) + { + throw new Exception( + "CRL issuer information from distribution point cannot be decoded.", e); + } + } + } + if (matchIssuer && !isIndirect) + { + throw new Exception("Distribution point contains cRLIssuer field but CRL is not indirect."); + } + if (!matchIssuer) + { + throw new Exception("CRL issuer of CRL does not match CRL issuer of distribution point."); + } + } + else + { + if (crl.IssuerDN.Equivalent(PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert), true)) + { + matchIssuer = true; + } + } + if (!matchIssuer) + { + throw new Exception("Cannot find matching CRL issuer for certificate."); + } + } + + internal static ReasonsMask ProcessCrlD( + X509Crl crl, + DistributionPoint dp) + //throws AnnotatedException + { + IssuingDistributionPoint idp = null; + try + { + idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint)); + } + catch (Exception e) + { + throw new Exception("issuing distribution point extension could not be decoded.", e); + } + + // (d) (1) + if (idp != null && idp.OnlySomeReasons != null && dp.Reasons != null) + { + return new ReasonsMask(dp.Reasons.IntValue).Intersect(new ReasonsMask(idp.OnlySomeReasons + .IntValue)); + } + // (d) (4) + if ((idp == null || idp.OnlySomeReasons == null) && dp.Reasons == null) + { + return ReasonsMask.AllReasons; + } + + // (d) (2) and (d)(3) + + ReasonsMask dpReasons = null; + + if (dp.Reasons == null) + { + dpReasons = ReasonsMask.AllReasons; + } + else + { + dpReasons = new ReasonsMask(dp.Reasons.IntValue); + } + + ReasonsMask idpReasons = null; + + if (idp == null) + { + idpReasons = ReasonsMask.AllReasons; + } + else + { + idpReasons = new ReasonsMask(idp.OnlySomeReasons.IntValue); + } + + return dpReasons.Intersect(idpReasons); + } + + /** + * Obtain and validate the certification path for the complete CRL issuer. + * If a key usage extension is present in the CRL issuer's certificate, + * verify that the cRLSign bit is set. + * + * @param crl CRL which contains revocation information for the certificate + * cert. + * @param cert The attribute certificate or certificate to check if it is + * revoked. + * @param defaultCRLSignCert The issuer certificate of the certificate cert. + * @param defaultCRLSignKey The public key of the issuer certificate + * defaultCRLSignCert. + * @param paramsPKIX paramsPKIX PKIX parameters. + * @param certPathCerts The certificates on the certification path. + * @return A Set with all keys of possible CRL issuer + * certificates. + * @throws AnnotatedException if the CRL is not valid or the status cannot be checked or + * some error occurs. + */ + internal static ISet ProcessCrlF( + X509Crl crl, + object cert, + X509Certificate defaultCRLSignCert, + AsymmetricKeyParameter defaultCRLSignKey, + PkixParameters paramsPKIX, + IList certPathCerts) + { + // (f) + + // get issuer from CRL + X509CertStoreSelector selector = new X509CertStoreSelector(); + try + { + selector.Subject = crl.IssuerDN; + } + catch (IOException e) + { + throw new Exception( + "Subject criteria for certificate selector to find issuer certificate for CRL could not be set.", e); + } + + // get CRL signing certs + IList coll = Platform.CreateArrayList(); + + try + { + CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetStores())); + CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetAdditionalStores())); + } + catch (Exception e) + { + throw new Exception("Issuer certificate for CRL cannot be searched.", e); + } + + coll.Add(defaultCRLSignCert); + + IEnumerator cert_it = coll.GetEnumerator(); + + IList validCerts = Platform.CreateArrayList(); + IList validKeys = Platform.CreateArrayList(); + + while (cert_it.MoveNext()) + { + X509Certificate signingCert = (X509Certificate)cert_it.Current; + + /* + * CA of the certificate, for which this CRL is checked, has also + * signed CRL, so skip the path validation, because is already done + */ + if (signingCert.Equals(defaultCRLSignCert)) + { + validCerts.Add(signingCert); + validKeys.Add(defaultCRLSignKey); + continue; + } + try + { +// CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX"); + PkixCertPathBuilder builder = new PkixCertPathBuilder(); + selector = new X509CertStoreSelector(); + selector.Certificate = signingCert; + + PkixParameters temp = (PkixParameters)paramsPKIX.Clone(); + temp.SetTargetCertConstraints(selector); + + PkixBuilderParameters parameters = (PkixBuilderParameters) + PkixBuilderParameters.GetInstance(temp); + + /* + * if signingCert is placed not higher on the cert path a + * dependency loop results. CRL for cert is checked, but + * signingCert is needed for checking the CRL which is dependent + * on checking cert because it is higher in the cert path and so + * signing signingCert transitively. so, revocation is disabled, + * forgery attacks of the CRL are detected in this outer loop + * for all other it must be enabled to prevent forgery attacks + */ + if (certPathCerts.Contains(signingCert)) + { + parameters.IsRevocationEnabled = false; + } + else + { + parameters.IsRevocationEnabled = true; + } + IList certs = builder.Build(parameters).CertPath.Certificates; + validCerts.Add(signingCert); + validKeys.Add(PkixCertPathValidatorUtilities.GetNextWorkingKey(certs, 0)); + } + catch (PkixCertPathBuilderException e) + { + throw new Exception("Internal error.", e); + } + catch (PkixCertPathValidatorException e) + { + throw new Exception("Public key of issuer certificate of CRL could not be retrieved.", e); + } + //catch (Exception e) + //{ + // throw new Exception(e.Message); + //} + } + + ISet checkKeys = new HashSet(); + + Exception lastException = null; + for (int i = 0; i < validCerts.Count; i++) + { + X509Certificate signCert = (X509Certificate)validCerts[i]; + bool[] keyusage = signCert.GetKeyUsage(); + + if (keyusage != null && (keyusage.Length < 7 || !keyusage[CRL_SIGN])) + { + lastException = new Exception( + "Issuer certificate key usage extension does not permit CRL signing."); + } + else + { + checkKeys.Add(validKeys[i]); + } + } + + if ((checkKeys.Count == 0) && lastException == null) + { + throw new Exception("Cannot find a valid issuer certificate."); + } + if ((checkKeys.Count == 0) && lastException != null) + { + throw lastException; + } + + return checkKeys; + } + + internal static AsymmetricKeyParameter ProcessCrlG( + X509Crl crl, + ISet keys) + { + Exception lastException = null; + foreach (AsymmetricKeyParameter key in keys) + { + try + { + crl.Verify(key); + return key; + } + catch (Exception e) + { + lastException = e; + } + } + throw new Exception("Cannot verify CRL.", lastException); + } + + internal static X509Crl ProcessCrlH( + ISet deltaCrls, + AsymmetricKeyParameter key) + { + Exception lastException = null; + foreach (X509Crl crl in deltaCrls) + { + try + { + crl.Verify(key); + return crl; + } + catch (Exception e) + { + lastException = e; + } + } + if (lastException != null) + { + throw new Exception("Cannot verify delta CRL.", lastException); + } + return null; + } + + /** + * Checks a distribution point for revocation information for the + * certificate cert. + * + * @param dp The distribution point to consider. + * @param paramsPKIX PKIX parameters. + * @param cert Certificate to check if it is revoked. + * @param validDate The date when the certificate revocation status should be + * checked. + * @param defaultCRLSignCert The issuer certificate of the certificate cert. + * @param defaultCRLSignKey The public key of the issuer certificate + * defaultCRLSignCert. + * @param certStatus The current certificate revocation status. + * @param reasonMask The reasons mask which is already checked. + * @param certPathCerts The certificates of the certification path. + * @throws AnnotatedException if the certificate is revoked or the status cannot be checked + * or some error occurs. + */ + private static void CheckCrl( + DistributionPoint dp, + PkixParameters paramsPKIX, + X509Certificate cert, + DateTime validDate, + X509Certificate defaultCRLSignCert, + AsymmetricKeyParameter defaultCRLSignKey, + CertStatus certStatus, + ReasonsMask reasonMask, + IList certPathCerts) + //throws AnnotatedException + { + DateTime currentDate = DateTime.UtcNow; + + if (validDate.Ticks > currentDate.Ticks) + { + throw new Exception("Validation time is in future."); + } + + // (a) + /* + * We always get timely valid CRLs, so there is no step (a) (1). + * "locally cached" CRLs are assumed to be in getStore(), additional + * CRLs must be enabled in the ExtendedPKIXParameters and are in + * getAdditionalStore() + */ + + ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, cert, currentDate, paramsPKIX); + bool validCrlFound = false; + Exception lastException = null; + + IEnumerator crl_iter = crls.GetEnumerator(); + + while (crl_iter.MoveNext() && certStatus.Status == CertStatus.Unrevoked && !reasonMask.IsAllReasons) + { + try + { + X509Crl crl = (X509Crl)crl_iter.Current; + + // (d) + ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp); + + // (e) + /* + * The reasons mask is updated at the end, so only valid CRLs + * can update it. If this CRL does not contain new reasons it + * must be ignored. + */ + if (!interimReasonsMask.HasNewReasons(reasonMask)) + { + continue; + } + + // (f) + ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, cert, defaultCRLSignCert, defaultCRLSignKey, + paramsPKIX, certPathCerts); + // (g) + AsymmetricKeyParameter key = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys); + + X509Crl deltaCRL = null; + + if (paramsPKIX.IsUseDeltasEnabled) + { + // get delta CRLs + ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl); + // we only want one valid delta CRL + // (h) + deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, key); + } + + /* + * CRL must be be valid at the current time, not the validation + * time. If a certificate is revoked with reason keyCompromise, + * cACompromise, it can be used for forgery, also for the past. + * This reason may not be contained in older CRLs. + */ + + /* + * in the chain model signatures stay valid also after the + * certificate has been expired, so they do not have to be in + * the CRL validity time + */ + + if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel) + { + /* + * if a certificate has expired, but was revoked, it is not + * more in the CRL, so it would be regarded as valid if the + * first check is not done + */ + if (cert.NotAfter.Ticks < crl.ThisUpdate.Ticks) + { + throw new Exception("No valid CRL for current time found."); + } + } + + Rfc3280CertPathUtilities.ProcessCrlB1(dp, cert, crl); + + // (b) (2) + Rfc3280CertPathUtilities.ProcessCrlB2(dp, cert, crl); + + // (c) + Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX); + + // (i) + Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL, cert, certStatus, paramsPKIX); + + // (j) + Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, cert, certStatus); + + // (k) + if (certStatus.Status == CrlReason.RemoveFromCrl) + { + certStatus.Status = CertStatus.Unrevoked; + } + + // update reasons mask + reasonMask.AddReasons(interimReasonsMask); + + ISet criticalExtensions = crl.GetCriticalExtensionOids(); + + if (criticalExtensions != null) + { + criticalExtensions = new HashSet(criticalExtensions); + criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id); + criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id); + + if (!criticalExtensions.IsEmpty) + throw new Exception("CRL contains unsupported critical extensions."); + } + + if (deltaCRL != null) + { + criticalExtensions = deltaCRL.GetCriticalExtensionOids(); + if (criticalExtensions != null) + { + criticalExtensions = new HashSet(criticalExtensions); + criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id); + criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id); + + if (!criticalExtensions.IsEmpty) + throw new Exception("Delta CRL contains unsupported critical extension."); + } + } + + validCrlFound = true; + } + catch (Exception e) + { + lastException = e; + } + } + if (!validCrlFound) + { + throw lastException; + } + } + + /** + * Checks a certificate if it is revoked. + * + * @param paramsPKIX PKIX parameters. + * @param cert Certificate to check if it is revoked. + * @param validDate The date when the certificate revocation status should be + * checked. + * @param sign The issuer certificate of the certificate cert. + * @param workingPublicKey The public key of the issuer certificate sign. + * @param certPathCerts The certificates of the certification path. + * @throws AnnotatedException if the certificate is revoked or the status cannot be checked + * or some error occurs. + */ + protected static void CheckCrls( + PkixParameters paramsPKIX, + X509Certificate cert, + DateTime validDate, + X509Certificate sign, + AsymmetricKeyParameter workingPublicKey, + IList certPathCerts) + { + Exception lastException = null; + CrlDistPoint crldp = null; + + try + { + crldp = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CrlDistributionPoints)); + } + catch (Exception e) + { + throw new Exception("CRL distribution point extension could not be read.", e); + } + + try + { + PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX); + } + catch (Exception e) + { + throw new Exception( + "No additional CRL locations could be decoded from CRL distribution point extension.", e); + } + CertStatus certStatus = new CertStatus(); + ReasonsMask reasonsMask = new ReasonsMask(); + + bool validCrlFound = false; + + // for each distribution point + if (crldp != null) + { + DistributionPoint[] dps = null; + try + { + dps = crldp.GetDistributionPoints(); + } + catch (Exception e) + { + throw new Exception("Distribution points could not be read.", e); + } + if (dps != null) + { + for (int i = 0; i < dps.Length && certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons; i++) + { + PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone(); + try + { + CheckCrl(dps[i], paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts); + validCrlFound = true; + } + catch (Exception e) + { + lastException = e; + } + } + } + } + + /* + * If the revocation status has not been determined, repeat the process + * above with any available CRLs not specified in a distribution point + * but issued by the certificate issuer. + */ + + if (certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons) + { + try + { + /* + * assume a DP with both the reasons and the cRLIssuer fields + * omitted and a distribution point name of the certificate + * issuer. + */ + Asn1Object issuer = null; + try + { + issuer = new Asn1InputStream(cert.IssuerDN.GetEncoded()).ReadObject(); + } + catch (Exception e) + { + throw new Exception("Issuer from certificate for CRL could not be reencoded.", e); + } + DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames( + new GeneralName(GeneralName.DirectoryName, issuer))), null, null); + PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone(); + + CheckCrl(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, + certPathCerts); + + validCrlFound = true; + } + catch (Exception e) + { + lastException = e; + } + } + + if (!validCrlFound) + { + throw lastException; + } + if (certStatus.Status != CertStatus.Unrevoked) + { + // TODO This format is forced by the NistCertPath tests + string formattedDate = certStatus.RevocationDate.Value.ToString( + "G", new CultureInfo("en-us")); + string message = "Certificate revocation after " + formattedDate; + message += ", reason: " + CrlReasons[certStatus.Status]; + throw new Exception(message); + } + + if (!reasonsMask.IsAllReasons && certStatus.Status == CertStatus.Unrevoked) + { + certStatus.Status = CertStatus.Undetermined; + } + + if (certStatus.Status == CertStatus.Undetermined) + { + throw new Exception("Certificate status could not be determined."); + } + } + + internal static PkixPolicyNode PrepareCertB( + PkixCertPath certPath, + int index, + IList[] policyNodes, + PkixPolicyNode validPolicyTree, + int policyMapping) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + int n = certs.Count; + // i as defined in the algorithm description + int i = n - index; + // (b) + // + Asn1Sequence pm = null; + try + { + pm = (Asn1Sequence)Asn1Sequence.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings)); + } + catch (Exception ex) + { + throw new PkixCertPathValidatorException( + "Policy mappings extension could not be decoded.", ex, certPath, index); + } + PkixPolicyNode _validPolicyTree = validPolicyTree; + if (pm != null) + { + Asn1Sequence mappings = (Asn1Sequence)pm; + IDictionary m_idp = Platform.CreateHashtable(); + ISet s_idp = new HashSet(); + + for (int j = 0; j < mappings.Count; j++) + { + Asn1Sequence mapping = (Asn1Sequence) mappings[j]; + string id_p = ((DerObjectIdentifier) mapping[0]).Id; + string sd_p = ((DerObjectIdentifier) mapping[1]).Id; + ISet tmp; + + if (!m_idp.Contains(id_p)) + { + tmp = new HashSet(); + tmp.Add(sd_p); + m_idp[id_p] = tmp; + s_idp.Add(id_p); + } + else + { + tmp = (ISet)m_idp[id_p]; + tmp.Add(sd_p); + } + } + + IEnumerator it_idp = s_idp.GetEnumerator(); + while (it_idp.MoveNext()) + { + string id_p = (string)it_idp.Current; + + // + // (1) + // + if (policyMapping > 0) + { + bool idp_found = false; + IEnumerator nodes_i = policyNodes[i].GetEnumerator(); + + while (nodes_i.MoveNext()) + { + PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current; + if (node.ValidPolicy.Equals(id_p)) + { + idp_found = true; + node.ExpectedPolicies = (ISet)m_idp[id_p]; + break; + } + } + + if (!idp_found) + { + nodes_i = policyNodes[i].GetEnumerator(); + while (nodes_i.MoveNext()) + { + PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current; + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(node.ValidPolicy)) + { + ISet pq = null; + Asn1Sequence policies = null; + try + { + policies = (Asn1Sequence)PkixCertPathValidatorUtilities.GetExtensionValue(cert, + X509Extensions.CertificatePolicies); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Certificate policies extension could not be decoded.", e, certPath, index); + } + + foreach (Asn1Encodable ae in policies) + { + PolicyInformation pinfo = null; + try + { + pinfo = PolicyInformation.GetInstance(ae.ToAsn1Object()); + } + catch (Exception ex) + { + throw new PkixCertPathValidatorException( + "Policy information could not be decoded.", ex, certPath, index); + } + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id)) + { + try + { + pq = PkixCertPathValidatorUtilities + .GetQualifierSet(pinfo.PolicyQualifiers); + } + catch (PkixCertPathValidatorException ex) + { + throw new PkixCertPathValidatorException( + "Policy qualifier info set could not be decoded.", ex, certPath, + index); + } + break; + } + } + bool ci = false; + ISet critExtOids = cert.GetCriticalExtensionOids(); + if (critExtOids != null) + { + ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id); + } + + PkixPolicyNode p_node = (PkixPolicyNode)node.Parent; + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(p_node.ValidPolicy)) + { + PkixPolicyNode c_node = new PkixPolicyNode(Platform.CreateArrayList(), i, + (ISet)m_idp[id_p], p_node, pq, id_p, ci); + p_node.AddChild(c_node); + policyNodes[i].Add(c_node); + } + break; + } + } + } + + // + // (2) + // + } + else if (policyMapping <= 0) + { + foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i])) + { + if (node.ValidPolicy.Equals(id_p)) + { + node.Parent.RemoveChild(node); + + for (int k = i - 1; k >= 0; k--) + { + foreach (PkixPolicyNode node2 in Platform.CreateArrayList(policyNodes[k])) + { + if (!node2.HasChildren) + { + _validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode( + _validPolicyTree, policyNodes, node2); + + if (_validPolicyTree == null) + break; + } + } + } + } + } + } + } + } + return _validPolicyTree; + } + + internal static ISet[] ProcessCrlA1ii( + DateTime currentDate, + PkixParameters paramsPKIX, + X509Certificate cert, + X509Crl crl) + { + ISet deltaSet = new HashSet(); + X509CrlStoreSelector crlselect = new X509CrlStoreSelector(); + crlselect.CertificateChecking = cert; + + try + { + IList issuer = Platform.CreateArrayList(); + issuer.Add(crl.IssuerDN); + crlselect.Issuers = issuer; + } + catch (IOException e) + { + throw new Exception("Cannot extract issuer from CRL." + e, e); + } + + crlselect.CompleteCrlEnabled = true; + ISet completeSet = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate); + + if (paramsPKIX.IsUseDeltasEnabled) + { + // get delta CRL(s) + try + { + deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl)); + } + catch (Exception e) + { + throw new Exception("Exception obtaining delta CRLs.", e); + } + } + + return new ISet[]{ completeSet, deltaSet }; + } + + internal static ISet ProcessCrlA1i( + DateTime currentDate, + PkixParameters paramsPKIX, + X509Certificate cert, + X509Crl crl) + { + ISet deltaSet = new HashSet(); + if (paramsPKIX.IsUseDeltasEnabled) + { + CrlDistPoint freshestCRL = null; + try + { + freshestCRL = CrlDistPoint.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.FreshestCrl)); + } + catch (Exception e) + { + throw new Exception("Freshest CRL extension could not be decoded from certificate.", e); + } + + if (freshestCRL == null) + { + try + { + freshestCRL = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.FreshestCrl)); + } + catch (Exception e) + { + throw new Exception("Freshest CRL extension could not be decoded from CRL.", e); + } + } + if (freshestCRL != null) + { + try + { + PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(freshestCRL, paramsPKIX); + } + catch (Exception e) + { + throw new Exception( + "No new delta CRL locations could be added from Freshest CRL extension.", e); + } + // get delta CRL(s) + try + { + deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl)); + } + catch (Exception e) + { + throw new Exception("Exception obtaining delta CRLs.", e); + } + } + } + return deltaSet; + } + + internal static void ProcessCertF( + PkixCertPath certPath, + int index, + PkixPolicyNode validPolicyTree, + int explicitPolicy) + { + // + // (f) + // + if (explicitPolicy <= 0 && validPolicyTree == null) + { + throw new PkixCertPathValidatorException( + "No valid policy tree found when one expected.", null, certPath, index); + } + } + + internal static void ProcessCertA( + PkixCertPath certPath, + PkixParameters paramsPKIX, + int index, + AsymmetricKeyParameter workingPublicKey, + X509Name workingIssuerName, + X509Certificate sign) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + // + // (a) verify + // + try + { + // (a) (1) + // + cert.Verify(workingPublicKey); + } + catch (GeneralSecurityException e) + { + throw new PkixCertPathValidatorException("Could not validate certificate signature.", e, certPath, index); + } + + try + { + // (a) (2) + // + cert.CheckValidity(PkixCertPathValidatorUtilities + .GetValidCertDateFromValidityModel(paramsPKIX, certPath, index)); + } + catch (CertificateExpiredException e) + { + throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index); + } + catch (CertificateNotYetValidException e) + { + throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Could not validate time of certificate.", e, certPath, index); + } + + // + // (a) (3) + // + if (paramsPKIX.IsRevocationEnabled) + { + try + { + CheckCrls(paramsPKIX, cert, PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(paramsPKIX, + certPath, index), sign, workingPublicKey, certs); + } + catch (Exception e) + { + Exception cause = e.InnerException; + if (cause == null) + { + cause = e; + } + throw new PkixCertPathValidatorException(e.Message, cause, certPath, index); + } + } + + // + // (a) (4) name chaining + // + X509Name issuer = PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert); + if (!issuer.Equivalent(workingIssuerName, true)) + { + throw new PkixCertPathValidatorException("IssuerName(" + issuer + + ") does not match SubjectName(" + workingIssuerName + ") of signing certificate.", null, + certPath, index); + } + } + + internal static int PrepareNextCertI1( + PkixCertPath certPath, + int index, + int explicitPolicy) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + // + // (i) + // + Asn1Sequence pc = null; + try + { + pc = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Policy constraints extension cannot be decoded.", e, certPath, index); + } + + int tmpInt; + + if (pc != null) + { + IEnumerator policyConstraints = pc.GetEnumerator(); + + while (policyConstraints.MoveNext()) + { + try + { + Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current); + if (constraint.TagNo == 0) + { + tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue; + if (tmpInt < explicitPolicy) + { + return tmpInt; + } + break; + } + } + catch (ArgumentException e) + { + throw new PkixCertPathValidatorException( + "Policy constraints extension contents cannot be decoded.", e, certPath, index); + } + } + } + return explicitPolicy; + } + + internal static int PrepareNextCertI2( + PkixCertPath certPath, + int index, + int policyMapping) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (i) + // + Asn1Sequence pc = null; + try + { + pc = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Policy constraints extension cannot be decoded.", e, certPath, index); + } + + int tmpInt; + + if (pc != null) + { + IEnumerator policyConstraints = pc.GetEnumerator(); + + while (policyConstraints.MoveNext()) + { + try + { + Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current); + if (constraint.TagNo == 1) + { + tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue; + if (tmpInt < policyMapping) + { + return tmpInt; + } + break; + } + } + catch (ArgumentException e) + { + throw new PkixCertPathValidatorException( + "Policy constraints extension contents cannot be decoded.", e, certPath, index); + } + } + } + return policyMapping; + } + + internal static void PrepareNextCertG( + PkixCertPath certPath, + int index, + PkixNameConstraintValidator nameConstraintValidator) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (g) handle the name constraints extension + // + NameConstraints nc = null; + try + { + Asn1Sequence ncSeq = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.NameConstraints)); + if (ncSeq != null) + { + nc = new NameConstraints(ncSeq); + } + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Name constraints extension could not be decoded.", e, certPath, index); + } + if (nc != null) + { + // + // (g) (1) permitted subtrees + // + Asn1Sequence permitted = nc.PermittedSubtrees; + if (permitted != null) + { + try + { + nameConstraintValidator.IntersectPermittedSubtree(permitted); + } + catch (Exception ex) + { + throw new PkixCertPathValidatorException( + "Permitted subtrees cannot be build from name constraints extension.", ex, certPath, index); + } + } + + // + // (g) (2) excluded subtrees + // + Asn1Sequence excluded = nc.ExcludedSubtrees; + if (excluded != null) + { + IEnumerator e = excluded.GetEnumerator(); + try + { + while (e.MoveNext()) + { + GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current); + nameConstraintValidator.AddExcludedSubtree(subtree); + } + } + catch (Exception ex) + { + throw new PkixCertPathValidatorException( + "Excluded subtrees cannot be build from name constraints extension.", ex, certPath, index); + } + } + } + } + + internal static int PrepareNextCertJ( + PkixCertPath certPath, + int index, + int inhibitAnyPolicy) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (j) + // + DerInteger iap = null; + try + { + iap = DerInteger.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.InhibitAnyPolicy)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Inhibit any-policy extension cannot be decoded.", e, certPath, index); + } + + if (iap != null) + { + int _inhibitAnyPolicy = iap.Value.IntValue; + + if (_inhibitAnyPolicy < inhibitAnyPolicy) + return _inhibitAnyPolicy; + } + return inhibitAnyPolicy; + } + + internal static void PrepareNextCertK( + PkixCertPath certPath, + int index) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + // + // (k) + // + BasicConstraints bc = null; + try + { + bc = BasicConstraints.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath, + index); + } + if (bc != null) + { + if (!(bc.IsCA())) + throw new PkixCertPathValidatorException("Not a CA certificate"); + } + else + { + throw new PkixCertPathValidatorException("Intermediate certificate lacks BasicConstraints"); + } + } + + internal static int PrepareNextCertL( + PkixCertPath certPath, + int index, + int maxPathLength) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + // + // (l) + // + if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert)) + { + if (maxPathLength <= 0) + { + throw new PkixCertPathValidatorException("Max path length not greater than zero", null, certPath, index); + } + + return maxPathLength - 1; + } + return maxPathLength; + } + + internal static int PrepareNextCertM( + PkixCertPath certPath, + int index, + int maxPathLength) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (m) + // + BasicConstraints bc = null; + try + { + bc = BasicConstraints.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath, + index); + } + if (bc != null) + { + BigInteger _pathLengthConstraint = bc.PathLenConstraint; + + if (_pathLengthConstraint != null) + { + int _plc = _pathLengthConstraint.IntValue; + + if (_plc < maxPathLength) + { + return _plc; + } + } + } + return maxPathLength; + } + + internal static void PrepareNextCertN( + PkixCertPath certPath, + int index) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (n) + // + bool[] _usage = cert.GetKeyUsage(); + + if ((_usage != null) && !_usage[Rfc3280CertPathUtilities.KEY_CERT_SIGN]) + { + throw new PkixCertPathValidatorException( + "Issuer certificate keyusage extension is critical and does not permit key signing.", null, + certPath, index); + } + } + + internal static void PrepareNextCertO( + PkixCertPath certPath, + int index, + ISet criticalExtensions, + IList pathCheckers) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (o) + // + IEnumerator tmpIter = pathCheckers.GetEnumerator(); + while (tmpIter.MoveNext()) + { + try + { + ((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions); + } + catch (PkixCertPathValidatorException e) + { + throw new PkixCertPathValidatorException(e.Message, e.InnerException, certPath, index); + } + } + if (!criticalExtensions.IsEmpty) + { + throw new PkixCertPathValidatorException("Certificate has unsupported critical extension.", null, certPath, + index); + } + } + + internal static int PrepareNextCertH1( + PkixCertPath certPath, + int index, + int explicitPolicy) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (h) + // + if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert)) + { + // + // (1) + // + if (explicitPolicy != 0) + return explicitPolicy - 1; + } + return explicitPolicy; + } + + internal static int PrepareNextCertH2( + PkixCertPath certPath, + int index, + int policyMapping) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (h) + // + if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert)) + { + // + // (2) + // + if (policyMapping != 0) + return policyMapping - 1; + } + return policyMapping; + } + + + internal static int PrepareNextCertH3( + PkixCertPath certPath, + int index, + int inhibitAnyPolicy) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (h) + // + if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert)) + { + // + // (3) + // + if (inhibitAnyPolicy != 0) + return inhibitAnyPolicy - 1; + } + return inhibitAnyPolicy; + } + + internal static int WrapupCertA( + int explicitPolicy, + X509Certificate cert) + { + // + // (a) + // + if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (explicitPolicy != 0)) + { + explicitPolicy--; + } + return explicitPolicy; + } + + internal static int WrapupCertB( + PkixCertPath certPath, + int index, + int explicitPolicy) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (b) + // + int tmpInt; + Asn1Sequence pc = null; + try + { + pc = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Policy constraints could not be decoded.", e, certPath, index); + } + + if (pc != null) + { + IEnumerator policyConstraints = pc.GetEnumerator(); + + while (policyConstraints.MoveNext()) + { + Asn1TaggedObject constraint = (Asn1TaggedObject)policyConstraints.Current; + switch (constraint.TagNo) + { + case 0: + try + { + tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue; + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Policy constraints requireExplicitPolicy field could not be decoded.", e, certPath, + index); + } + if (tmpInt == 0) + { + return 0; + } + break; + } + } + } + return explicitPolicy; + } + + internal static void WrapupCertF( + PkixCertPath certPath, + int index, + IList pathCheckers, + ISet criticalExtensions) + //throws CertPathValidatorException + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + IEnumerator tmpIter = pathCheckers.GetEnumerator(); + + while (tmpIter.MoveNext()) + { + try + { + ((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions); + } + catch (PkixCertPathValidatorException e) + { + throw new PkixCertPathValidatorException("Additional certificate path checker failed.", e, certPath, + index); + } + } + + if (!criticalExtensions.IsEmpty) + { + throw new PkixCertPathValidatorException("Certificate has unsupported critical extension", + null, certPath, index); + } + } + + internal static PkixPolicyNode WrapupCertG( + PkixCertPath certPath, + PkixParameters paramsPKIX, + ISet userInitialPolicySet, + int index, + IList[] policyNodes, + PkixPolicyNode validPolicyTree, + ISet acceptablePolicies) + { + int n = certPath.Certificates.Count; + + // + // (g) + // + PkixPolicyNode intersection; + + // + // (g) (i) + // + if (validPolicyTree == null) + { + if (paramsPKIX.IsExplicitPolicyRequired) + { + throw new PkixCertPathValidatorException( + "Explicit policy requested but none available.", null, certPath, index); + } + intersection = null; + } + else if (PkixCertPathValidatorUtilities.IsAnyPolicy(userInitialPolicySet)) // (g) + // (ii) + { + if (paramsPKIX.IsExplicitPolicyRequired) + { + if (acceptablePolicies.IsEmpty) + { + throw new PkixCertPathValidatorException( + "Explicit policy requested but none available.", null, certPath, index); + } + else + { + ISet _validPolicyNodeSet = new HashSet(); + + for (int j = 0; j < policyNodes.Length; j++) + { + IList _nodeDepth = policyNodes[j]; + + for (int k = 0; k < _nodeDepth.Count; k++) + { + PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k]; + + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy)) + { + foreach (object o in _node.Children) + { + _validPolicyNodeSet.Add(o); + } + } + } + } + + foreach (PkixPolicyNode _node in _validPolicyNodeSet) + { + string _validPolicy = _node.ValidPolicy; + + if (!acceptablePolicies.Contains(_validPolicy)) + { + // TODO? + // validPolicyTree = + // removePolicyNode(validPolicyTree, policyNodes, + // _node); + } + } + if (validPolicyTree != null) + { + for (int j = (n - 1); j >= 0; j--) + { + IList nodes = policyNodes[j]; + + for (int k = 0; k < nodes.Count; k++) + { + PkixPolicyNode node = (PkixPolicyNode)nodes[k]; + if (!node.HasChildren) + { + validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, + policyNodes, node); + } + } + } + } + } + } + + intersection = validPolicyTree; + } + else + { + // + // (g) (iii) + // + // This implementation is not exactly same as the one described in + // RFC3280. + // However, as far as the validation result is concerned, both + // produce + // adequate result. The only difference is whether AnyPolicy is + // remain + // in the policy tree or not. + // + // (g) (iii) 1 + // + ISet _validPolicyNodeSet = new HashSet(); + + for (int j = 0; j < policyNodes.Length; j++) + { + IList _nodeDepth = policyNodes[j]; + + for (int k = 0; k < _nodeDepth.Count; k++) + { + PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k]; + + if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy)) + { + foreach (PkixPolicyNode _c_node in _node.Children) + { + if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(_c_node.ValidPolicy)) + { + _validPolicyNodeSet.Add(_c_node); + } + } + } + } + } + + // + // (g) (iii) 2 + // + IEnumerator _vpnsIter = _validPolicyNodeSet.GetEnumerator(); + while (_vpnsIter.MoveNext()) + { + PkixPolicyNode _node = (PkixPolicyNode)_vpnsIter.Current; + string _validPolicy = _node.ValidPolicy; + + if (!userInitialPolicySet.Contains(_validPolicy)) + { + validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes, _node); + } + } + + // + // (g) (iii) 4 + // + if (validPolicyTree != null) + { + for (int j = (n - 1); j >= 0; j--) + { + IList nodes = policyNodes[j]; + + for (int k = 0; k < nodes.Count; k++) + { + PkixPolicyNode node = (PkixPolicyNode)nodes[k]; + if (!node.HasChildren) + { + validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes, + node); + } + } + } + } + + intersection = validPolicyTree; + } + return intersection; + } + + /** + * If use-deltas is set, verify the issuer and scope of the delta CRL. + * + * @param deltaCRL The delta CRL. + * @param completeCRL The complete CRL. + * @param pkixParams The PKIX paramaters. + * @throws AnnotatedException if an exception occurs. + */ + internal static void ProcessCrlC( + X509Crl deltaCRL, + X509Crl completeCRL, + PkixParameters pkixParams) + { + if (deltaCRL == null) + return; + + IssuingDistributionPoint completeidp = null; + try + { + completeidp = IssuingDistributionPoint.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint)); + } + catch (Exception e) + { + throw new Exception("000 Issuing distribution point extension could not be decoded.", e); + } + + if (pkixParams.IsUseDeltasEnabled) + { + // (c) (1) + if (!deltaCRL.IssuerDN.Equivalent(completeCRL.IssuerDN, true)) + throw new Exception("Complete CRL issuer does not match delta CRL issuer."); + + // (c) (2) + IssuingDistributionPoint deltaidp = null; + try + { + deltaidp = IssuingDistributionPoint.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(deltaCRL, X509Extensions.IssuingDistributionPoint)); + } + catch (Exception e) + { + throw new Exception( + "Issuing distribution point extension from delta CRL could not be decoded.", e); + } + + if (!Platform.Equals(completeidp, deltaidp)) + { + throw new Exception( + "Issuing distribution point extension from delta CRL and complete CRL does not match."); + } + + // (c) (3) + Asn1Object completeKeyIdentifier = null; + try + { + completeKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue( + completeCRL, X509Extensions.AuthorityKeyIdentifier); + } + catch (Exception e) + { + throw new Exception( + "Authority key identifier extension could not be extracted from complete CRL.", e); + } + + Asn1Object deltaKeyIdentifier = null; + try + { + deltaKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue( + deltaCRL, X509Extensions.AuthorityKeyIdentifier); + } + catch (Exception e) + { + throw new Exception( + "Authority key identifier extension could not be extracted from delta CRL.", e); + } + + if (completeKeyIdentifier == null) + throw new Exception("CRL authority key identifier is null."); + + if (deltaKeyIdentifier == null) + throw new Exception("Delta CRL authority key identifier is null."); + + if (!completeKeyIdentifier.Equals(deltaKeyIdentifier)) + { + throw new Exception( + "Delta CRL authority key identifier does not match complete CRL authority key identifier."); + } + } + } + + internal static void ProcessCrlI( + DateTime validDate, + X509Crl deltacrl, + object cert, + CertStatus certStatus, + PkixParameters pkixParams) + { + if (pkixParams.IsUseDeltasEnabled && deltacrl != null) + { + PkixCertPathValidatorUtilities.GetCertStatus(validDate, deltacrl, cert, certStatus); + } + } + + internal static void ProcessCrlJ( + DateTime validDate, + X509Crl completecrl, + object cert, + CertStatus certStatus) + { + if (certStatus.Status == CertStatus.Unrevoked) + { + PkixCertPathValidatorUtilities.GetCertStatus(validDate, completecrl, cert, certStatus); + } + } + + internal static PkixPolicyNode ProcessCertE( + PkixCertPath certPath, + int index, + PkixPolicyNode validPolicyTree) + { + IList certs = certPath.Certificates; + X509Certificate cert = (X509Certificate)certs[index]; + + // + // (e) + // + Asn1Sequence certPolicies = null; + try + { + certPolicies = DerSequence.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException("Could not read certificate policies extension from certificate.", + e, certPath, index); + } + if (certPolicies == null) + { + validPolicyTree = null; + } + return validPolicyTree; + } + + internal static readonly string[] CrlReasons = new string[] + { + "unspecified", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "unknown", + "removeFromCRL", + "privilegeWithdrawn", + "aACompromise" + }; + } +} diff --git a/crypto/src/pkix/Rfc3281CertPathUtilities.cs b/crypto/src/pkix/Rfc3281CertPathUtilities.cs new file mode 100644 index 000000000..bda2aa737 --- /dev/null +++ b/crypto/src/pkix/Rfc3281CertPathUtilities.cs @@ -0,0 +1,608 @@ +using System; +using System.Collections; +using System.Globalization; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Pkix +{ + internal class Rfc3281CertPathUtilities + { + internal static void ProcessAttrCert7( + IX509AttributeCertificate attrCert, + PkixCertPath certPath, + PkixCertPath holderCertPath, + PkixParameters pkixParams) + { + // TODO: + // AA Controls + // Attribute encryption + // Proxy + ISet critExtOids = attrCert.GetCriticalExtensionOids(); + + // 7.1 + // process extensions + + // target information checked in step 6 / X509AttributeCertStoreSelector + if (critExtOids.Contains(X509Extensions.TargetInformation.Id)) + { + try + { + TargetInformation.GetInstance(PkixCertPathValidatorUtilities + .GetExtensionValue(attrCert, X509Extensions.TargetInformation)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Target information extension could not be read.", e); + } + } + critExtOids.Remove(X509Extensions.TargetInformation.Id); + foreach (PkixAttrCertChecker checker in pkixParams.GetAttrCertCheckers()) + { + checker.Check(attrCert, certPath, holderCertPath, critExtOids); + } + if (!critExtOids.IsEmpty) + { + throw new PkixCertPathValidatorException( + "Attribute certificate contains unsupported critical extensions: " + + critExtOids); + } + } + + /** + * Checks if an attribute certificate is revoked. + * + * @param attrCert Attribute certificate to check if it is revoked. + * @param paramsPKIX PKIX parameters. + * @param issuerCert The issuer certificate of the attribute certificate + * attrCert. + * @param validDate The date when the certificate revocation status should + * be checked. + * @param certPathCerts The certificates of the certification path to be + * checked. + * + * @throws CertPathValidatorException if the certificate is revoked or the + * status cannot be checked or some error occurs. + */ + internal static void CheckCrls( + IX509AttributeCertificate attrCert, + PkixParameters paramsPKIX, + X509Certificate issuerCert, + DateTime validDate, + IList certPathCerts) + { + if (paramsPKIX.IsRevocationEnabled) + { + // check if revocation is available + if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) == null) + { + CrlDistPoint crldp = null; + try + { + crldp = CrlDistPoint.GetInstance( + PkixCertPathValidatorUtilities.GetExtensionValue( + attrCert, X509Extensions.CrlDistributionPoints)); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "CRL distribution point extension could not be read.", e); + } + try + { + PkixCertPathValidatorUtilities + .AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "No additional CRL locations could be decoded from CRL distribution point extension.", e); + } + CertStatus certStatus = new CertStatus(); + ReasonsMask reasonsMask = new ReasonsMask(); + + Exception lastException = null; + bool validCrlFound = false; + // for each distribution point + if (crldp != null) + { + DistributionPoint[] dps = null; + try + { + dps = crldp.GetDistributionPoints(); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Distribution points could not be read.", e); + } + try + { + for (int i = 0; i < dps.Length + && certStatus.Status == CertStatus.Unrevoked + && !reasonsMask.IsAllReasons; i++) + { + PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX + .Clone(); + CheckCrl(dps[i], attrCert, paramsPKIXClone, + validDate, issuerCert, certStatus, reasonsMask, + certPathCerts); + validCrlFound = true; + } + } + catch (Exception e) + { + lastException = new Exception( + "No valid CRL for distribution point found.", e); + } + } + + /* + * If the revocation status has not been determined, repeat the + * process above with any available CRLs not specified in a + * distribution point but issued by the certificate issuer. + */ + + if (certStatus.Status == CertStatus.Unrevoked + && !reasonsMask.IsAllReasons) + { + try + { + /* + * assume a DP with both the reasons and the cRLIssuer + * fields omitted and a distribution point name of the + * certificate issuer. + */ + Asn1Object issuer = null; + try + { + issuer = new Asn1InputStream( + attrCert.Issuer.GetPrincipals()[0].GetEncoded()).ReadObject(); + } + catch (Exception e) + { + throw new Exception( + "Issuer from certificate for CRL could not be reencoded.", + e); + } + DistributionPoint dp = new DistributionPoint( + new DistributionPointName(0, new GeneralNames( + new GeneralName(GeneralName.DirectoryName, issuer))), null, null); + PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX.Clone(); + CheckCrl(dp, attrCert, paramsPKIXClone, validDate, + issuerCert, certStatus, reasonsMask, certPathCerts); + validCrlFound = true; + } + catch (Exception e) + { + lastException = new Exception( + "No valid CRL for distribution point found.", e); + } + } + + if (!validCrlFound) + { + throw new PkixCertPathValidatorException( + "No valid CRL found.", lastException); + } + if (certStatus.Status != CertStatus.Unrevoked) + { + // TODO This format is forced by the NistCertPath tests + string formattedDate = certStatus.RevocationDate.Value.ToString( + "G", new CultureInfo("en-us")); + string message = "Attribute certificate revocation after " + + formattedDate; + message += ", reason: " + + Rfc3280CertPathUtilities.CrlReasons[certStatus.Status]; + throw new PkixCertPathValidatorException(message); + } + if (!reasonsMask.IsAllReasons + && certStatus.Status == CertStatus.Unrevoked) + { + certStatus.Status = CertStatus.Undetermined; + } + if (certStatus.Status == CertStatus.Undetermined) + { + throw new PkixCertPathValidatorException( + "Attribute certificate status could not be determined."); + } + + } + else + { + if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null + || attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null) + { + throw new PkixCertPathValidatorException( + "No rev avail extension is set, but also an AC revocation pointer."); + } + } + } + } + + internal static void AdditionalChecks( + IX509AttributeCertificate attrCert, + PkixParameters pkixParams) + { + // 1 + foreach (string oid in pkixParams.GetProhibitedACAttributes()) + { + if (attrCert.GetAttributes(oid) != null) + { + throw new PkixCertPathValidatorException( + "Attribute certificate contains prohibited attribute: " + + oid + "."); + } + } + foreach (string oid in pkixParams.GetNecessaryACAttributes()) + { + if (attrCert.GetAttributes(oid) == null) + { + throw new PkixCertPathValidatorException( + "Attribute certificate does not contain necessary attribute: " + + oid + "."); + } + } + } + + internal static void ProcessAttrCert5( + IX509AttributeCertificate attrCert, + PkixParameters pkixParams) + { + try + { + attrCert.CheckValidity(PkixCertPathValidatorUtilities.GetValidDate(pkixParams)); + } + catch (CertificateExpiredException e) + { + throw new PkixCertPathValidatorException( + "Attribute certificate is not valid.", e); + } + catch (CertificateNotYetValidException e) + { + throw new PkixCertPathValidatorException( + "Attribute certificate is not valid.", e); + } + } + + internal static void ProcessAttrCert4( + X509Certificate acIssuerCert, + PkixParameters pkixParams) + { + ISet set = pkixParams.GetTrustedACIssuers(); + bool trusted = false; + foreach (TrustAnchor anchor in set) + { + IDictionary symbols = X509Name.RFC2253Symbols; + if (acIssuerCert.SubjectDN.ToString(false, symbols).Equals(anchor.CAName) + || acIssuerCert.Equals(anchor.TrustedCert)) + { + trusted = true; + } + } + if (!trusted) + { + throw new PkixCertPathValidatorException( + "Attribute certificate issuer is not directly trusted."); + } + } + + internal static void ProcessAttrCert3( + X509Certificate acIssuerCert, + PkixParameters pkixParams) + { + if (acIssuerCert.GetKeyUsage() != null + && (!acIssuerCert.GetKeyUsage()[0] && !acIssuerCert.GetKeyUsage()[1])) + { + throw new PkixCertPathValidatorException( + "Attribute certificate issuer public key cannot be used to validate digital signatures."); + } + if (acIssuerCert.GetBasicConstraints() != -1) + { + throw new PkixCertPathValidatorException( + "Attribute certificate issuer is also a public key certificate issuer."); + } + } + + internal static PkixCertPathValidatorResult ProcessAttrCert2( + PkixCertPath certPath, + PkixParameters pkixParams) + { + PkixCertPathValidator validator = new PkixCertPathValidator(); + + try + { + return validator.Validate(certPath, pkixParams); + } + catch (PkixCertPathValidatorException e) + { + throw new PkixCertPathValidatorException( + "Certification path for issuer certificate of attribute certificate could not be validated.", + e); + } + } + + /** + * Searches for a holder public key certificate and verifies its + * certification path. + * + * @param attrCert the attribute certificate. + * @param pkixParams The PKIX parameters. + * @return The certificate path of the holder certificate. + * @throws Exception if + *
      + *
    • no public key certificate can be found although holder + * information is given by an entity name or a base certificate + * ID
    • + *
    • support classes cannot be created
    • + *
    • no certification path for the public key certificate can + * be built
    • + *
    + */ + internal static PkixCertPath ProcessAttrCert1( + IX509AttributeCertificate attrCert, + PkixParameters pkixParams) + { + PkixCertPathBuilderResult result = null; + // find holder PKCs + ISet holderPKCs = new HashSet(); + if (attrCert.Holder.GetIssuer() != null) + { + X509CertStoreSelector selector = new X509CertStoreSelector(); + selector.SerialNumber = attrCert.Holder.SerialNumber; + X509Name[] principals = attrCert.Holder.GetIssuer(); + for (int i = 0; i < principals.Length; i++) + { + try + { +// if (principals[i] is X500Principal) + { + selector.Issuer = principals[i]; + } + holderPKCs.AddAll(PkixCertPathValidatorUtilities + .FindCertificates(selector, pkixParams.GetStores())); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Public key certificate for attribute certificate cannot be searched.", + e); + } + } + if (holderPKCs.IsEmpty) + { + throw new PkixCertPathValidatorException( + "Public key certificate specified in base certificate ID for attribute certificate cannot be found."); + } + } + if (attrCert.Holder.GetEntityNames() != null) + { + X509CertStoreSelector selector = new X509CertStoreSelector(); + X509Name[] principals = attrCert.Holder.GetEntityNames(); + for (int i = 0; i < principals.Length; i++) + { + try + { +// if (principals[i] is X500Principal) + { + selector.Issuer = principals[i]; + } + holderPKCs.AddAll(PkixCertPathValidatorUtilities + .FindCertificates(selector, pkixParams.GetStores())); + } + catch (Exception e) + { + throw new PkixCertPathValidatorException( + "Public key certificate for attribute certificate cannot be searched.", + e); + } + } + if (holderPKCs.IsEmpty) + { + throw new PkixCertPathValidatorException( + "Public key certificate specified in entity name for attribute certificate cannot be found."); + } + } + + // verify cert paths for PKCs + PkixBuilderParameters parameters = (PkixBuilderParameters) + PkixBuilderParameters.GetInstance(pkixParams); + + PkixCertPathValidatorException lastException = null; + foreach (X509Certificate cert in holderPKCs) + { + X509CertStoreSelector selector = new X509CertStoreSelector(); + selector.Certificate = cert; + parameters.SetTargetConstraints(selector); + + PkixCertPathBuilder builder = new PkixCertPathBuilder(); + + try + { + result = builder.Build(PkixBuilderParameters.GetInstance(parameters)); + } + catch (PkixCertPathBuilderException e) + { + lastException = new PkixCertPathValidatorException( + "Certification path for public key certificate of attribute certificate could not be build.", + e); + } + } + if (lastException != null) + { + throw lastException; + } + return result.CertPath; + } + + /** + * + * Checks a distribution point for revocation information for the + * certificate attrCert. + * + * @param dp The distribution point to consider. + * @param attrCert The attribute certificate which should be checked. + * @param paramsPKIX PKIX parameters. + * @param validDate The date when the certificate revocation status should + * be checked. + * @param issuerCert Certificate to check if it is revoked. + * @param reasonMask The reasons mask which is already checked. + * @param certPathCerts The certificates of the certification path to be + * checked. + * @throws Exception if the certificate is revoked or the status + * cannot be checked or some error occurs. + */ + private static void CheckCrl( + DistributionPoint dp, + IX509AttributeCertificate attrCert, + PkixParameters paramsPKIX, + DateTime validDate, + X509Certificate issuerCert, + CertStatus certStatus, + ReasonsMask reasonMask, + IList certPathCerts) + { + /* + * 4.3.6 No Revocation Available + * + * The noRevAvail extension, defined in [X.509-2000], allows an AC + * issuer to indicate that no revocation information will be made + * available for this AC. + */ + if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) != null) + { + return; + } + + DateTime currentDate = DateTime.UtcNow; + if (validDate.CompareTo(currentDate) > 0) + { + throw new Exception("Validation time is in future."); + } + + // (a) + /* + * We always get timely valid CRLs, so there is no step (a) (1). + * "locally cached" CRLs are assumed to be in getStore(), additional + * CRLs must be enabled in the ExtendedPkixParameters and are in + * getAdditionalStore() + */ + ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, attrCert, + currentDate, paramsPKIX); + bool validCrlFound = false; + Exception lastException = null; + + IEnumerator crl_iter = crls.GetEnumerator(); + + while (crl_iter.MoveNext() + && certStatus.Status == CertStatus.Unrevoked + && !reasonMask.IsAllReasons) + { + try + { + X509Crl crl = (X509Crl) crl_iter.Current; + + // (d) + ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp); + + // (e) + /* + * The reasons mask is updated at the end, so only valid CRLs + * can update it. If this CRL does not contain new reasons it + * must be ignored. + */ + if (!interimReasonsMask.HasNewReasons(reasonMask)) + { + continue; + } + + // (f) + ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, attrCert, + null, null, paramsPKIX, certPathCerts); + // (g) + AsymmetricKeyParameter pubKey = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys); + + X509Crl deltaCRL = null; + + if (paramsPKIX.IsUseDeltasEnabled) + { + // get delta CRLs + ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls( + currentDate, paramsPKIX, crl); + // we only want one valid delta CRL + // (h) + deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, pubKey); + } + + /* + * CRL must be be valid at the current time, not the validation + * time. If a certificate is revoked with reason keyCompromise, + * cACompromise, it can be used for forgery, also for the past. + * This reason may not be contained in older CRLs. + */ + + /* + * in the chain model signatures stay valid also after the + * certificate has been expired, so they do not have to be in + * the CRL vality time + */ + if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel) + { + /* + * if a certificate has expired, but was revoked, it is not + * more in the CRL, so it would be regarded as valid if the + * first check is not done + */ + if (attrCert.NotAfter.CompareTo(crl.ThisUpdate) < 0) + { + throw new Exception( + "No valid CRL for current time found."); + } + } + + Rfc3280CertPathUtilities.ProcessCrlB1(dp, attrCert, crl); + + // (b) (2) + Rfc3280CertPathUtilities.ProcessCrlB2(dp, attrCert, crl); + + // (c) + Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX); + + // (i) + Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL, + attrCert, certStatus, paramsPKIX); + + // (j) + Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, attrCert, + certStatus); + + // (k) + if (certStatus.Status == CrlReason.RemoveFromCrl) + { + certStatus.Status = CertStatus.Unrevoked; + } + + // update reasons mask + reasonMask.AddReasons(interimReasonsMask); + validCrlFound = true; + } + catch (Exception e) + { + lastException = e; + } + } + if (!validCrlFound) + { + throw lastException; + } + } + } +} diff --git a/crypto/src/pkix/TrustAnchor.cs b/crypto/src/pkix/TrustAnchor.cs new file mode 100644 index 000000000..22078baf2 --- /dev/null +++ b/crypto/src/pkix/TrustAnchor.cs @@ -0,0 +1,259 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkix +{ + /// + /// A trust anchor or most-trusted Certification Authority (CA). + /// + /// This class represents a "most-trusted CA", which is used as a trust anchor + /// for validating X.509 certification paths. A most-trusted CA includes the + /// public key of the CA, the CA's name, and any constraints upon the set of + /// paths which may be validated using this key. These parameters can be + /// specified in the form of a trusted X509Certificate or as individual + /// parameters. + /// + public class TrustAnchor + { + private readonly AsymmetricKeyParameter pubKey; + private readonly string caName; + private readonly X509Name caPrincipal; + private readonly X509Certificate trustedCert; + private byte[] ncBytes; + private NameConstraints nc; + + /// + /// Creates an instance of TrustAnchor with the specified X509Certificate and + /// optional name constraints, which are intended to be used as additional + /// constraints when validating an X.509 certification path. + /// The name constraints are specified as a byte array. This byte array + /// should contain the DER encoded form of the name constraints, as they + /// would appear in the NameConstraints structure defined in RFC 2459 and + /// X.509. The ASN.1 definition of this structure appears below. + /// + ///
    +	    ///	NameConstraints ::= SEQUENCE {
    +	    ///		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
    +	    ///		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
    +	    ///	   
    +        /// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
    +        /// 
    +        ///		GeneralSubtree ::= SEQUENCE {
    +        ///		base                    GeneralName,
    +        ///		minimum         [0]     BaseDistance DEFAULT 0,
    +        ///		maximum         [1]     BaseDistance OPTIONAL }
    +        ///		
    +        ///		BaseDistance ::= INTEGER (0..MAX)
    +		///
    +		///		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}
    +		///	
    + /// + /// Note that the name constraints byte array supplied is cloned to protect + /// against subsequent modifications. + ///
    + /// a trusted X509Certificate + /// a byte array containing the ASN.1 DER encoding of a + /// NameConstraints extension to be used for checking name + /// constraints. Only the value of the extension is included, not + /// the OID or criticality flag. Specify null to omit the + /// parameter. + /// if the specified X509Certificate is null + public TrustAnchor( + X509Certificate trustedCert, + byte[] nameConstraints) + { + if (trustedCert == null) + throw new ArgumentNullException("trustedCert"); + + this.trustedCert = trustedCert; + this.pubKey = null; + this.caName = null; + this.caPrincipal = null; + setNameConstraints(nameConstraints); + } + + /// + /// Creates an instance of TrustAnchor where the + /// most-trusted CA is specified as an X500Principal and public key. + /// + /// + ///

    + /// Name constraints are an optional parameter, and are intended to be used + /// as additional constraints when validating an X.509 certification path. + ///

    + /// The name constraints are specified as a byte array. This byte array + /// contains the DER encoded form of the name constraints, as they + /// would appear in the NameConstraints structure defined in RFC 2459 + /// and X.509. The ASN.1 notation for this structure is supplied in the + /// documentation for the other constructors. + ///

    + /// Note that the name constraints byte array supplied here is cloned to + /// protect against subsequent modifications. + ///

    + ///
    + /// the name of the most-trusted CA as X509Name + /// the public key of the most-trusted CA + /// + /// a byte array containing the ASN.1 DER encoding of a NameConstraints extension to + /// be used for checking name constraints. Only the value of the extension is included, + /// not the OID or criticality flag. Specify null to omit the parameter. + /// + /// + /// if caPrincipal or pubKey is null + /// + public TrustAnchor( + X509Name caPrincipal, + AsymmetricKeyParameter pubKey, + byte[] nameConstraints) + { + if (caPrincipal == null) + throw new ArgumentNullException("caPrincipal"); + if (pubKey == null) + throw new ArgumentNullException("pubKey"); + + this.trustedCert = null; + this.caPrincipal = caPrincipal; + this.caName = caPrincipal.ToString(); + this.pubKey = pubKey; + setNameConstraints(nameConstraints); + } + + /// + /// Creates an instance of TrustAnchor where the most-trusted + /// CA is specified as a distinguished name and public key. Name constraints + /// are an optional parameter, and are intended to be used as additional + /// constraints when validating an X.509 certification path. + ///
    + /// The name constraints are specified as a byte array. This byte array + /// contains the DER encoded form of the name constraints, as they would + /// appear in the NameConstraints structure defined in RFC 2459 and X.509. + ///
    + /// the X.500 distinguished name of the most-trusted CA in RFC + /// 2253 string format + /// the public key of the most-trusted CA + /// a byte array containing the ASN.1 DER encoding of a + /// NameConstraints extension to be used for checking name + /// constraints. Only the value of the extension is included, not + /// the OID or criticality flag. Specify null to omit the + /// parameter. + /// throws NullPointerException, IllegalArgumentException + public TrustAnchor( + string caName, + AsymmetricKeyParameter pubKey, + byte[] nameConstraints) + { + if (caName == null) + throw new ArgumentNullException("caName"); + if (pubKey == null) + throw new ArgumentNullException("pubKey"); + if (caName.Length == 0) + throw new ArgumentException("caName can not be an empty string"); + + this.caPrincipal = new X509Name(caName); + this.pubKey = pubKey; + this.caName = caName; + this.trustedCert = null; + setNameConstraints(nameConstraints); + } + + /// + /// Returns the most-trusted CA certificate. + /// + public X509Certificate TrustedCert + { + get { return this.trustedCert; } + } + + /// + /// Returns the name of the most-trusted CA as an X509Name. + /// + public X509Name CA + { + get { return this.caPrincipal; } + } + + /// + /// Returns the name of the most-trusted CA in RFC 2253 string format. + /// + public string CAName + { + get { return this.caName; } + } + + /// + /// Returns the public key of the most-trusted CA. + /// + public AsymmetricKeyParameter CAPublicKey + { + get { return this.pubKey; } + } + + /// + /// Decode the name constraints and clone them if not null. + /// + private void setNameConstraints( + byte[] bytes) + { + if (bytes == null) + { + ncBytes = null; + nc = null; + } + else + { + ncBytes = (byte[]) bytes.Clone(); + // validate DER encoding + //nc = new NameConstraintsExtension(Boolean.FALSE, bytes); + nc = NameConstraints.GetInstance(Asn1Object.FromByteArray(bytes)); + } + } + + public byte[] GetNameConstraints + { + get { return Arrays.Clone(ncBytes); } + } + + /// + /// Returns a formatted string describing the TrustAnchor. + /// + /// a formatted string describing the TrustAnchor + public override string ToString() + { + // TODO Some of the sub-objects might not implement ToString() properly + string nl = Platform.NewLine; + StringBuilder sb = new StringBuilder(); + sb.Append("["); + sb.Append(nl); + if (this.pubKey != null) + { + sb.Append(" Trusted CA Public Key: ").Append(this.pubKey).Append(nl); + sb.Append(" Trusted CA Issuer Name: ").Append(this.caName).Append(nl); + } + else + { + sb.Append(" Trusted CA cert: ").Append(this.TrustedCert).Append(nl); + } + if (nc != null) + { + sb.Append(" Name Constraints: ").Append(nc).Append(nl); + } + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/crypto/src/security/AgreementUtilities.cs b/crypto/src/security/AgreementUtilities.cs new file mode 100644 index 000000000..4c61ac354 --- /dev/null +++ b/crypto/src/security/AgreementUtilities.cs @@ -0,0 +1,105 @@ +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Agreement.Kdf; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Utility class for creating IBasicAgreement objects from their names/Oids + /// + public sealed class AgreementUtilities + { + private AgreementUtilities() + { + } + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + //private static readonly IDictionary oids = Platform.CreateHashtable(); + + static AgreementUtilities() + { + //algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?; + algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF"; + algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF"; + } + + public static IBasicAgreement GetBasicAgreement( + DerObjectIdentifier oid) + { + return GetBasicAgreement(oid.Id); + } + + public static IBasicAgreement GetBasicAgreement( + string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + string mechanism = (string) algorithms[upper]; + + if (mechanism == null) + { + mechanism = upper; + } + + if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN") + return new DHBasicAgreement(); + + if (mechanism == "ECDH") + return new ECDHBasicAgreement(); + + if (mechanism == "ECDHC") + return new ECDHCBasicAgreement(); + + if (mechanism == "ECMQV") + return new ECMqvBasicAgreement(); + + throw new SecurityUtilityException("Basic Agreement " + algorithm + " not recognised."); + } + + public static IBasicAgreement GetBasicAgreementWithKdf( + DerObjectIdentifier oid, + string wrapAlgorithm) + { + return GetBasicAgreementWithKdf(oid.Id, wrapAlgorithm); + } + + public static IBasicAgreement GetBasicAgreementWithKdf( + string agreeAlgorithm, + string wrapAlgorithm) + { + string upper = Platform.ToUpperInvariant(agreeAlgorithm); + string mechanism = (string) algorithms[upper]; + + if (mechanism == null) + { + mechanism = upper; + } + + // 'DHWITHSHA1KDF' retained for backward compatibility + if (mechanism == "DHWITHSHA1KDF" || mechanism == "ECDHWITHSHA1KDF") + return new ECDHWithKdfBasicAgreement( + wrapAlgorithm, + new ECDHKekGenerator( + new Sha1Digest())); + + if (mechanism == "ECMQVWITHSHA1KDF") + return new ECMqvWithKdfBasicAgreement( + wrapAlgorithm, + new ECDHKekGenerator( + new Sha1Digest())); + + throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised."); + } + + public static string GetAlgorithmName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + } +} diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs new file mode 100644 index 000000000..cda769535 --- /dev/null +++ b/crypto/src/security/CipherUtilities.cs @@ -0,0 +1,739 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Cipher Utility class contains methods that can not be specifically grouped into other classes. + /// + public sealed class CipherUtilities + { + private enum CipherAlgorithm { + AES, + ARC4, + BLOWFISH, + CAMELLIA, + CAST5, + CAST6, + DES, + DESEDE, + ELGAMAL, + GOST28147, + HC128, + HC256, + IDEA, + NOEKEON, + PBEWITHSHAAND128BITRC4, + PBEWITHSHAAND40BITRC4, + RC2, + RC5, + RC5_64, + RC6, + RIJNDAEL, + RSA, + SALSA20, + SEED, + SERPENT, + SKIPJACK, + TEA, + TWOFISH, + VMPC, + VMPC_KSA3, + XTEA, + }; + + private enum CipherMode { ECB, NONE, CBC, CCM, CFB, CTR, CTS, EAX, GCM, GOFB, OCB, OFB, OPENPGPCFB, SIC }; + private enum CipherPadding + { + NOPADDING, + RAW, + ISO10126PADDING, + ISO10126D2PADDING, + ISO10126_2PADDING, + ISO7816_4PADDING, + ISO9797_1PADDING, + ISO9796_1, + ISO9796_1PADDING, + OAEP, + OAEPPADDING, + OAEPWITHMD5ANDMGF1PADDING, + OAEPWITHSHA1ANDMGF1PADDING, + OAEPWITHSHA_1ANDMGF1PADDING, + OAEPWITHSHA224ANDMGF1PADDING, + OAEPWITHSHA_224ANDMGF1PADDING, + OAEPWITHSHA256ANDMGF1PADDING, + OAEPWITHSHA_256ANDMGF1PADDING, + OAEPWITHSHA384ANDMGF1PADDING, + OAEPWITHSHA_384ANDMGF1PADDING, + OAEPWITHSHA512ANDMGF1PADDING, + OAEPWITHSHA_512ANDMGF1PADDING, + PKCS1, + PKCS1PADDING, + PKCS5, + PKCS5PADDING, + PKCS7, + PKCS7PADDING, + TBCPADDING, + WITHCTS, + X923PADDING, + ZEROBYTEPADDING, + }; + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary oids = Platform.CreateHashtable(); + + static CipherUtilities() + { + // Signal to obfuscation tools not to change enum constants + ((CipherAlgorithm)Enums.GetArbitraryValue(typeof(CipherAlgorithm))).ToString(); + ((CipherMode)Enums.GetArbitraryValue(typeof(CipherMode))).ToString(); + ((CipherPadding)Enums.GetArbitraryValue(typeof(CipherPadding))).ToString(); + + // TODO Flesh out the list of aliases + + algorithms[NistObjectIdentifiers.IdAes128Ecb.Id] = "AES/ECB/PKCS7PADDING"; + algorithms[NistObjectIdentifiers.IdAes192Ecb.Id] = "AES/ECB/PKCS7PADDING"; + algorithms[NistObjectIdentifiers.IdAes256Ecb.Id] = "AES/ECB/PKCS7PADDING"; + algorithms["AES//PKCS7"] = "AES/ECB/PKCS7PADDING"; + algorithms["AES//PKCS7PADDING"] = "AES/ECB/PKCS7PADDING"; + algorithms["AES//PKCS5"] = "AES/ECB/PKCS7PADDING"; + algorithms["AES//PKCS5PADDING"] = "AES/ECB/PKCS7PADDING"; + + algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "AES/CBC/PKCS7PADDING"; + algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "AES/CBC/PKCS7PADDING"; + algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "AES/CBC/PKCS7PADDING"; + + algorithms[NistObjectIdentifiers.IdAes128Ofb.Id] = "AES/OFB/NOPADDING"; + algorithms[NistObjectIdentifiers.IdAes192Ofb.Id] = "AES/OFB/NOPADDING"; + algorithms[NistObjectIdentifiers.IdAes256Ofb.Id] = "AES/OFB/NOPADDING"; + + algorithms[NistObjectIdentifiers.IdAes128Cfb.Id] = "AES/CFB/NOPADDING"; + algorithms[NistObjectIdentifiers.IdAes192Cfb.Id] = "AES/CFB/NOPADDING"; + algorithms[NistObjectIdentifiers.IdAes256Cfb.Id] = "AES/CFB/NOPADDING"; + + algorithms["RSA/ECB/PKCS1"] = "RSA//PKCS1PADDING"; + algorithms["RSA/ECB/PKCS1PADDING"] = "RSA//PKCS1PADDING"; + algorithms[PkcsObjectIdentifiers.RsaEncryption.Id] = "RSA//PKCS1PADDING"; + algorithms[PkcsObjectIdentifiers.IdRsaesOaep.Id] = "RSA//OAEPPADDING"; + + algorithms[OiwObjectIdentifiers.DesCbc.Id] = "DES/CBC"; + algorithms[OiwObjectIdentifiers.DesCfb.Id] = "DES/CFB"; + algorithms[OiwObjectIdentifiers.DesEcb.Id] = "DES/ECB"; + algorithms[OiwObjectIdentifiers.DesOfb.Id] = "DES/OFB"; + algorithms[OiwObjectIdentifiers.DesEde.Id] = "DESEDE"; + algorithms["TDEA"] = "DESEDE"; + algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDE/CBC"; + algorithms[PkcsObjectIdentifiers.RC2Cbc.Id] = "RC2/CBC"; + algorithms["1.3.6.1.4.1.188.7.1.1.2"] = "IDEA/CBC"; + algorithms["1.2.840.113533.7.66.10"] = "CAST5/CBC"; + + algorithms["RC4"] = "ARC4"; + algorithms["ARCFOUR"] = "ARC4"; + algorithms["1.2.840.113549.3.4"] = "ARC4"; + + + + algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEWITHSHAAND128BITRC4"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEWITHSHAAND128BITRC4"; + algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEWITHSHAAND40BITRC4"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEWITHSHAAND40BITRC4"; + + algorithms["PBEWITHSHA1ANDDES"] = "PBEWITHSHA1ANDDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEWITHSHA1ANDDES-CBC"; + algorithms["PBEWITHSHA1ANDRC2"] = "PBEWITHSHA1ANDRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEWITHSHA1ANDRC2-CBC"; + + algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"; + algorithms["PBEWITHSHAAND3KEYTRIPLEDES"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"; + algorithms["PBEWITHSHA1ANDDESEDE"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"; + + algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"; + + algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEWITHSHAAND128BITRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEWITHSHAAND128BITRC2-CBC"; + + algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEWITHSHAAND40BITRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEWITHSHAAND40BITRC2-CBC"; + + algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC"; + + algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC"; + + algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC"; + + algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEWITHSHA256AND128BITAES-CBC-BC"; + algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEWITHSHA256AND192BITAES-CBC-BC"; + algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEWITHSHA256AND256BITAES-CBC-BC"; + + + algorithms["GOST"] = "GOST28147"; + algorithms["GOST-28147"] = "GOST28147"; + algorithms[CryptoProObjectIdentifiers.GostR28147Cbc.Id] = "GOST28147/CBC/PKCS7PADDING"; + + algorithms["RC5-32"] = "RC5"; + + algorithms[NttObjectIdentifiers.IdCamellia128Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING"; + algorithms[NttObjectIdentifiers.IdCamellia192Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING"; + algorithms[NttObjectIdentifiers.IdCamellia256Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING"; + + algorithms[KisaObjectIdentifiers.IdSeedCbc.Id] = "SEED/CBC/PKCS7PADDING"; + + algorithms["1.3.6.1.4.1.3029.1.2"] = "BLOWFISH/CBC"; + } + + private CipherUtilities() + { + } + + /// + /// Returns a ObjectIdentifier for a give encoding. + /// + /// A string representation of the encoding. + /// A DerObjectIdentifier, null if the Oid is not available. + // TODO Don't really want to support this + public static DerObjectIdentifier GetObjectIdentifier( + string mechanism) + { + if (mechanism == null) + throw new ArgumentNullException("mechanism"); + + mechanism = Platform.ToUpperInvariant(mechanism); + string aliased = (string) algorithms[mechanism]; + + if (aliased != null) + mechanism = aliased; + + return (DerObjectIdentifier) oids[mechanism]; + } + + public static ICollection Algorithms + { + get { return oids.Keys; } + } + + public static IBufferedCipher GetCipher( + DerObjectIdentifier oid) + { + return GetCipher(oid.Id); + } + + public static IBufferedCipher GetCipher( + string algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm = Platform.ToUpperInvariant(algorithm); + + { + string aliased = (string) algorithms[algorithm]; + + if (aliased != null) + algorithm = aliased; + } + + IBasicAgreement iesAgreement = null; + if (algorithm == "IES") + { + iesAgreement = new DHBasicAgreement(); + } + else if (algorithm == "ECIES") + { + iesAgreement = new ECDHBasicAgreement(); + } + + if (iesAgreement != null) + { + return new BufferedIesCipher( + new IesEngine( + iesAgreement, + new Kdf2BytesGenerator( + new Sha1Digest()), + new HMac( + new Sha1Digest()))); + } + + + + if (algorithm.StartsWith("PBE")) + { + if (algorithm.EndsWith("-CBC")) + { + if (algorithm == "PBEWITHSHA1ANDDES-CBC") + { + return new PaddedBufferedBlockCipher( + new CbcBlockCipher(new DesEngine())); + } + else if (algorithm == "PBEWITHSHA1ANDRC2-CBC") + { + return new PaddedBufferedBlockCipher( + new CbcBlockCipher(new RC2Engine())); + } + else if (Strings.IsOneOf(algorithm, + "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC")) + { + return new PaddedBufferedBlockCipher( + new CbcBlockCipher(new DesEdeEngine())); + } + else if (Strings.IsOneOf(algorithm, + "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC")) + { + return new PaddedBufferedBlockCipher( + new CbcBlockCipher(new RC2Engine())); + } + } + else if (algorithm.EndsWith("-BC") || algorithm.EndsWith("-OPENSSL")) + { + if (Strings.IsOneOf(algorithm, + "PBEWITHSHAAND128BITAES-CBC-BC", + "PBEWITHSHAAND192BITAES-CBC-BC", + "PBEWITHSHAAND256BITAES-CBC-BC", + "PBEWITHSHA256AND128BITAES-CBC-BC", + "PBEWITHSHA256AND192BITAES-CBC-BC", + "PBEWITHSHA256AND256BITAES-CBC-BC", + "PBEWITHMD5AND128BITAES-CBC-OPENSSL", + "PBEWITHMD5AND192BITAES-CBC-OPENSSL", + "PBEWITHMD5AND256BITAES-CBC-OPENSSL")) + { + return new PaddedBufferedBlockCipher( + new CbcBlockCipher(new AesFastEngine())); + } + } + } + + + + string[] parts = algorithm.Split('/'); + + IBlockCipher blockCipher = null; + IAsymmetricBlockCipher asymBlockCipher = null; + IStreamCipher streamCipher = null; + + string algorithmName = parts[0]; + + { + string aliased = (string)algorithms[algorithmName]; + + if (aliased != null) + algorithmName = aliased; + } + + CipherAlgorithm cipherAlgorithm; + try + { + cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName); + } + catch (ArgumentException) + { + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + + switch (cipherAlgorithm) + { + case CipherAlgorithm.AES: + blockCipher = new AesFastEngine(); + break; + case CipherAlgorithm.ARC4: + streamCipher = new RC4Engine(); + break; + case CipherAlgorithm.BLOWFISH: + blockCipher = new BlowfishEngine(); + break; + case CipherAlgorithm.CAMELLIA: + blockCipher = new CamelliaEngine(); + break; + case CipherAlgorithm.CAST5: + blockCipher = new Cast5Engine(); + break; + case CipherAlgorithm.CAST6: + blockCipher = new Cast6Engine(); + break; + case CipherAlgorithm.DES: + blockCipher = new DesEngine(); + break; + case CipherAlgorithm.DESEDE: + blockCipher = new DesEdeEngine(); + break; + case CipherAlgorithm.ELGAMAL: + asymBlockCipher = new ElGamalEngine(); + break; + case CipherAlgorithm.GOST28147: + blockCipher = new Gost28147Engine(); + break; + case CipherAlgorithm.HC128: + streamCipher = new HC128Engine(); + break; + case CipherAlgorithm.HC256: + streamCipher = new HC256Engine(); + break; +#if INCLUDE_IDEA + case CipherAlgorithm.IDEA: + blockCipher = new IdeaEngine(); + break; +#endif + case CipherAlgorithm.NOEKEON: + blockCipher = new NoekeonEngine(); + break; + case CipherAlgorithm.PBEWITHSHAAND128BITRC4: + case CipherAlgorithm.PBEWITHSHAAND40BITRC4: + streamCipher = new RC4Engine(); + break; + case CipherAlgorithm.RC2: + blockCipher = new RC2Engine(); + break; + case CipherAlgorithm.RC5: + blockCipher = new RC532Engine(); + break; + case CipherAlgorithm.RC5_64: + blockCipher = new RC564Engine(); + break; + case CipherAlgorithm.RC6: + blockCipher = new RC6Engine(); + break; + case CipherAlgorithm.RIJNDAEL: + blockCipher = new RijndaelEngine(); + break; + case CipherAlgorithm.RSA: + asymBlockCipher = new RsaBlindedEngine(); + break; + case CipherAlgorithm.SALSA20: + streamCipher = new Salsa20Engine(); + break; + case CipherAlgorithm.SEED: + blockCipher = new SeedEngine(); + break; + case CipherAlgorithm.SERPENT: + blockCipher = new SerpentEngine(); + break; + case CipherAlgorithm.SKIPJACK: + blockCipher = new SkipjackEngine(); + break; + case CipherAlgorithm.TEA: + blockCipher = new TeaEngine(); + break; + case CipherAlgorithm.TWOFISH: + blockCipher = new TwofishEngine(); + break; + case CipherAlgorithm.VMPC: + streamCipher = new VmpcEngine(); + break; + case CipherAlgorithm.VMPC_KSA3: + streamCipher = new VmpcKsa3Engine(); + break; + case CipherAlgorithm.XTEA: + blockCipher = new XteaEngine(); + break; + default: + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + + if (streamCipher != null) + { + if (parts.Length > 1) + throw new ArgumentException("Modes and paddings not used for stream ciphers"); + + return new BufferedStreamCipher(streamCipher); + } + + + bool cts = false; + bool padded = true; + IBlockCipherPadding padding = null; + IAeadBlockCipher aeadBlockCipher = null; + + if (parts.Length > 2) + { + if (streamCipher != null) + throw new ArgumentException("Paddings not used for stream ciphers"); + + string paddingName = parts[2]; + + CipherPadding cipherPadding; + if (paddingName == "") + { + cipherPadding = CipherPadding.RAW; + } + else if (paddingName == "X9.23PADDING") + { + cipherPadding = CipherPadding.X923PADDING; + } + else + { + try + { + cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName); + } + catch (ArgumentException) + { + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + } + + switch (cipherPadding) + { + case CipherPadding.NOPADDING: + padded = false; + break; + case CipherPadding.RAW: + break; + case CipherPadding.ISO10126PADDING: + case CipherPadding.ISO10126D2PADDING: + case CipherPadding.ISO10126_2PADDING: + padding = new ISO10126d2Padding(); + break; + case CipherPadding.ISO7816_4PADDING: + case CipherPadding.ISO9797_1PADDING: + padding = new ISO7816d4Padding(); + break; + case CipherPadding.ISO9796_1: + case CipherPadding.ISO9796_1PADDING: + asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher); + break; + case CipherPadding.OAEP: + case CipherPadding.OAEPPADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher); + break; + case CipherPadding.OAEPWITHMD5ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest()); + break; + case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING: + case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest()); + break; + case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING: + case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest()); + break; + case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING: + case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest()); + break; + case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING: + case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest()); + break; + case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING: + case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING: + asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest()); + break; + case CipherPadding.PKCS1: + case CipherPadding.PKCS1PADDING: + asymBlockCipher = new Pkcs1Encoding(asymBlockCipher); + break; + case CipherPadding.PKCS5: + case CipherPadding.PKCS5PADDING: + case CipherPadding.PKCS7: + case CipherPadding.PKCS7PADDING: + padding = new Pkcs7Padding(); + break; + case CipherPadding.TBCPADDING: + padding = new TbcPadding(); + break; + case CipherPadding.WITHCTS: + cts = true; + break; + case CipherPadding.X923PADDING: + padding = new X923Padding(); + break; + case CipherPadding.ZEROBYTEPADDING: + padding = new ZeroBytePadding(); + break; + default: + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + } + + string mode = ""; + if (parts.Length > 1) + { + mode = parts[1]; + + int di = GetDigitIndex(mode); + string modeName = di >= 0 ? mode.Substring(0, di) : mode; + + try + { + CipherMode cipherMode = modeName == "" + ? CipherMode.NONE + : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName); + + switch (cipherMode) + { + case CipherMode.ECB: + case CipherMode.NONE: + break; + case CipherMode.CBC: + blockCipher = new CbcBlockCipher(blockCipher); + break; + case CipherMode.CCM: + aeadBlockCipher = new CcmBlockCipher(blockCipher); + break; + case CipherMode.CFB: + { + int bits = (di < 0) + ? 8 * blockCipher.GetBlockSize() + : int.Parse(mode.Substring(di)); + + blockCipher = new CfbBlockCipher(blockCipher, bits); + break; + } + case CipherMode.CTR: + blockCipher = new SicBlockCipher(blockCipher); + break; + case CipherMode.CTS: + cts = true; + blockCipher = new CbcBlockCipher(blockCipher); + break; + case CipherMode.EAX: + aeadBlockCipher = new EaxBlockCipher(blockCipher); + break; + case CipherMode.GCM: + aeadBlockCipher = new GcmBlockCipher(blockCipher); + break; + case CipherMode.GOFB: + blockCipher = new GOfbBlockCipher(blockCipher); + break; + case CipherMode.OCB: + aeadBlockCipher = new OcbBlockCipher(blockCipher, CreateBlockCipher(cipherAlgorithm)); + break; + case CipherMode.OFB: + { + int bits = (di < 0) + ? 8 * blockCipher.GetBlockSize() + : int.Parse(mode.Substring(di)); + + blockCipher = new OfbBlockCipher(blockCipher, bits); + break; + } + case CipherMode.OPENPGPCFB: + blockCipher = new OpenPgpCfbBlockCipher(blockCipher); + break; + case CipherMode.SIC: + if (blockCipher.GetBlockSize() < 16) + { + throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); + } + blockCipher = new SicBlockCipher(blockCipher); + break; + default: + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + } + catch (ArgumentException) + { + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + } + + if (aeadBlockCipher != null) + { + if (cts) + throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers."); + if (padded && parts.Length > 2 && parts[2] != "") + throw new SecurityUtilityException("Bad padding specified for AEAD cipher."); + + return new BufferedAeadBlockCipher(aeadBlockCipher); + } + + if (blockCipher != null) + { + if (cts) + { + return new CtsBlockCipher(blockCipher); + } + + if (padding != null) + { + return new PaddedBufferedBlockCipher(blockCipher, padding); + } + + if (!padded || blockCipher.IsPartialBlockOkay) + { + return new BufferedBlockCipher(blockCipher); + } + + return new PaddedBufferedBlockCipher(blockCipher); + } + + if (asymBlockCipher != null) + { + return new BufferedAsymmetricBlockCipher(asymBlockCipher); + } + + throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); + } + + public static string GetAlgorithmName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + + private static int GetDigitIndex( + string s) + { + for (int i = 0; i < s.Length; ++i) + { + if (char.IsDigit(s[i])) + return i; + } + + return -1; + } + + private static IBlockCipher CreateBlockCipher(CipherAlgorithm cipherAlgorithm) + { + switch (cipherAlgorithm) + { + case CipherAlgorithm.AES: return new AesFastEngine(); + case CipherAlgorithm.BLOWFISH: return new BlowfishEngine(); + case CipherAlgorithm.CAMELLIA: return new CamelliaEngine(); + case CipherAlgorithm.CAST5: return new Cast5Engine(); + case CipherAlgorithm.CAST6: return new Cast6Engine(); + case CipherAlgorithm.DES: return new DesEngine(); + case CipherAlgorithm.DESEDE: return new DesEdeEngine(); + case CipherAlgorithm.GOST28147: return new Gost28147Engine(); +#if INCLUDE_IDEA + case CipherAlgorithm.IDEA: return new IdeaEngine(); +#endif + case CipherAlgorithm.NOEKEON: return new NoekeonEngine(); + case CipherAlgorithm.RC2: return new RC2Engine(); + case CipherAlgorithm.RC5: return new RC532Engine(); + case CipherAlgorithm.RC5_64: return new RC564Engine(); + case CipherAlgorithm.RC6: return new RC6Engine(); + case CipherAlgorithm.RIJNDAEL: return new RijndaelEngine(); + case CipherAlgorithm.SEED: return new SeedEngine(); + case CipherAlgorithm.SERPENT: return new SerpentEngine(); + case CipherAlgorithm.SKIPJACK: return new SkipjackEngine(); + case CipherAlgorithm.TEA: return new TeaEngine(); + case CipherAlgorithm.TWOFISH: return new TwofishEngine(); + case CipherAlgorithm.XTEA: return new XteaEngine(); + default: + throw new SecurityUtilityException("Cipher " + cipherAlgorithm + " not recognised or not a block cipher"); + } + } + } +} diff --git a/crypto/src/security/DigestUtilities.cs b/crypto/src/security/DigestUtilities.cs new file mode 100644 index 000000000..ec3f63940 --- /dev/null +++ b/crypto/src/security/DigestUtilities.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Utility class for creating IDigest objects from their names/Oids + /// + public sealed class DigestUtilities + { + private enum DigestAlgorithm { + GOST3411, + MD2, MD4, MD5, + RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320, + SHA_1, SHA_224, SHA_256, SHA_384, SHA_512, + SHA_512_224, SHA_512_256, + SHA3_224, SHA3_256, SHA3_384, SHA3_512, + TIGER, + WHIRLPOOL, + }; + + private DigestUtilities() + { + } + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary oids = Platform.CreateHashtable(); + + static DigestUtilities() + { + // Signal to obfuscation tools not to change enum constants + ((DigestAlgorithm)Enums.GetArbitraryValue(typeof(DigestAlgorithm))).ToString(); + + algorithms[PkcsObjectIdentifiers.MD2.Id] = "MD2"; + algorithms[PkcsObjectIdentifiers.MD4.Id] = "MD4"; + algorithms[PkcsObjectIdentifiers.MD5.Id] = "MD5"; + + algorithms["SHA1"] = "SHA-1"; + algorithms[OiwObjectIdentifiers.IdSha1.Id] = "SHA-1"; + algorithms["SHA224"] = "SHA-224"; + algorithms[NistObjectIdentifiers.IdSha224.Id] = "SHA-224"; + algorithms["SHA256"] = "SHA-256"; + algorithms[NistObjectIdentifiers.IdSha256.Id] = "SHA-256"; + algorithms["SHA384"] = "SHA-384"; + algorithms[NistObjectIdentifiers.IdSha384.Id] = "SHA-384"; + algorithms["SHA512"] = "SHA-512"; + algorithms[NistObjectIdentifiers.IdSha512.Id] = "SHA-512"; + algorithms["SHA512/224"] = "SHA-512/224"; + algorithms[NistObjectIdentifiers.IdSha512_224.Id] = "SHA-512/224"; + algorithms["SHA512/256"] = "SHA-512/256"; + algorithms[NistObjectIdentifiers.IdSha512_256.Id] = "SHA-512/256"; + + algorithms["RIPEMD-128"] = "RIPEMD128"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "RIPEMD128"; + algorithms["RIPEMD-160"] = "RIPEMD160"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "RIPEMD160"; + algorithms["RIPEMD-256"] = "RIPEMD256"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "RIPEMD256"; + algorithms["RIPEMD-320"] = "RIPEMD320"; +// algorithms[TeleTrusTObjectIdentifiers.RipeMD320.Id] = "RIPEMD320"; + + algorithms[CryptoProObjectIdentifiers.GostR3411.Id] = "GOST3411"; + + + + oids["MD2"] = PkcsObjectIdentifiers.MD2; + oids["MD4"] = PkcsObjectIdentifiers.MD4; + oids["MD5"] = PkcsObjectIdentifiers.MD5; + oids["SHA-1"] = OiwObjectIdentifiers.IdSha1; + oids["SHA-224"] = NistObjectIdentifiers.IdSha224; + oids["SHA-256"] = NistObjectIdentifiers.IdSha256; + oids["SHA-384"] = NistObjectIdentifiers.IdSha384; + oids["SHA-512"] = NistObjectIdentifiers.IdSha512; + oids["SHA-512/224"] = NistObjectIdentifiers.IdSha512_224; + oids["SHA-512/256"] = NistObjectIdentifiers.IdSha512_256; + oids["RIPEMD128"] = TeleTrusTObjectIdentifiers.RipeMD128; + oids["RIPEMD160"] = TeleTrusTObjectIdentifiers.RipeMD160; + oids["RIPEMD256"] = TeleTrusTObjectIdentifiers.RipeMD256; + oids["GOST3411"] = CryptoProObjectIdentifiers.GostR3411; + } + + /// + /// Returns a ObjectIdentifier for a given digest mechanism. + /// + /// A string representation of the digest meanism. + /// A DerObjectIdentifier, null if the Oid is not available. + + public static DerObjectIdentifier GetObjectIdentifier( + string mechanism) + { + if (mechanism == null) + throw new System.ArgumentNullException("mechanism"); + + mechanism = Platform.ToUpperInvariant(mechanism); + string aliased = (string) algorithms[mechanism]; + + if (aliased != null) + mechanism = aliased; + + return (DerObjectIdentifier) oids[mechanism]; + } + + public static ICollection Algorithms + { + get { return oids.Keys; } + } + + public static IDigest GetDigest( + DerObjectIdentifier id) + { + return GetDigest(id.Id); + } + + public static IDigest GetDigest( + string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + string mechanism = (string) algorithms[upper]; + + if (mechanism == null) + { + mechanism = upper; + } + + try + { + DigestAlgorithm digestAlgorithm = (DigestAlgorithm)Enums.GetEnumValue( + typeof(DigestAlgorithm), mechanism); + + switch (digestAlgorithm) + { + case DigestAlgorithm.GOST3411: return new Gost3411Digest(); + case DigestAlgorithm.MD2: return new MD2Digest(); + case DigestAlgorithm.MD4: return new MD4Digest(); + case DigestAlgorithm.MD5: return new MD5Digest(); + case DigestAlgorithm.RIPEMD128: return new RipeMD128Digest(); + case DigestAlgorithm.RIPEMD160: return new RipeMD160Digest(); + case DigestAlgorithm.RIPEMD256: return new RipeMD256Digest(); + case DigestAlgorithm.RIPEMD320: return new RipeMD320Digest(); + case DigestAlgorithm.SHA_1: return new Sha1Digest(); + case DigestAlgorithm.SHA_224: return new Sha224Digest(); + case DigestAlgorithm.SHA_256: return new Sha256Digest(); + case DigestAlgorithm.SHA_384: return new Sha384Digest(); + case DigestAlgorithm.SHA_512: return new Sha512Digest(); + case DigestAlgorithm.SHA_512_224: return new Sha512tDigest(224); + case DigestAlgorithm.SHA_512_256: return new Sha512tDigest(256); + case DigestAlgorithm.SHA3_224: return new Sha3Digest(224); + case DigestAlgorithm.SHA3_256: return new Sha3Digest(256); + case DigestAlgorithm.SHA3_384: return new Sha3Digest(384); + case DigestAlgorithm.SHA3_512: return new Sha3Digest(512); + case DigestAlgorithm.TIGER: return new TigerDigest(); + case DigestAlgorithm.WHIRLPOOL: return new WhirlpoolDigest(); + } + } + catch (ArgumentException) + { + } + + throw new SecurityUtilityException("Digest " + mechanism + " not recognised."); + } + + public static string GetAlgorithmName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + + public static byte[] CalculateDigest(string algorithm, byte[] input) + { + IDigest digest = GetDigest(algorithm); + digest.BlockUpdate(input, 0, input.Length); + return DoFinal(digest); + } + + public static byte[] DoFinal( + IDigest digest) + { + byte[] b = new byte[digest.GetDigestSize()]; + digest.DoFinal(b, 0); + return b; + } + + public static byte[] DoFinal( + IDigest digest, + byte[] input) + { + digest.BlockUpdate(input, 0, input.Length); + return DoFinal(digest); + } + } +} diff --git a/crypto/src/security/DotNetUtilities.cs b/crypto/src/security/DotNetUtilities.cs new file mode 100644 index 000000000..036c0d519 --- /dev/null +++ b/crypto/src/security/DotNetUtilities.cs @@ -0,0 +1,222 @@ +#if !(NETCF_1_0 || SILVERLIGHT) + +using System; +using System.Security.Cryptography; +using SystemX509 = System.Security.Cryptography.X509Certificates; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Security +{ + /// + /// A class containing methods to interface the BouncyCastle world to the .NET Crypto world. + /// + public sealed class DotNetUtilities + { + private DotNetUtilities() + { + } + + /// + /// Create an System.Security.Cryptography.X509Certificate from an X509Certificate Structure. + /// + /// + /// A System.Security.Cryptography.X509Certificate. + public static SystemX509.X509Certificate ToX509Certificate( + X509CertificateStructure x509Struct) + { + return new SystemX509.X509Certificate(x509Struct.GetDerEncoded()); + } + + public static SystemX509.X509Certificate ToX509Certificate( + X509Certificate x509Cert) + { + return new SystemX509.X509Certificate(x509Cert.GetEncoded()); + } + + public static X509Certificate FromX509Certificate( + SystemX509.X509Certificate x509Cert) + { + return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData()); + } + + public static AsymmetricCipherKeyPair GetDsaKeyPair( + DSA dsa) + { + return GetDsaKeyPair(dsa.ExportParameters(true)); + } + + public static AsymmetricCipherKeyPair GetDsaKeyPair( + DSAParameters dp) + { + DsaValidationParameters validationParameters = (dp.Seed != null) + ? new DsaValidationParameters(dp.Seed, dp.Counter) + : null; + + DsaParameters parameters = new DsaParameters( + new BigInteger(1, dp.P), + new BigInteger(1, dp.Q), + new BigInteger(1, dp.G), + validationParameters); + + DsaPublicKeyParameters pubKey = new DsaPublicKeyParameters( + new BigInteger(1, dp.Y), + parameters); + + DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters( + new BigInteger(1, dp.X), + parameters); + + return new AsymmetricCipherKeyPair(pubKey, privKey); + } + + public static DsaPublicKeyParameters GetDsaPublicKey( + DSA dsa) + { + return GetDsaPublicKey(dsa.ExportParameters(false)); + } + + public static DsaPublicKeyParameters GetDsaPublicKey( + DSAParameters dp) + { + DsaValidationParameters validationParameters = (dp.Seed != null) + ? new DsaValidationParameters(dp.Seed, dp.Counter) + : null; + + DsaParameters parameters = new DsaParameters( + new BigInteger(1, dp.P), + new BigInteger(1, dp.Q), + new BigInteger(1, dp.G), + validationParameters); + + return new DsaPublicKeyParameters( + new BigInteger(1, dp.Y), + parameters); + } + + public static AsymmetricCipherKeyPair GetRsaKeyPair( + RSA rsa) + { + return GetRsaKeyPair(rsa.ExportParameters(true)); + } + + public static AsymmetricCipherKeyPair GetRsaKeyPair( + RSAParameters rp) + { + BigInteger modulus = new BigInteger(1, rp.Modulus); + BigInteger pubExp = new BigInteger(1, rp.Exponent); + + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + modulus, + pubExp); + + RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters( + modulus, + pubExp, + new BigInteger(1, rp.D), + new BigInteger(1, rp.P), + new BigInteger(1, rp.Q), + new BigInteger(1, rp.DP), + new BigInteger(1, rp.DQ), + new BigInteger(1, rp.InverseQ)); + + return new AsymmetricCipherKeyPair(pubKey, privKey); + } + + public static RsaKeyParameters GetRsaPublicKey( + RSA rsa) + { + return GetRsaPublicKey(rsa.ExportParameters(false)); + } + + public static RsaKeyParameters GetRsaPublicKey( + RSAParameters rp) + { + return new RsaKeyParameters( + false, + new BigInteger(1, rp.Modulus), + new BigInteger(1, rp.Exponent)); + } + + public static AsymmetricCipherKeyPair GetKeyPair(AsymmetricAlgorithm privateKey) + { + if (privateKey is DSA) + { + return GetDsaKeyPair((DSA)privateKey); + } + + if (privateKey is RSA) + { + return GetRsaKeyPair((RSA)privateKey); + } + + throw new ArgumentException("Unsupported algorithm specified", "privateKey"); + } + + public static RSA ToRSA(RsaKeyParameters rsaKey) + { + RSAParameters rp = ToRSAParameters(rsaKey); + RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(); + // TODO This call appears to not work for private keys (when no CRT info) + rsaCsp.ImportParameters(rp); + return rsaCsp; + } + + public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey) + { + RSAParameters rp = ToRSAParameters(privKey); + RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(); + rsaCsp.ImportParameters(rp); + return rsaCsp; + } + + public static RSAParameters ToRSAParameters(RsaKeyParameters rsaKey) + { + RSAParameters rp = new RSAParameters(); + rp.Modulus = rsaKey.Modulus.ToByteArrayUnsigned(); + if (rsaKey.IsPrivate) + rp.D = ConvertRSAParametersField(rsaKey.Exponent, rp.Modulus.Length); + else + rp.Exponent = rsaKey.Exponent.ToByteArrayUnsigned(); + return rp; + } + + public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey) + { + RSAParameters rp = new RSAParameters(); + rp.Modulus = privKey.Modulus.ToByteArrayUnsigned(); + rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned(); + rp.P = privKey.P.ToByteArrayUnsigned(); + rp.Q = privKey.Q.ToByteArrayUnsigned(); + rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length); + rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length); + rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length); + rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length); + return rp; + } + + // TODO Move functionality to more general class + private static byte[] ConvertRSAParametersField(BigInteger n, int size) + { + byte[] bs = n.ToByteArrayUnsigned(); + + if (bs.Length == size) + return bs; + + if (bs.Length > size) + throw new ArgumentException("Specified size too small", "size"); + + byte[] padded = new byte[size]; + Array.Copy(bs, 0, padded, size - bs.Length, bs.Length); + return padded; + } + } +} + +#endif diff --git a/crypto/src/security/GeneralSecurityException.cs b/crypto/src/security/GeneralSecurityException.cs new file mode 100644 index 000000000..2c3f2a555 --- /dev/null +++ b/crypto/src/security/GeneralSecurityException.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class GeneralSecurityException + : Exception + { + public GeneralSecurityException() + : base() + { + } + + public GeneralSecurityException( + string message) + : base(message) + { + } + + public GeneralSecurityException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs new file mode 100644 index 000000000..45fbc9425 --- /dev/null +++ b/crypto/src/security/GeneratorUtilities.cs @@ -0,0 +1,349 @@ +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Security +{ + public sealed class GeneratorUtilities + { + private GeneratorUtilities() + { + } + + private static readonly IDictionary kgAlgorithms = Platform.CreateHashtable(); + private static readonly IDictionary kpgAlgorithms = Platform.CreateHashtable(); + private static readonly IDictionary defaultKeySizes = Platform.CreateHashtable(); + + static GeneratorUtilities() + { + // + // key generators. + // + AddKgAlgorithm("AES", + "AESWRAP"); + AddKgAlgorithm("AES128", + "2.16.840.1.101.3.4.2", + NistObjectIdentifiers.IdAes128Cbc, + NistObjectIdentifiers.IdAes128Cfb, + NistObjectIdentifiers.IdAes128Ecb, + NistObjectIdentifiers.IdAes128Ofb, + NistObjectIdentifiers.IdAes128Wrap); + AddKgAlgorithm("AES192", + "2.16.840.1.101.3.4.22", + NistObjectIdentifiers.IdAes192Cbc, + NistObjectIdentifiers.IdAes192Cfb, + NistObjectIdentifiers.IdAes192Ecb, + NistObjectIdentifiers.IdAes192Ofb, + NistObjectIdentifiers.IdAes192Wrap); + AddKgAlgorithm("AES256", + "2.16.840.1.101.3.4.42", + NistObjectIdentifiers.IdAes256Cbc, + NistObjectIdentifiers.IdAes256Cfb, + NistObjectIdentifiers.IdAes256Ecb, + NistObjectIdentifiers.IdAes256Ofb, + NistObjectIdentifiers.IdAes256Wrap); + AddKgAlgorithm("BLOWFISH", + "1.3.6.1.4.1.3029.1.2"); + AddKgAlgorithm("CAMELLIA", + "CAMELLIAWRAP"); + AddKgAlgorithm("CAMELLIA128", + NttObjectIdentifiers.IdCamellia128Cbc, + NttObjectIdentifiers.IdCamellia128Wrap); + AddKgAlgorithm("CAMELLIA192", + NttObjectIdentifiers.IdCamellia192Cbc, + NttObjectIdentifiers.IdCamellia192Wrap); + AddKgAlgorithm("CAMELLIA256", + NttObjectIdentifiers.IdCamellia256Cbc, + NttObjectIdentifiers.IdCamellia256Wrap); + AddKgAlgorithm("CAST5", + "1.2.840.113533.7.66.10"); + AddKgAlgorithm("CAST6"); + AddKgAlgorithm("DES", + OiwObjectIdentifiers.DesCbc, + OiwObjectIdentifiers.DesCfb, + OiwObjectIdentifiers.DesEcb, + OiwObjectIdentifiers.DesOfb); + AddKgAlgorithm("DESEDE", + "DESEDEWRAP", + "TDEA", + OiwObjectIdentifiers.DesEde); + AddKgAlgorithm("DESEDE3", + PkcsObjectIdentifiers.DesEde3Cbc, + PkcsObjectIdentifiers.IdAlgCms3DesWrap); + AddKgAlgorithm("GOST28147", + "GOST", + "GOST-28147", + CryptoProObjectIdentifiers.GostR28147Cbc); + AddKgAlgorithm("HC128"); + AddKgAlgorithm("HC256"); + AddKgAlgorithm("IDEA", + "1.3.6.1.4.1.188.7.1.1.2"); + AddKgAlgorithm("NOEKEON"); + AddKgAlgorithm("RC2", + PkcsObjectIdentifiers.RC2Cbc, + PkcsObjectIdentifiers.IdAlgCmsRC2Wrap); + AddKgAlgorithm("RC4", + "ARC4", + "1.2.840.113549.3.4"); + AddKgAlgorithm("RC5", + "RC5-32"); + AddKgAlgorithm("RC5-64"); + AddKgAlgorithm("RC6"); + AddKgAlgorithm("RIJNDAEL"); + AddKgAlgorithm("SALSA20"); + AddKgAlgorithm("SEED", + KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap, + KisaObjectIdentifiers.IdSeedCbc); + AddKgAlgorithm("SERPENT"); + AddKgAlgorithm("SKIPJACK"); + AddKgAlgorithm("TEA"); + AddKgAlgorithm("TWOFISH"); + AddKgAlgorithm("VMPC"); + AddKgAlgorithm("VMPC-KSA3"); + AddKgAlgorithm("XTEA"); + + // + // HMac key generators + // + AddHMacKeyGenerator("MD2"); + AddHMacKeyGenerator("MD4"); + AddHMacKeyGenerator("MD5", + IanaObjectIdentifiers.HmacMD5); + AddHMacKeyGenerator("SHA1", + PkcsObjectIdentifiers.IdHmacWithSha1, + IanaObjectIdentifiers.HmacSha1); + AddHMacKeyGenerator("SHA224", + PkcsObjectIdentifiers.IdHmacWithSha224); + AddHMacKeyGenerator("SHA256", + PkcsObjectIdentifiers.IdHmacWithSha256); + AddHMacKeyGenerator("SHA384", + PkcsObjectIdentifiers.IdHmacWithSha384); + AddHMacKeyGenerator("SHA512", + PkcsObjectIdentifiers.IdHmacWithSha512); + AddHMacKeyGenerator("SHA512/224"); + AddHMacKeyGenerator("SHA512/256"); + AddHMacKeyGenerator("SHA3-224"); + AddHMacKeyGenerator("SHA3-256"); + AddHMacKeyGenerator("SHA3-384"); + AddHMacKeyGenerator("SHA3-512"); + AddHMacKeyGenerator("RIPEMD128"); + AddHMacKeyGenerator("RIPEMD160", + IanaObjectIdentifiers.HmacRipeMD160); + AddHMacKeyGenerator("TIGER", + IanaObjectIdentifiers.HmacTiger); + + + + // + // key pair generators. + // + AddKpgAlgorithm("DH", + "DIFFIEHELLMAN"); + AddKpgAlgorithm("DSA"); + AddKpgAlgorithm("EC", + // TODO Should this be an alias for ECDH? + X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme); + AddKpgAlgorithm("ECDH", + "ECIES"); + AddKpgAlgorithm("ECDHC"); + AddKpgAlgorithm("ECMQV", + X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme); + AddKpgAlgorithm("ECDSA"); + AddKpgAlgorithm("ECGOST3410", + "ECGOST-3410", + "GOST-3410-2001"); + AddKpgAlgorithm("ELGAMAL"); + AddKpgAlgorithm("GOST3410", + "GOST-3410", + "GOST-3410-94"); + AddKpgAlgorithm("RSA", + "1.2.840.113549.1.1.1"); + + AddDefaultKeySizeEntries(64, "DES"); + AddDefaultKeySizeEntries(80, "SKIPJACK"); + AddDefaultKeySizeEntries(128, "AES128", "BLOWFISH", "CAMELLIA128", "CAST5", "DESEDE", + "HC128", "HMACMD2", "HMACMD4", "HMACMD5", "HMACRIPEMD128", "IDEA", "NOEKEON", + "RC2", "RC4", "RC5", "SALSA20", "SEED", "TEA", "XTEA", "VMPC", "VMPC-KSA3"); + AddDefaultKeySizeEntries(160, "HMACRIPEMD160", "HMACSHA1"); + AddDefaultKeySizeEntries(192, "AES", "AES192", "CAMELLIA192", "DESEDE3", "HMACTIGER", + "RIJNDAEL", "SERPENT"); + AddDefaultKeySizeEntries(224, "HMACSHA224"); + AddDefaultKeySizeEntries(256, "AES256", "CAMELLIA", "CAMELLIA256", "CAST6", "GOST28147", + "HC256", "HMACSHA256", "RC5-64", "RC6", "TWOFISH"); + AddDefaultKeySizeEntries(384, "HMACSHA384"); + AddDefaultKeySizeEntries(512, "HMACSHA512"); + AddDefaultKeySizeEntries(224, "HMACSHA512/224"); + AddDefaultKeySizeEntries(256, "HMACSHA512/256"); + } + + private static void AddDefaultKeySizeEntries(int size, params string[] algorithms) + { + foreach (string algorithm in algorithms) + { + defaultKeySizes.Add(algorithm, size); + } + } + + private static void AddKgAlgorithm( + string canonicalName, + params object[] aliases) + { + kgAlgorithms[canonicalName] = canonicalName; + + foreach (object alias in aliases) + { + kgAlgorithms[alias.ToString()] = canonicalName; + } + } + + private static void AddKpgAlgorithm( + string canonicalName, + params object[] aliases) + { + kpgAlgorithms[canonicalName] = canonicalName; + + foreach (object alias in aliases) + { + kpgAlgorithms[alias.ToString()] = canonicalName; + } + } + + private static void AddHMacKeyGenerator( + string algorithm, + params object[] aliases) + { + string mainName = "HMAC" + algorithm; + + kgAlgorithms[mainName] = mainName; + kgAlgorithms["HMAC-" + algorithm] = mainName; + kgAlgorithms["HMAC/" + algorithm] = mainName; + + foreach (object alias in aliases) + { + kgAlgorithms[alias.ToString()] = mainName; + } + } + + // TODO Consider making this public + internal static string GetCanonicalKeyGeneratorAlgorithm( + string algorithm) + { + return (string) kgAlgorithms[Platform.ToUpperInvariant(algorithm)]; + } + + // TODO Consider making this public + internal static string GetCanonicalKeyPairGeneratorAlgorithm( + string algorithm) + { + return (string)kpgAlgorithms[Platform.ToUpperInvariant(algorithm)]; + } + + public static CipherKeyGenerator GetKeyGenerator( + DerObjectIdentifier oid) + { + return GetKeyGenerator(oid.Id); + } + + public static CipherKeyGenerator GetKeyGenerator( + string algorithm) + { + string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm); + + if (canonicalName == null) + throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised."); + + int defaultKeySize = FindDefaultKeySize(canonicalName); + if (defaultKeySize == -1) + throw new SecurityUtilityException("KeyGenerator " + algorithm + + " (" + canonicalName + ") not supported."); + + if (canonicalName == "DES") + return new DesKeyGenerator(defaultKeySize); + + if (canonicalName == "DESEDE" || canonicalName == "DESEDE3") + return new DesEdeKeyGenerator(defaultKeySize); + + return new CipherKeyGenerator(defaultKeySize); + } + + public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator( + DerObjectIdentifier oid) + { + return GetKeyPairGenerator(oid.Id); + } + + public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator( + string algorithm) + { + string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm); + + if (canonicalName == null) + throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised."); + + if (canonicalName == "DH") + return new DHKeyPairGenerator(); + + if (canonicalName == "DSA") + return new DsaKeyPairGenerator(); + + // "EC", "ECDH", "ECDHC", "ECDSA", "ECGOST3410", "ECMQV" + if (canonicalName.StartsWith("EC")) + return new ECKeyPairGenerator(canonicalName); + + if (canonicalName == "ELGAMAL") + return new ElGamalKeyPairGenerator(); + + if (canonicalName == "GOST3410") + return new Gost3410KeyPairGenerator(); + + if (canonicalName == "RSA") + return new RsaKeyPairGenerator(); + + throw new SecurityUtilityException("KeyPairGenerator " + algorithm + + " (" + canonicalName + ") not supported."); + } + + internal static int GetDefaultKeySize( + DerObjectIdentifier oid) + { + return GetDefaultKeySize(oid.Id); + } + + internal static int GetDefaultKeySize( + string algorithm) + { + string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm); + + if (canonicalName == null) + throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised."); + + int defaultKeySize = FindDefaultKeySize(canonicalName); + if (defaultKeySize == -1) + throw new SecurityUtilityException("KeyGenerator " + algorithm + + " (" + canonicalName + ") not supported."); + + return defaultKeySize; + } + + private static int FindDefaultKeySize( + string canonicalName) + { + if (!defaultKeySizes.Contains(canonicalName)) + return -1; + + return (int)defaultKeySizes[canonicalName]; + } + } +} diff --git a/crypto/src/security/InvalidKeyException.cs b/crypto/src/security/InvalidKeyException.cs new file mode 100644 index 000000000..4d4488ef2 --- /dev/null +++ b/crypto/src/security/InvalidKeyException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class InvalidKeyException : KeyException + { + public InvalidKeyException() : base() { } + public InvalidKeyException(string message) : base(message) { } + public InvalidKeyException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/InvalidParameterException.cs b/crypto/src/security/InvalidParameterException.cs new file mode 100644 index 000000000..57a912d03 --- /dev/null +++ b/crypto/src/security/InvalidParameterException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class InvalidParameterException : KeyException + { + public InvalidParameterException() : base() { } + public InvalidParameterException(string message) : base(message) { } + public InvalidParameterException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/KeyException.cs b/crypto/src/security/KeyException.cs new file mode 100644 index 000000000..9304c1c4d --- /dev/null +++ b/crypto/src/security/KeyException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class KeyException : GeneralSecurityException + { + public KeyException() : base() { } + public KeyException(string message) : base(message) { } + public KeyException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/MacUtilities.cs b/crypto/src/security/MacUtilities.cs new file mode 100644 index 000000000..49162fb57 --- /dev/null +++ b/crypto/src/security/MacUtilities.cs @@ -0,0 +1,243 @@ +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Utility class for creating HMac object from their names/Oids + /// + public sealed class MacUtilities + { + private MacUtilities() + { + } + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + //private static readonly IDictionary oids = Platform.CreateHashtable(); + + static MacUtilities() + { + algorithms[IanaObjectIdentifiers.HmacMD5.Id] = "HMAC-MD5"; + algorithms[IanaObjectIdentifiers.HmacRipeMD160.Id] = "HMAC-RIPEMD160"; + algorithms[IanaObjectIdentifiers.HmacSha1.Id] = "HMAC-SHA1"; + algorithms[IanaObjectIdentifiers.HmacTiger.Id] = "HMAC-TIGER"; + + algorithms[PkcsObjectIdentifiers.IdHmacWithSha1.Id] = "HMAC-SHA1"; + algorithms[PkcsObjectIdentifiers.IdHmacWithSha224.Id] = "HMAC-SHA224"; + algorithms[PkcsObjectIdentifiers.IdHmacWithSha256.Id] = "HMAC-SHA256"; + algorithms[PkcsObjectIdentifiers.IdHmacWithSha384.Id] = "HMAC-SHA384"; + algorithms[PkcsObjectIdentifiers.IdHmacWithSha512.Id] = "HMAC-SHA512"; + + // TODO AESMAC? + + algorithms["DES"] = "DESMAC"; + algorithms["DES/CFB8"] = "DESMAC/CFB8"; + algorithms["DES64"] = "DESMAC64"; + algorithms["DESEDE"] = "DESEDEMAC"; + algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDEMAC"; + algorithms["DESEDE/CFB8"] = "DESEDEMAC/CFB8"; + algorithms["DESISO9797MAC"] = "DESWITHISO9797"; + algorithms["DESEDE64"] = "DESEDEMAC64"; + + algorithms["DESEDE64WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING"; + algorithms["DESEDEISO9797ALG1MACWITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING"; + algorithms["DESEDEISO9797ALG1WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING"; + + algorithms["ISO9797ALG3"] = "ISO9797ALG3MAC"; + algorithms["ISO9797ALG3MACWITHISO7816-4PADDING"] = "ISO9797ALG3WITHISO7816-4PADDING"; + + algorithms["SKIPJACK"] = "SKIPJACKMAC"; + algorithms["SKIPJACK/CFB8"] = "SKIPJACKMAC/CFB8"; + algorithms["IDEA"] = "IDEAMAC"; + algorithms["IDEA/CFB8"] = "IDEAMAC/CFB8"; + algorithms["RC2"] = "RC2MAC"; + algorithms["RC2/CFB8"] = "RC2MAC/CFB8"; + algorithms["RC5"] = "RC5MAC"; + algorithms["RC5/CFB8"] = "RC5MAC/CFB8"; + algorithms["GOST28147"] = "GOST28147MAC"; + algorithms["VMPC"] = "VMPCMAC"; + algorithms["VMPC-MAC"] = "VMPCMAC"; + algorithms["SIPHASH"] = "SIPHASH-2-4"; + + algorithms["PBEWITHHMACSHA"] = "PBEWITHHMACSHA1"; + algorithms["1.3.14.3.2.26"] = "PBEWITHHMACSHA1"; + } + +// /// +// /// Returns a ObjectIdentifier for a given digest mechanism. +// /// +// /// A string representation of the digest meanism. +// /// A DerObjectIdentifier, null if the Oid is not available. +// public static DerObjectIdentifier GetObjectIdentifier( +// string mechanism) +// { +// mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)]; +// +// if (mechanism != null) +// { +// return (DerObjectIdentifier)oids[mechanism]; +// } +// +// return null; +// } + +// public static ICollection Algorithms +// { +// get { return oids.Keys; } +// } + + public static IMac GetMac( + DerObjectIdentifier id) + { + return GetMac(id.Id); + } + + public static IMac GetMac( + string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + + string mechanism = (string) algorithms[upper]; + + if (mechanism == null) + { + mechanism = upper; + } + + if (mechanism.StartsWith("PBEWITH")) + { + mechanism = mechanism.Substring("PBEWITH".Length); + } + + if (mechanism.StartsWith("HMAC")) + { + string digestName; + if (mechanism.StartsWith("HMAC-") || mechanism.StartsWith("HMAC/")) + { + digestName = mechanism.Substring(5); + } + else + { + digestName = mechanism.Substring(4); + } + + return new HMac(DigestUtilities.GetDigest(digestName)); + } + + if (mechanism == "AESCMAC") + { + return new CMac(new AesFastEngine()); + } + if (mechanism == "DESMAC") + { + return new CbcBlockCipherMac(new DesEngine()); + } + if (mechanism == "DESMAC/CFB8") + { + return new CfbBlockCipherMac(new DesEngine()); + } + if (mechanism == "DESMAC64") + { + return new CbcBlockCipherMac(new DesEngine(), 64); + } + if (mechanism == "DESEDECMAC") + { + return new CMac(new DesEdeEngine()); + } + if (mechanism == "DESEDEMAC") + { + return new CbcBlockCipherMac(new DesEdeEngine()); + } + if (mechanism == "DESEDEMAC/CFB8") + { + return new CfbBlockCipherMac(new DesEdeEngine()); + } + if (mechanism == "DESEDEMAC64") + { + return new CbcBlockCipherMac(new DesEdeEngine(), 64); + } + if (mechanism == "DESEDEMAC64WITHISO7816-4PADDING") + { + return new CbcBlockCipherMac(new DesEdeEngine(), 64, new ISO7816d4Padding()); + } + if (mechanism == "DESWITHISO9797" + || mechanism == "ISO9797ALG3MAC") + { + return new ISO9797Alg3Mac(new DesEngine()); + } + if (mechanism == "ISO9797ALG3WITHISO7816-4PADDING") + { + return new ISO9797Alg3Mac(new DesEngine(), new ISO7816d4Padding()); + } + if (mechanism == "SKIPJACKMAC") + { + return new CbcBlockCipherMac(new SkipjackEngine()); + } + if (mechanism == "SKIPJACKMAC/CFB8") + { + return new CfbBlockCipherMac(new SkipjackEngine()); + } +#if INCLUDE_IDEA + if (mechanism == "IDEAMAC") + { + return new CbcBlockCipherMac(new IdeaEngine()); + } + if (mechanism == "IDEAMAC/CFB8") + { + return new CfbBlockCipherMac(new IdeaEngine()); + } +#endif + if (mechanism == "RC2MAC") + { + return new CbcBlockCipherMac(new RC2Engine()); + } + if (mechanism == "RC2MAC/CFB8") + { + return new CfbBlockCipherMac(new RC2Engine()); + } + if (mechanism == "RC5MAC") + { + return new CbcBlockCipherMac(new RC532Engine()); + } + if (mechanism == "RC5MAC/CFB8") + { + return new CfbBlockCipherMac(new RC532Engine()); + } + if (mechanism == "GOST28147MAC") + { + return new Gost28147Mac(); + } + if (mechanism == "VMPCMAC") + { + return new VmpcMac(); + } + if (mechanism == "SIPHASH-2-4") + { + return new SipHash(); + } + throw new SecurityUtilityException("Mac " + mechanism + " not recognised."); + } + + public static string GetAlgorithmName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + + public static byte[] DoFinal( + IMac mac) + { + byte[] b = new byte[mac.GetMacSize()]; + mac.DoFinal(b, 0); + return b; + } + } +} diff --git a/crypto/src/security/NoSuchAlgorithmException.cs b/crypto/src/security/NoSuchAlgorithmException.cs new file mode 100644 index 000000000..d120c5f77 --- /dev/null +++ b/crypto/src/security/NoSuchAlgorithmException.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.Security +{ + [Obsolete("Never thrown")] +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class NoSuchAlgorithmException : GeneralSecurityException + { + public NoSuchAlgorithmException() : base() {} + public NoSuchAlgorithmException(string message) : base(message) {} + public NoSuchAlgorithmException(string message, Exception exception) : base(message, exception) {} + } +} diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs new file mode 100644 index 000000000..bf448edff --- /dev/null +++ b/crypto/src/security/ParameterUtilities.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Misc; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + public sealed class ParameterUtilities + { + private ParameterUtilities() + { + } + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary basicIVSizes = Platform.CreateHashtable(); + + static ParameterUtilities() + { + AddAlgorithm("AES", + "AESWRAP"); + AddAlgorithm("AES128", + "2.16.840.1.101.3.4.2", + NistObjectIdentifiers.IdAes128Cbc, + NistObjectIdentifiers.IdAes128Cfb, + NistObjectIdentifiers.IdAes128Ecb, + NistObjectIdentifiers.IdAes128Ofb, + NistObjectIdentifiers.IdAes128Wrap); + AddAlgorithm("AES192", + "2.16.840.1.101.3.4.22", + NistObjectIdentifiers.IdAes192Cbc, + NistObjectIdentifiers.IdAes192Cfb, + NistObjectIdentifiers.IdAes192Ecb, + NistObjectIdentifiers.IdAes192Ofb, + NistObjectIdentifiers.IdAes192Wrap); + AddAlgorithm("AES256", + "2.16.840.1.101.3.4.42", + NistObjectIdentifiers.IdAes256Cbc, + NistObjectIdentifiers.IdAes256Cfb, + NistObjectIdentifiers.IdAes256Ecb, + NistObjectIdentifiers.IdAes256Ofb, + NistObjectIdentifiers.IdAes256Wrap); + AddAlgorithm("BLOWFISH", + "1.3.6.1.4.1.3029.1.2"); + AddAlgorithm("CAMELLIA", + "CAMELLIAWRAP"); + AddAlgorithm("CAMELLIA128", + NttObjectIdentifiers.IdCamellia128Cbc, + NttObjectIdentifiers.IdCamellia128Wrap); + AddAlgorithm("CAMELLIA192", + NttObjectIdentifiers.IdCamellia192Cbc, + NttObjectIdentifiers.IdCamellia192Wrap); + AddAlgorithm("CAMELLIA256", + NttObjectIdentifiers.IdCamellia256Cbc, + NttObjectIdentifiers.IdCamellia256Wrap); + AddAlgorithm("CAST5", + "1.2.840.113533.7.66.10"); + AddAlgorithm("CAST6"); + AddAlgorithm("DES", + OiwObjectIdentifiers.DesCbc, + OiwObjectIdentifiers.DesCfb, + OiwObjectIdentifiers.DesEcb, + OiwObjectIdentifiers.DesOfb); + AddAlgorithm("DESEDE", + "DESEDEWRAP", + "TDEA", + OiwObjectIdentifiers.DesEde, + PkcsObjectIdentifiers.IdAlgCms3DesWrap); + AddAlgorithm("DESEDE3", + PkcsObjectIdentifiers.DesEde3Cbc); + AddAlgorithm("GOST28147", + "GOST", + "GOST-28147", + CryptoProObjectIdentifiers.GostR28147Cbc); + AddAlgorithm("HC128"); + AddAlgorithm("HC256"); +#if INCLUDE_IDEA + AddAlgorithm("IDEA", + "1.3.6.1.4.1.188.7.1.1.2"); +#endif + AddAlgorithm("NOEKEON"); + AddAlgorithm("RC2", + PkcsObjectIdentifiers.RC2Cbc, + PkcsObjectIdentifiers.IdAlgCmsRC2Wrap); + AddAlgorithm("RC4", + "ARC4", + "1.2.840.113549.3.4"); + AddAlgorithm("RC5", + "RC5-32"); + AddAlgorithm("RC5-64"); + AddAlgorithm("RC6"); + AddAlgorithm("RIJNDAEL"); + AddAlgorithm("SALSA20"); + AddAlgorithm("SEED", + KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap, + KisaObjectIdentifiers.IdSeedCbc); + AddAlgorithm("SERPENT"); + AddAlgorithm("SKIPJACK"); + AddAlgorithm("TEA"); + AddAlgorithm("TWOFISH"); + AddAlgorithm("VMPC"); + AddAlgorithm("VMPC-KSA3"); + AddAlgorithm("XTEA"); + + AddBasicIVSizeEntries(8, "BLOWFISH", "DES", "DESEDE", "DESEDE3"); + AddBasicIVSizeEntries(16, "AES", "AES128", "AES192", "AES256", + "CAMELLIA", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "NOEKEON", "SEED"); + + // TODO These algorithms support an IV + // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them + // "RIJNDAEL", "SKIPJACK", "TWOFISH" + } + + private static void AddAlgorithm( + string canonicalName, + params object[] aliases) + { + algorithms[canonicalName] = canonicalName; + + foreach (object alias in aliases) + { + algorithms[alias.ToString()] = canonicalName; + } + } + + private static void AddBasicIVSizeEntries(int size, params string[] algorithms) + { + foreach (string algorithm in algorithms) + { + basicIVSizes.Add(algorithm, size); + } + } + + public static string GetCanonicalAlgorithmName( + string algorithm) + { + return (string) algorithms[Platform.ToUpperInvariant(algorithm)]; + } + + public static KeyParameter CreateKeyParameter( + DerObjectIdentifier algOid, + byte[] keyBytes) + { + return CreateKeyParameter(algOid.Id, keyBytes, 0, keyBytes.Length); + } + + public static KeyParameter CreateKeyParameter( + string algorithm, + byte[] keyBytes) + { + return CreateKeyParameter(algorithm, keyBytes, 0, keyBytes.Length); + } + + public static KeyParameter CreateKeyParameter( + DerObjectIdentifier algOid, + byte[] keyBytes, + int offset, + int length) + { + return CreateKeyParameter(algOid.Id, keyBytes, offset, length); + } + + public static KeyParameter CreateKeyParameter( + string algorithm, + byte[] keyBytes, + int offset, + int length) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + string canonical = GetCanonicalAlgorithmName(algorithm); + + if (canonical == null) + throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); + + if (canonical == "DES") + return new DesParameters(keyBytes, offset, length); + + if (canonical == "DESEDE" || canonical =="DESEDE3") + return new DesEdeParameters(keyBytes, offset, length); + + if (canonical == "RC2") + return new RC2Parameters(keyBytes, offset, length); + + return new KeyParameter(keyBytes, offset, length); + } + + public static ICipherParameters GetCipherParameters( + DerObjectIdentifier algOid, + ICipherParameters key, + Asn1Object asn1Params) + { + return GetCipherParameters(algOid.Id, key, asn1Params); + } + + public static ICipherParameters GetCipherParameters( + string algorithm, + ICipherParameters key, + Asn1Object asn1Params) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + string canonical = GetCanonicalAlgorithmName(algorithm); + + if (canonical == null) + throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); + + byte[] iv = null; + + try + { + // TODO These algorithms support an IV + // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them + // "RIJNDAEL", "SKIPJACK", "TWOFISH" + + int basicIVKeySize = FindBasicIVSize(canonical); + if (basicIVKeySize != -1 + || canonical == "RIJNDAEL" || canonical == "SKIPJACK" || canonical == "TWOFISH") + { + iv = ((Asn1OctetString) asn1Params).GetOctets(); + } + else if (canonical == "CAST5") + { + iv = Cast5CbcParameters.GetInstance(asn1Params).GetIV(); + } +#if INCLUDE_IDEA + else if (canonical == "IDEA") + { + iv = IdeaCbcPar.GetInstance(asn1Params).GetIV(); + } +#endif + else if (canonical == "RC2") + { + iv = RC2CbcParameter.GetInstance(asn1Params).GetIV(); + } + } + catch (Exception e) + { + throw new ArgumentException("Could not process ASN.1 parameters", e); + } + + if (iv != null) + { + return new ParametersWithIV(key, iv); + } + + throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); + } + + public static Asn1Encodable GenerateParameters( + DerObjectIdentifier algID, + SecureRandom random) + { + return GenerateParameters(algID.Id, random); + } + + public static Asn1Encodable GenerateParameters( + string algorithm, + SecureRandom random) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + string canonical = GetCanonicalAlgorithmName(algorithm); + + if (canonical == null) + throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); + + // TODO These algorithms support an IV + // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them + // "RIJNDAEL", "SKIPJACK", "TWOFISH" + + int basicIVKeySize = FindBasicIVSize(canonical); + if (basicIVKeySize != -1) + return CreateIVOctetString(random, basicIVKeySize); + + if (canonical == "CAST5") + return new Cast5CbcParameters(CreateIV(random, 8), 128); + +#if INCLUDE_IDEA + if (canonical == "IDEA") + return new IdeaCbcPar(CreateIV(random, 8)); +#endif + + if (canonical == "RC2") + return new RC2CbcParameter(CreateIV(random, 8)); + + throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); + } + + private static Asn1OctetString CreateIVOctetString( + SecureRandom random, + int ivLength) + { + return new DerOctetString(CreateIV(random, ivLength)); + } + + private static byte[] CreateIV( + SecureRandom random, + int ivLength) + { + byte[] iv = new byte[ivLength]; + random.NextBytes(iv); + return iv; + } + + private static int FindBasicIVSize( + string canonicalName) + { + if (!basicIVSizes.Contains(canonicalName)) + return -1; + + return (int)basicIVSizes[canonicalName]; + } + } +} diff --git a/crypto/src/security/PbeUtilities.cs b/crypto/src/security/PbeUtilities.cs new file mode 100644 index 000000000..56d68ba0a --- /dev/null +++ b/crypto/src/security/PbeUtilities.cs @@ -0,0 +1,663 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.BC; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// + /// + public sealed class PbeUtilities + { + private PbeUtilities() + { + } + + const string Pkcs5S1 = "Pkcs5S1"; + const string Pkcs5S2 = "Pkcs5S2"; + const string Pkcs12 = "Pkcs12"; + const string OpenSsl = "OpenSsl"; + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary algorithmType = Platform.CreateHashtable(); + private static readonly IDictionary oids = Platform.CreateHashtable(); + + static PbeUtilities() + { + algorithms["PKCS5SCHEME1"] = "Pkcs5scheme1"; + algorithms["PKCS5SCHEME2"] = "Pkcs5scheme2"; + algorithms[PkcsObjectIdentifiers.IdPbeS2.Id] = "Pkcs5scheme2"; +// algorithms[PkcsObjectIdentifiers.IdPbkdf2.Id] = "Pkcs5scheme2"; + + // FIXME Add support for these? (see Pkcs8Generator) +// algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "Pkcs5scheme2"; +// algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "Pkcs5scheme2"; +// algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "Pkcs5scheme2"; +// algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "Pkcs5scheme2"; + + algorithms["PBEWITHMD2ANDDES-CBC"] = "PBEwithMD2andDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithMD2AndDesCbc.Id] = "PBEwithMD2andDES-CBC"; + algorithms["PBEWITHMD2ANDRC2-CBC"] = "PBEwithMD2andRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc.Id] = "PBEwithMD2andRC2-CBC"; + algorithms["PBEWITHMD5ANDDES-CBC"] = "PBEwithMD5andDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithMD5AndDesCbc.Id] = "PBEwithMD5andDES-CBC"; + algorithms["PBEWITHMD5ANDRC2-CBC"] = "PBEwithMD5andRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc.Id] = "PBEwithMD5andRC2-CBC"; + algorithms["PBEWITHSHA1ANDDES"] = "PBEwithSHA-1andDES-CBC"; + algorithms["PBEWITHSHA-1ANDDES"] = "PBEwithSHA-1andDES-CBC"; + algorithms["PBEWITHSHA1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC"; + algorithms["PBEWITHSHA-1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEwithSHA-1andDES-CBC"; + algorithms["PBEWITHSHA1ANDRC2"] = "PBEwithSHA-1andRC2-CBC"; + algorithms["PBEWITHSHA-1ANDRC2"] = "PBEwithSHA-1andRC2-CBC"; + algorithms["PBEWITHSHA1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC"; + algorithms["PBEWITHSHA-1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEwithSHA-1andRC2-CBC"; + algorithms["PKCS12"] = "Pkcs12"; + algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.Id] = "PBEwithSHA-1and128bitAES-CBC-BC"; + algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.Id] = "PBEwithSHA-1and192bitAES-CBC-BC"; + algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.Id] = "PBEwithSHA-1and256bitAES-CBC-BC"; + algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.Id] = "PBEwithSHA-256and128bitAES-CBC-BC"; + algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.Id] = "PBEwithSHA-256and192bitAES-CBC-BC"; + algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.Id] = "PBEwithSHA-256and256bitAES-CBC-BC"; + algorithms["PBEWITHSHAAND128BITRC4"] = "PBEwithSHA-1and128bitRC4"; + algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4"; + algorithms["PBEWITHSHA-1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEwithSHA-1and128bitRC4"; + algorithms["PBEWITHSHAAND40BITRC4"] = "PBEwithSHA-1and40bitRC4"; + algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4"; + algorithms["PBEWITHSHA-1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEwithSHA-1and40bitRC4"; + algorithms["PBEWITHSHAAND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHAAND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHA1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHA-1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHA-1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEwithSHA-1and3-keyDESEDE-CBC"; + algorithms["PBEWITHSHAAND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHAAND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHA1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHA-1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHA-1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEwithSHA-1and2-keyDESEDE-CBC"; + algorithms["PBEWITHSHAAND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC"; + algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC"; + algorithms["PBEWITHSHA-1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEwithSHA-1and128bitRC2-CBC"; + algorithms["PBEWITHSHAAND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC"; + algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC"; + algorithms["PBEWITHSHA-1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC"; + algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEwithSHA-1and40bitRC2-CBC"; + algorithms["PBEWITHSHAAND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC"; + algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC"; + algorithms["PBEWITHSHAAND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC"; + algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC"; + algorithms["PBEWITHSHAAND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC"; + algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC"; + algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC"; + algorithms["PBEWITHSHA256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC"; + algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC"; + algorithms["PBEWITHSHA256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC"; + algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC"; + algorithms["PBEWITHSHA256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC"; + algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC"; + algorithms["PBEWITHSHAANDIDEA"] = "PBEwithSHA-1andIDEA-CBC"; + algorithms["PBEWITHSHAANDIDEA-CBC"] = "PBEwithSHA-1andIDEA-CBC"; + algorithms["PBEWITHSHAANDTWOFISH"] = "PBEwithSHA-1andTWOFISH-CBC"; + algorithms["PBEWITHSHAANDTWOFISH-CBC"] = "PBEwithSHA-1andTWOFISH-CBC"; + algorithms["PBEWITHHMACSHA1"] = "PBEwithHmacSHA-1"; + algorithms["PBEWITHHMACSHA-1"] = "PBEwithHmacSHA-1"; + algorithms[OiwObjectIdentifiers.IdSha1.Id] = "PBEwithHmacSHA-1"; + algorithms["PBEWITHHMACSHA224"] = "PBEwithHmacSHA-224"; + algorithms["PBEWITHHMACSHA-224"] = "PBEwithHmacSHA-224"; + algorithms[NistObjectIdentifiers.IdSha224.Id] = "PBEwithHmacSHA-224"; + algorithms["PBEWITHHMACSHA256"] = "PBEwithHmacSHA-256"; + algorithms["PBEWITHHMACSHA-256"] = "PBEwithHmacSHA-256"; + algorithms[NistObjectIdentifiers.IdSha256.Id] = "PBEwithHmacSHA-256"; + algorithms["PBEWITHHMACRIPEMD128"] = "PBEwithHmacRipeMD128"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "PBEwithHmacRipeMD128"; + algorithms["PBEWITHHMACRIPEMD160"] = "PBEwithHmacRipeMD160"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "PBEwithHmacRipeMD160"; + algorithms["PBEWITHHMACRIPEMD256"] = "PBEwithHmacRipeMD256"; + algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "PBEwithHmacRipeMD256"; + algorithms["PBEWITHHMACTIGER"] = "PBEwithHmacTiger"; + + algorithms["PBEWITHMD5AND128BITAES-CBC-OPENSSL"] = "PBEwithMD5and128bitAES-CBC-OpenSSL"; + algorithms["PBEWITHMD5AND192BITAES-CBC-OPENSSL"] = "PBEwithMD5and192bitAES-CBC-OpenSSL"; + algorithms["PBEWITHMD5AND256BITAES-CBC-OPENSSL"] = "PBEwithMD5and256bitAES-CBC-OpenSSL"; + + algorithmType["Pkcs5scheme1"] = Pkcs5S1; + algorithmType["Pkcs5scheme2"] = Pkcs5S2; + algorithmType["PBEwithMD2andDES-CBC"] = Pkcs5S1; + algorithmType["PBEwithMD2andRC2-CBC"] = Pkcs5S1; + algorithmType["PBEwithMD5andDES-CBC"] = Pkcs5S1; + algorithmType["PBEwithMD5andRC2-CBC"] = Pkcs5S1; + algorithmType["PBEwithSHA-1andDES-CBC"] = Pkcs5S1; + algorithmType["PBEwithSHA-1andRC2-CBC"] = Pkcs5S1; + algorithmType["Pkcs12"] = Pkcs12; + algorithmType["PBEwithSHA-1and128bitRC4"] = Pkcs12; + algorithmType["PBEwithSHA-1and40bitRC4"] = Pkcs12; + algorithmType["PBEwithSHA-1and3-keyDESEDE-CBC"] = Pkcs12; + algorithmType["PBEwithSHA-1and2-keyDESEDE-CBC"] = Pkcs12; + algorithmType["PBEwithSHA-1and128bitRC2-CBC"] = Pkcs12; + algorithmType["PBEwithSHA-1and40bitRC2-CBC"] = Pkcs12; + algorithmType["PBEwithSHA-1and128bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-1and192bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-1and256bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-256and128bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-256and192bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-256and256bitAES-CBC-BC"] = Pkcs12; + algorithmType["PBEwithSHA-1andIDEA-CBC"] = Pkcs12; + algorithmType["PBEwithSHA-1andTWOFISH-CBC"] = Pkcs12; + algorithmType["PBEwithHmacSHA-1"] = Pkcs12; + algorithmType["PBEwithHmacSHA-224"] = Pkcs12; + algorithmType["PBEwithHmacSHA-256"] = Pkcs12; + algorithmType["PBEwithHmacRipeMD128"] = Pkcs12; + algorithmType["PBEwithHmacRipeMD160"] = Pkcs12; + algorithmType["PBEwithHmacRipeMD256"] = Pkcs12; + algorithmType["PBEwithHmacTiger"] = Pkcs12; + + algorithmType["PBEwithMD5and128bitAES-CBC-OpenSSL"] = OpenSsl; + algorithmType["PBEwithMD5and192bitAES-CBC-OpenSSL"] = OpenSsl; + algorithmType["PBEwithMD5and256bitAES-CBC-OpenSSL"] = OpenSsl; + + oids["PBEwithMD2andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndDesCbc; + oids["PBEwithMD2andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc; + oids["PBEwithMD5andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndDesCbc; + oids["PBEwithMD5andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc; + oids["PBEwithSHA-1andDES-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndDesCbc; + oids["PBEwithSHA-1andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc; + oids["PBEwithSHA-1and128bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4; + oids["PBEwithSHA-1and40bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4; + oids["PBEwithSHA-1and3-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc; + oids["PBEwithSHA-1and2-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc; + oids["PBEwithSHA-1and128bitRC2-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc; + oids["PBEwithSHA-1and40bitRC2-CBC"] = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc; + oids["PBEwithHmacSHA-1"] = OiwObjectIdentifiers.IdSha1; + oids["PBEwithHmacSHA-224"] = NistObjectIdentifiers.IdSha224; + oids["PBEwithHmacSHA-256"] = NistObjectIdentifiers.IdSha256; + oids["PBEwithHmacRipeMD128"] = TeleTrusTObjectIdentifiers.RipeMD128; + oids["PBEwithHmacRipeMD160"] = TeleTrusTObjectIdentifiers.RipeMD160; + oids["PBEwithHmacRipeMD256"] = TeleTrusTObjectIdentifiers.RipeMD256; + oids["Pkcs5scheme2"] = PkcsObjectIdentifiers.IdPbeS2; + } + + static PbeParametersGenerator MakePbeGenerator( + string type, + IDigest digest, + byte[] key, + byte[] salt, + int iterationCount) + { + PbeParametersGenerator generator; + + if (type.Equals(Pkcs5S1)) + { + generator = new Pkcs5S1ParametersGenerator(digest); + } + else if (type.Equals(Pkcs5S2)) + { + generator = new Pkcs5S2ParametersGenerator(); + } + else if (type.Equals(Pkcs12)) + { + generator = new Pkcs12ParametersGenerator(digest); + } + else if (type.Equals(OpenSsl)) + { + generator = new OpenSslPbeParametersGenerator(); + } + else + { + throw new ArgumentException("Unknown PBE type: " + type, "type"); + } + + generator.Init(key, salt, iterationCount); + return generator; + } + + /// + /// Returns a ObjectIdentifier for a give encoding. + /// + /// A string representation of the encoding. + /// A DerObjectIdentifier, null if the Oid is not available. + public static DerObjectIdentifier GetObjectIdentifier( + string mechanism) + { + mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)]; + if (mechanism != null) + { + return (DerObjectIdentifier)oids[mechanism]; + } + return null; + } + + public static ICollection Algorithms + { + get { return oids.Keys; } + } + + public static bool IsPkcs12( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + return mechanism != null && Pkcs12.Equals(algorithmType[mechanism]); + } + + public static bool IsPkcs5Scheme1( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + return mechanism != null && Pkcs5S1.Equals(algorithmType[mechanism]); + } + + public static bool IsPkcs5Scheme2( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + return mechanism != null && Pkcs5S2.Equals(algorithmType[mechanism]); + } + + public static bool IsOpenSsl( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + return mechanism != null && OpenSsl.Equals(algorithmType[mechanism]); + } + + public static bool IsPbeAlgorithm( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + return mechanism != null && algorithmType[mechanism] != null; + } + + public static Asn1Encodable GenerateAlgorithmParameters( + DerObjectIdentifier algorithmOid, + byte[] salt, + int iterationCount) + { + return GenerateAlgorithmParameters(algorithmOid.Id, salt, iterationCount); + } + + public static Asn1Encodable GenerateAlgorithmParameters( + string algorithm, + byte[] salt, + int iterationCount) + { + if (IsPkcs12(algorithm)) + { + return new Pkcs12PbeParams(salt, iterationCount); + } + else if (IsPkcs5Scheme2(algorithm)) + { + return new Pbkdf2Params(salt, iterationCount); + } + else + { + return new PbeParameter(salt, iterationCount); + } + } + + public static ICipherParameters GenerateCipherParameters( + DerObjectIdentifier algorithmOid, + char[] password, + Asn1Encodable pbeParameters) + { + return GenerateCipherParameters(algorithmOid.Id, password, false, pbeParameters); + } + + public static ICipherParameters GenerateCipherParameters( + DerObjectIdentifier algorithmOid, + char[] password, + bool wrongPkcs12Zero, + Asn1Encodable pbeParameters) + { + return GenerateCipherParameters(algorithmOid.Id, password, wrongPkcs12Zero, pbeParameters); + } + + public static ICipherParameters GenerateCipherParameters( + AlgorithmIdentifier algID, + char[] password) + { + return GenerateCipherParameters(algID.ObjectID.Id, password, false, algID.Parameters); + } + + public static ICipherParameters GenerateCipherParameters( + AlgorithmIdentifier algID, + char[] password, + bool wrongPkcs12Zero) + { + return GenerateCipherParameters(algID.ObjectID.Id, password, wrongPkcs12Zero, algID.Parameters); + } + + public static ICipherParameters GenerateCipherParameters( + string algorithm, + char[] password, + Asn1Encodable pbeParameters) + { + return GenerateCipherParameters(algorithm, password, false, pbeParameters); + } + + public static ICipherParameters GenerateCipherParameters( + string algorithm, + char[] password, + bool wrongPkcs12Zero, + Asn1Encodable pbeParameters) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + byte[] keyBytes = null; + byte[] salt = null; + int iterationCount = 0; + + if (IsPkcs12(mechanism)) + { + Pkcs12PbeParams pbeParams = Pkcs12PbeParams.GetInstance(pbeParameters); + salt = pbeParams.GetIV(); + iterationCount = pbeParams.Iterations.IntValue; + keyBytes = PbeParametersGenerator.Pkcs12PasswordToBytes(password, wrongPkcs12Zero); + } + else if (IsPkcs5Scheme2(mechanism)) + { + // See below + } + else + { + PbeParameter pbeParams = PbeParameter.GetInstance(pbeParameters); + salt = pbeParams.GetSalt(); + iterationCount = pbeParams.IterationCount.IntValue; + keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password); + } + + ICipherParameters parameters = null; + + if (IsPkcs5Scheme2(mechanism)) + { + PbeS2Parameters s2p = PbeS2Parameters.GetInstance(pbeParameters.ToAsn1Object()); + AlgorithmIdentifier encScheme = s2p.EncryptionScheme; + DerObjectIdentifier encOid = encScheme.ObjectID; + Asn1Object encParams = encScheme.Parameters.ToAsn1Object(); + + // TODO What about s2p.KeyDerivationFunc.ObjectID? + Pbkdf2Params pbeParams = Pbkdf2Params.GetInstance(s2p.KeyDerivationFunc.Parameters.ToAsn1Object()); + + byte[] iv; + if (encOid.Equals(PkcsObjectIdentifiers.RC2Cbc)) // PKCS5.B.2.3 + { + RC2CbcParameter rc2Params = RC2CbcParameter.GetInstance(encParams); + iv = rc2Params.GetIV(); + } + else + { + iv = Asn1OctetString.GetInstance(encParams).GetOctets(); + } + + salt = pbeParams.GetSalt(); + iterationCount = pbeParams.IterationCount.IntValue; + keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password); + + int keyLength = pbeParams.KeyLength != null + ? pbeParams.KeyLength.IntValue * 8 + : GeneratorUtilities.GetDefaultKeySize(encOid); + + PbeParametersGenerator gen = MakePbeGenerator( + (string)algorithmType[mechanism], null, keyBytes, salt, iterationCount); + + parameters = gen.GenerateDerivedParameters(encOid.Id, keyLength); + + if (iv != null) + { + // FIXME? OpenSSL weirdness with IV of zeros (for ECB keys?) + if (Arrays.AreEqual(iv, new byte[iv.Length])) + { + //Console.Error.Write("***** IV all 0 (length " + iv.Length + ") *****"); + } + else + { + parameters = new ParametersWithIV(parameters, iv); + } + } + } + else if (mechanism.StartsWith("PBEwithSHA-1")) + { + PbeParametersGenerator generator = MakePbeGenerator( + (string) algorithmType[mechanism], new Sha1Digest(), keyBytes, salt, iterationCount); + + if (mechanism.Equals("PBEwithSHA-1and128bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 128, 128); + } + else if (mechanism.Equals("PBEwithSHA-1and192bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 192, 128); + } + else if (mechanism.Equals("PBEwithSHA-1and256bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 256, 128); + } + else if (mechanism.Equals("PBEwithSHA-1and128bitRC4")) + { + parameters = generator.GenerateDerivedParameters("RC4", 128); + } + else if (mechanism.Equals("PBEwithSHA-1and40bitRC4")) + { + parameters = generator.GenerateDerivedParameters("RC4", 40); + } + else if (mechanism.Equals("PBEwithSHA-1and3-keyDESEDE-CBC")) + { + parameters = generator.GenerateDerivedParameters("DESEDE", 192, 64); + } + else if (mechanism.Equals("PBEwithSHA-1and2-keyDESEDE-CBC")) + { + parameters = generator.GenerateDerivedParameters("DESEDE", 128, 64); + } + else if (mechanism.Equals("PBEwithSHA-1and128bitRC2-CBC")) + { + parameters = generator.GenerateDerivedParameters("RC2", 128, 64); + } + else if (mechanism.Equals("PBEwithSHA-1and40bitRC2-CBC")) + { + parameters = generator.GenerateDerivedParameters("RC2", 40, 64); + } + else if (mechanism.Equals("PBEwithSHA-1andDES-CBC")) + { + parameters = generator.GenerateDerivedParameters("DES", 64, 64); + } + else if (mechanism.Equals("PBEwithSHA-1andRC2-CBC")) + { + parameters = generator.GenerateDerivedParameters("RC2", 64, 64); + } + } + else if (mechanism.StartsWith("PBEwithSHA-256")) + { + PbeParametersGenerator generator = MakePbeGenerator( + (string) algorithmType[mechanism], new Sha256Digest(), keyBytes, salt, iterationCount); + + if (mechanism.Equals("PBEwithSHA-256and128bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 128, 128); + } + else if (mechanism.Equals("PBEwithSHA-256and192bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 192, 128); + } + else if (mechanism.Equals("PBEwithSHA-256and256bitAES-CBC-BC")) + { + parameters = generator.GenerateDerivedParameters("AES", 256, 128); + } + } + else if (mechanism.StartsWith("PBEwithMD5")) + { + PbeParametersGenerator generator = MakePbeGenerator( + (string)algorithmType[mechanism], new MD5Digest(), keyBytes, salt, iterationCount); + + if (mechanism.Equals("PBEwithMD5andDES-CBC")) + { + parameters = generator.GenerateDerivedParameters("DES", 64, 64); + } + else if (mechanism.Equals("PBEwithMD5andRC2-CBC")) + { + parameters = generator.GenerateDerivedParameters("RC2", 64, 64); + } + else if (mechanism.Equals("PBEwithMD5and128bitAES-CBC-OpenSSL")) + { + parameters = generator.GenerateDerivedParameters("AES", 128, 128); + } + else if (mechanism.Equals("PBEwithMD5and192bitAES-CBC-OpenSSL")) + { + parameters = generator.GenerateDerivedParameters("AES", 192, 128); + } + else if (mechanism.Equals("PBEwithMD5and256bitAES-CBC-OpenSSL")) + { + parameters = generator.GenerateDerivedParameters("AES", 256, 128); + } + } + else if (mechanism.StartsWith("PBEwithMD2")) + { + PbeParametersGenerator generator = MakePbeGenerator( + (string)algorithmType[mechanism], new MD2Digest(), keyBytes, salt, iterationCount); + if (mechanism.Equals("PBEwithMD2andDES-CBC")) + { + parameters = generator.GenerateDerivedParameters("DES", 64, 64); + } + else if (mechanism.Equals("PBEwithMD2andRC2-CBC")) + { + parameters = generator.GenerateDerivedParameters("RC2", 64, 64); + } + } + else if (mechanism.StartsWith("PBEwithHmac")) + { + string digestName = mechanism.Substring("PBEwithHmac".Length); + IDigest digest = DigestUtilities.GetDigest(digestName); + + PbeParametersGenerator generator = MakePbeGenerator( + (string) algorithmType[mechanism], digest, keyBytes, salt, iterationCount); + + int bitLen = digest.GetDigestSize() * 8; + parameters = generator.GenerateDerivedMacParameters(bitLen); + } + + Array.Clear(keyBytes, 0, keyBytes.Length); + + return FixDesParity(mechanism, parameters); + } + + public static object CreateEngine( + DerObjectIdentifier algorithmOid) + { + return CreateEngine(algorithmOid.Id); + } + + public static object CreateEngine( + AlgorithmIdentifier algID) + { + string algorithm = algID.ObjectID.Id; + + if (IsPkcs5Scheme2(algorithm)) + { + PbeS2Parameters s2p = PbeS2Parameters.GetInstance(algID.Parameters.ToAsn1Object()); + AlgorithmIdentifier encScheme = s2p.EncryptionScheme; + return CipherUtilities.GetCipher(encScheme.ObjectID); + } + + return CreateEngine(algorithm); + } + + public static object CreateEngine( + string algorithm) + { + string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)]; + + if (mechanism.StartsWith("PBEwithHmac")) + { + string digestName = mechanism.Substring("PBEwithHmac".Length); + + return MacUtilities.GetMac("HMAC/" + digestName); + } + + if (mechanism.StartsWith("PBEwithMD2") + || mechanism.StartsWith("PBEwithMD5") + || mechanism.StartsWith("PBEwithSHA-1") + || mechanism.StartsWith("PBEwithSHA-256")) + { + if (mechanism.EndsWith("AES-CBC-BC") || mechanism.EndsWith("AES-CBC-OPENSSL")) + { + return CipherUtilities.GetCipher("AES/CBC"); + } + + if (mechanism.EndsWith("DES-CBC")) + { + return CipherUtilities.GetCipher("DES/CBC"); + } + + if (mechanism.EndsWith("DESEDE-CBC")) + { + return CipherUtilities.GetCipher("DESEDE/CBC"); + } + + if (mechanism.EndsWith("RC2-CBC")) + { + return CipherUtilities.GetCipher("RC2/CBC"); + } + + if (mechanism.EndsWith("RC4")) + { + return CipherUtilities.GetCipher("RC4"); + } + } + + return null; + } + + public static string GetEncodingName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + + private static ICipherParameters FixDesParity(string mechanism, ICipherParameters parameters) + { + if (!mechanism.EndsWith("DES-CBC") & !mechanism.EndsWith("DESEDE-CBC")) + { + return parameters; + } + + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParams = (ParametersWithIV)parameters; + return new ParametersWithIV(FixDesParity(mechanism, ivParams.Parameters), ivParams.GetIV()); + } + + KeyParameter kParam = (KeyParameter)parameters; + byte[] keyBytes = kParam.GetKey(); + DesParameters.SetOddParity(keyBytes); + return new KeyParameter(keyBytes); + } + } +} diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs new file mode 100644 index 000000000..5ebebd55a --- /dev/null +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; + +namespace Org.BouncyCastle.Security +{ + public sealed class PrivateKeyFactory + { + private PrivateKeyFactory() + { + } + + public static AsymmetricKeyParameter CreateKey( + byte[] privateKeyInfoData) + { + return CreateKey( + PrivateKeyInfo.GetInstance( + Asn1Object.FromByteArray(privateKeyInfoData))); + } + + public static AsymmetricKeyParameter CreateKey( + Stream inStr) + { + return CreateKey( + PrivateKeyInfo.GetInstance( + Asn1Object.FromStream(inStr))); + } + + public static AsymmetricKeyParameter CreateKey( + PrivateKeyInfo keyInfo) + { + AlgorithmIdentifier algID = keyInfo.AlgorithmID; + DerObjectIdentifier algOid = algID.ObjectID; + + // TODO See RSAUtil.isRsaOid in Java build + if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption) + || algOid.Equals(X509ObjectIdentifiers.IdEARsa) + || algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss) + || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) + { + RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure( + Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + + return new RsaPrivateCrtKeyParameters( + keyStructure.Modulus, + keyStructure.PublicExponent, + keyStructure.PrivateExponent, + keyStructure.Prime1, + keyStructure.Prime2, + keyStructure.Exponent1, + keyStructure.Exponent2, + keyStructure.Coefficient); + } + // TODO? +// else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber)) + else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement)) + { + DHParameter para = new DHParameter( + Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + DerInteger derX = (DerInteger)keyInfo.PrivateKey; + + BigInteger lVal = para.L; + int l = lVal == null ? 0 : lVal.IntValue; + DHParameters dhParams = new DHParameters(para.P, para.G, null, l); + + return new DHPrivateKeyParameters(derX.Value, dhParams, algOid); + } + else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm)) + { + ElGamalParameter para = new ElGamalParameter( + Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + DerInteger derX = (DerInteger)keyInfo.PrivateKey; + + return new ElGamalPrivateKeyParameters( + derX.Value, + new ElGamalParameters(para.P, para.G)); + } + else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)) + { + DerInteger derX = (DerInteger) keyInfo.PrivateKey; + Asn1Encodable ae = algID.Parameters; + + DsaParameters parameters = null; + if (ae != null) + { + DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object()); + parameters = new DsaParameters(para.P, para.Q, para.G); + } + + return new DsaPrivateKeyParameters(derX.Value, parameters); + } + else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey)) + { + X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object()); + + X9ECParameters x9; + if (para.IsNamedCurve) + { + x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters); + } + else + { + x9 = new X9ECParameters((Asn1Sequence)para.Parameters); + } + + ECPrivateKeyStructure ec = new ECPrivateKeyStructure( + Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + BigInteger d = ec.GetKey(); + + if (para.IsNamedCurve) + { + return new ECPrivateKeyParameters("EC", d, (DerObjectIdentifier)para.Parameters); + } + + ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + return new ECPrivateKeyParameters(d, dParams); + } + else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) + { + Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( + Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + + ECPrivateKeyStructure ec = new ECPrivateKeyStructure( + Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + + ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); + + if (ecP == null) + return null; + + return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet); + } + else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94)) + { + Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( + Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + + DerOctetString derX = (DerOctetString) keyInfo.PrivateKey; + byte[] keyEnc = derX.GetOctets(); + byte[] keyBytes = new byte[keyEnc.Length]; + + for (int i = 0; i != keyEnc.Length; i++) + { + keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian + } + + BigInteger x = new BigInteger(1, keyBytes); + + return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet); + } + else + { + throw new SecurityUtilityException("algorithm identifier in key not recognised"); + } + } + + public static AsymmetricKeyParameter DecryptKey( + char[] passPhrase, + EncryptedPrivateKeyInfo encInfo) + { + return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo)); + } + + public static AsymmetricKeyParameter DecryptKey( + char[] passPhrase, + byte[] encryptedPrivateKeyInfoData) + { + return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData)); + } + + public static AsymmetricKeyParameter DecryptKey( + char[] passPhrase, + Stream encryptedPrivateKeyInfoStream) + { + return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream)); + } + + private static AsymmetricKeyParameter DecryptKey( + char[] passPhrase, + Asn1Object asn1Object) + { + return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object)); + } + + public static byte[] EncryptKey( + DerObjectIdentifier algorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + AsymmetricKeyParameter key) + { + return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + algorithm, passPhrase, salt, iterationCount, key).GetEncoded(); + } + + public static byte[] EncryptKey( + string algorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + AsymmetricKeyParameter key) + { + return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + algorithm, passPhrase, salt, iterationCount, key).GetEncoded(); + } + } +} diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs new file mode 100644 index 000000000..c15e24a41 --- /dev/null +++ b/crypto/src/security/PublicKeyFactory.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; + +namespace Org.BouncyCastle.Security +{ + public sealed class PublicKeyFactory + { + private PublicKeyFactory() + { + } + + public static AsymmetricKeyParameter CreateKey( + byte[] keyInfoData) + { + return CreateKey( + SubjectPublicKeyInfo.GetInstance( + Asn1Object.FromByteArray(keyInfoData))); + } + + public static AsymmetricKeyParameter CreateKey( + Stream inStr) + { + return CreateKey( + SubjectPublicKeyInfo.GetInstance( + Asn1Object.FromStream(inStr))); + } + + public static AsymmetricKeyParameter CreateKey( + SubjectPublicKeyInfo keyInfo) + { + AlgorithmIdentifier algID = keyInfo.AlgorithmID; + DerObjectIdentifier algOid = algID.ObjectID; + + // TODO See RSAUtil.isRsaOid in Java build + if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption) + || algOid.Equals(X509ObjectIdentifiers.IdEARsa) + || algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss) + || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) + { + RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance( + keyInfo.GetPublicKey()); + + return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent); + } + else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber)) + { + Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()); + + DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey()); + + BigInteger y = dhPublicKey.Y.Value; + + if (IsPkcsDHParam(seq)) + return ReadPkcsDHParam(algOid, y, seq); + + DHDomainParameters dhParams = DHDomainParameters.GetInstance(seq); + + BigInteger p = dhParams.P.Value; + BigInteger g = dhParams.G.Value; + BigInteger q = dhParams.Q.Value; + + BigInteger j = null; + if (dhParams.J != null) + { + j = dhParams.J.Value; + } + + DHValidationParameters validation = null; + DHValidationParms dhValidationParms = dhParams.ValidationParms; + if (dhValidationParms != null) + { + byte[] seed = dhValidationParms.Seed.GetBytes(); + BigInteger pgenCounter = dhValidationParms.PgenCounter.Value; + + // TODO Check pgenCounter size? + + validation = new DHValidationParameters(seed, pgenCounter.IntValue); + } + + return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation)); + } + else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement)) + { + Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()); + + DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + + return ReadPkcsDHParam(algOid, derY.Value, seq); + } + else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm)) + { + ElGamalParameter para = new ElGamalParameter( + Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + + return new ElGamalPublicKeyParameters( + derY.Value, + new ElGamalParameters(para.P, para.G)); + } + else if (algOid.Equals(X9ObjectIdentifiers.IdDsa) + || algOid.Equals(OiwObjectIdentifiers.DsaWithSha1)) + { + DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + Asn1Encodable ae = algID.Parameters; + + DsaParameters parameters = null; + if (ae != null) + { + DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object()); + parameters = new DsaParameters(para.P, para.Q, para.G); + } + + return new DsaPublicKeyParameters(derY.Value, parameters); + } + else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey)) + { + X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object()); + + X9ECParameters x9; + if (para.IsNamedCurve) + { + x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters); + } + else + { + x9 = new X9ECParameters((Asn1Sequence)para.Parameters); + } + + Asn1OctetString key = new DerOctetString(keyInfo.PublicKeyData.GetBytes()); + X9ECPoint derQ = new X9ECPoint(x9.Curve, key); + ECPoint q = derQ.Point; + + if (para.IsNamedCurve) + { + return new ECPublicKeyParameters("EC", q, (DerObjectIdentifier)para.Parameters); + } + + ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + return new ECPublicKeyParameters(q, dParams); + } + else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) + { + Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( + (Asn1Sequence) algID.Parameters); + + Asn1OctetString key; + try + { + key = (Asn1OctetString) keyInfo.GetPublicKey(); + } + catch (IOException) + { + throw new ArgumentException("invalid info structure in GOST3410 public key"); + } + + byte[] keyEnc = key.GetOctets(); + byte[] x = new byte[32]; + byte[] y = new byte[32]; + + for (int i = 0; i != y.Length; i++) + { + x[i] = keyEnc[32 - 1 - i]; + } + + for (int i = 0; i != x.Length; i++) + { + y[i] = keyEnc[64 - 1 - i]; + } + + ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); + + if (ecP == null) + return null; + + ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y), false); + + return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet); + } + else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94)) + { + Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters( + (Asn1Sequence) algID.Parameters); + + DerOctetString derY; + try + { + derY = (DerOctetString) keyInfo.GetPublicKey(); + } + catch (IOException) + { + throw new ArgumentException("invalid info structure in GOST3410 public key"); + } + + byte[] keyEnc = derY.GetOctets(); + byte[] keyBytes = new byte[keyEnc.Length]; + + for (int i = 0; i != keyEnc.Length; i++) + { + keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian + } + + BigInteger y = new BigInteger(1, keyBytes); + + return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet); + } + else + { + throw new SecurityUtilityException("algorithm identifier in key not recognised: " + algOid); + } + } + + private static bool IsPkcsDHParam(Asn1Sequence seq) + { + if (seq.Count == 2) + return true; + + if (seq.Count > 3) + return false; + + DerInteger l = DerInteger.GetInstance(seq[2]); + DerInteger p = DerInteger.GetInstance(seq[0]); + + return l.Value.CompareTo(BigInteger.ValueOf(p.Value.BitLength)) <= 0; + } + + private static DHPublicKeyParameters ReadPkcsDHParam(DerObjectIdentifier algOid, + BigInteger y, Asn1Sequence seq) + { + DHParameter para = new DHParameter(seq); + + BigInteger lVal = para.L; + int l = lVal == null ? 0 : lVal.IntValue; + DHParameters dhParams = new DHParameters(para.P, para.G, null, l); + + return new DHPublicKeyParameters(y, dhParams, algOid); + } + } +} diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs new file mode 100644 index 000000000..ac9d98158 --- /dev/null +++ b/crypto/src/security/SecureRandom.cs @@ -0,0 +1,228 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + public class SecureRandom + : Random + { + // Note: all objects of this class should be deriving their random data from + // a single generator appropriate to the digest being used. + private static readonly IRandomGenerator sha1Generator = new DigestRandomGenerator(new Sha1Digest()); + private static readonly IRandomGenerator sha256Generator = new DigestRandomGenerator(new Sha256Digest()); + + private static readonly SecureRandom[] master = { null }; + private static SecureRandom Master + { + get + { + if (master[0] == null) + { + IRandomGenerator gen = sha256Generator; + gen = new ReversedWindowGenerator(gen, 32); + SecureRandom sr = master[0] = new SecureRandom(gen); + + sr.SetSeed(DateTime.Now.Ticks); + sr.SetSeed(new ThreadedSeedGenerator().GenerateSeed(24, true)); + sr.GenerateSeed(1 + sr.Next(32)); + } + + return master[0]; + } + } + + public static SecureRandom GetInstance( + string algorithm) + { + // TODO Compared to JDK, we don't auto-seed if the client forgets - problem? + + // TODO Support all digests more generally, by stripping PRNG and calling DigestUtilities? + string drgName = Platform.ToUpperInvariant(algorithm); + + IRandomGenerator drg = null; + if (drgName == "SHA1PRNG") + { + drg = sha1Generator; + } + else if (drgName == "SHA256PRNG") + { + drg = sha256Generator; + } + + if (drg != null) + { + return new SecureRandom(drg); + } + + throw new ArgumentException("Unrecognised PRNG algorithm: " + algorithm, "algorithm"); + } + + public static byte[] GetSeed( + int length) + { + return Master.GenerateSeed(length); + } + + protected IRandomGenerator generator; + + public SecureRandom() + : this(sha1Generator) + { + SetSeed(GetSeed(8)); + } + + public SecureRandom( + byte[] inSeed) + : this(sha1Generator) + { + SetSeed(inSeed); + } + + /// Use the specified instance of IRandomGenerator as random source. + /// + /// This constructor performs no seeding of either the IRandomGenerator or the + /// constructed SecureRandom. It is the responsibility of the client to provide + /// proper seed material as necessary/appropriate for the given IRandomGenerator + /// implementation. + /// + /// The source to generate all random bytes from. + public SecureRandom( + IRandomGenerator generator) + : base(0) + { + this.generator = generator; + } + + public virtual byte[] GenerateSeed( + int length) + { + SetSeed(DateTime.Now.Ticks); + + byte[] rv = new byte[length]; + NextBytes(rv); + return rv; + } + + public virtual void SetSeed( + byte[] inSeed) + { + generator.AddSeedMaterial(inSeed); + } + + public virtual void SetSeed( + long seed) + { + generator.AddSeedMaterial(seed); + } + + public override int Next() + { + for (;;) + { + int i = NextInt() & int.MaxValue; + + if (i != int.MaxValue) + return i; + } + } + + public override int Next( + int maxValue) + { + if (maxValue < 2) + { + if (maxValue < 0) + throw new ArgumentOutOfRangeException("maxValue", "cannot be negative"); + + return 0; + } + + // Test whether maxValue is a power of 2 + if ((maxValue & -maxValue) == maxValue) + { + int val = NextInt() & int.MaxValue; + long lr = ((long) maxValue * (long) val) >> 31; + return (int) lr; + } + + int bits, result; + do + { + bits = NextInt() & int.MaxValue; + result = bits % maxValue; + } + while (bits - result + (maxValue - 1) < 0); // Ignore results near overflow + + return result; + } + + public override int Next( + int minValue, + int maxValue) + { + if (maxValue <= minValue) + { + if (maxValue == minValue) + return minValue; + + throw new ArgumentException("maxValue cannot be less than minValue"); + } + + int diff = maxValue - minValue; + if (diff > 0) + return minValue + Next(diff); + + for (;;) + { + int i = NextInt(); + + if (i >= minValue && i < maxValue) + return i; + } + } + + public override void NextBytes( + byte[] buffer) + { + generator.NextBytes(buffer); + } + + public virtual void NextBytes( + byte[] buffer, + int start, + int length) + { + generator.NextBytes(buffer, start, length); + } + + private static readonly double DoubleScale = System.Math.Pow(2.0, 64.0); + + public override double NextDouble() + { + return Convert.ToDouble((ulong) NextLong()) / DoubleScale; + } + + public virtual int NextInt() + { + byte[] intBytes = new byte[4]; + NextBytes(intBytes); + + int result = 0; + for (int i = 0; i < 4; i++) + { + result = (result << 8) + (intBytes[i] & 0xff); + } + + return result; + } + + public virtual long NextLong() + { + return ((long)(uint) NextInt() << 32) | (long)(uint) NextInt(); + } + } +} diff --git a/crypto/src/security/SecurityUtilityException.cs b/crypto/src/security/SecurityUtilityException.cs new file mode 100644 index 000000000..02a3e806e --- /dev/null +++ b/crypto/src/security/SecurityUtilityException.cs @@ -0,0 +1,36 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class SecurityUtilityException + : Exception + { + /** + * base constructor. + */ + public SecurityUtilityException() + { + } + + /** + * create a SecurityUtilityException with the given message. + * + * @param message the message to be carried with the exception. + */ + public SecurityUtilityException( + string message) + : base(message) + { + } + + public SecurityUtilityException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/security/SignatureException.cs b/crypto/src/security/SignatureException.cs new file mode 100644 index 000000000..cea3c59cd --- /dev/null +++ b/crypto/src/security/SignatureException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class SignatureException : GeneralSecurityException + { + public SignatureException() : base() { } + public SignatureException(string message) : base(message) { } + public SignatureException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs new file mode 100644 index 000000000..136361532 --- /dev/null +++ b/crypto/src/security/SignerUtilities.cs @@ -0,0 +1,549 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Signer Utility class contains methods that can not be specifically grouped into other classes. + /// + public sealed class SignerUtilities + { + private SignerUtilities() + { + } + + internal static readonly IDictionary algorithms = Platform.CreateHashtable(); + internal static readonly IDictionary oids = Platform.CreateHashtable(); + + static SignerUtilities() + { + algorithms["MD2WITHRSA"] = "MD2withRSA"; + algorithms["MD2WITHRSAENCRYPTION"] = "MD2withRSA"; + algorithms[PkcsObjectIdentifiers.MD2WithRsaEncryption.Id] = "MD2withRSA"; + + algorithms["MD4WITHRSA"] = "MD4withRSA"; + algorithms["MD4WITHRSAENCRYPTION"] = "MD4withRSA"; + algorithms[PkcsObjectIdentifiers.MD4WithRsaEncryption.Id] = "MD4withRSA"; + + algorithms["MD5WITHRSA"] = "MD5withRSA"; + algorithms["MD5WITHRSAENCRYPTION"] = "MD5withRSA"; + algorithms[PkcsObjectIdentifiers.MD5WithRsaEncryption.Id] = "MD5withRSA"; + + algorithms["SHA1WITHRSA"] = "SHA-1withRSA"; + algorithms["SHA1WITHRSAENCRYPTION"] = "SHA-1withRSA"; + algorithms[PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id] = "SHA-1withRSA"; + algorithms["SHA-1WITHRSA"] = "SHA-1withRSA"; + + algorithms["SHA224WITHRSA"] = "SHA-224withRSA"; + algorithms["SHA224WITHRSAENCRYPTION"] = "SHA-224withRSA"; + algorithms[PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id] = "SHA-224withRSA"; + algorithms["SHA-224WITHRSA"] = "SHA-224withRSA"; + + algorithms["SHA256WITHRSA"] = "SHA-256withRSA"; + algorithms["SHA256WITHRSAENCRYPTION"] = "SHA-256withRSA"; + algorithms[PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id] = "SHA-256withRSA"; + algorithms["SHA-256WITHRSA"] = "SHA-256withRSA"; + + algorithms["SHA384WITHRSA"] = "SHA-384withRSA"; + algorithms["SHA384WITHRSAENCRYPTION"] = "SHA-384withRSA"; + algorithms[PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id] = "SHA-384withRSA"; + algorithms["SHA-384WITHRSA"] = "SHA-384withRSA"; + + algorithms["SHA512WITHRSA"] = "SHA-512withRSA"; + algorithms["SHA512WITHRSAENCRYPTION"] = "SHA-512withRSA"; + algorithms[PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id] = "SHA-512withRSA"; + algorithms["SHA-512WITHRSA"] = "SHA-512withRSA"; + + algorithms["PSSWITHRSA"] = "PSSwithRSA"; + algorithms["RSASSA-PSS"] = "PSSwithRSA"; + algorithms[PkcsObjectIdentifiers.IdRsassaPss.Id] = "PSSwithRSA"; + algorithms["RSAPSS"] = "PSSwithRSA"; + + algorithms["SHA1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1"; + algorithms["SHA-1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1"; + algorithms["SHA1WITHRSA/PSS"] = "SHA-1withRSAandMGF1"; + algorithms["SHA-1WITHRSA/PSS"] = "SHA-1withRSAandMGF1"; + + algorithms["SHA224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1"; + algorithms["SHA-224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1"; + algorithms["SHA224WITHRSA/PSS"] = "SHA-224withRSAandMGF1"; + algorithms["SHA-224WITHRSA/PSS"] = "SHA-224withRSAandMGF1"; + + algorithms["SHA256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1"; + algorithms["SHA-256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1"; + algorithms["SHA256WITHRSA/PSS"] = "SHA-256withRSAandMGF1"; + algorithms["SHA-256WITHRSA/PSS"] = "SHA-256withRSAandMGF1"; + + algorithms["SHA384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1"; + algorithms["SHA-384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1"; + algorithms["SHA384WITHRSA/PSS"] = "SHA-384withRSAandMGF1"; + algorithms["SHA-384WITHRSA/PSS"] = "SHA-384withRSAandMGF1"; + + algorithms["SHA512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1"; + algorithms["SHA-512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1"; + algorithms["SHA512WITHRSA/PSS"] = "SHA-512withRSAandMGF1"; + algorithms["SHA-512WITHRSA/PSS"] = "SHA-512withRSAandMGF1"; + + algorithms["RIPEMD128WITHRSA"] = "RIPEMD128withRSA"; + algorithms["RIPEMD128WITHRSAENCRYPTION"] = "RIPEMD128withRSA"; + algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128.Id] = "RIPEMD128withRSA"; + + algorithms["RIPEMD160WITHRSA"] = "RIPEMD160withRSA"; + algorithms["RIPEMD160WITHRSAENCRYPTION"] = "RIPEMD160withRSA"; + algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160.Id] = "RIPEMD160withRSA"; + + algorithms["RIPEMD256WITHRSA"] = "RIPEMD256withRSA"; + algorithms["RIPEMD256WITHRSAENCRYPTION"] = "RIPEMD256withRSA"; + algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256.Id] = "RIPEMD256withRSA"; + + algorithms["NONEWITHRSA"] = "RSA"; + algorithms["RSAWITHNONE"] = "RSA"; + algorithms["RAWRSA"] = "RSA"; + + algorithms["RAWRSAPSS"] = "RAWRSASSA-PSS"; + algorithms["NONEWITHRSAPSS"] = "RAWRSASSA-PSS"; + algorithms["NONEWITHRSASSA-PSS"] = "RAWRSASSA-PSS"; + + algorithms["NONEWITHDSA"] = "NONEwithDSA"; + algorithms["DSAWITHNONE"] = "NONEwithDSA"; + algorithms["RAWDSA"] = "NONEwithDSA"; + + algorithms["DSA"] = "SHA-1withDSA"; + algorithms["DSAWITHSHA1"] = "SHA-1withDSA"; + algorithms["DSAWITHSHA-1"] = "SHA-1withDSA"; + algorithms["SHA/DSA"] = "SHA-1withDSA"; + algorithms["SHA1/DSA"] = "SHA-1withDSA"; + algorithms["SHA-1/DSA"] = "SHA-1withDSA"; + algorithms["SHA1WITHDSA"] = "SHA-1withDSA"; + algorithms["SHA-1WITHDSA"] = "SHA-1withDSA"; + algorithms[X9ObjectIdentifiers.IdDsaWithSha1.Id] = "SHA-1withDSA"; + + algorithms["DSAWITHSHA224"] = "SHA-224withDSA"; + algorithms["DSAWITHSHA-224"] = "SHA-224withDSA"; + algorithms["SHA224/DSA"] = "SHA-224withDSA"; + algorithms["SHA-224/DSA"] = "SHA-224withDSA"; + algorithms["SHA224WITHDSA"] = "SHA-224withDSA"; + algorithms["SHA-224WITHDSA"] = "SHA-224withDSA"; + algorithms[NistObjectIdentifiers.DsaWithSha224.Id] = "SHA-224withDSA"; + + algorithms["DSAWITHSHA256"] = "SHA-256withDSA"; + algorithms["DSAWITHSHA-256"] = "SHA-256withDSA"; + algorithms["SHA256/DSA"] = "SHA-256withDSA"; + algorithms["SHA-256/DSA"] = "SHA-256withDSA"; + algorithms["SHA256WITHDSA"] = "SHA-256withDSA"; + algorithms["SHA-256WITHDSA"] = "SHA-256withDSA"; + algorithms[NistObjectIdentifiers.DsaWithSha256.Id] = "SHA-256withDSA"; + + algorithms["DSAWITHSHA384"] = "SHA-384withDSA"; + algorithms["DSAWITHSHA-384"] = "SHA-384withDSA"; + algorithms["SHA384/DSA"] = "SHA-384withDSA"; + algorithms["SHA-384/DSA"] = "SHA-384withDSA"; + algorithms["SHA384WITHDSA"] = "SHA-384withDSA"; + algorithms["SHA-384WITHDSA"] = "SHA-384withDSA"; + algorithms[NistObjectIdentifiers.DsaWithSha384.Id] = "SHA-384withDSA"; + + algorithms["DSAWITHSHA512"] = "SHA-512withDSA"; + algorithms["DSAWITHSHA-512"] = "SHA-512withDSA"; + algorithms["SHA512/DSA"] = "SHA-512withDSA"; + algorithms["SHA-512/DSA"] = "SHA-512withDSA"; + algorithms["SHA512WITHDSA"] = "SHA-512withDSA"; + algorithms["SHA-512WITHDSA"] = "SHA-512withDSA"; + algorithms[NistObjectIdentifiers.DsaWithSha512.Id] = "SHA-512withDSA"; + + algorithms["NONEWITHECDSA"] = "NONEwithECDSA"; + algorithms["ECDSAWITHNONE"] = "NONEwithECDSA"; + + algorithms["ECDSA"] = "SHA-1withECDSA"; + algorithms["SHA1/ECDSA"] = "SHA-1withECDSA"; + algorithms["SHA-1/ECDSA"] = "SHA-1withECDSA"; + algorithms["ECDSAWITHSHA1"] = "SHA-1withECDSA"; + algorithms["ECDSAWITHSHA-1"] = "SHA-1withECDSA"; + algorithms["SHA1WITHECDSA"] = "SHA-1withECDSA"; + algorithms["SHA-1WITHECDSA"] = "SHA-1withECDSA"; + algorithms[X9ObjectIdentifiers.ECDsaWithSha1.Id] = "SHA-1withECDSA"; + algorithms[TeleTrusTObjectIdentifiers.ECSignWithSha1.Id] = "SHA-1withECDSA"; + + algorithms["SHA224/ECDSA"] = "SHA-224withECDSA"; + algorithms["SHA-224/ECDSA"] = "SHA-224withECDSA"; + algorithms["ECDSAWITHSHA224"] = "SHA-224withECDSA"; + algorithms["ECDSAWITHSHA-224"] = "SHA-224withECDSA"; + algorithms["SHA224WITHECDSA"] = "SHA-224withECDSA"; + algorithms["SHA-224WITHECDSA"] = "SHA-224withECDSA"; + algorithms[X9ObjectIdentifiers.ECDsaWithSha224.Id] = "SHA-224withECDSA"; + + algorithms["SHA256/ECDSA"] = "SHA-256withECDSA"; + algorithms["SHA-256/ECDSA"] = "SHA-256withECDSA"; + algorithms["ECDSAWITHSHA256"] = "SHA-256withECDSA"; + algorithms["ECDSAWITHSHA-256"] = "SHA-256withECDSA"; + algorithms["SHA256WITHECDSA"] = "SHA-256withECDSA"; + algorithms["SHA-256WITHECDSA"] = "SHA-256withECDSA"; + algorithms[X9ObjectIdentifiers.ECDsaWithSha256.Id] = "SHA-256withECDSA"; + + algorithms["SHA384/ECDSA"] = "SHA-384withECDSA"; + algorithms["SHA-384/ECDSA"] = "SHA-384withECDSA"; + algorithms["ECDSAWITHSHA384"] = "SHA-384withECDSA"; + algorithms["ECDSAWITHSHA-384"] = "SHA-384withECDSA"; + algorithms["SHA384WITHECDSA"] = "SHA-384withECDSA"; + algorithms["SHA-384WITHECDSA"] = "SHA-384withECDSA"; + algorithms[X9ObjectIdentifiers.ECDsaWithSha384.Id] = "SHA-384withECDSA"; + + algorithms["SHA512/ECDSA"] = "SHA-512withECDSA"; + algorithms["SHA-512/ECDSA"] = "SHA-512withECDSA"; + algorithms["ECDSAWITHSHA512"] = "SHA-512withECDSA"; + algorithms["ECDSAWITHSHA-512"] = "SHA-512withECDSA"; + algorithms["SHA512WITHECDSA"] = "SHA-512withECDSA"; + algorithms["SHA-512WITHECDSA"] = "SHA-512withECDSA"; + algorithms[X9ObjectIdentifiers.ECDsaWithSha512.Id] = "SHA-512withECDSA"; + + algorithms["RIPEMD160/ECDSA"] = "RIPEMD160withECDSA"; + algorithms["SHA-512/ECDSA"] = "RIPEMD160withECDSA"; + algorithms["ECDSAWITHRIPEMD160"] = "RIPEMD160withECDSA"; + algorithms["ECDSAWITHRIPEMD160"] = "RIPEMD160withECDSA"; + algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA"; + algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA"; + algorithms[TeleTrusTObjectIdentifiers.ECSignWithRipeMD160.Id] = "RIPEMD160withECDSA"; + + algorithms["GOST-3410"] = "GOST3410"; + algorithms["GOST-3410-94"] = "GOST3410"; + algorithms["GOST3411WITHGOST3410"] = "GOST3410"; + algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94.Id] = "GOST3410"; + + algorithms["ECGOST-3410"] = "ECGOST3410"; + algorithms["ECGOST-3410-2001"] = "ECGOST3410"; + algorithms["GOST3411WITHECGOST3410"] = "ECGOST3410"; + algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001.Id] = "ECGOST3410"; + + + + oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption; + oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption; + oids["MD5withRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption; + + oids["SHA-1withRSA"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption; + oids["SHA-224withRSA"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption; + oids["SHA-256withRSA"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption; + oids["SHA-384withRSA"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption; + oids["SHA-512withRSA"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption; + + oids["PSSwithRSA"] = PkcsObjectIdentifiers.IdRsassaPss; + oids["SHA-1withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss; + oids["SHA-224withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss; + oids["SHA-256withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss; + oids["SHA-384withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss; + oids["SHA-512withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss; + + oids["RIPEMD128withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128; + oids["RIPEMD160withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160; + oids["RIPEMD256withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256; + + oids["SHA-1withDSA"] = X9ObjectIdentifiers.IdDsaWithSha1; + + oids["SHA-1withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha1; + oids["SHA-224withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha224; + oids["SHA-256withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha256; + oids["SHA-384withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha384; + oids["SHA-512withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha512; + + oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94; + oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001; + } + + /// + /// Returns a ObjectIdentifier for a give encoding. + /// + /// A string representation of the encoding. + /// A DerObjectIdentifier, null if the Oid is not available. + // TODO Don't really want to support this + public static DerObjectIdentifier GetObjectIdentifier( + string mechanism) + { + if (mechanism == null) + throw new ArgumentNullException("mechanism"); + + mechanism = Platform.ToUpperInvariant(mechanism); + string aliased = (string) algorithms[mechanism]; + + if (aliased != null) + mechanism = aliased; + + return (DerObjectIdentifier) oids[mechanism]; + } + + public static ICollection Algorithms + { + get { return oids.Keys; } + } + + public static Asn1Encodable GetDefaultX509Parameters( + DerObjectIdentifier id) + { + return GetDefaultX509Parameters(id.Id); + } + + public static Asn1Encodable GetDefaultX509Parameters( + string algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm = Platform.ToUpperInvariant(algorithm); + + string mechanism = (string) algorithms[algorithm]; + + if (mechanism == null) + mechanism = algorithm; + + if (mechanism == "PSSwithRSA") + { + // TODO The Sha1Digest here is a default. In JCE version, the actual digest + // to be used can be overridden by subsequent parameter settings. + return GetPssX509Parameters("SHA-1"); + } + + if (mechanism.EndsWith("withRSAandMGF1")) + { + string digestName = mechanism.Substring(0, mechanism.Length - "withRSAandMGF1".Length); + return GetPssX509Parameters(digestName); + } + + return DerNull.Instance; + } + + private static Asn1Encodable GetPssX509Parameters( + string digestName) + { + AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier( + DigestUtilities.GetObjectIdentifier(digestName), DerNull.Instance); + + // TODO Is it possible for the MGF hash alg to be different from the PSS one? + AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier( + PkcsObjectIdentifiers.IdMgf1, hashAlgorithm); + + int saltLen = DigestUtilities.GetDigest(digestName).GetDigestSize(); + return new RsassaPssParameters(hashAlgorithm, maskGenAlgorithm, + new DerInteger(saltLen), new DerInteger(1)); + } + + public static ISigner GetSigner( + DerObjectIdentifier id) + { + return GetSigner(id.Id); + } + + public static ISigner GetSigner( + string algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm = Platform.ToUpperInvariant(algorithm); + + string mechanism = (string) algorithms[algorithm]; + + if (mechanism == null) + mechanism = algorithm; + + if (mechanism.Equals("RSA")) + { + return (new RsaDigestSigner(new NullDigest())); + } + if (mechanism.Equals("MD2withRSA")) + { + return (new RsaDigestSigner(new MD2Digest())); + } + if (mechanism.Equals("MD4withRSA")) + { + return (new RsaDigestSigner(new MD4Digest())); + } + if (mechanism.Equals("MD5withRSA")) + { + return (new RsaDigestSigner(new MD5Digest())); + } + if (mechanism.Equals("SHA-1withRSA")) + { + return (new RsaDigestSigner(new Sha1Digest())); + } + if (mechanism.Equals("SHA-224withRSA")) + { + return (new RsaDigestSigner(new Sha224Digest())); + } + if (mechanism.Equals("SHA-256withRSA")) + { + return (new RsaDigestSigner(new Sha256Digest())); + } + if (mechanism.Equals("SHA-384withRSA")) + { + return (new RsaDigestSigner(new Sha384Digest())); + } + if (mechanism.Equals("SHA-512withRSA")) + { + return (new RsaDigestSigner(new Sha512Digest())); + } + if (mechanism.Equals("RIPEMD128withRSA")) + { + return (new RsaDigestSigner(new RipeMD128Digest())); + } + if (mechanism.Equals("RIPEMD160withRSA")) + { + return (new RsaDigestSigner(new RipeMD160Digest())); + } + if (mechanism.Equals("RIPEMD256withRSA")) + { + return (new RsaDigestSigner(new RipeMD256Digest())); + } + + if (mechanism.Equals("RAWRSASSA-PSS")) + { + // TODO Add support for other parameter settings + return PssSigner.CreateRawSigner(new RsaBlindedEngine(), new Sha1Digest()); + } + if (mechanism.Equals("PSSwithRSA")) + { + // TODO The Sha1Digest here is a default. In JCE version, the actual digest + // to be used can be overridden by subsequent parameter settings. + return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest())); + } + if (mechanism.Equals("SHA-1withRSAandMGF1")) + { + return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest())); + } + if (mechanism.Equals("SHA-224withRSAandMGF1")) + { + return (new PssSigner(new RsaBlindedEngine(), new Sha224Digest())); + } + if (mechanism.Equals("SHA-256withRSAandMGF1")) + { + return (new PssSigner(new RsaBlindedEngine(), new Sha256Digest())); + } + if (mechanism.Equals("SHA-384withRSAandMGF1")) + { + return (new PssSigner(new RsaBlindedEngine(), new Sha384Digest())); + } + if (mechanism.Equals("SHA-512withRSAandMGF1")) + { + return (new PssSigner(new RsaBlindedEngine(), new Sha512Digest())); + } + + if (mechanism.Equals("NONEwithDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new NullDigest())); + } + if (mechanism.Equals("SHA-1withDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new Sha1Digest())); + } + if (mechanism.Equals("SHA-224withDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new Sha224Digest())); + } + if (mechanism.Equals("SHA-256withDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new Sha256Digest())); + } + if (mechanism.Equals("SHA-384withDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new Sha384Digest())); + } + if (mechanism.Equals("SHA-512withDSA")) + { + return (new DsaDigestSigner(new DsaSigner(), new Sha512Digest())); + } + + if (mechanism.Equals("NONEwithECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new NullDigest())); + } + if (mechanism.Equals("SHA-1withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new Sha1Digest())); + } + if (mechanism.Equals("SHA-224withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new Sha224Digest())); + } + if (mechanism.Equals("SHA-256withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new Sha256Digest())); + } + if (mechanism.Equals("SHA-384withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new Sha384Digest())); + } + if (mechanism.Equals("SHA-512withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new Sha512Digest())); + } + + if (mechanism.Equals("RIPEMD160withECDSA")) + { + return (new DsaDigestSigner(new ECDsaSigner(), new RipeMD160Digest())); + } + + if (mechanism.Equals("SHA1WITHECNR")) + { + return (new DsaDigestSigner(new ECNRSigner(), new Sha1Digest())); + } + if (mechanism.Equals("SHA224WITHECNR")) + { + return (new DsaDigestSigner(new ECNRSigner(), new Sha224Digest())); + } + if (mechanism.Equals("SHA256WITHECNR")) + { + return (new DsaDigestSigner(new ECNRSigner(), new Sha256Digest())); + } + if (mechanism.Equals("SHA384WITHECNR")) + { + return (new DsaDigestSigner(new ECNRSigner(), new Sha384Digest())); + } + if (mechanism.Equals("SHA512WITHECNR")) + { + return (new DsaDigestSigner(new ECNRSigner(), new Sha512Digest())); + } + + if (mechanism.Equals("GOST3410")) + { + return new Gost3410DigestSigner(new Gost3410Signer(), new Gost3411Digest()); + } + if (mechanism.Equals("ECGOST3410")) + { + return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411Digest()); + } + + if (mechanism.Equals("SHA1WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new Sha1Digest(), true); + } + if (mechanism.Equals("MD5WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new MD5Digest(), true); + } + if (mechanism.Equals("RIPEMD160WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true); + } + + throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); + } + + public static string GetEncodingName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + } +} diff --git a/crypto/src/security/WrapperUtilities.cs b/crypto/src/security/WrapperUtilities.cs new file mode 100644 index 000000000..ce31ea519 --- /dev/null +++ b/crypto/src/security/WrapperUtilities.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security +{ + /// + /// Utility class for creating IWrapper objects from their names/Oids + /// + public sealed class WrapperUtilities + { + private enum WrapAlgorithm { AESWRAP, CAMELLIAWRAP, DESEDEWRAP, RC2WRAP, SEEDWRAP, + DESEDERFC3211WRAP, AESRFC3211WRAP, CAMELLIARFC3211WRAP }; + + private WrapperUtilities() + { + } + + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + //private static readonly IDictionary oids = Platform.CreateHashtable(); + + static WrapperUtilities() + { + // Signal to obfuscation tools not to change enum constants + ((WrapAlgorithm)Enums.GetArbitraryValue(typeof(WrapAlgorithm))).ToString(); + + algorithms[NistObjectIdentifiers.IdAes128Wrap.Id] = "AESWRAP"; + algorithms[NistObjectIdentifiers.IdAes192Wrap.Id] = "AESWRAP"; + algorithms[NistObjectIdentifiers.IdAes256Wrap.Id] = "AESWRAP"; + + algorithms[NttObjectIdentifiers.IdCamellia128Wrap.Id] = "CAMELLIAWRAP"; + algorithms[NttObjectIdentifiers.IdCamellia192Wrap.Id] = "CAMELLIAWRAP"; + algorithms[NttObjectIdentifiers.IdCamellia256Wrap.Id] = "CAMELLIAWRAP"; + + algorithms[PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id] = "DESEDEWRAP"; + algorithms["TDEAWRAP"] = "DESEDEWRAP"; + + algorithms[PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id] = "RC2WRAP"; + + algorithms[KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id] = "SEEDWRAP"; + } + + public static IWrapper GetWrapper( + DerObjectIdentifier oid) + { + return GetWrapper(oid.Id); + } + + public static IWrapper GetWrapper( + string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + string mechanism = (string)algorithms[upper]; + + if (mechanism == null) + { + mechanism = upper; + } + + try + { + WrapAlgorithm wrapAlgorithm = (WrapAlgorithm)Enums.GetEnumValue( + typeof(WrapAlgorithm), mechanism); + + switch (wrapAlgorithm) + { + case WrapAlgorithm.AESWRAP: return new AesWrapEngine(); + case WrapAlgorithm.CAMELLIAWRAP: return new CamelliaWrapEngine(); + case WrapAlgorithm.DESEDEWRAP: return new DesEdeWrapEngine(); + case WrapAlgorithm.RC2WRAP: return new RC2WrapEngine(); + case WrapAlgorithm.SEEDWRAP: return new SeedWrapEngine(); + case WrapAlgorithm.DESEDERFC3211WRAP: return new Rfc3211WrapEngine(new DesEdeEngine()); + case WrapAlgorithm.AESRFC3211WRAP: return new Rfc3211WrapEngine(new AesFastEngine()); + case WrapAlgorithm.CAMELLIARFC3211WRAP: return new Rfc3211WrapEngine(new CamelliaEngine()); + } + } + catch (ArgumentException) + { + } + + // Create an IBufferedCipher and use it as IWrapper (via BufferedCipherWrapper) + IBufferedCipher blockCipher = CipherUtilities.GetCipher(algorithm); + + if (blockCipher != null) + return new BufferedCipherWrapper(blockCipher); + + throw new SecurityUtilityException("Wrapper " + algorithm + " not recognised."); + } + + public static string GetAlgorithmName( + DerObjectIdentifier oid) + { + return (string) algorithms[oid.Id]; + } + + private class BufferedCipherWrapper + : IWrapper + { + private readonly IBufferedCipher cipher; + private bool forWrapping; + + public BufferedCipherWrapper( + IBufferedCipher cipher) + { + this.cipher = cipher; + } + + public string AlgorithmName + { + get { return cipher.AlgorithmName; } + } + + public void Init( + bool forWrapping, + ICipherParameters parameters) + { + this.forWrapping = forWrapping; + + cipher.Init(forWrapping, parameters); + } + + public byte[] Wrap( + byte[] input, + int inOff, + int length) + { + if (!forWrapping) + throw new InvalidOperationException("Not initialised for wrapping"); + + return cipher.DoFinal(input, inOff, length); + } + + public byte[] Unwrap( + byte[] input, + int inOff, + int length) + { + if (forWrapping) + throw new InvalidOperationException("Not initialised for unwrapping"); + + return cipher.DoFinal(input, inOff, length); + } + } + } +} diff --git a/crypto/src/security/cert/CertificateEncodingException.cs b/crypto/src/security/cert/CertificateEncodingException.cs new file mode 100644 index 000000000..a2909b0d5 --- /dev/null +++ b/crypto/src/security/cert/CertificateEncodingException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CertificateEncodingException : CertificateException + { + public CertificateEncodingException() : base() { } + public CertificateEncodingException(string msg) : base(msg) { } + public CertificateEncodingException(string msg, Exception e) : base(msg, e) { } + } +} diff --git a/crypto/src/security/cert/CertificateException.cs b/crypto/src/security/cert/CertificateException.cs new file mode 100644 index 000000000..441c598e4 --- /dev/null +++ b/crypto/src/security/cert/CertificateException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CertificateException : GeneralSecurityException + { + public CertificateException() : base() { } + public CertificateException(string message) : base(message) { } + public CertificateException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/cert/CertificateExpiredException.cs b/crypto/src/security/cert/CertificateExpiredException.cs new file mode 100644 index 000000000..c893c07ee --- /dev/null +++ b/crypto/src/security/cert/CertificateExpiredException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CertificateExpiredException : CertificateException + { + public CertificateExpiredException() : base() { } + public CertificateExpiredException(string message) : base(message) { } + public CertificateExpiredException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/cert/CertificateNotYetValidException.cs b/crypto/src/security/cert/CertificateNotYetValidException.cs new file mode 100644 index 000000000..a0081ce23 --- /dev/null +++ b/crypto/src/security/cert/CertificateNotYetValidException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CertificateNotYetValidException : CertificateException + { + public CertificateNotYetValidException() : base() { } + public CertificateNotYetValidException(string message) : base(message) { } + public CertificateNotYetValidException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/cert/CertificateParsingException.cs b/crypto/src/security/cert/CertificateParsingException.cs new file mode 100644 index 000000000..8d8ed1e92 --- /dev/null +++ b/crypto/src/security/cert/CertificateParsingException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CertificateParsingException : CertificateException + { + public CertificateParsingException() : base() { } + public CertificateParsingException(string message) : base(message) { } + public CertificateParsingException(string message, Exception exception) : base(message, exception) { } + } +} diff --git a/crypto/src/security/cert/CrlException.cs b/crypto/src/security/cert/CrlException.cs new file mode 100644 index 000000000..0df007b1e --- /dev/null +++ b/crypto/src/security/cert/CrlException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Org.BouncyCastle.Security.Certificates +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class CrlException : GeneralSecurityException + { + public CrlException() : base() { } + public CrlException(string msg) : base(msg) {} + public CrlException(string msg, Exception e) : base(msg, e) {} + } +} diff --git a/crypto/src/tsp/GenTimeAccuracy.cs b/crypto/src/tsp/GenTimeAccuracy.cs new file mode 100644 index 000000000..8a2f29989 --- /dev/null +++ b/crypto/src/tsp/GenTimeAccuracy.cs @@ -0,0 +1,33 @@ +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Tsp; + +namespace Org.BouncyCastle.Tsp +{ + public class GenTimeAccuracy + { + private Accuracy accuracy; + + public GenTimeAccuracy( + Accuracy accuracy) + { + this.accuracy = accuracy; + } + + public int Seconds { get { return GetTimeComponent(accuracy.Seconds); } } + + public int Millis { get { return GetTimeComponent(accuracy.Millis); } } + + public int Micros { get { return GetTimeComponent(accuracy.Micros); } } + + private int GetTimeComponent( + DerInteger time) + { + return time == null ? 0 : time.Value.IntValue; + } + + public override string ToString() + { + return Seconds + "." + Millis.ToString("000") + Micros.ToString("000"); + } + } +} diff --git a/crypto/src/tsp/TSPAlgorithms.cs b/crypto/src/tsp/TSPAlgorithms.cs new file mode 100644 index 000000000..e3dfc7916 --- /dev/null +++ b/crypto/src/tsp/TSPAlgorithms.cs @@ -0,0 +1,48 @@ +using System.Collections; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Recognised hash algorithms for the time stamp protocol. + */ + public abstract class TspAlgorithms + { + public static readonly string MD5 = PkcsObjectIdentifiers.MD5.Id; + + public static readonly string Sha1 = OiwObjectIdentifiers.IdSha1.Id; + + public static readonly string Sha224 = NistObjectIdentifiers.IdSha224.Id; + public static readonly string Sha256 = NistObjectIdentifiers.IdSha256.Id; + public static readonly string Sha384 = NistObjectIdentifiers.IdSha384.Id; + public static readonly string Sha512 = NistObjectIdentifiers.IdSha512.Id; + + public static readonly string RipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id; + public static readonly string RipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id; + public static readonly string RipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id; + + public static readonly string Gost3411 = CryptoProObjectIdentifiers.GostR3411.Id; + + public static readonly IList Allowed; + + static TspAlgorithms() + { + string[] algs = new string[] + { + Gost3411, MD5, Sha1, Sha224, Sha256, Sha384, Sha512, RipeMD128, RipeMD160, RipeMD256 + }; + + Allowed = Platform.CreateArrayList(); + foreach (string alg in algs) + { + Allowed.Add(alg); + } + } + } +} diff --git a/crypto/src/tsp/TSPException.cs b/crypto/src/tsp/TSPException.cs new file mode 100644 index 000000000..3917e96a7 --- /dev/null +++ b/crypto/src/tsp/TSPException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Tsp +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class TspException + : Exception + { + public TspException() + { + } + + public TspException( + string message) + : base(message) + { + } + + public TspException( + string message, + Exception e) + : base(message, e) + { + } + } +} diff --git a/crypto/src/tsp/TSPUtil.cs b/crypto/src/tsp/TSPUtil.cs new file mode 100644 index 000000000..1026914f4 --- /dev/null +++ b/crypto/src/tsp/TSPUtil.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tsp +{ + public class TspUtil + { + private static ISet EmptySet = CollectionUtilities.ReadOnly(new HashSet()); + private static IList EmptyList = CollectionUtilities.ReadOnly(Platform.CreateArrayList()); + + private static readonly IDictionary digestLengths = Platform.CreateHashtable(); + private static readonly IDictionary digestNames = Platform.CreateHashtable(); + + static TspUtil() + { + digestLengths.Add(PkcsObjectIdentifiers.MD5.Id, 16); + digestLengths.Add(OiwObjectIdentifiers.IdSha1.Id, 20); + digestLengths.Add(NistObjectIdentifiers.IdSha224.Id, 28); + digestLengths.Add(NistObjectIdentifiers.IdSha256.Id, 32); + digestLengths.Add(NistObjectIdentifiers.IdSha384.Id, 48); + digestLengths.Add(NistObjectIdentifiers.IdSha512.Id, 64); + digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, 16); + digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, 20); + digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, 32); + digestLengths.Add(CryptoProObjectIdentifiers.GostR3411.Id, 32); + + digestNames.Add(PkcsObjectIdentifiers.MD5.Id, "MD5"); + digestNames.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1"); + digestNames.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224"); + digestNames.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256"); + digestNames.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384"); + digestNames.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512"); + digestNames.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id, "SHA1"); + digestNames.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id, "SHA224"); + digestNames.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, "SHA256"); + digestNames.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id, "SHA384"); + digestNames.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id, "SHA512"); + digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128"); + digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160"); + digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256"); + digestNames.Add(CryptoProObjectIdentifiers.GostR3411.Id, "GOST3411"); + } + + + /** + * Fetches the signature time-stamp attributes from a SignerInformation object. + * Checks that the MessageImprint for each time-stamp matches the signature field. + * (see RFC 3161 Appendix A). + * + * @param signerInfo a SignerInformation to search for time-stamps + * @return a collection of TimeStampToken objects + * @throws TSPValidationException + */ + public static ICollection GetSignatureTimestamps( + SignerInformation signerInfo) + { + IList timestamps = Platform.CreateArrayList(); + + Asn1.Cms.AttributeTable unsignedAttrs = signerInfo.UnsignedAttributes; + if (unsignedAttrs != null) + { + foreach (Asn1.Cms.Attribute tsAttr in unsignedAttrs.GetAll( + PkcsObjectIdentifiers.IdAASignatureTimeStampToken)) + { + foreach (Asn1Encodable asn1 in tsAttr.AttrValues) + { + try + { + Asn1.Cms.ContentInfo contentInfo = Asn1.Cms.ContentInfo.GetInstance( + asn1.ToAsn1Object()); + TimeStampToken timeStampToken = new TimeStampToken(contentInfo); + TimeStampTokenInfo tstInfo = timeStampToken.TimeStampInfo; + + byte[] expectedDigest = DigestUtilities.CalculateDigest( + GetDigestAlgName(tstInfo.MessageImprintAlgOid), + signerInfo.GetSignature()); + + if (!Arrays.ConstantTimeAreEqual(expectedDigest, tstInfo.GetMessageImprintDigest())) + throw new TspValidationException("Incorrect digest in message imprint"); + + timestamps.Add(timeStampToken); + } + catch (SecurityUtilityException) + { + throw new TspValidationException("Unknown hash algorithm specified in timestamp"); + } + catch (Exception) + { + throw new TspValidationException("Timestamp could not be parsed"); + } + } + } + } + + return timestamps; + } + + /** + * Validate the passed in certificate as being of the correct type to be used + * for time stamping. To be valid it must have an ExtendedKeyUsage extension + * which has a key purpose identifier of id-kp-timeStamping. + * + * @param cert the certificate of interest. + * @throws TspValidationException if the certicate fails on one of the check points. + */ + public static void ValidateCertificate( + X509Certificate cert) + { + if (cert.Version != 3) + throw new ArgumentException("Certificate must have an ExtendedKeyUsage extension."); + + Asn1OctetString ext = cert.GetExtensionValue(X509Extensions.ExtendedKeyUsage); + if (ext == null) + throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension."); + + if (!cert.GetCriticalExtensionOids().Contains(X509Extensions.ExtendedKeyUsage.Id)) + throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical."); + + try + { + ExtendedKeyUsage extKey = ExtendedKeyUsage.GetInstance( + Asn1Object.FromByteArray(ext.GetOctets())); + + if (!extKey.HasKeyPurposeId(KeyPurposeID.IdKPTimeStamping) || extKey.Count != 1) + throw new TspValidationException("ExtendedKeyUsage not solely time stamping."); + } + catch (IOException) + { + throw new TspValidationException("cannot process ExtendedKeyUsage extension"); + } + } + + /// + /// Return the digest algorithm using one of the standard JCA string + /// representations rather than the algorithm identifier (if possible). + /// + internal static string GetDigestAlgName( + string digestAlgOID) + { + string digestName = (string) digestNames[digestAlgOID]; + + return digestName != null ? digestName : digestAlgOID; + } + + internal static int GetDigestLength( + string digestAlgOID) + { + if (!digestLengths.Contains(digestAlgOID)) + throw new TspException("digest algorithm cannot be found."); + + return (int)digestLengths[digestAlgOID]; + } + + internal static IDigest CreateDigestInstance( + String digestAlgOID) + { + string digestName = GetDigestAlgName(digestAlgOID); + + return DigestUtilities.GetDigest(digestName); + } + + internal static ISet GetCriticalExtensionOids(X509Extensions extensions) + { + if (extensions == null) + return EmptySet; + + return CollectionUtilities.ReadOnly(new HashSet(extensions.GetCriticalExtensionOids())); + } + + internal static ISet GetNonCriticalExtensionOids(X509Extensions extensions) + { + if (extensions == null) + return EmptySet; + + // TODO: should probably produce a set that imposes correct ordering + return CollectionUtilities.ReadOnly(new HashSet(extensions.GetNonCriticalExtensionOids())); + } + + internal static IList GetExtensionOids(X509Extensions extensions) + { + if (extensions == null) + return EmptyList; + + return CollectionUtilities.ReadOnly(Platform.CreateArrayList(extensions.GetExtensionOids())); + } + } +} diff --git a/crypto/src/tsp/TSPValidationException.cs b/crypto/src/tsp/TSPValidationException.cs new file mode 100644 index 000000000..8ef2ec6cf --- /dev/null +++ b/crypto/src/tsp/TSPValidationException.cs @@ -0,0 +1,44 @@ +using System; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Exception thrown if a TSP request or response fails to validate. + *

    + * If a failure code is associated with the exception it can be retrieved using + * the getFailureCode() method.

    + */ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class TspValidationException + : TspException + { + private int failureCode; + + public TspValidationException( + string message) + : base(message) + { + this.failureCode = -1; + } + + public TspValidationException( + string message, + int failureCode) + : base(message) + { + this.failureCode = failureCode; + } + + /** + * Return the failure code associated with this exception - if one is set. + * + * @return the failure code if set, -1 otherwise. + */ + public int FailureCode + { + get { return failureCode; } + } + } +} diff --git a/crypto/src/tsp/TimeStampRequest.cs b/crypto/src/tsp/TimeStampRequest.cs new file mode 100644 index 000000000..6b9699379 --- /dev/null +++ b/crypto/src/tsp/TimeStampRequest.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Base class for an RFC 3161 Time Stamp Request. + */ + public class TimeStampRequest + : X509ExtensionBase + { + private TimeStampReq req; + private X509Extensions extensions; + + public TimeStampRequest( + TimeStampReq req) + { + this.req = req; + this.extensions = req.Extensions; + } + + /** + * Create a TimeStampRequest from the past in byte array. + * + * @param req byte array containing the request. + * @throws IOException if the request is malformed. + */ + public TimeStampRequest( + byte[] req) + : this(new Asn1InputStream(req)) + { + } + + /** + * Create a TimeStampRequest from the past in input stream. + * + * @param in input stream containing the request. + * @throws IOException if the request is malformed. + */ + public TimeStampRequest( + Stream input) + : this(new Asn1InputStream(input)) + { + } + + private TimeStampRequest( + Asn1InputStream str) + { + try + { + this.req = TimeStampReq.GetInstance(str.ReadObject()); + } + catch (InvalidCastException e) + { + throw new IOException("malformed request: " + e); + } + catch (ArgumentException e) + { + throw new IOException("malformed request: " + e); + } + } + + public int Version + { + get { return req.Version.Value.IntValue; } + } + + public string MessageImprintAlgOid + { + get { return req.MessageImprint.HashAlgorithm.ObjectID.Id; } + } + + public byte[] GetMessageImprintDigest() + { + return req.MessageImprint.GetHashedMessage(); + } + + public string ReqPolicy + { + get + { + return req.ReqPolicy == null + ? null + : req.ReqPolicy.Id; + } + } + + public BigInteger Nonce + { + get + { + return req.Nonce == null + ? null + : req.Nonce.Value; + } + } + + public bool CertReq + { + get + { + return req.CertReq == null + ? false + : req.CertReq.IsTrue; + } + } + + /** + * Validate the timestamp request, checking the digest to see if it is of an + * accepted type and whether it is of the correct length for the algorithm specified. + * + * @param algorithms a set of string OIDS giving accepted algorithms. + * @param policies if non-null a set of policies we are willing to sign under. + * @param extensions if non-null a set of extensions we are willing to accept. + * @throws TspException if the request is invalid, or processing fails. + */ + public void Validate( + IList algorithms, + IList policies, + IList extensions) + { + if (!algorithms.Contains(this.MessageImprintAlgOid)) + { + throw new TspValidationException("request contains unknown algorithm.", PkiFailureInfo.BadAlg); + } + + if (policies != null && this.ReqPolicy != null && !policies.Contains(this.ReqPolicy)) + { + throw new TspValidationException("request contains unknown policy.", PkiFailureInfo.UnacceptedPolicy); + } + + if (this.Extensions != null && extensions != null) + { + foreach (DerObjectIdentifier oid in this.Extensions.ExtensionOids) + { + if (!extensions.Contains(oid.Id)) + { + throw new TspValidationException("request contains unknown extension.", + PkiFailureInfo.UnacceptedExtension); + } + } + } + + int digestLength = TspUtil.GetDigestLength(this.MessageImprintAlgOid); + + if (digestLength != this.GetMessageImprintDigest().Length) + { + throw new TspValidationException("imprint digest the wrong length.", + PkiFailureInfo.BadDataFormat); + } + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return req.GetEncoded(); + } + + internal X509Extensions Extensions + { + get { return req.Extensions; } + } + + public virtual bool HasExtensions + { + get { return extensions != null; } + } + + public virtual X509Extension GetExtension(DerObjectIdentifier oid) + { + return extensions == null ? null : extensions.GetExtension(oid); + } + + public virtual IList GetExtensionOids() + { + return TspUtil.GetExtensionOids(extensions); + } + + protected override X509Extensions GetX509Extensions() + { + return Extensions; + } + } +} diff --git a/crypto/src/tsp/TimeStampRequestGenerator.cs b/crypto/src/tsp/TimeStampRequestGenerator.cs new file mode 100644 index 000000000..2c698e476 --- /dev/null +++ b/crypto/src/tsp/TimeStampRequestGenerator.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Generator for RFC 3161 Time Stamp Request objects. + */ + public class TimeStampRequestGenerator + { + private DerObjectIdentifier reqPolicy; + + private DerBoolean certReq; + + private IDictionary extensions = Platform.CreateHashtable(); + private IList extOrdering = Platform.CreateArrayList(); + + public void SetReqPolicy( + string reqPolicy) + { + this.reqPolicy = new DerObjectIdentifier(reqPolicy); + } + + public void SetCertReq( + bool certReq) + { + this.certReq = DerBoolean.GetInstance(certReq); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * @throws IOException + */ + [Obsolete("Use method taking DerObjectIdentifier")] + public void AddExtension( + string oid, + bool critical, + Asn1Encodable value) + { + this.AddExtension(oid, critical, value.GetEncoded()); + } + + /** + * add a given extension field for the standard extensions tag + * The value parameter becomes the contents of the octet string associated + * with the extension. + */ + [Obsolete("Use method taking DerObjectIdentifier")] + public void AddExtension( + string oid, + bool critical, + byte[] value) + { + DerObjectIdentifier derOid = new DerObjectIdentifier(oid); + extensions[derOid] = new X509Extension(critical, new DerOctetString(value)); + extOrdering.Add(derOid); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * @throws IOException + */ + public virtual void AddExtension( + DerObjectIdentifier oid, + bool critical, + Asn1Encodable extValue) + { + this.AddExtension(oid, critical, extValue.GetEncoded()); + } + + /** + * add a given extension field for the standard extensions tag + * The value parameter becomes the contents of the octet string associated + * with the extension. + */ + public virtual void AddExtension( + DerObjectIdentifier oid, + bool critical, + byte[] extValue) + { + extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue))); + extOrdering.Add(oid); + } + + public TimeStampRequest Generate( + string digestAlgorithm, + byte[] digest) + { + return this.Generate(digestAlgorithm, digest, null); + } + + public TimeStampRequest Generate( + string digestAlgorithmOid, + byte[] digest, + BigInteger nonce) + { + if (digestAlgorithmOid == null) + { + throw new ArgumentException("No digest algorithm specified"); + } + + DerObjectIdentifier digestAlgOid = new DerObjectIdentifier(digestAlgorithmOid); + + AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOid, DerNull.Instance); + MessageImprint messageImprint = new MessageImprint(algID, digest); + + X509Extensions ext = null; + + if (extOrdering.Count != 0) + { + ext = new X509Extensions(extOrdering, extensions); + } + + DerInteger derNonce = nonce == null + ? null + : new DerInteger(nonce); + + return new TimeStampRequest( + new TimeStampReq(messageImprint, reqPolicy, derNonce, certReq, ext)); + } + + public virtual TimeStampRequest Generate(DerObjectIdentifier digestAlgorithm, byte[] digest) + { + return Generate(digestAlgorithm.Id, digest); + } + + public virtual TimeStampRequest Generate(DerObjectIdentifier digestAlgorithm, byte[] digest, BigInteger nonce) + { + return Generate(digestAlgorithm.Id, digest, nonce); + } + } +} diff --git a/crypto/src/tsp/TimeStampResponse.cs b/crypto/src/tsp/TimeStampResponse.cs new file mode 100644 index 000000000..069521111 --- /dev/null +++ b/crypto/src/tsp/TimeStampResponse.cs @@ -0,0 +1,184 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Base class for an RFC 3161 Time Stamp Response object. + */ + public class TimeStampResponse + { + private TimeStampResp resp; + private TimeStampToken timeStampToken; + + public TimeStampResponse( + TimeStampResp resp) + { + this.resp = resp; + + if (resp.TimeStampToken != null) + { + timeStampToken = new TimeStampToken(resp.TimeStampToken); + } + } + + /** + * Create a TimeStampResponse from a byte array containing an ASN.1 encoding. + * + * @param resp the byte array containing the encoded response. + * @throws TspException if the response is malformed. + * @throws IOException if the byte array doesn't represent an ASN.1 encoding. + */ + public TimeStampResponse( + byte[] resp) + : this(readTimeStampResp(new Asn1InputStream(resp))) + { + } + + /** + * Create a TimeStampResponse from an input stream containing an ASN.1 encoding. + * + * @param input the input stream containing the encoded response. + * @throws TspException if the response is malformed. + * @throws IOException if the stream doesn't represent an ASN.1 encoding. + */ + public TimeStampResponse( + Stream input) + : this(readTimeStampResp(new Asn1InputStream(input))) + { + } + + private static TimeStampResp readTimeStampResp( + Asn1InputStream input) + { + try + { + return TimeStampResp.GetInstance(input.ReadObject()); + } + catch (ArgumentException e) + { + throw new TspException("malformed timestamp response: " + e, e); + } + catch (InvalidCastException e) + { + throw new TspException("malformed timestamp response: " + e, e); + } + } + + public int Status + { + get { return resp.Status.Status.IntValue; } + } + + public string GetStatusString() + { + if (resp.Status.StatusString == null) + { + return null; + } + + StringBuilder statusStringBuf = new StringBuilder(); + PkiFreeText text = resp.Status.StatusString; + for (int i = 0; i != text.Count; i++) + { + statusStringBuf.Append(text[i].GetString()); + } + + return statusStringBuf.ToString(); + } + + public PkiFailureInfo GetFailInfo() + { + if (resp.Status.FailInfo == null) + { + return null; + } + + return new PkiFailureInfo(resp.Status.FailInfo); + } + + public TimeStampToken TimeStampToken + { + get { return timeStampToken; } + } + + /** + * Check this response against to see if it a well formed response for + * the passed in request. Validation will include checking the time stamp + * token if the response status is GRANTED or GRANTED_WITH_MODS. + * + * @param request the request to be checked against + * @throws TspException if the request can not match this response. + */ + public void Validate( + TimeStampRequest request) + { + TimeStampToken tok = this.TimeStampToken; + + if (tok != null) + { + TimeStampTokenInfo tstInfo = tok.TimeStampInfo; + + if (request.Nonce != null && !request.Nonce.Equals(tstInfo.Nonce)) + { + throw new TspValidationException("response contains wrong nonce value."); + } + + if (this.Status != (int) PkiStatus.Granted && this.Status != (int) PkiStatus.GrantedWithMods) + { + throw new TspValidationException("time stamp token found in failed request."); + } + + if (!Arrays.ConstantTimeAreEqual(request.GetMessageImprintDigest(), tstInfo.GetMessageImprintDigest())) + { + throw new TspValidationException("response for different message imprint digest."); + } + + if (!tstInfo.MessageImprintAlgOid.Equals(request.MessageImprintAlgOid)) + { + throw new TspValidationException("response for different message imprint algorithm."); + } + + Asn1.Cms.Attribute scV1 = tok.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificate]; + Asn1.Cms.Attribute scV2 = tok.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2]; + + if (scV1 == null && scV2 == null) + { + throw new TspValidationException("no signing certificate attribute present."); + } + + if (scV1 != null && scV2 != null) + { + /* + * RFC 5035 5.4. If both attributes exist in a single message, + * they are independently evaluated. + */ + } + + if (request.ReqPolicy != null && !request.ReqPolicy.Equals(tstInfo.Policy)) + { + throw new TspValidationException("TSA policy wrong for request."); + } + } + else if (this.Status == (int) PkiStatus.Granted || this.Status == (int) PkiStatus.GrantedWithMods) + { + throw new TspValidationException("no time stamp token found and one expected."); + } + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] GetEncoded() + { + return resp.GetEncoded(); + } + } +} diff --git a/crypto/src/tsp/TimeStampResponseGenerator.cs b/crypto/src/tsp/TimeStampResponseGenerator.cs new file mode 100644 index 000000000..8d798de67 --- /dev/null +++ b/crypto/src/tsp/TimeStampResponseGenerator.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Generator for RFC 3161 Time Stamp Responses. + */ + public class TimeStampResponseGenerator + { + private PkiStatus status; + + private Asn1EncodableVector statusStrings; + + private int failInfo; + private TimeStampTokenGenerator tokenGenerator; + private IList acceptedAlgorithms; + private IList acceptedPolicies; + private IList acceptedExtensions; + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms) + : this(tokenGenerator, acceptedAlgorithms, null, null) + { + } + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms, + IList acceptedPolicy) + : this(tokenGenerator, acceptedAlgorithms, acceptedPolicy, null) + { + } + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms, + IList acceptedPolicies, + IList acceptedExtensions) + { + this.tokenGenerator = tokenGenerator; + this.acceptedAlgorithms = acceptedAlgorithms; + this.acceptedPolicies = acceptedPolicies; + this.acceptedExtensions = acceptedExtensions; + + statusStrings = new Asn1EncodableVector(); + } + + private void AddStatusString(string statusString) + { + statusStrings.Add(new DerUtf8String(statusString)); + } + + private void SetFailInfoField(int field) + { + failInfo |= field; + } + + private PkiStatusInfo GetPkiStatusInfo() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger((int)status)); + + if (statusStrings.Count > 0) + { + v.Add(new PkiFreeText(new DerSequence(statusStrings))); + } + + if (failInfo != 0) + { + v.Add(new FailInfo(failInfo)); + } + + return new PkiStatusInfo(new DerSequence(v)); + } + + public TimeStampResponse Generate( + TimeStampRequest request, + BigInteger serialNumber, + DateTime genTime) + { + return Generate(request, serialNumber, new DateTimeObject(genTime)); + } + + /** + * Return an appropriate TimeStampResponse. + *

    + * If genTime is null a timeNotAvailable error response will be returned. + * + * @param request the request this response is for. + * @param serialNumber serial number for the response token. + * @param genTime generation time for the response token. + * @param provider provider to use for signature calculation. + * @return + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws TSPException + *

    + */ + public TimeStampResponse Generate( + TimeStampRequest request, + BigInteger serialNumber, + DateTimeObject genTime) + { + TimeStampResp resp; + + try + { + if (genTime == null) + throw new TspValidationException("The time source is not available.", + PkiFailureInfo.TimeNotAvailable); + + request.Validate(acceptedAlgorithms, acceptedPolicies, acceptedExtensions); + + this.status = PkiStatus.Granted; + this.AddStatusString("Operation Okay"); + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + ContentInfo tstTokenContentInfo; + try + { + TimeStampToken token = tokenGenerator.Generate(request, serialNumber, genTime.Value); + byte[] encoded = token.ToCmsSignedData().GetEncoded(); + + tstTokenContentInfo = ContentInfo.GetInstance(Asn1Object.FromByteArray(encoded)); + } + catch (IOException e) + { + throw new TspException("Timestamp token received cannot be converted to ContentInfo", e); + } + + resp = new TimeStampResp(pkiStatusInfo, tstTokenContentInfo); + } + catch (TspValidationException e) + { + status = PkiStatus.Rejection; + + this.SetFailInfoField(e.FailureCode); + this.AddStatusString(e.Message); + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + resp = new TimeStampResp(pkiStatusInfo, null); + } + + try + { + return new TimeStampResponse(resp); + } + catch (IOException e) + { + throw new TspException("created badly formatted response!", e); + } + } + + class FailInfo + : DerBitString + { + internal FailInfo( + int failInfoValue) + : base(GetBytes(failInfoValue), GetPadBits(failInfoValue)) + { + } + } + + /** + * Generate a TimeStampResponse with chosen status and FailInfoField. + * + * @param status the PKIStatus to set. + * @param failInfoField the FailInfoField to set. + * @param statusString an optional string describing the failure. + * @return a TimeStampResponse with a failInfoField and optional statusString + * @throws TSPException in case the response could not be created + */ + public TimeStampResponse GenerateFailResponse(PkiStatus status, int failInfoField, string statusString) + { + this.status = status; + + this.SetFailInfoField(failInfoField); + + if (statusString != null) + { + this.AddStatusString(statusString); + } + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + TimeStampResp resp = new TimeStampResp(pkiStatusInfo, null); + + try + { + return new TimeStampResponse(resp); + } + catch (IOException e) + { + throw new TspException("created badly formatted response!", e); + } + } + } +} diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs new file mode 100644 index 000000000..51a9592dc --- /dev/null +++ b/crypto/src/tsp/TimeStampToken.cs @@ -0,0 +1,305 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ess; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tsp +{ + public class TimeStampToken + { + private readonly CmsSignedData tsToken; + private readonly SignerInformation tsaSignerInfo; +// private readonly DateTime genTime; + private readonly TimeStampTokenInfo tstInfo; + private readonly CertID certID; + + public TimeStampToken( + Asn1.Cms.ContentInfo contentInfo) + : this(new CmsSignedData(contentInfo)) + { + } + + public TimeStampToken( + CmsSignedData signedData) + { + this.tsToken = signedData; + + if (!this.tsToken.SignedContentType.Equals(PkcsObjectIdentifiers.IdCTTstInfo)) + { + throw new TspValidationException("ContentInfo object not for a time stamp."); + } + + ICollection signers = tsToken.GetSignerInfos().GetSigners(); + + if (signers.Count != 1) + { + throw new ArgumentException("Time-stamp token signed by " + + signers.Count + + " signers, but it must contain just the TSA signature."); + } + + + IEnumerator signerEnum = signers.GetEnumerator(); + + signerEnum.MoveNext(); + tsaSignerInfo = (SignerInformation) signerEnum.Current; + + try + { + CmsProcessable content = tsToken.SignedContent; + MemoryStream bOut = new MemoryStream(); + + content.Write(bOut); + + this.tstInfo = new TimeStampTokenInfo( + TstInfo.GetInstance( + Asn1Object.FromByteArray(bOut.ToArray()))); + + Asn1.Cms.Attribute attr = tsaSignerInfo.SignedAttributes[ + PkcsObjectIdentifiers.IdAASigningCertificate]; + +// if (attr == null) +// { +// throw new TspValidationException( +// "no signing certificate attribute found, time stamp invalid."); +// } +// +// SigningCertificate signCert = SigningCertificate.GetInstance( +// attr.AttrValues[0]); +// +// this.certID = EssCertID.GetInstance(signCert.GetCerts()[0]); + + if (attr != null) + { + SigningCertificate signCert = SigningCertificate.GetInstance(attr.AttrValues[0]); + + this.certID = new CertID(EssCertID.GetInstance(signCert.GetCerts()[0])); + } + else + { + attr = tsaSignerInfo.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2]; + + if (attr == null) + throw new TspValidationException("no signing certificate attribute found, time stamp invalid."); + + SigningCertificateV2 signCertV2 = SigningCertificateV2.GetInstance(attr.AttrValues[0]); + + this.certID = new CertID(EssCertIDv2.GetInstance(signCertV2.GetCerts()[0])); + } + } + catch (CmsException e) + { + throw new TspException(e.Message, e.InnerException); + } + } + + public TimeStampTokenInfo TimeStampInfo + { + get { return tstInfo; } + } + + public SignerID SignerID + { + get { return tsaSignerInfo.SignerID; } + } + + public Asn1.Cms.AttributeTable SignedAttributes + { + get { return tsaSignerInfo.SignedAttributes; } + } + + public Asn1.Cms.AttributeTable UnsignedAttributes + { + get { return tsaSignerInfo.UnsignedAttributes; } + } + + public IX509Store GetCertificates( + string type) + { + return tsToken.GetCertificates(type); + } + + public IX509Store GetCrls( + string type) + { + return tsToken.GetCrls(type); + } + + public IX509Store GetAttributeCertificates( + string type) + { + return tsToken.GetAttributeCertificates(type); + } + + /** + * Validate the time stamp token. + *

    + * To be valid the token must be signed by the passed in certificate and + * the certificate must be the one referred to by the SigningCertificate + * attribute included in the hashed attributes of the token. The + * certificate must also have the ExtendedKeyUsageExtension with only + * KeyPurposeID.IdKPTimeStamping and have been valid at the time the + * timestamp was created. + *

    + *

    + * A successful call to validate means all the above are true. + *

    + */ + public void Validate( + X509Certificate cert) + { + try + { + byte[] hash = DigestUtilities.CalculateDigest( + certID.GetHashAlgorithmName(), cert.GetEncoded()); + + if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash)) + { + throw new TspValidationException("certificate hash does not match certID hash."); + } + + if (certID.IssuerSerial != null) + { + if (!certID.IssuerSerial.Serial.Value.Equals(cert.SerialNumber)) + { + throw new TspValidationException("certificate serial number does not match certID for signature."); + } + + GeneralName[] names = certID.IssuerSerial.Issuer.GetNames(); + X509Name principal = PrincipalUtilities.GetIssuerX509Principal(cert); + bool found = false; + + for (int i = 0; i != names.Length; i++) + { + if (names[i].TagNo == 4 + && X509Name.GetInstance(names[i].Name).Equivalent(principal)) + { + found = true; + break; + } + } + + if (!found) + { + throw new TspValidationException("certificate name does not match certID for signature. "); + } + } + + TspUtil.ValidateCertificate(cert); + + cert.CheckValidity(tstInfo.GenTime); + + if (!tsaSignerInfo.Verify(cert)) + { + throw new TspValidationException("signature not created by certificate."); + } + } + catch (CmsException e) + { + if (e.InnerException != null) + { + throw new TspException(e.Message, e.InnerException); + } + + throw new TspException("CMS exception: " + e, e); + } + catch (CertificateEncodingException e) + { + throw new TspException("problem processing certificate: " + e, e); + } + catch (SecurityUtilityException e) + { + throw new TspException("cannot find algorithm: " + e.Message, e); + } + } + + /** + * Return the underlying CmsSignedData object. + * + * @return the underlying CMS structure. + */ + public CmsSignedData ToCmsSignedData() + { + return tsToken; + } + + /** + * Return a ASN.1 encoded byte stream representing the encoded object. + * + * @throws IOException if encoding fails. + */ + public byte[] GetEncoded() + { + return tsToken.GetEncoded(); + } + + + // perhaps this should be done using an interface on the ASN.1 classes... + private class CertID + { + private EssCertID certID; + private EssCertIDv2 certIDv2; + + internal CertID(EssCertID certID) + { + this.certID = certID; + this.certIDv2 = null; + } + + internal CertID(EssCertIDv2 certID) + { + this.certIDv2 = certID; + this.certID = null; + } + + public string GetHashAlgorithmName() + { + if (certID != null) + return "SHA-1"; + + if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.ObjectID)) + return "SHA-256"; + + return certIDv2.HashAlgorithm.ObjectID.Id; + } + + public AlgorithmIdentifier GetHashAlgorithm() + { + return (certID != null) + ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1) + : certIDv2.HashAlgorithm; + } + + public byte[] GetCertHash() + { + return certID != null + ? certID.GetCertHash() + : certIDv2.GetCertHash(); + } + + public IssuerSerial IssuerSerial + { + get + { + return certID != null + ? certID.IssuerSerial + : certIDv2.IssuerSerial; + } + } + } + } +} diff --git a/crypto/src/tsp/TimeStampTokenGenerator.cs b/crypto/src/tsp/TimeStampTokenGenerator.cs new file mode 100644 index 000000000..07eddd4b9 --- /dev/null +++ b/crypto/src/tsp/TimeStampTokenGenerator.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ess; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tsp +{ + public class TimeStampTokenGenerator + { + private int accuracySeconds = -1; + private int accuracyMillis = -1; + private int accuracyMicros = -1; + private bool ordering = false; + private GeneralName tsa = null; + private string tsaPolicyOID; + + private AsymmetricKeyParameter key; + private X509Certificate cert; + private string digestOID; + private Asn1.Cms.AttributeTable signedAttr; + private Asn1.Cms.AttributeTable unsignedAttr; + private IX509Store x509Certs; + private IX509Store x509Crls; + + /** + * basic creation - only the default attributes will be included here. + */ + public TimeStampTokenGenerator( + AsymmetricKeyParameter key, + X509Certificate cert, + string digestOID, + string tsaPolicyOID) + : this(key, cert, digestOID, tsaPolicyOID, null, null) + { + } + + /** + * create with a signer with extra signed/unsigned attributes. + */ + public TimeStampTokenGenerator( + AsymmetricKeyParameter key, + X509Certificate cert, + string digestOID, + string tsaPolicyOID, + Asn1.Cms.AttributeTable signedAttr, + Asn1.Cms.AttributeTable unsignedAttr) + { + this.key = key; + this.cert = cert; + this.digestOID = digestOID; + this.tsaPolicyOID = tsaPolicyOID; + this.unsignedAttr = unsignedAttr; + + TspUtil.ValidateCertificate(cert); + + // + // Add the ESSCertID attribute + // + IDictionary signedAttrs; + if (signedAttr != null) + { + signedAttrs = signedAttr.ToDictionary(); + } + else + { + signedAttrs = Platform.CreateHashtable(); + } + + try + { + byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded()); + + EssCertID essCertid = new EssCertID(hash); + + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute( + PkcsObjectIdentifiers.IdAASigningCertificate, + new DerSet(new SigningCertificate(essCertid))); + + signedAttrs[attr.AttrType] = attr; + } + catch (CertificateEncodingException e) + { + throw new TspException("Exception processing certificate.", e); + } + catch (SecurityUtilityException e) + { + throw new TspException("Can't find a SHA-1 implementation.", e); + } + + this.signedAttr = new Asn1.Cms.AttributeTable(signedAttrs); + } + + public void SetCertificates( + IX509Store certificates) + { + this.x509Certs = certificates; + } + + public void SetCrls( + IX509Store crls) + { + this.x509Crls = crls; + } + + public void SetAccuracySeconds( + int accuracySeconds) + { + this.accuracySeconds = accuracySeconds; + } + + public void SetAccuracyMillis( + int accuracyMillis) + { + this.accuracyMillis = accuracyMillis; + } + + public void SetAccuracyMicros( + int accuracyMicros) + { + this.accuracyMicros = accuracyMicros; + } + + public void SetOrdering( + bool ordering) + { + this.ordering = ordering; + } + + public void SetTsa( + GeneralName tsa) + { + this.tsa = tsa; + } + + //------------------------------------------------------------------------------ + + public TimeStampToken Generate( + TimeStampRequest request, + BigInteger serialNumber, + DateTime genTime) + { + DerObjectIdentifier digestAlgOID = new DerObjectIdentifier(request.MessageImprintAlgOid); + + AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DerNull.Instance); + MessageImprint messageImprint = new MessageImprint(algID, request.GetMessageImprintDigest()); + + Accuracy accuracy = null; + if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0) + { + DerInteger seconds = null; + if (accuracySeconds > 0) + { + seconds = new DerInteger(accuracySeconds); + } + + DerInteger millis = null; + if (accuracyMillis > 0) + { + millis = new DerInteger(accuracyMillis); + } + + DerInteger micros = null; + if (accuracyMicros > 0) + { + micros = new DerInteger(accuracyMicros); + } + + accuracy = new Accuracy(seconds, millis, micros); + } + + DerBoolean derOrdering = null; + if (ordering) + { + derOrdering = DerBoolean.GetInstance(ordering); + } + + DerInteger nonce = null; + if (request.Nonce != null) + { + nonce = new DerInteger(request.Nonce); + } + + DerObjectIdentifier tsaPolicy = new DerObjectIdentifier(tsaPolicyOID); + if (request.ReqPolicy != null) + { + tsaPolicy = new DerObjectIdentifier(request.ReqPolicy); + } + + TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint, + new DerInteger(serialNumber), new DerGeneralizedTime(genTime), accuracy, + derOrdering, nonce, tsa, request.Extensions); + + try + { + CmsSignedDataGenerator signedDataGenerator = new CmsSignedDataGenerator(); + + byte[] derEncodedTstInfo = tstInfo.GetDerEncoded(); + + if (request.CertReq) + { + signedDataGenerator.AddCertificates(x509Certs); + } + + signedDataGenerator.AddCrls(x509Crls); + signedDataGenerator.AddSigner(key, cert, digestOID, signedAttr, unsignedAttr); + + CmsSignedData signedData = signedDataGenerator.Generate( + PkcsObjectIdentifiers.IdCTTstInfo.Id, + new CmsProcessableByteArray(derEncodedTstInfo), + true); + + return new TimeStampToken(signedData); + } + catch (CmsException cmsEx) + { + throw new TspException("Error generating time-stamp token", cmsEx); + } + catch (IOException e) + { + throw new TspException("Exception encoding info", e); + } + catch (X509StoreException e) + { + throw new TspException("Exception handling CertStore", e); + } +// catch (InvalidAlgorithmParameterException e) +// { +// throw new TspException("Exception handling CertStore CRLs", e); +// } + } + } +} diff --git a/crypto/src/tsp/TimeStampTokenInfo.cs b/crypto/src/tsp/TimeStampTokenInfo.cs new file mode 100644 index 000000000..5027a87c4 --- /dev/null +++ b/crypto/src/tsp/TimeStampTokenInfo.cs @@ -0,0 +1,107 @@ +using System; + +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Tsp +{ + public class TimeStampTokenInfo + { + private TstInfo tstInfo; + private DateTime genTime; + + public TimeStampTokenInfo( + TstInfo tstInfo) + { + this.tstInfo = tstInfo; + + try + { + this.genTime = tstInfo.GenTime.ToDateTime(); + } + catch (Exception e) + { + throw new TspException("unable to parse genTime field: " + e.Message); + } + } + + public bool IsOrdered + { + get { return tstInfo.Ordering.IsTrue; } + } + + public Accuracy Accuracy + { + get { return tstInfo.Accuracy; } + } + + public DateTime GenTime + { + get { return genTime; } + } + + public GenTimeAccuracy GenTimeAccuracy + { + get + { + return this.Accuracy == null + ? null + : new GenTimeAccuracy(this.Accuracy); + } + } + + public string Policy + { + get { return tstInfo.Policy.Id; } + } + + public BigInteger SerialNumber + { + get { return tstInfo.SerialNumber.Value; } + } + + public GeneralName Tsa + { + get { return tstInfo.Tsa; } + } + + /** + * @return the nonce value, null if there isn't one. + */ + public BigInteger Nonce + { + get + { + return tstInfo.Nonce == null + ? null + : tstInfo.Nonce.Value; + } + } + + public AlgorithmIdentifier HashAlgorithm + { + get { return tstInfo.MessageImprint.HashAlgorithm; } + } + + public string MessageImprintAlgOid + { + get { return tstInfo.MessageImprint.HashAlgorithm.ObjectID.Id; } + } + + public byte[] GetMessageImprintDigest() + { + return tstInfo.MessageImprint.GetHashedMessage(); + } + + public byte[] GetEncoded() + { + return tstInfo.GetEncoded(); + } + + public TstInfo TstInfo + { + get { return tstInfo; } + } + } +} diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs new file mode 100644 index 000000000..3c083034e --- /dev/null +++ b/crypto/src/util/Arrays.cs @@ -0,0 +1,233 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Utilities +{ + + /// General array utilities. + public sealed class Arrays + { + private Arrays() + { + } + + public static bool AreEqual( + bool[] a, + bool[] b) + { + if (a == b) + return true; + + if (a == null || b == null) + return false; + + return HaveSameContents(a, b); + } + + public static bool AreEqual( + char[] a, + char[] b) + { + if (a == b) + return true; + + if (a == null || b == null) + return false; + + return HaveSameContents(a, b); + } + + /// + /// Are two arrays equal. + /// + /// Left side. + /// Right side. + /// True if equal. + public static bool AreEqual( + byte[] a, + byte[] b) + { + if (a == b) + return true; + + if (a == null || b == null) + return false; + + return HaveSameContents(a, b); + } + + [Obsolete("Use 'AreEqual' method instead")] + public static bool AreSame( + byte[] a, + byte[] b) + { + return AreEqual(a, b); + } + + /// + /// A constant time equals comparison - does not terminate early if + /// test will fail. + /// + /// first array + /// second array + /// true if arrays equal, false otherwise. + public static bool ConstantTimeAreEqual( + byte[] a, + byte[] b) + { + int i = a.Length; + if (i != b.Length) + return false; + int cmp = 0; + while (i != 0) + { + --i; + cmp |= (a[i] ^ b[i]); + } + return cmp == 0; + } + + public static bool AreEqual( + int[] a, + int[] b) + { + if (a == b) + return true; + + if (a == null || b == null) + return false; + + return HaveSameContents(a, b); + } + + private static bool HaveSameContents( + bool[] a, + bool[] b) + { + int i = a.Length; + if (i != b.Length) + return false; + while (i != 0) + { + --i; + if (a[i] != b[i]) + return false; + } + return true; + } + + private static bool HaveSameContents( + char[] a, + char[] b) + { + int i = a.Length; + if (i != b.Length) + return false; + while (i != 0) + { + --i; + if (a[i] != b[i]) + return false; + } + return true; + } + + private static bool HaveSameContents( + byte[] a, + byte[] b) + { + int i = a.Length; + if (i != b.Length) + return false; + while (i != 0) + { + --i; + if (a[i] != b[i]) + return false; + } + return true; + } + + private static bool HaveSameContents( + int[] a, + int[] b) + { + int i = a.Length; + if (i != b.Length) + return false; + while (i != 0) + { + --i; + if (a[i] != b[i]) + return false; + } + return true; + } + + public static string ToString( + object[] a) + { + StringBuilder sb = new StringBuilder('['); + if (a.Length > 0) + { + sb.Append(a[0]); + for (int index = 1; index < a.Length; ++index) + { + sb.Append(", ").Append(a[index]); + } + } + sb.Append(']'); + return sb.ToString(); + } + + public static int GetHashCode( + 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 byte[] Clone( + byte[] data) + { + return data == null ? null : (byte[]) data.Clone(); + } + + public static int[] Clone( + int[] data) + { + return data == null ? null : (int[]) data.Clone(); + } + + public static void Fill( + byte[] buf, + byte b) + { + int i = buf.Length; + while (i > 0) + { + buf[--i] = b; + } + } + + public static byte[] Copy(byte[] data, int off, int len) + { + byte[] result = new byte[len]; + Array.Copy(data, off, result, 0, len); + return result; + } + } +} diff --git a/crypto/src/util/BigIntegers.cs b/crypto/src/util/BigIntegers.cs new file mode 100644 index 000000000..9e15d2559 --- /dev/null +++ b/crypto/src/util/BigIntegers.cs @@ -0,0 +1,94 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Utilities +{ + /** + * BigInteger utilities. + */ + public sealed class BigIntegers + { + private const int MaxIterations = 1000; + + private BigIntegers() + { + } + + /** + * 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 n) + { + return n.ToByteArrayUnsigned(); + } + + /** + * Return the passed in value as an unsigned byte array of specified length, zero-extended as necessary. + * + * @param length desired length of result array. + * @param n value to be converted. + * @return a byte array of specified length, with leading zeroes as necessary given the size of n. + */ + public static byte[] AsUnsignedByteArray(int length, BigInteger n) + { + byte[] bytes = n.ToByteArrayUnsigned(); + + if (bytes.Length > length) + throw new ArgumentException("standard length exceeded", "n"); + + if (bytes.Length == length) + return bytes; + + byte[] tmp = new byte[length]; + Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length); + 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, + // TODO Should have been just Random class + SecureRandom random) + { + int cmp = min.CompareTo(max); + if (cmp >= 0) + { + if (cmp > 0) + throw new ArgumentException("'min' may not be greater than 'max'"); + + return min; + } + + if (min.BitLength > max.BitLength / 2) + { + return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min); + } + + for (int i = 0; i < MaxIterations; ++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); + } + } +} diff --git a/crypto/src/util/Enums.cs b/crypto/src/util/Enums.cs new file mode 100644 index 000000000..eaf49e1b3 --- /dev/null +++ b/crypto/src/util/Enums.cs @@ -0,0 +1,73 @@ +using System; +using System.Text; + +#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT +using System.Collections; +using System.Reflection; +#endif + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Utilities +{ + internal sealed class Enums + { + private Enums() + { + } + + internal static Enum GetEnumValue(System.Type enumType, string s) + { + if (!enumType.IsEnum) + throw new ArgumentException("Not an enumeration type", "enumType"); + + // We only want to parse single named constants + if (s.Length > 0 && char.IsLetter(s[0]) && s.IndexOf(',') < 0) + { + s = s.Replace('-', '_'); + s = s.Replace('/', '_'); + +#if NETCF_1_0 + FieldInfo field = enumType.GetField(s, BindingFlags.Static | BindingFlags.Public); + if (field != null) + { + return (Enum)field.GetValue(null); + } +#else + return (Enum)Enum.Parse(enumType, s, false); +#endif + } + + throw new ArgumentException(); + } + + internal static Array GetEnumValues(System.Type enumType) + { + if (!enumType.IsEnum) + throw new ArgumentException("Not an enumeration type", "enumType"); + +#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT + IList result = Platform.CreateArrayList(); + FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | BindingFlags.Public); + foreach (FieldInfo field in fields) + { + // Note: Argument to GetValue() ignored since the fields are static, + // but Silverlight for Windows Phone throws exception if we pass null + result.Add(field.GetValue(enumType)); + } + object[] arr = new object[result.Count]; + result.CopyTo(arr, 0); + return arr; +#else + return Enum.GetValues(enumType); +#endif + } + + internal static Enum GetArbitraryValue(System.Type enumType) + { + Array values = GetEnumValues(enumType); + int pos = (int)(DateTimeUtilities.CurrentUnixMs() & int.MaxValue) % values.Length; + return (Enum)values.GetValue(pos); + } + } +} diff --git a/crypto/src/util/Platform.cs b/crypto/src/util/Platform.cs new file mode 100644 index 000000000..cdfba789e --- /dev/null +++ b/crypto/src/util/Platform.cs @@ -0,0 +1,182 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; + +#if SILVERLIGHT +using System.Collections.Generic; +#else +using System.Collections; +#endif + +namespace Org.BouncyCastle.Utilities +{ + internal sealed class Platform + { + private Platform() + { + } + +#if NETCF_1_0 || NETCF_2_0 + private static string GetNewLine() + { + MemoryStream buf = new MemoryStream(); + StreamWriter w = new StreamWriter(buf, Encoding.UTF8); + w.WriteLine(); + w.Close(); + byte[] bs = buf.ToArray(); + return Encoding.UTF8.GetString(bs, 0, bs.Length); + } +#else + private static string GetNewLine() + { + return Environment.NewLine; + } +#endif + + internal static int CompareIgnoreCase(string a, string b) + { +#if SILVERLIGHT + return String.Compare(a, b, StringComparison.InvariantCultureIgnoreCase); +#else + return String.Compare(a, b, true); +#endif + } + +#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT + internal static string GetEnvironmentVariable( + string variable) + { + return null; + } +#else + internal static string GetEnvironmentVariable( + string variable) + { + try + { + return Environment.GetEnvironmentVariable(variable); + } + catch (System.Security.SecurityException) + { + // We don't have the required permission to read this environment variable, + // which is fine, just act as if it's not set + return null; + } + } +#endif + +#if NETCF_1_0 + internal static Exception CreateNotImplementedException( + string message) + { + return new Exception("Not implemented: " + message); + } + + internal static bool Equals( + object a, + object b) + { + return a == b || (a != null && b != null && a.Equals(b)); + } +#else + internal static Exception CreateNotImplementedException( + string message) + { + return new NotImplementedException(message); + } +#endif + +#if SILVERLIGHT + internal static System.Collections.IList CreateArrayList() + { + return new List(); + } + internal static System.Collections.IList CreateArrayList(int capacity) + { + return new List(capacity); + } + internal static System.Collections.IList CreateArrayList(System.Collections.ICollection collection) + { + System.Collections.IList result = new List(collection.Count); + foreach (object o in collection) + { + result.Add(o); + } + return result; + } + internal static System.Collections.IList CreateArrayList(System.Collections.IEnumerable collection) + { + System.Collections.IList result = new List(); + foreach (object o in collection) + { + result.Add(o); + } + return result; + } + internal static System.Collections.IDictionary CreateHashtable() + { + return new Dictionary(); + } + internal static System.Collections.IDictionary CreateHashtable(int capacity) + { + return new Dictionary(capacity); + } + internal static System.Collections.IDictionary CreateHashtable(System.Collections.IDictionary dictionary) + { + System.Collections.IDictionary result = new Dictionary(dictionary.Count); + foreach (System.Collections.DictionaryEntry entry in dictionary) + { + result.Add(entry.Key, entry.Value); + } + return result; + } +#else + internal static System.Collections.IList CreateArrayList() + { + return new ArrayList(); + } + internal static System.Collections.IList CreateArrayList(int capacity) + { + return new ArrayList(capacity); + } + internal static System.Collections.IList CreateArrayList(System.Collections.ICollection collection) + { + return new ArrayList(collection); + } + internal static System.Collections.IList CreateArrayList(System.Collections.IEnumerable collection) + { + ArrayList result = new ArrayList(); + foreach (object o in collection) + { + result.Add(o); + } + return result; + } + internal static System.Collections.IDictionary CreateHashtable() + { + return new Hashtable(); + } + internal static System.Collections.IDictionary CreateHashtable(int capacity) + { + return new Hashtable(capacity); + } + internal static System.Collections.IDictionary CreateHashtable(System.Collections.IDictionary dictionary) + { + return new Hashtable(dictionary); + } +#endif + + internal static string ToLowerInvariant(string s) + { + return s.ToLower(CultureInfo.InvariantCulture); + } + + internal static string ToUpperInvariant(string s) + { + return s.ToUpper(CultureInfo.InvariantCulture); + } + + internal static readonly string NewLine = GetNewLine(); + } +} diff --git a/crypto/src/util/Strings.cs b/crypto/src/util/Strings.cs new file mode 100644 index 000000000..96032bdc5 --- /dev/null +++ b/crypto/src/util/Strings.cs @@ -0,0 +1,107 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Utilities +{ + /// General string utilities. + public sealed class Strings + { + private Strings() + { + } + + internal static bool IsOneOf(string s, params string[] candidates) + { + foreach (string candidate in candidates) + { + if (s == candidate) + return true; + } + return false; + } + + public static string FromByteArray( + byte[] bs) + { + char[] cs = new char[bs.Length]; + for (int i = 0; i < cs.Length; ++i) + { + cs[i] = Convert.ToChar(bs[i]); + } + return new string(cs); + } + + public static byte[] ToByteArray( + char[] cs) + { + byte[] bs = new byte[cs.Length]; + for (int i = 0; i < bs.Length; ++i) + { + bs[i] = Convert.ToByte(cs[i]); + } + return bs; + } + + public static byte[] ToByteArray( + string s) + { + byte[] bs = new byte[s.Length]; + for (int i = 0; i < bs.Length; ++i) + { + bs[i] = Convert.ToByte(s[i]); + } + return bs; + } + + public static string FromAsciiByteArray( + byte[] bytes) + { +#if SILVERLIGHT + // TODO Check for non-ASCII bytes in input? + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); +#else + return Encoding.ASCII.GetString(bytes, 0, bytes.Length); +#endif + } + + public static byte[] ToAsciiByteArray( + char[] cs) + { +#if SILVERLIGHT + // TODO Check for non-ASCII characters in input? + return Encoding.UTF8.GetBytes(cs); +#else + return Encoding.ASCII.GetBytes(cs); +#endif + } + + public static byte[] ToAsciiByteArray( + string s) + { +#if SILVERLIGHT + // TODO Check for non-ASCII characters in input? + return Encoding.UTF8.GetBytes(s); +#else + return Encoding.ASCII.GetBytes(s); +#endif + } + + public static string FromUtf8ByteArray( + byte[] bytes) + { + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + } + + public static byte[] ToUtf8ByteArray( + char[] cs) + { + return Encoding.UTF8.GetBytes(cs); + } + + public static byte[] ToUtf8ByteArray( + string s) + { + return Encoding.UTF8.GetBytes(s); + } + } +} diff --git a/crypto/src/util/collections/CollectionUtilities.cs b/crypto/src/util/collections/CollectionUtilities.cs new file mode 100644 index 000000000..fd0bdcc7a --- /dev/null +++ b/crypto/src/util/collections/CollectionUtilities.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections; +using System.Text; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public sealed class CollectionUtilities + { + private CollectionUtilities() + { + } + + public static void AddRange(IList to, ICollection range) + { + foreach (object o in range) + { + to.Add(o); + } + } + + public static bool CheckElementsAreOfType( + IEnumerable e, + Type t) + { + foreach (object o in e) + { + if (!t.IsInstanceOfType(o)) + return false; + } + return true; + } + + public static IDictionary ReadOnly(IDictionary d) + { + return new UnmodifiableDictionaryProxy(d); + } + + public static IList ReadOnly(IList l) + { + return new UnmodifiableListProxy(l); + } + + public static ISet ReadOnly(ISet s) + { + return new UnmodifiableSetProxy(s); + } + + public static string ToString( + IEnumerable c) + { + StringBuilder sb = new StringBuilder("["); + + IEnumerator e = c.GetEnumerator(); + + if (e.MoveNext()) + { + sb.Append(e.Current.ToString()); + + while (e.MoveNext()) + { + sb.Append(", "); + sb.Append(e.Current.ToString()); + } + } + + sb.Append(']'); + + return sb.ToString(); + } + } +} diff --git a/crypto/src/util/collections/EmptyEnumerable.cs b/crypto/src/util/collections/EmptyEnumerable.cs new file mode 100644 index 000000000..a61a0789a --- /dev/null +++ b/crypto/src/util/collections/EmptyEnumerable.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public sealed class EmptyEnumerable + : IEnumerable + { + public static readonly IEnumerable Instance = new EmptyEnumerable(); + + private EmptyEnumerable() + { + } + + public IEnumerator GetEnumerator() + { + return EmptyEnumerator.Instance; + } + } + + public sealed class EmptyEnumerator + : IEnumerator + { + public static readonly IEnumerator Instance = new EmptyEnumerator(); + + private EmptyEnumerator() + { + } + + public bool MoveNext() + { + return false; + } + + public void Reset() + { + } + + public object Current + { + get { throw new InvalidOperationException("No elements"); } + } + } +} diff --git a/crypto/src/util/collections/EnumerableProxy.cs b/crypto/src/util/collections/EnumerableProxy.cs new file mode 100644 index 000000000..9eec4af21 --- /dev/null +++ b/crypto/src/util/collections/EnumerableProxy.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public sealed class EnumerableProxy + : IEnumerable + { + private readonly IEnumerable inner; + + public EnumerableProxy( + IEnumerable inner) + { + if (inner == null) + throw new ArgumentNullException("inner"); + + this.inner = inner; + } + + public IEnumerator GetEnumerator() + { + return inner.GetEnumerator(); + } + } +} diff --git a/crypto/src/util/collections/HashSet.cs b/crypto/src/util/collections/HashSet.cs new file mode 100644 index 000000000..1facb58e3 --- /dev/null +++ b/crypto/src/util/collections/HashSet.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public class HashSet + : ISet + { + private readonly IDictionary impl = Platform.CreateHashtable(); + + public HashSet() + { + } + + public HashSet(IEnumerable s) + { + foreach (object o in s) + { + Add(o); + } + } + + public virtual void Add(object o) + { + impl[o] = null; + } + + public virtual void AddAll(IEnumerable e) + { + foreach (object o in e) + { + Add(o); + } + } + + public virtual void Clear() + { + impl.Clear(); + } + + public virtual bool Contains(object o) + { + return impl.Contains(o); + } + + public virtual void CopyTo(Array array, int index) + { + impl.Keys.CopyTo(array, index); + } + + public virtual int Count + { + get { return impl.Count; } + } + + public virtual IEnumerator GetEnumerator() + { + return impl.Keys.GetEnumerator(); + } + + public virtual bool IsEmpty + { + get { return impl.Count == 0; } + } + + public virtual bool IsFixedSize + { + get { return impl.IsFixedSize; } + } + + public virtual bool IsReadOnly + { + get { return impl.IsReadOnly; } + } + + public virtual bool IsSynchronized + { + get { return impl.IsSynchronized; } + } + + public virtual void Remove(object o) + { + impl.Remove(o); + } + + public virtual void RemoveAll(IEnumerable e) + { + foreach (object o in e) + { + Remove(o); + } + } + + public virtual object SyncRoot + { + get { return impl.SyncRoot; } + } + } +} diff --git a/crypto/src/util/collections/ISet.cs b/crypto/src/util/collections/ISet.cs new file mode 100644 index 000000000..1f8edba40 --- /dev/null +++ b/crypto/src/util/collections/ISet.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public interface ISet + : ICollection + { + void Add(object o); + void AddAll(IEnumerable e); + void Clear(); + bool Contains(object o); + bool IsEmpty { get; } + bool IsFixedSize { get; } + bool IsReadOnly { get; } + void Remove(object o); + void RemoveAll(IEnumerable e); + } +} diff --git a/crypto/src/util/collections/LinkedDictionary.cs b/crypto/src/util/collections/LinkedDictionary.cs new file mode 100644 index 000000000..933d38ded --- /dev/null +++ b/crypto/src/util/collections/LinkedDictionary.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public class LinkedDictionary + : IDictionary + { + internal readonly IDictionary hash = Platform.CreateHashtable(); + internal readonly IList keys = Platform.CreateArrayList(); + + public LinkedDictionary() + { + } + + public virtual void Add(object k, object v) + { + hash.Add(k, v); + keys.Add(k); + } + + public virtual void Clear() + { + hash.Clear(); + keys.Clear(); + } + + public virtual bool Contains(object k) + { + return hash.Contains(k); + } + + public virtual void CopyTo(Array array, int index) + { + foreach (object k in keys) + { + array.SetValue(hash[k], index++); + } + } + + public virtual int Count + { + get { return hash.Count; } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public virtual IDictionaryEnumerator GetEnumerator() + { + return new LinkedDictionaryEnumerator(this); + } + + public virtual void Remove(object k) + { + hash.Remove(k); + keys.Remove(k); + } + + public virtual bool IsFixedSize + { + get { return false; } + } + + public virtual bool IsReadOnly + { + get { return false; } + } + + public virtual bool IsSynchronized + { + get { return false; } + } + + public virtual object SyncRoot + { + get { return false; } + } + + public virtual ICollection Keys + { + get { return Platform.CreateArrayList(keys); } + } + + public virtual ICollection Values + { + // NB: Order has to be the same as for Keys property + get + { + IList values = Platform.CreateArrayList(keys.Count); + foreach (object k in keys) + { + values.Add(hash[k]); + } + return values; + } + } + + public virtual object this[object k] + { + get + { + return hash[k]; + } + set + { + if (!hash.Contains(k)) + keys.Add(k); + hash[k] = value; + } + } + } + + internal class LinkedDictionaryEnumerator : IDictionaryEnumerator + { + private readonly LinkedDictionary parent; + private int pos = -1; + + internal LinkedDictionaryEnumerator(LinkedDictionary parent) + { + this.parent = parent; + } + + public virtual object Current + { + get { return Entry; } + } + + public virtual DictionaryEntry Entry + { + get + { + object k = CurrentKey; + return new DictionaryEntry(k, parent.hash[k]); + } + } + + public virtual object Key + { + get + { + return CurrentKey; + } + } + + public virtual bool MoveNext() + { + if (pos >= parent.keys.Count) + return false; + return ++pos < parent.keys.Count; + } + + public virtual void Reset() + { + this.pos = -1; + } + + public virtual object Value + { + get + { + return parent.hash[CurrentKey]; + } + } + + private object CurrentKey + { + get + { + if (pos < 0 || pos >= parent.keys.Count) + throw new InvalidOperationException(); + return parent.keys[pos]; + } + } + } +} diff --git a/crypto/src/util/collections/UnmodifiableDictionary.cs b/crypto/src/util/collections/UnmodifiableDictionary.cs new file mode 100644 index 000000000..0bdf70ad7 --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableDictionary.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public abstract class UnmodifiableDictionary + : IDictionary + { + protected UnmodifiableDictionary() + { + } + + public virtual void Add(object k, object v) + { + throw new NotSupportedException(); + } + + public virtual void Clear() + { + throw new NotSupportedException(); + } + + public abstract bool Contains(object k); + + public abstract void CopyTo(Array array, int index); + + public abstract int Count { get; } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public abstract IDictionaryEnumerator GetEnumerator(); + + public virtual void Remove(object k) + { + throw new NotSupportedException(); + } + + public abstract bool IsFixedSize { get; } + + public virtual bool IsReadOnly + { + get { return true; } + } + + public abstract bool IsSynchronized { get; } + + public abstract object SyncRoot { get; } + + public abstract ICollection Keys { get; } + + public abstract ICollection Values { get; } + + public virtual object this[object k] + { + get { return GetValue(k); } + set { throw new NotSupportedException(); } + } + + protected abstract object GetValue(object k); + } +} diff --git a/crypto/src/util/collections/UnmodifiableDictionaryProxy.cs b/crypto/src/util/collections/UnmodifiableDictionaryProxy.cs new file mode 100644 index 000000000..0fca909a3 --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableDictionaryProxy.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public class UnmodifiableDictionaryProxy + : UnmodifiableDictionary + { + private readonly IDictionary d; + + public UnmodifiableDictionaryProxy(IDictionary d) + { + this.d = d; + } + + public override bool Contains(object k) + { + return d.Contains(k); + } + + public override void CopyTo(Array array, int index) + { + d.CopyTo(array, index); + } + + public override int Count + { + get { return d.Count; } + } + + public override IDictionaryEnumerator GetEnumerator() + { + return d.GetEnumerator(); + } + + public override bool IsFixedSize + { + get { return d.IsFixedSize; } + } + + public override bool IsSynchronized + { + get { return d.IsSynchronized; } + } + + public override object SyncRoot + { + get { return d.SyncRoot; } + } + + public override ICollection Keys + { + get { return d.Keys; } + } + + public override ICollection Values + { + get { return d.Values; } + } + + protected override object GetValue(object k) + { + return d[k]; + } + } +} diff --git a/crypto/src/util/collections/UnmodifiableList.cs b/crypto/src/util/collections/UnmodifiableList.cs new file mode 100644 index 000000000..28e49eac3 --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableList.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public abstract class UnmodifiableList + : IList + { + protected UnmodifiableList() + { + } + + public virtual int Add(object o) + { + throw new NotSupportedException(); + } + + public virtual void Clear() + { + throw new NotSupportedException(); + } + + public abstract bool Contains(object o); + + public abstract void CopyTo(Array array, int index); + + public abstract int Count { get; } + + public abstract IEnumerator GetEnumerator(); + + public abstract int IndexOf(object o); + + public virtual void Insert(int i, object o) + { + throw new NotSupportedException(); + } + + public abstract bool IsFixedSize { get; } + + public virtual bool IsReadOnly + { + get { return true; } + } + + public abstract bool IsSynchronized { get; } + + public virtual void Remove(object o) + { + throw new NotSupportedException(); + } + + public virtual void RemoveAt(int i) + { + throw new NotSupportedException(); + } + + public abstract object SyncRoot { get; } + + public virtual object this[int i] + { + get { return GetValue(i); } + set { throw new NotSupportedException(); } + } + + protected abstract object GetValue(int i); + } +} diff --git a/crypto/src/util/collections/UnmodifiableListProxy.cs b/crypto/src/util/collections/UnmodifiableListProxy.cs new file mode 100644 index 000000000..9d00737ef --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableListProxy.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public class UnmodifiableListProxy + : UnmodifiableList + { + private readonly IList l; + + public UnmodifiableListProxy(IList l) + { + this.l = l; + } + + public override bool Contains(object o) + { + return l.Contains(o); + } + + public override void CopyTo(Array array, int index) + { + l.CopyTo(array, index); + } + + public override int Count + { + get { return l.Count; } + } + + public override IEnumerator GetEnumerator() + { + return l.GetEnumerator(); + } + + public override int IndexOf(object o) + { + return l.IndexOf(o); + } + + public override bool IsFixedSize + { + get { return l.IsFixedSize; } + } + + public override bool IsSynchronized + { + get { return l.IsSynchronized; } + } + + public override object SyncRoot + { + get { return l.SyncRoot; } + } + + protected override object GetValue(int i) + { + return l[i]; + } + } +} diff --git a/crypto/src/util/collections/UnmodifiableSet.cs b/crypto/src/util/collections/UnmodifiableSet.cs new file mode 100644 index 000000000..8792815ac --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableSet.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public abstract class UnmodifiableSet + : ISet + { + protected UnmodifiableSet() + { + } + + public virtual void Add(object o) + { + throw new NotSupportedException(); + } + + public virtual void AddAll(IEnumerable e) + { + throw new NotSupportedException(); + } + + public virtual void Clear() + { + throw new NotSupportedException(); + } + + public abstract bool Contains(object o); + + public abstract void CopyTo(Array array, int index); + + public abstract int Count { get; } + + public abstract IEnumerator GetEnumerator(); + + public abstract bool IsEmpty { get; } + + public abstract bool IsFixedSize { get; } + + public virtual bool IsReadOnly + { + get { return true; } + } + + public abstract bool IsSynchronized { get; } + + public abstract object SyncRoot { get; } + + public virtual void Remove(object o) + { + throw new NotSupportedException(); + } + + public virtual void RemoveAll(IEnumerable e) + { + throw new NotSupportedException(); + } + } +} diff --git a/crypto/src/util/collections/UnmodifiableSetProxy.cs b/crypto/src/util/collections/UnmodifiableSetProxy.cs new file mode 100644 index 000000000..e119e2957 --- /dev/null +++ b/crypto/src/util/collections/UnmodifiableSetProxy.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.Utilities.Collections +{ + public class UnmodifiableSetProxy + : UnmodifiableSet + { + private readonly ISet s; + + public UnmodifiableSetProxy (ISet s) + { + this.s = s; + } + + public override bool Contains(object o) + { + return s.Contains(o); + } + + public override void CopyTo(Array array, int index) + { + s.CopyTo(array, index); + } + + public override int Count + { + get { return s.Count; } + } + + public override IEnumerator GetEnumerator() + { + return s.GetEnumerator(); + } + + public override bool IsEmpty + { + get { return s.IsEmpty; } + } + + public override bool IsFixedSize + { + get { return s.IsFixedSize; } + } + + public override bool IsSynchronized + { + get { return s.IsSynchronized; } + } + + public override object SyncRoot + { + get { return s.SyncRoot; } + } + } +} diff --git a/crypto/src/util/date/DateTimeObject.cs b/crypto/src/util/date/DateTimeObject.cs new file mode 100644 index 000000000..793376b6d --- /dev/null +++ b/crypto/src/util/date/DateTimeObject.cs @@ -0,0 +1,25 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Date +{ + public sealed class DateTimeObject + { + private readonly DateTime dt; + + public DateTimeObject( + DateTime dt) + { + this.dt = dt; + } + + public DateTime Value + { + get { return dt; } + } + + public override string ToString() + { + return dt.ToString(); + } + } +} diff --git a/crypto/src/util/date/DateTimeUtilities.cs b/crypto/src/util/date/DateTimeUtilities.cs new file mode 100644 index 000000000..311ad5d37 --- /dev/null +++ b/crypto/src/util/date/DateTimeUtilities.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Date +{ + public class DateTimeUtilities + { + public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1); + + private DateTimeUtilities() + { + } + + /// + /// Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value. + /// + /// A UTC DateTime value not before epoch. + /// Number of whole milliseconds after epoch. + /// 'dateTime' is before epoch. + public static long DateTimeToUnixMs( + DateTime dateTime) + { + if (dateTime.CompareTo(UnixEpoch) < 0) + throw new ArgumentException("DateTime value may not be before the epoch", "dateTime"); + + return (dateTime.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond; + } + + /// + /// Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC). + /// + /// Number of milliseconds since the epoch. + /// A UTC DateTime value + public static DateTime UnixMsToDateTime( + long unixMs) + { + return new DateTime(unixMs * TimeSpan.TicksPerMillisecond + UnixEpoch.Ticks); + } + + /// + /// Return the current number of milliseconds since the Unix epoch (1 Jan., 1970 UTC). + /// + public static long CurrentUnixMs() + { + return DateTimeToUnixMs(DateTime.UtcNow); + } + } +} diff --git a/crypto/src/util/encoders/Base64.cs b/crypto/src/util/encoders/Base64.cs new file mode 100644 index 000000000..ccecd8dc2 --- /dev/null +++ b/crypto/src/util/encoders/Base64.cs @@ -0,0 +1,120 @@ +using System; +using System.IO; +using System.Text; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + public sealed class Base64 + { + private Base64() + { + } + + public static string ToBase64String( + byte[] data) + { + return Convert.ToBase64String(data, 0, data.Length); + } + + public static string ToBase64String( + byte[] data, + int off, + int length) + { + return Convert.ToBase64String(data, off, 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) + { + 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) + { + string s = Convert.ToBase64String(data, off, length); + return Strings.ToAsciiByteArray(s); + } + + /** + * 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, + Stream outStream) + { + byte[] encoded = Encode(data); + outStream.Write(encoded, 0, encoded.Length); + return encoded.Length; + } + + /** + * 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, + Stream outStream) + { + byte[] encoded = Encode(data, off, length); + outStream.Write(encoded, 0, encoded.Length); + return encoded.Length; + } + + /** + * 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) + { + string s = Strings.FromAsciiByteArray(data); + return Convert.FromBase64String(s); + } + + /** + * 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) + { + return Convert.FromBase64String(data); + } + + /** + * 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, + Stream outStream) + { + byte[] decoded = Decode(data); + outStream.Write(decoded, 0, decoded.Length); + return decoded.Length; + } + } +} diff --git a/crypto/src/util/encoders/Base64Encoder.cs b/crypto/src/util/encoders/Base64Encoder.cs new file mode 100644 index 000000000..c94ce9d3c --- /dev/null +++ b/crypto/src/util/encoders/Base64Encoder.cs @@ -0,0 +1,307 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + public class Base64Encoder + : IEncoder + { + protected readonly 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 readonly byte[] decodingTable = new byte[128]; + + protected void InitialiseDecodingTable() + { + 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, + Stream outStream) + { + 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; + + outStream.WriteByte(encodingTable[(int) ((uint) a1 >> 2) & 0x3f]); + outStream.WriteByte(encodingTable[((a1 << 4) | (int) ((uint) a2 >> 4)) & 0x3f]); + outStream.WriteByte(encodingTable[((a2 << 2) | (int) ((uint) a3 >> 6)) & 0x3f]); + outStream.WriteByte(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; + + outStream.WriteByte(encodingTable[b1]); + outStream.WriteByte(encodingTable[b2]); + outStream.WriteByte(padding); + outStream.WriteByte(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; + + outStream.WriteByte(encodingTable[b1]); + outStream.WriteByte(encodingTable[b2]); + outStream.WriteByte(encodingTable[b3]); + outStream.WriteByte(padding); + break; + } + + return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4); + } + + private bool 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, + Stream outStream) + { + 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++]]; + + outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4))); + outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2))); + outStream.WriteByte((byte)((b3 << 6) | b4)); + + outLen += 3; + + i = nextI(data, i, finish); + } + + outLen += decodeLastBlock(outStream, (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 DecodeString( + string data, + Stream outStream) + { + // Platform Implementation +// byte[] bytes = Convert.FromBase64String(data); +// outStream.Write(bytes, 0, bytes.Length); +// return bytes.Length; + + byte b1, b2, b3, b4; + int length = 0; + + int end = data.Length; + + while (end > 0) + { + if (!ignore(data[end - 1])) + { + break; + } + + end--; + } + + int i = 0; + 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++]]; + + outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4))); + outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2))); + outStream.WriteByte((byte)((b3 << 6) | b4)); + + length += 3; + + i = nextI(data, i, finish); + } + + length += decodeLastBlock(outStream, data[end - 4], data[end - 3], data[end - 2], data[end - 1]); + + return length; + } + + private int decodeLastBlock( + Stream outStream, + char c1, + char c2, + char c3, + char c4) + { + if (c3 == padding) + { + byte b1 = decodingTable[c1]; + byte b2 = decodingTable[c2]; + + outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4))); + + return 1; + } + + if (c4 == padding) + { + byte b1 = decodingTable[c1]; + byte b2 = decodingTable[c2]; + byte b3 = decodingTable[c3]; + + outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4))); + outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2))); + + return 2; + } + + { + byte b1 = decodingTable[c1]; + byte b2 = decodingTable[c2]; + byte b3 = decodingTable[c3]; + byte b4 = decodingTable[c4]; + + outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4))); + outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2))); + outStream.WriteByte((byte)((b3 << 6) | b4)); + + return 3; + } + } + + private int nextI(string data, int i, int finish) + { + while ((i < finish) && ignore(data[i])) + { + i++; + } + return i; + } + } +} diff --git a/crypto/src/util/encoders/BufferedDecoder.cs b/crypto/src/util/encoders/BufferedDecoder.cs new file mode 100644 index 000000000..633cf1e97 --- /dev/null +++ b/crypto/src/util/encoders/BufferedDecoder.cs @@ -0,0 +1,117 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /// + /// A buffering class to allow translation from one format to another to + /// be done in discrete chunks. + /// + public class BufferedDecoder + { + internal byte[] buffer; + internal int bufOff; + + internal ITranslator translator; + + /// + /// Create a buffered Decoder. + /// + /// The translater to use. + /// The size of the buffer. + public BufferedDecoder( + ITranslator translator, + int bufferSize) + { + this.translator = translator; + + if ((bufferSize % translator.GetEncodedBlockSize()) != 0) + { + throw new ArgumentException("buffer size not multiple of input block size"); + } + + buffer = new byte[bufferSize]; +// bufOff = 0; + } + + /// + /// Process one byte of data. + /// + /// Data in. + /// Byte array for the output. + /// The offset in the output byte array to start writing from. + /// The amount of output bytes. + public int ProcessByte( + byte input, + byte[] output, + int outOff) + { + int resultLen = 0; + + buffer[bufOff++] = input; + + if (bufOff == buffer.Length) + { + resultLen = translator.Decode(buffer, 0, buffer.Length, output, outOff); + bufOff = 0; + } + + return resultLen; + } + + + /// + /// Process data from a byte array. + /// + /// The input data. + /// Start position within input data array. + /// Amount of data to process from input data array. + /// Array to store output. + /// Position in output array to start writing from. + /// The amount of output bytes. + public int ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] outBytes, + int outOff) + { + if (len < 0) + { + throw new ArgumentException("Can't have a negative input length!"); + } + + int resultLen = 0; + int gapLen = buffer.Length - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, buffer, bufOff, gapLen); + + resultLen += translator.Decode(buffer, 0, buffer.Length, outBytes, outOff); + + bufOff = 0; + + len -= gapLen; + inOff += gapLen; + outOff += resultLen; + + int chunkSize = len - (len % buffer.Length); + + resultLen += translator.Decode(input, inOff, chunkSize, outBytes, outOff); + + len -= chunkSize; + inOff += chunkSize; + } + + if (len != 0) + { + Array.Copy(input, inOff, buffer, bufOff, len); + + bufOff += len; + } + + return resultLen; + } + } + +} diff --git a/crypto/src/util/encoders/BufferedEncoder.cs b/crypto/src/util/encoders/BufferedEncoder.cs new file mode 100644 index 000000000..5c3b1ab46 --- /dev/null +++ b/crypto/src/util/encoders/BufferedEncoder.cs @@ -0,0 +1,117 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /// + /// A class that allows encoding of data using a specific encoder to be processed in chunks. + /// + public class BufferedEncoder + { + internal byte[] Buffer; + internal int bufOff; + + internal ITranslator translator; + + + /// + /// Create. + /// + /// The translator to use. + /// Size of the chunks. + public BufferedEncoder( + ITranslator translator, + int bufferSize) + { + this.translator = translator; + + if ((bufferSize % translator.GetEncodedBlockSize()) != 0) + { + throw new ArgumentException("buffer size not multiple of input block size"); + } + + Buffer = new byte[bufferSize]; +// bufOff = 0; + } + + + /// + /// Process one byte of data. + /// + /// The byte. + /// An array to store output in. + /// Offset within output array to start writing from. + /// + public int ProcessByte( + byte input, + byte[] outBytes, + int outOff) + { + int resultLen = 0; + + Buffer[bufOff++] = input; + + if (bufOff == Buffer.Length) + { + resultLen = translator.Encode(Buffer, 0, Buffer.Length, outBytes, outOff); + bufOff = 0; + } + + return resultLen; + } + + /// + /// Process data from a byte array. + /// + /// Input data Byte array containing data to be processed. + /// Start position within input data array. + /// Amount of input data to be processed. + /// Output data array. + /// Offset within output data array to start writing to. + /// The amount of data written. + public int ProcessBytes( + byte[] input, + int inOff, + int len, + byte[] outBytes, + int outOff) + { + if (len < 0) + { + throw new ArgumentException("Can't have a negative input length!"); + } + + int resultLen = 0; + int gapLen = Buffer.Length - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, Buffer, bufOff, gapLen); + + resultLen += translator.Encode(Buffer, 0, Buffer.Length, outBytes, outOff); + + bufOff = 0; + + len -= gapLen; + inOff += gapLen; + outOff += resultLen; + + int chunkSize = len - (len % Buffer.Length); + + resultLen += translator.Encode(input, inOff, chunkSize, outBytes, outOff); + + len -= chunkSize; + inOff += chunkSize; + } + + if (len != 0) + { + Array.Copy(input, inOff, Buffer, bufOff, len); + + bufOff += len; + } + + return resultLen; + } + } + +} diff --git a/crypto/src/util/encoders/Hex.cs b/crypto/src/util/encoders/Hex.cs new file mode 100644 index 000000000..3540a9d1e --- /dev/null +++ b/crypto/src/util/encoders/Hex.cs @@ -0,0 +1,130 @@ +using System; +using System.IO; +using System.Text; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /// + /// Class to decode and encode Hex. + /// + public sealed class Hex + { + private static readonly IEncoder encoder = new HexEncoder(); + + private Hex() + { + } + + public static string ToHexString( + byte[] data) + { + return ToHexString(data, 0, data.Length); + } + + public static string ToHexString( + byte[] data, + int off, + int length) + { + byte[] hex = Encode(data, off, length); + return Strings.FromAsciiByteArray(hex); + } + + /** + * 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) + { + MemoryStream bOut = new MemoryStream(length * 2); + + encoder.Encode(data, off, length, bOut); + + return bOut.ToArray(); + } + + /** + * Hex encode the byte data writing it to the given output stream. + * + * @return the number of bytes produced. + */ + public static int Encode( + byte[] data, + Stream outStream) + { + return encoder.Encode(data, 0, data.Length, outStream); + } + + /** + * 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, + Stream outStream) + { + return encoder.Encode(data, off, length, outStream); + } + + /** + * 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) + { + MemoryStream bOut = new MemoryStream((data.Length + 1) / 2); + + encoder.Decode(data, 0, data.Length, bOut); + + return bOut.ToArray(); + } + + /** + * decode the Hex encoded string data - whitespace will be ignored. + * + * @return a byte array representing the decoded data. + */ + public static byte[] Decode( + string data) + { + MemoryStream bOut = new MemoryStream((data.Length + 1) / 2); + + encoder.DecodeString(data, bOut); + + return bOut.ToArray(); + } + + /** + * 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, + Stream outStream) + { + return encoder.DecodeString(data, outStream); + } + } +} diff --git a/crypto/src/util/encoders/HexEncoder.cs b/crypto/src/util/encoders/HexEncoder.cs new file mode 100644 index 000000000..e69a78b0b --- /dev/null +++ b/crypto/src/util/encoders/HexEncoder.cs @@ -0,0 +1,163 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + public class HexEncoder + : IEncoder + { + private static readonly 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' + }; + + private static readonly byte[] decodingTable = ConstructDecodingTable(encodingTable); + + private static byte[] ConstructDecodingTable(byte[] et) + { + byte[] dt = new byte[128]; + for (int i = 0; i < et.Length; i++) + { + dt[et[i]] = (byte)i; + } + + dt['A'] = dt['a']; + dt['B'] = dt['b']; + dt['C'] = dt['c']; + dt['D'] = dt['d']; + dt['E'] = dt['e']; + dt['F'] = dt['f']; + + return dt; + } + + /** + * encode the input data producing a Hex output stream. + * + * @return the number of bytes produced. + */ + public int Encode( + byte[] data, + int off, + int length, + Stream outStream) + { + for (int i = off; i < (off + length); i++) + { + int v = data[i]; + + outStream.WriteByte(encodingTable[v >> 4]); + outStream.WriteByte(encodingTable[v & 0xf]); + } + + return length * 2; + } + + private static bool 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, + Stream outStream) + { + 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++]]; + + outStream.WriteByte((byte)((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 DecodeString( + string data, + Stream outStream) + { + byte b1, b2; + int length = 0; + + int end = data.Length; + + while (end > 0) + { + if (!Ignore(data[end - 1])) + { + break; + } + + end--; + } + + int i = 0; + while (i < end) + { + while (i < end && Ignore(data[i])) + { + i++; + } + + b1 = decodingTable[data[i++]]; + + while (i < end && Ignore(data[i])) + { + i++; + } + + b2 = decodingTable[data[i++]]; + + outStream.WriteByte((byte)((b1 << 4) | b2)); + + length++; + } + + return length; + } + } +} diff --git a/crypto/src/util/encoders/HexTranslator.cs b/crypto/src/util/encoders/HexTranslator.cs new file mode 100644 index 000000000..9775b6948 --- /dev/null +++ b/crypto/src/util/encoders/HexTranslator.cs @@ -0,0 +1,108 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /// + /// A hex translator. + /// + public class HexTranslator : ITranslator + { + private static readonly 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' + }; + + /// + /// Return encoded block size. + /// + /// 2 + public int GetEncodedBlockSize() + { + return 2; + } + + /// + /// Encode some data. + /// + /// Input data array. + /// Start position within input data array. + /// The amount of data to process. + /// The output data array. + /// The offset within the output data array to start writing from. + /// Amount of data encoded. + public int Encode( + byte[] input, + int inOff, + int length, + byte[] outBytes, + int outOff) + { + for (int i = 0, j = 0; i < length; i++, j += 2) + { + outBytes[outOff + j] = hexTable[(input[inOff] >> 4) & 0x0f]; + outBytes[outOff + j + 1] = hexTable[input[inOff] & 0x0f]; + + inOff++; + } + + return length * 2; + } + + /// + /// Returns the decoded block size. + /// + /// 1 + public int GetDecodedBlockSize() + { + return 1; + } + + /// + /// Decode data from a byte array. + /// + /// The input data array. + /// Start position within input data array. + /// The amounty of data to process. + /// The output data array. + /// The position within the output data array to start writing from. + /// The amount of data written. + public int Decode( + byte[] input, + int inOff, + int length, + byte[] outBytes, + int outOff) + { + int halfLength = length / 2; + byte left, right; + for (int i = 0; i < halfLength; i++) + { + left = input[inOff + i * 2]; + right = input[inOff + i * 2 + 1]; + + if (left < (byte)'a') + { + outBytes[outOff] = (byte)((left - '0') << 4); + } + else + { + outBytes[outOff] = (byte)((left - 'a' + 10) << 4); + } + if (right < (byte)'a') + { + outBytes[outOff] += (byte)(right - '0'); + } + else + { + outBytes[outOff] += (byte)(right - 'a' + 10); + } + + outOff++; + } + + return halfLength; + } + } + +} diff --git a/crypto/src/util/encoders/IEncoder.cs b/crypto/src/util/encoders/IEncoder.cs new file mode 100644 index 000000000..5887d5daa --- /dev/null +++ b/crypto/src/util/encoders/IEncoder.cs @@ -0,0 +1,18 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /** + * Encode and decode byte arrays (typically from binary to 7-bit ASCII + * encodings). + */ + public interface IEncoder + { + int Encode(byte[] data, int off, int length, Stream outStream); + + int Decode(byte[] data, int off, int length, Stream outStream); + + int DecodeString(string data, Stream outStream); + } +} diff --git a/crypto/src/util/encoders/Translator.cs b/crypto/src/util/encoders/Translator.cs new file mode 100644 index 000000000..10bd24b63 --- /dev/null +++ b/crypto/src/util/encoders/Translator.cs @@ -0,0 +1,19 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Encoders +{ + /// + /// Translator interface. + /// + public interface ITranslator + { + int GetEncodedBlockSize(); + + int Encode(byte[] input, int inOff, int length, byte[] outBytes, int outOff); + + int GetDecodedBlockSize(); + + int Decode(byte[] input, int inOff, int length, byte[] outBytes, int outOff); + } + +} diff --git a/crypto/src/util/encoders/UrlBase64.cs b/crypto/src/util/encoders/UrlBase64.cs new file mode 100644 index 000000000..94195ef5e --- /dev/null +++ b/crypto/src/util/encoders/UrlBase64.cs @@ -0,0 +1,127 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.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 "/". + *

    + * 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 readonly IEncoder 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) + { + MemoryStream bOut = new MemoryStream(); + + try + { + encoder.Encode(data, 0, data.Length, bOut); + } + catch (IOException e) + { + throw new Exception("exception encoding URL safe base64 string: " + e.Message, e); + } + + return bOut.ToArray(); + } + + /** + * Encode the byte data writing it to the given output stream. + * + * @return the number of bytes produced. + */ + public static int Encode( + byte[] data, + Stream outStr) + { + return encoder.Encode(data, 0, data.Length, outStr); + } + + /** + * 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) + { + MemoryStream bOut = new MemoryStream(); + + try + { + encoder.Decode(data, 0, data.Length, bOut); + } + catch (IOException e) + { + throw new Exception("exception decoding URL safe base64 string: " + e.Message, e); + } + + return bOut.ToArray(); + } + + /** + * 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, + Stream outStr) + { + return encoder.Decode(data, 0, data.Length, outStr); + } + + /** + * 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) + { + MemoryStream bOut = new MemoryStream(); + + try + { + encoder.DecodeString(data, bOut); + } + catch (IOException e) + { + throw new Exception("exception decoding URL safe base64 string: " + e.Message, e); + } + + return bOut.ToArray(); + } + + /** + * 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, + Stream outStr) + { + return encoder.DecodeString(data, outStr); + } + } +} diff --git a/crypto/src/util/encoders/UrlBase64Encoder.cs b/crypto/src/util/encoders/UrlBase64Encoder.cs new file mode 100644 index 000000000..5611a831c --- /dev/null +++ b/crypto/src/util/encoders/UrlBase64Encoder.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.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 "/". + *

    + * 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 + : 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(); + } + } +} \ No newline at end of file diff --git a/crypto/src/util/io/BaseInputStream.cs b/crypto/src/util/io/BaseInputStream.cs new file mode 100644 index 000000000..3ff4a1957 --- /dev/null +++ b/crypto/src/util/io/BaseInputStream.cs @@ -0,0 +1,47 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + public abstract class BaseInputStream : Stream + { + private bool closed; + + public sealed override bool CanRead { get { return !closed; } } + public sealed override bool CanSeek { get { return false; } } + public sealed override bool CanWrite { get { return false; } } + public override void Close() { closed = true; } + public sealed override void Flush() {} + public sealed override long Length { get { throw new NotSupportedException(); } } + public sealed override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + public override int Read(byte[] buffer, int offset, int count) + { + int pos = offset; + try + { + int end = offset + count; + while (pos < end) + { + int b = ReadByte(); + if (b == -1) break; + buffer[pos++] = (byte) b; + } + } + catch (IOException) + { + if (pos == offset) throw; + } + return pos - offset; + } + + public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } + public sealed override void SetLength(long value) { throw new NotSupportedException(); } + public sealed override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } + } +} diff --git a/crypto/src/util/io/BaseOutputStream.cs b/crypto/src/util/io/BaseOutputStream.cs new file mode 100644 index 000000000..6e6c6d346 --- /dev/null +++ b/crypto/src/util/io/BaseOutputStream.cs @@ -0,0 +1,47 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + public abstract class BaseOutputStream : Stream + { + private bool closed; + + public sealed override bool CanRead { get { return false; } } + public sealed override bool CanSeek { get { return false; } } + public sealed override bool CanWrite { get { return !closed; } } + public override void Close() { closed = true; } + public override void Flush() {} + public sealed override long Length { get { throw new NotSupportedException(); } } + public sealed override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } + public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } + public sealed override void SetLength(long value) { throw new NotSupportedException(); } + + public override void Write(byte[] buffer, int offset, int count) + { + Debug.Assert(buffer != null); + Debug.Assert(0 <= offset && offset <= buffer.Length); + Debug.Assert(count >= 0); + + int end = offset + count; + + Debug.Assert(0 <= end && end <= buffer.Length); + + for (int i = offset; i < end; ++i) + { + this.WriteByte(buffer[i]); + } + } + + public virtual void Write(params byte[] buffer) + { + Write(buffer, 0, buffer.Length); + } + } +} diff --git a/crypto/src/util/io/PushbackStream.cs b/crypto/src/util/io/PushbackStream.cs new file mode 100644 index 000000000..954694259 --- /dev/null +++ b/crypto/src/util/io/PushbackStream.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; + +namespace Org.BouncyCastle.Utilities.IO +{ + public class PushbackStream + : FilterStream + { + private int buf = -1; + + public PushbackStream( + Stream s) + : base(s) + { + } + + public override int ReadByte() + { + if (buf != -1) + { + int tmp = buf; + buf = -1; + return tmp; + } + + return base.ReadByte(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (buf != -1 && count > 0) + { + // TODO Can this case be made more efficient? + buffer[offset] = (byte) buf; + buf = -1; + return 1; + } + + return base.Read(buffer, offset, count); + } + + public virtual void Unread(int b) + { + if (buf != -1) + throw new InvalidOperationException("Can only push back one byte"); + + buf = b & 0xFF; + } + } +} diff --git a/crypto/src/util/io/StreamOverflowException.cs b/crypto/src/util/io/StreamOverflowException.cs new file mode 100644 index 000000000..d8fcb558c --- /dev/null +++ b/crypto/src/util/io/StreamOverflowException.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class StreamOverflowException + : IOException + { + public StreamOverflowException() + : base() + { + } + + public StreamOverflowException( + string message) + : base(message) + { + } + + public StreamOverflowException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs new file mode 100644 index 000000000..ee95d3b01 --- /dev/null +++ b/crypto/src/util/io/Streams.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + public sealed class Streams + { + private const int BufferSize = 512; + + private Streams() + { + } + + public static void Drain(Stream inStr) + { + byte[] bs = new byte[BufferSize]; + while (inStr.Read(bs, 0, bs.Length) > 0) + { + } + } + + public static byte[] ReadAll(Stream inStr) + { + MemoryStream buf = new MemoryStream(); + PipeAll(inStr, buf); + return buf.ToArray(); + } + + public static byte[] ReadAllLimited(Stream inStr, int limit) + { + MemoryStream buf = new MemoryStream(); + PipeAllLimited(inStr, limit, buf); + return buf.ToArray(); + } + + public static int ReadFully(Stream inStr, byte[] buf) + { + return ReadFully(inStr, buf, 0, buf.Length); + } + + public static int ReadFully(Stream inStr, byte[] buf, int off, int len) + { + int totalRead = 0; + while (totalRead < len) + { + int numRead = inStr.Read(buf, off + totalRead, len - totalRead); + if (numRead < 1) + break; + totalRead += numRead; + } + return totalRead; + } + + public static void PipeAll(Stream inStr, Stream outStr) + { + byte[] bs = new byte[BufferSize]; + int numRead; + while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0) + { + outStr.Write(bs, 0, numRead); + } + } + + /// + /// Pipe all bytes from inStr to outStr, throwing StreamFlowException if greater + /// than limit bytes in inStr. + /// + /// + /// A + /// + /// + /// A + /// + /// + /// A + /// + /// The number of bytes actually transferred, if not greater than limit + /// + public static long PipeAllLimited(Stream inStr, long limit, Stream outStr) + { + byte[] bs = new byte[BufferSize]; + long total = 0; + 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/crypto/src/util/io/TeeInputStream.cs b/crypto/src/util/io/TeeInputStream.cs new file mode 100644 index 000000000..373df4502 --- /dev/null +++ b/crypto/src/util/io/TeeInputStream.cs @@ -0,0 +1,51 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + public class TeeInputStream + : BaseInputStream + { + private readonly Stream input, tee; + + public TeeInputStream(Stream input, Stream tee) + { + Debug.Assert(input.CanRead); + Debug.Assert(tee.CanWrite); + + this.input = input; + this.tee = tee; + } + + public override void Close() + { + input.Close(); + tee.Close(); + } + + public override int Read(byte[] buf, int off, int len) + { + int i = input.Read(buf, off, len); + + if (i > 0) + { + tee.Write(buf, off, i); + } + + return i; + } + + public override int ReadByte() + { + int i = input.ReadByte(); + + if (i >= 0) + { + tee.WriteByte((byte)i); + } + + return i; + } + } +} diff --git a/crypto/src/util/io/TeeOutputStream.cs b/crypto/src/util/io/TeeOutputStream.cs new file mode 100644 index 000000000..fe3a7586a --- /dev/null +++ b/crypto/src/util/io/TeeOutputStream.cs @@ -0,0 +1,39 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + public class TeeOutputStream + : BaseOutputStream + { + private readonly Stream output, tee; + + public TeeOutputStream(Stream output, Stream tee) + { + Debug.Assert(output.CanWrite); + Debug.Assert(tee.CanWrite); + + this.output = output; + this.tee = tee; + } + + public override void Close() + { + output.Close(); + tee.Close(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + output.Write(buffer, offset, count); + tee.Write(buffer, offset, count); + } + + public override void WriteByte(byte b) + { + output.WriteByte(b); + tee.WriteByte(b); + } + } +} diff --git a/crypto/src/util/io/pem/PemGenerationException.cs b/crypto/src/util/io/pem/PemGenerationException.cs new file mode 100644 index 000000000..b8edc622b --- /dev/null +++ b/crypto/src/util/io/pem/PemGenerationException.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class PemGenerationException + : Exception + { + public PemGenerationException() + : base() + { + } + + public PemGenerationException( + string message) + : base(message) + { + } + + public PemGenerationException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/util/io/pem/PemHeader.cs b/crypto/src/util/io/pem/PemHeader.cs new file mode 100644 index 000000000..72da8a4f7 --- /dev/null +++ b/crypto/src/util/io/pem/PemHeader.cs @@ -0,0 +1,55 @@ +using System; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + public class PemHeader + { + private string name; + private string val; + + public PemHeader(string name, string val) + { + this.name = name; + this.val = val; + } + + public virtual string Name + { + get { return name; } + } + + public virtual string Value + { + get { return val; } + } + + public override int GetHashCode() + { + return GetHashCode(this.name) + 31 * GetHashCode(this.val); + } + + public override bool Equals(object obj) + { + if (obj == this) + return true; + + if (!(obj is PemHeader)) + return false; + + PemHeader other = (PemHeader)obj; + + return Platform.Equals(this.name, other.name) + && Platform.Equals(this.val, other.val); + } + + private int GetHashCode(string s) + { + if (s == null) + { + return 1; + } + + return s.GetHashCode(); + } + } +} diff --git a/crypto/src/util/io/pem/PemObject.cs b/crypto/src/util/io/pem/PemObject.cs new file mode 100644 index 000000000..41212f997 --- /dev/null +++ b/crypto/src/util/io/pem/PemObject.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + public class PemObject + : PemObjectGenerator + { + private string type; + private IList headers; + private byte[] content; + + public PemObject(string type, byte[] content) + : this(type, Platform.CreateArrayList(), content) + { + } + + public PemObject(String type, IList headers, byte[] content) + { + this.type = type; + this.headers = Platform.CreateArrayList(headers); + this.content = content; + } + + public string Type + { + get { return type; } + } + + public IList Headers + { + get { return headers; } + } + + public byte[] Content + { + get { return content; } + } + + public PemObject Generate() + { + return this; + } + } +} diff --git a/crypto/src/util/io/pem/PemObjectGenerator.cs b/crypto/src/util/io/pem/PemObjectGenerator.cs new file mode 100644 index 000000000..6f9bfc191 --- /dev/null +++ b/crypto/src/util/io/pem/PemObjectGenerator.cs @@ -0,0 +1,13 @@ +using System; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + public interface PemObjectGenerator + { + /// + /// A + /// + /// + PemObject Generate(); + } +} diff --git a/crypto/src/util/io/pem/PemObjectParser.cs b/crypto/src/util/io/pem/PemObjectParser.cs new file mode 100644 index 000000000..91d26dc3a --- /dev/null +++ b/crypto/src/util/io/pem/PemObjectParser.cs @@ -0,0 +1,17 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + public interface PemObjectParser + { + /// + /// A + /// + /// + /// A + /// + /// + object ParseObject(PemObject obj); + } +} diff --git a/crypto/src/util/io/pem/PemReader.cs b/crypto/src/util/io/pem/PemReader.cs new file mode 100644 index 000000000..b3284705d --- /dev/null +++ b/crypto/src/util/io/pem/PemReader.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + public class PemReader + { + private const string BeginString = "-----BEGIN "; + private const string EndString = "-----END "; + + private readonly TextReader reader; + + public PemReader(TextReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + this.reader = reader; + } + + public TextReader Reader + { + get { return reader; } + } + + /// + /// A + /// + /// + public PemObject ReadPemObject() + { + string line = reader.ReadLine(); + + if (line != null && line.StartsWith(BeginString)) + { + line = line.Substring(BeginString.Length); + int index = line.IndexOf('-'); + string type = line.Substring(0, index); + + if (index > 0) + return LoadObject(type); + } + + return null; + } + + private PemObject LoadObject(string type) + { + string endMarker = EndString + type; + IList headers = Platform.CreateArrayList(); + StringBuilder buf = new StringBuilder(); + + string line; + while ((line = reader.ReadLine()) != null + && line.IndexOf(endMarker) == -1) + { + int colonPos = line.IndexOf(':'); + + if (colonPos == -1) + { + buf.Append(line.Trim()); + } + else + { + // Process field + string fieldName = line.Substring(0, colonPos).Trim(); + + if (fieldName.StartsWith("X-")) + fieldName = fieldName.Substring(2); + + string fieldValue = line.Substring(colonPos + 1).Trim(); + + headers.Add(new PemHeader(fieldName, fieldValue)); + } + } + + if (line == null) + { + throw new IOException(endMarker + " not found"); + } + + if (buf.Length % 4 != 0) + { + throw new IOException("base64 data appears to be truncated"); + } + + return new PemObject(type, headers, Base64.Decode(buf.ToString())); + } + } +} diff --git a/crypto/src/util/io/pem/PemWriter.cs b/crypto/src/util/io/pem/PemWriter.cs new file mode 100644 index 000000000..e85b31543 --- /dev/null +++ b/crypto/src/util/io/pem/PemWriter.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Utilities.IO.Pem +{ + /** + * A generic PEM writer, based on RFC 1421 + */ + public class PemWriter + { + private const int LineLength = 64; + + private readonly TextWriter writer; + private readonly int nlLength; + private char[] buf = new char[LineLength]; + + /** + * Base constructor. + * + * @param out output stream to use. + */ + public PemWriter(TextWriter writer) + { + if (writer == null) + throw new ArgumentNullException("writer"); + + this.writer = writer; + this.nlLength = Platform.NewLine.Length; + } + + public TextWriter Writer + { + get { return writer; } + } + + /** + * 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.Type.Length + 10 + nlLength)) + 6 + 4; + + if (obj.Headers.Count > 0) + { + foreach (PemHeader header in obj.Headers) + { + size += header.Name.Length + ": ".Length + header.Value.Length + nlLength; + } + + size += nlLength; + } + + // base64 encoding + int dataLen = ((obj.Content.Length + 2) / 3) * 4; + + size += dataLen + (((dataLen + LineLength - 1) / LineLength) * nlLength); + + return size; + } + + public void WriteObject(PemObjectGenerator objGen) + { + PemObject obj = objGen.Generate(); + + WritePreEncapsulationBoundary(obj.Type); + + if (obj.Headers.Count > 0) + { + foreach (PemHeader header in obj.Headers) + { + writer.Write(header.Name); + writer.Write(": "); + writer.WriteLine(header.Value); + } + + writer.WriteLine(); + } + + WriteEncoded(obj.Content); + WritePostEncapsulationBoundary(obj.Type); + } + + private void WriteEncoded(byte[] bytes) + { + 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++; + } + writer.WriteLine(buf, 0, index); + } + } + + private void WritePreEncapsulationBoundary(string type) + { + writer.WriteLine("-----BEGIN " + type + "-----"); + } + + private void WritePostEncapsulationBoundary(string type) + { + writer.WriteLine("-----END " + type + "-----"); + } + } +} diff --git a/crypto/src/util/net/IPAddress.cs b/crypto/src/util/net/IPAddress.cs new file mode 100644 index 000000000..2a30a15f0 --- /dev/null +++ b/crypto/src/util/net/IPAddress.cs @@ -0,0 +1,197 @@ +using System; +using System.Globalization; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Utilities.Net +{ + 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 bool 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 bool 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 bool IsValidIPv4( + string address) + { + try + { + return unsafeIsValidIPv4(address); + } + catch (FormatException) {} + catch (OverflowException) {} + return false; + } + + private static bool unsafeIsValidIPv4( + string address) + { + if (address.Length == 0) + return false; + + 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; + + string octetStr = temp.Substring(start, pos - start); + int octet = Int32.Parse(octetStr); + + if (octet < 0 || octet > 255) + return false; + + start = pos + 1; + octets++; + } + + return octets == 4; + } + + public static bool 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 bool 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 bool IsMaskValue( + string component, + int size) + { + int val = Int32.Parse(component); + try + { + return val >= 0 && val <= size; + } + catch (FormatException) {} + catch (OverflowException) {} + 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 bool IsValidIPv6( + string address) + { + try + { + return unsafeIsValidIPv6(address); + } + catch (FormatException) {} + catch (OverflowException) {} + return false; + } + + private static bool unsafeIsValidIPv6( + string address) + { + if (address.Length == 0) + { + return false; + } + + int octets = 0; + + string temp = address + ":"; + bool 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 - start); + + if (pos == (temp.Length - 1) && value.IndexOf('.') > 0) + { + if (!IsValidIPv4(value)) + { + return false; + } + + octets++; // add an extra one as address covers 2 words. + } + else + { + string octetStr = temp.Substring(start, pos - start); + int octet = Int32.Parse(octetStr, NumberStyles.AllowHexSpecifier); + + 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/crypto/src/util/zlib/Adler32.cs b/crypto/src/util/zlib/Adler32.cs new file mode 100644 index 000000000..c38258f2a --- /dev/null +++ b/crypto/src/util/zlib/Adler32.cs @@ -0,0 +1,88 @@ +using System; +/* + * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + internal sealed class Adler32{ + + // largest prime smaller than 65536 + private const int BASE=65521; + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + private const int NMAX=5552; + + internal long adler32(long adler, byte[] buf, int index, int len){ + if(buf == null){ return 1L; } + + long s1=adler&0xffff; + long s2=(adler>>16)&0xffff; + int k; + + while(len > 0) { + k=len=16){ + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + s1+=buf[index++]&0xff; s2+=s1; + k-=16; + } + if(k!=0){ + do{ + s1+=buf[index++]&0xff; s2+=s1; + } + while(--k!=0); + } + s1%=BASE; + s2%=BASE; + } + return (s2<<16)|s1; + } + + } +} \ No newline at end of file diff --git a/crypto/src/util/zlib/Deflate.cs b/crypto/src/util/zlib/Deflate.cs new file mode 100644 index 000000000..ca0430939 --- /dev/null +++ b/crypto/src/util/zlib/Deflate.cs @@ -0,0 +1,1640 @@ +using System; +/* + * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + public sealed class Deflate{ + + private const int MAX_MEM_LEVEL=9; + + private const int Z_DEFAULT_COMPRESSION=-1; + + private const int MAX_WBITS=15; // 32K LZ77 window + private const int DEF_MEM_LEVEL=8; + + internal class Config{ + internal int good_length; // reduce lazy search above this match length + internal int max_lazy; // do not perform lazy search above this match length + internal int nice_length; // quit search above this match length + internal int max_chain; + internal int func; + internal Config(int good_length, int max_lazy, + int nice_length, int max_chain, int func){ + this.good_length=good_length; + this.max_lazy=max_lazy; + this.nice_length=nice_length; + this.max_chain=max_chain; + this.func=func; + } + } + + private const int STORED=0; + private const int FAST=1; + private const int SLOW=2; + private static readonly Config[] config_table; + + static Deflate(){ + config_table=new Config[10]; + // good lazy nice chain + config_table[0]=new Config(0, 0, 0, 0, STORED); + config_table[1]=new Config(4, 4, 8, 4, FAST); + config_table[2]=new Config(4, 5, 16, 8, FAST); + config_table[3]=new Config(4, 6, 32, 32, FAST); + + config_table[4]=new Config(4, 4, 16, 16, SLOW); + config_table[5]=new Config(8, 16, 32, 32, SLOW); + config_table[6]=new Config(8, 16, 128, 128, SLOW); + config_table[7]=new Config(8, 32, 128, 256, SLOW); + config_table[8]=new Config(32, 128, 258, 1024, SLOW); + config_table[9]=new Config(32, 258, 258, 4096, SLOW); + } + + private static readonly String[] z_errmsg = { + "need dictionary", // Z_NEED_DICT 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "file error", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "insufficient memory", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "incompatible version",// Z_VERSION_ERROR (-6) + "" + }; + + // block not completed, need more input or more output + private const int NeedMore=0; + + // block flush performed + private const int BlockDone=1; + + // finish started, need only more output at next deflate + private const int FinishStarted=2; + + // finish done, accept no more input or output + private const int FinishDone=3; + + // preset dictionary flag in zlib header + private const int PRESET_DICT=0x20; + + private const int Z_FILTERED=1; + private const int Z_HUFFMAN_ONLY=2; + private const int Z_DEFAULT_STRATEGY=0; + + private const int Z_NO_FLUSH=0; + private const int Z_PARTIAL_FLUSH=1; + private const int Z_SYNC_FLUSH=2; + private const int Z_FULL_FLUSH=3; + private const int Z_FINISH=4; + + private const int Z_OK=0; + private const int Z_STREAM_END=1; + private const int Z_NEED_DICT=2; + private const int Z_ERRNO=-1; + private const int Z_STREAM_ERROR=-2; + private const int Z_DATA_ERROR=-3; + private const int Z_MEM_ERROR=-4; + private const int Z_BUF_ERROR=-5; + private const int Z_VERSION_ERROR=-6; + + private const int INIT_STATE=42; + private const int BUSY_STATE=113; + private const int FINISH_STATE=666; + + // The deflate compression method + private const int Z_DEFLATED=8; + + private const int STORED_BLOCK=0; + private const int STATIC_TREES=1; + private const int DYN_TREES=2; + + // The three kinds of block type + private const int Z_BINARY=0; + private const int Z_ASCII=1; + private const int Z_UNKNOWN=2; + + private const int Buf_size=8*2; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + private const int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + private const int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + private const int REPZ_11_138=18; + + private const int MIN_MATCH=3; + private const int MAX_MATCH=258; + private const int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1); + + private const int MAX_BITS=15; + private const int D_CODES=30; + private const int BL_CODES=19; + private const int LENGTH_CODES=29; + private const int LITERALS=256; + private const int L_CODES=(LITERALS+1+LENGTH_CODES); + private const int HEAP_SIZE=(2*L_CODES+1); + + private const int END_BLOCK=256; + + internal ZStream strm; // pointer back to this zlib stream + internal int status; // as the name implies + internal byte[] pending_buf; // output still pending + internal int pending_buf_size; // size of pending_buf + internal int pending_out; // next pending byte to output to the stream + internal int pending; // nb of bytes in the pending buffer + internal int noheader; // suppress zlib header and adler32 + internal byte data_type; // UNKNOWN, BINARY or ASCII + internal byte method; // STORED (for zip only) or DEFLATED + internal int last_flush; // value of flush param for previous deflate call + + internal int w_size; // LZ77 window size (32K by default) + internal int w_bits; // log2(w_size) (8..16) + internal int w_mask; // w_size - 1 + + internal byte[] window; + // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + internal int window_size; + // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + internal short[] prev; + // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + internal short[] head; // Heads of the hash chains or NIL. + + internal int ins_h; // hash index of string to be inserted + internal int hash_size; // number of elements in hash table + internal int hash_bits; // log2(hash_size) + internal int hash_mask; // hash_size-1 + + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + internal int hash_shift; + + // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + internal int block_start; + + internal int match_length; // length of best match + internal int prev_match; // previous match + internal int match_available; // set if previous match exists + internal int strstart; // start of string to insert + internal int match_start; // start of matching string + internal int lookahead; // number of valid bytes ahead in window + + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + internal int prev_length; + + // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + internal int max_chain_length; + + // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + internal int max_lazy_match; + + // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + internal int level; // compression level (1..9) + internal int strategy; // favor or force Huffman coding + + // Use a faster search when the previous match is longer than this + internal int good_match; + + // Stop searching when current match exceeds this + internal int nice_match; + + internal short[] dyn_ltree; // literal and length tree + internal short[] dyn_dtree; // distance tree + internal short[] bl_tree; // Huffman tree for bit lengths + + internal Tree l_desc=new Tree(); // desc for literal tree + internal Tree d_desc=new Tree(); // desc for distance tree + internal Tree bl_desc=new Tree(); // desc for bit length tree + + // number of codes at each bit length for an optimal tree + internal short[] bl_count=new short[MAX_BITS+1]; + + // heap used to build the Huffman trees + internal int[] heap=new int[2*L_CODES+1]; + + internal int heap_len; // number of elements in the heap + internal int heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + + // Depth of each subtree used as tie breaker for trees of equal frequency + internal byte[] depth=new byte[2*L_CODES+1]; + + internal int l_buf; // index for literals or lengths */ + + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + internal int lit_bufsize; + + internal int last_lit; // running index in l_buf + + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + internal int d_buf; // index of pendig_buf + + internal int opt_len; // bit length of current block with optimal trees + internal int static_len; // bit length of current block with static trees + internal int matches; // number of string matches in current block + internal int last_eob_len; // bit length of EOB code for last block + + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + internal uint bi_buf; + + // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + internal int bi_valid; + + internal Deflate(){ + dyn_ltree=new short[HEAP_SIZE*2]; + dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree + bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths + } + + internal void lm_init() { + window_size=2*w_size; + + head[hash_size-1]=0; + for(int i=0; i= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break; + } + // Update opt_len to include the bit length tree and counts + opt_len += 3*(max_blindex+1) + 5+5+4; + + return max_blindex; + } + + + // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + internal void send_all_trees(int lcodes, int dcodes, int blcodes){ + int rank; // index in bl_order + + send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes-1, 5); + send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3); + } + send_tree(dyn_ltree, lcodes-1); // literal tree + send_tree(dyn_dtree, dcodes-1); // distance tree + } + + // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + internal void send_tree (short[] tree,// the tree to be sent + int max_code // and its largest code of non zero frequency + ){ + int n; // iterates over all tree elements + int prevlen = -1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0*2+1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0){ max_count = 138; min_count = 3; } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[(n+1)*2+1]; + if(++count < max_count && curlen == nextlen) { + continue; + } + else if(count < min_count) { + do { send_code(curlen, bl_tree); } while (--count != 0); + } + else if(curlen != 0){ + if(curlen != prevlen){ + send_code(curlen, bl_tree); count--; + } + send_code(REP_3_6, bl_tree); + send_bits(count-3, 2); + } + else if(count <= 10){ + send_code(REPZ_3_10, bl_tree); + send_bits(count-3, 3); + } + else{ + send_code(REPZ_11_138, bl_tree); + send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if(nextlen == 0){ + max_count = 138; min_count = 3; + } + else if(curlen == nextlen){ + max_count = 6; min_count = 3; + } + else{ + max_count = 7; min_count = 4; + } + } + } + + // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + internal void put_byte(byte[] p, int start, int len){ + System.Array.Copy(p, start, pending_buf, pending, len); + pending+=len; + } + + internal void put_byte(byte c){ + pending_buf[pending++]=c; + } + internal void put_short(int w) { + pending_buf[pending++]=(byte)(w/*&0xff*/); + pending_buf[pending++]=(byte)(w>>8); + } + internal void putShortMSB(int b){ + pending_buf[pending++]=(byte)(b>>8); + pending_buf[pending++]=(byte)(b/*&0xff*/); + } + + internal void send_code(int c, short[] tree){ + int c2=c*2; + send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff)); + } + + internal void send_bits(int val, int length){ + if (bi_valid > Buf_size - length) { + bi_buf |= (uint)(val << bi_valid); + pending_buf[pending++]=(byte)(bi_buf/*&0xff*/); + pending_buf[pending++]=(byte)(bi_buf>>8); + bi_buf = ((uint)val) >> (Buf_size - bi_valid); + bi_valid += length - Buf_size; + } else { + bi_buf |= (uint)(val << bi_valid); + bi_valid += length; + } +// int len = length; +// if (bi_valid > (int)Buf_size - len) { +// int val = value; +// // bi_buf |= (val << bi_valid); +// bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff)); +// put_short(bi_buf); +// bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid)); +// bi_valid += len - Buf_size; +// } else { +// // bi_buf |= (value) << bi_valid; +// bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff)); +// bi_valid += len; +// } + } + + // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + internal void _tr_align(){ + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + + bi_flush(); + + // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + last_eob_len = 7; + } + + + // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + internal bool _tr_tally (int dist, // distance of matched string + int lc // match length-MIN_MATCH or unmatched char (if dist==0) + ){ + + pending_buf[d_buf+last_lit*2] = (byte)(dist>>8); + pending_buf[d_buf+last_lit*2+1] = (byte)dist; + + pending_buf[l_buf+last_lit] = (byte)lc; last_lit++; + + if (dist == 0) { + // lc is the unmatched char + dyn_ltree[lc*2]++; + } + else { + matches++; + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++; + dyn_dtree[Tree.d_code(dist)*2]++; + } + + if ((last_lit & 0x1fff) == 0 && level > 2) { + // Compute an upper bound for the compressed length + int out_length = last_lit*8; + int in_length = strstart - block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (int)((int)dyn_dtree[dcode*2] * + (5L+Tree.extra_dbits[dcode])); + } + out_length >>= 3; + if ((matches < (last_lit/2)) && out_length < in_length/2) return true; + } + + return (last_lit == lit_bufsize-1); + // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + // Send the block data compressed using the given Huffman trees + internal void compress_block(short[] ltree, short[] dtree){ + int dist; // distance of matched string + int lc; // match length or unmatched char (if dist == 0) + int lx = 0; // running index in l_buf + int code; // the code to send + int extra; // number of extra bits to send + + if (last_lit != 0){ + do{ + dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)| + (pending_buf[d_buf+lx*2+1]&0xff); + lc=(pending_buf[l_buf+lx])&0xff; lx++; + + if(dist == 0){ + send_code(lc, ltree); // send a literal byte + } + else{ + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + + send_code(code+LITERALS+1, ltree); // send the length code + extra = Tree.extra_lbits[code]; + if(extra != 0){ + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist--; // dist is now the match distance - 1 + code = Tree.d_code(dist); + + send_code(code, dtree); // send the distance code + extra = Tree.extra_dbits[code]; + if (extra != 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + + // Check that the overlay between pending_buf and d_buf+l_buf is ok: + } + while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK*2+1]; + } + + // Set the data type to ASCII or BINARY, using a crude approximation: + // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + // IN assertion: the fields freq of dyn_ltree are set and the total of all + // frequencies does not exceed 64K (to fit in an int on 16 bit machines). + internal void set_data_type(){ + int n = 0; + int ascii_freq = 0; + int bin_freq = 0; + while(n<7){ bin_freq += dyn_ltree[n*2]; n++;} + while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;} + while(n (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); + } + + // Flush the bit buffer, keeping at most 7 bits in it. + internal void bi_flush(){ + if (bi_valid == 16) { + pending_buf[pending++]=(byte)(bi_buf/*&0xff*/); + pending_buf[pending++]=(byte)(bi_buf>>8); + bi_buf=0; + bi_valid=0; + } + else if (bi_valid >= 8) { + pending_buf[pending++]=(byte)(bi_buf); + bi_buf>>=8; + bi_buf &= 0x00ff; + bi_valid-=8; + } + } + + // Flush the bit buffer and align the output on a byte boundary + internal void bi_windup(){ + if (bi_valid > 8) { + pending_buf[pending++]=(byte)(bi_buf); + pending_buf[pending++]=(byte)(bi_buf>>8); + } else if (bi_valid > 0) { + pending_buf[pending++]=(byte)(bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + // Copy a stored block, storing first the length and its + // one's complement if requested. + internal void copy_block(int buf, // the input data + int len, // its length + bool header // true if block header must be written + ){ + //int index=0; + bi_windup(); // align on byte boundary + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short((short)len); + put_short((short)~len); + } + + // while(len--!=0) { + // put_byte(window[buf+index]); + // index++; + // } + put_byte(window, buf, len); + } + + internal void flush_block_only(bool eof){ + _tr_flush_block(block_start>=0 ? block_start : -1, + strstart-block_start, + eof); + block_start=strstart; + strm.flush_pending(); + } + + // Copy without compression as much as possible from the input stream, return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + internal int deflate_stored(int flush){ + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + + int max_block_size = 0xffff; + int max_start; + + if(max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } + + // Copy as much as possible from input to output: + while(true){ + // Fill the window as much as possible: + if(lookahead<=1){ + fill_window(); + if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore; + if(lookahead==0) break; // flush the current block + } + + strstart+=lookahead; + lookahead=0; + + // Emit a stored block if pending_buf will be full: + max_start=block_start+max_block_size; + if(strstart==0|| strstart>=max_start) { + // strstart == 0 is possible when wraparound on 16-bit machine + lookahead = (int)(strstart-max_start); + strstart = (int)max_start; + + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + + } + + // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + if(strstart-block_start >= w_size-MIN_LOOKAHEAD) { + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if(strm.avail_out==0) + return (flush == Z_FINISH) ? FinishStarted : NeedMore; + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + // Send a stored block + internal void _tr_stored_block(int buf, // input block + int stored_len, // length of input block + bool eof // true if this is the last block for a file + ){ + send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type + copy_block(buf, stored_len, true); // with header + } + + // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + internal void _tr_flush_block(int buf, // input block, or NULL if too old + int stored_len, // length of input block + bool eof // true if this is the last block for a file + ) { + int opt_lenb, static_lenb;// opt_len and static_len in bytes + int max_blindex = 0; // index of last bit length code of non zero freq + + // Build the Huffman trees unless a stored block is forced + if(level > 0) { + // Check if the file is ascii or binary + if(data_type == Z_UNKNOWN) set_data_type(); + + // Construct the literal and distance trees + l_desc.build_tree(this); + + d_desc.build_tree(this); + + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex=build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb=(opt_len+3+7)>>3; + static_lenb=(static_len+3+7)>>3; + + if(static_lenb<=opt_lenb) opt_lenb=static_lenb; + } + else { + opt_lenb=static_lenb=stored_len+5; // force a stored block + } + + if(stored_len+4<=opt_lenb && buf != -1){ + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } + else if(static_lenb == opt_lenb){ + send_bits((STATIC_TREES<<1)+(eof?1:0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } + else{ + send_bits((DYN_TREES<<1)+(eof?1:0), 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block(dyn_ltree, dyn_dtree); + } + + // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + init_block(); + + if(eof){ + bi_windup(); + } + } + + // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in == 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + internal void fill_window(){ + int n, m; + int p; + int more; // Amount of free space at the end of the window. + + do{ + more = (window_size-lookahead-strstart); + + // Deal with !@#$% 64K limit: + if(more==0 && strstart==0 && lookahead==0){ + more = w_size; + } + else if(more==-1) { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + } + else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) { + System.Array.Copy(window, w_size, window, 0, w_size); + match_start-=w_size; + strstart-=w_size; // we now have strstart >= MAX_DIST + block_start-=w_size; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == 0 + // to keep the hash table consistent if we switch back to level > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p=n; + do { + m = (head[--p]&0xffff); + head[p]=(short)(m>=w_size ? (m-w_size) : 0); + } + while (--n != 0); + + n = w_size; + p = n; + do { + m = (prev[--p]&0xffff); + prev[p] = (short)(m >= w_size ? (m-w_size) : 0); + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } + while (--n!=0); + more += w_size; + } + + if (strm.avail_in == 0) return; + + // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; + + // Initialize the hash value now that we have some input: + if(lookahead >= MIN_MATCH) { + ins_h = window[strstart]&0xff; + ins_h=(((ins_h)<= MIN_MATCH){ + ins_h=(((ins_h)<=MIN_MATCH){ + // check_match(strstart, match_start, match_length); + + bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH); + + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if(match_length <= max_lazy_match && + lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + do{ + strstart++; + + ins_h=((ins_h<= MIN_MATCH) { + ins_h=(((ins_h)< 4096))) { + + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH-1; + } + } + + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if(prev_length >= MIN_MATCH && match_length <= prev_length) { + int max_insert = strstart + lookahead - MIN_MATCH; + // Do not insert strings in hash table beyond this. + + // check_match(strstart-1, prev_match, prev_length); + + bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + lookahead -= prev_length-1; + prev_length -= 2; + do{ + if(++strstart <= max_insert) { + ins_h=(((ins_h)<(w_size-MIN_LOOKAHEAD) ? + strstart-(w_size-MIN_LOOKAHEAD) : 0; + int nice_match=this.nice_match; + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + int wmask = w_mask; + + int strend = strstart + MAX_MATCH; + byte scan_end1 = window[scan+best_len-1]; + byte scan_end = window[scan+best_len]; + + // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + // It is easy to get rid of this optimization if necessary. + + // Do not waste too much time if we already have a good match: + if (prev_length >= good_match) { + chain_length >>= 2; + } + + // Do not look for matches beyond the end of the input. This is necessary + // to make deflate deterministic. + if (nice_match > lookahead) nice_match = lookahead; + + do { + match = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[match+best_len] != scan_end || + window[match+best_len-1] != scan_end1 || + window[match] != window[scan] || + window[++match] != window[scan+1]) continue; + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scan += 2; match++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + do { + } while (window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + scan < strend); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + + if(len>best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; + scan_end1 = window[scan+best_len-1]; + scan_end = window[scan+best_len]; + } + + } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit + && --chain_length != 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } + + internal int deflateInit(ZStream strm, int level, int bits){ + return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY); + } + internal int deflateInit(ZStream strm, int level){ + return deflateInit(strm, level, MAX_WBITS); + } + internal int deflateInit2(ZStream strm, int level, int method, int windowBits, + int memLevel, int strategy){ + int noheader = 0; + // byte[] my_version=ZLIB_VERSION; + + // + // if (version == null || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + if (windowBits < 0) { // undocumented feature: suppress zlib header + noheader = 1; + windowBits = -windowBits; + } + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || + method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = (Deflate)this; + + this.noheader = noheader; + w_bits = windowBits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); + + window = new byte[w_size*2]; + prev = new short[w_size]; + head = new short[hash_size]; + + lit_bufsize = 1 << (memLevel + 6); // 16K elements by default + + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + pending_buf = new byte[lit_bufsize*4]; + pending_buf_size = lit_bufsize*4; + + d_buf = lit_bufsize/2; + l_buf = (1+2)*lit_bufsize; + + this.level = level; + + //System.out.println("level="+level); + + this.strategy = strategy; + this.method = (byte)method; + + return deflateReset(strm); + } + + internal int deflateReset(ZStream strm){ + strm.total_in = strm.total_out = 0; + strm.msg = null; // + strm.data_type = Z_UNKNOWN; + + pending = 0; + pending_out = 0; + + if(noheader < 0) { + noheader = 0; // was set to -1 by deflate(..., Z_FINISH); + } + status = (noheader!=0) ? BUSY_STATE : INIT_STATE; + strm.adler=strm._adler.adler32(0, null, 0, 0); + + last_flush = Z_NO_FLUSH; + + tr_init(); + lm_init(); + return Z_OK; + } + + internal int deflateEnd(){ + if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ + return Z_STREAM_ERROR; + } + // Deallocate in reverse order of allocations: + pending_buf=null; + head=null; + prev=null; + window=null; + // free + // dstate=null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + } + + internal int deflateParams(ZStream strm, int _level, int _strategy){ + int err=Z_OK; + + if(_level == Z_DEFAULT_COMPRESSION){ + _level = 6; + } + if(_level < 0 || _level > 9 || + _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if(config_table[level].func!=config_table[_level].func && + strm.total_in != 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if(level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + strategy = _strategy; + return err; + } + + internal int deflateSetDictionary (ZStream strm, byte[] dictionary, int dictLength){ + int length = dictLength; + int index=0; + + if(dictionary == null || status != INIT_STATE) + return Z_STREAM_ERROR; + + strm.adler=strm._adler.adler32(strm.adler, dictionary, 0, dictLength); + + if(length < MIN_MATCH) return Z_OK; + if(length > w_size-MIN_LOOKAHEAD){ + length = w_size-MIN_LOOKAHEAD; + index=dictLength-length; // use the tail of the dictionary + } + System.Array.Copy(dictionary, index, window, 0, length); + strstart = length; + block_start = length; + + // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0]&0xff; + ins_h=(((ins_h)<Z_FINISH || flush<0){ + return Z_STREAM_ERROR; + } + + if(strm.next_out == null || + (strm.next_in == null && strm.avail_in != 0) || + (status == FINISH_STATE && flush != Z_FINISH)) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; + return Z_STREAM_ERROR; + } + if(strm.avail_out == 0){ + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + this.strm = strm; // just in case + old_flush = last_flush; + last_flush = flush; + + // Write the zlib header + if(status == INIT_STATE) { + int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; + int level_flags=((level-1)&0xff)>>1; + + if(level_flags>3) level_flags=3; + header |= (level_flags<<6); + if(strstart!=0) header |= PRESET_DICT; + header+=31-(header % 31); + + status=BUSY_STATE; + putShortMSB(header); + + + // Save the adler32 of the preset dictionary: + if(strstart!=0){ + putShortMSB((int)(strm.adler>>16)); + putShortMSB((int)(strm.adler&0xffff)); + } + strm.adler=strm._adler.adler32(0, null, 0, 0); + } + + // Flush as much pending output as possible + if(pending != 0) { + strm.flush_pending(); + if(strm.avail_out == 0) { + //System.out.println(" avail_out==0"); + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } + + // Make sure there is something to do and avoid duplicate consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + } + else if(strm.avail_in==0 && flush <= old_flush && + flush != Z_FINISH) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // User must not provide more input after the first FINISH: + if(status == FINISH_STATE && strm.avail_in != 0) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // Start a new block or continue the current one. + if(strm.avail_in!=0 || lookahead!=0 || + (flush != Z_NO_FLUSH && status != FINISH_STATE)) { + int bstate=-1; + switch(config_table[level].func){ + case STORED: + bstate = deflate_stored(flush); + break; + case FAST: + bstate = deflate_fast(flush); + break; + case SLOW: + bstate = deflate_slow(flush); + break; + default: + break; + } + + if (bstate==FinishStarted || bstate==FinishDone) { + status = FINISH_STATE; + } + if (bstate==NeedMore || bstate==FinishStarted) { + if(strm.avail_out == 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + return Z_OK; + // If flush != Z_NO_FLUSH && avail_out == 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate==BlockDone) { + if(flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } + else { // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); + // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + if(flush == Z_FULL_FLUSH) { + //state.head[s.hash_size-1]=0; + for(int i=0; i>16)); + putShortMSB((int)(strm.adler&0xffff)); + strm.flush_pending(); + + // If avail_out is zero, the application will call deflate again + // to flush the rest. + noheader = -1; // write the trailer only once! + return pending != 0 ? Z_OK : Z_STREAM_END; + } + } +} \ No newline at end of file diff --git a/crypto/src/util/zlib/InfBlocks.cs b/crypto/src/util/zlib/InfBlocks.cs new file mode 100644 index 000000000..479d9b5c9 --- /dev/null +++ b/crypto/src/util/zlib/InfBlocks.cs @@ -0,0 +1,618 @@ +using System; +/* + * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + internal sealed class InfBlocks{ + private const int MANY=1440; + + // And'ing with mask[n] masks the lower n bits + private static readonly int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + // Table for deflate from PKZIP's appnote.txt. + static readonly int[] border = { // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + + private const int Z_OK=0; + private const int Z_STREAM_END=1; + private const int Z_NEED_DICT=2; + private const int Z_ERRNO=-1; + private const int Z_STREAM_ERROR=-2; + private const int Z_DATA_ERROR=-3; + private const int Z_MEM_ERROR=-4; + private const int Z_BUF_ERROR=-5; + private const int Z_VERSION_ERROR=-6; + + private const int TYPE=0; // get type bits (3, including end bit) + private const int LENS=1; // get lengths for stored + private const int STORED=2;// processing stored block + private const int TABLE=3; // get table lengths + private const int BTREE=4; // get bit lengths tree for a dynamic block + private const int DTREE=5; // get length, distance trees for a dynamic block + private const int CODES=6; // processing fixed or dynamic block + private const int DRY=7; // output remaining window bytes + private const int DONE=8; // finished last block, done + private const int BAD=9; // ot a data error--stuck here + + internal int mode; // current inflate_block mode + + internal int left; // if STORED, bytes left to copy + + internal int table; // table lengths (14 bits) + internal int index; // index into blens (or border) + internal int[] blens; // bit lengths of codes + internal int[] bb=new int[1]; // bit length tree depth + internal int[] tb=new int[1]; // bit length decoding tree + + internal InfCodes codes=new InfCodes(); // if CODES, current state + + int last; // true if this block is the last block + + // mode independent information + internal int bitk; // bits in bit buffer + internal int bitb; // bit buffer + internal int[] hufts; // single malloc for tree space + internal byte[] window; // sliding window + internal int end; // one byte after sliding window + internal int read; // window read pointer + internal int write; // window write pointer + internal Object checkfn; // check function + internal long check; // check on output + + internal InfTree inftree=new InfTree(); + + internal InfBlocks(ZStream z, Object checkfn, int w){ + hufts=new int[MANY*3]; + window=new byte[w]; + end=w; + this.checkfn = checkfn; + mode = TYPE; + reset(z, null); + } + + internal void reset(ZStream z, long[] c){ + if(c!=null) c[0]=check; + if(mode==BTREE || mode==DTREE){ + } + if(mode==CODES){ + codes.free(z); + } + mode=TYPE; + bitk=0; + bitb=0; + read=write=0; + + if(checkfn != null) + z.adler=check=z._adler.adler32(0L, null, 0, 0); + } + + internal int proc(ZStream z, int r){ + int t; // temporary storage + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; { // bytes to end of window or read pointer + + // copy input/output information to locals (UPDATE macro restores) + p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} { + q=write;m=(int)(q> 1){ + case 0: { // stored + b>>=(3);k-=(3);} + t = k & 7; { // go to byte boundary + + b>>=(t);k-=(t);} + mode = LENS; // get length of stored block + break; + case 1: { // fixed + int[] bl=new int[1]; + int[] bd=new int[1]; + int[][] tl=new int[1][]; + int[][] td=new int[1][]; + + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z); + } { + + b>>=(3);k-=(3);} + + mode = CODES; + break; + case 2: { // dynamic + + b>>=(3);k-=(3);} + + mode = TABLE; + break; + case 3: { // illegal + + b>>=(3);k-=(3);} + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + break; + case LENS: + + while(k<(32)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + }; + n--; + b|=(z.next_in[p++]&0xff)<> 16) & 0xffff) != (b & 0xffff)){ + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); + break; + case STORED: + if (n == 0){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + + if(m==0){ + if(q==end&&read!=0){ + q=0; m=(int)(qn) t = n; + if(t>m) t = m; + System.Array.Copy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + if ((left -= t) != 0) + break; + mode = last!=0 ? DRY : TYPE; + break; + case TABLE: + + while(k<(14)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + }; + n--; + b|=(z.next_in[p++]&0xff)< 29 || ((t >> 5) & 0x1f) > 29) { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if(blens==null || blens.Length>=(14);k-=(14);} + + index = 0; + mode = BTREE; + goto case BTREE; + case BTREE: + while (index < 4 + (table >> 10)){ + while(k<(3)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>=(3);k-=(3);} + } + + while(index < 19){ + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); + if (t != Z_OK){ + r = t; + if (r == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + + index = 0; + mode = DTREE; + goto case DTREE; + case DTREE: + while (true){ + t = table; + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ + break; + } + + int i, j, c; + + t = bb[0]; + + while(k<(t)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>=(t);k-=(t); + blens[index++] = c; + } + else { // c == 16..18 + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + + while(k<(t+i)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>=(t);k-=(t); + + j += (b & inflate_mask[i]); + + b>>=(i);k-=(i); + + i = index; + t = table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)){ + blens=null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + + c = c == 16 ? blens[i-1] : 0; + do{ + blens[i++] = c; + } + while (--j!=0); + index = i; + } + } + + tb[0]=-1; { + int[] bl=new int[1]; + int[] bd=new int[1]; + int[] tl=new int[1]; + int[] td=new int[1]; + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + + t = table; + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), + 1 + ((t >> 5) & 0x1f), + blens, bl, bd, tl, td, hufts, z); + + if (t != Z_OK){ + if (t == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + r = t; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(z,r); + } + codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); + } + mode = CODES; + goto case CODES; + case CODES: + bitb=b; bitk=k; + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + + if ((r = codes.proc(this, z, r)) != Z_STREAM_END){ + return inflate_flush(z, r); + } + r = Z_OK; + codes.free(z); + + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; + q=write;m=(int)(q z.avail_out) n = z.avail_out; + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(checkfn != null) + z.adler=check=z._adler.adler32(check, window, q, n); + + // copy as far as end of window + System.Array.Copy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end){ + // wrap pointers + q = 0; + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + if (n > z.avail_out) n = z.avail_out; + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(checkfn != null) + z.adler=check=z._adler.adler32(check, window, q, n); + + // copy + System.Array.Copy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + + // done + return r; + } + } +} \ No newline at end of file diff --git a/crypto/src/util/zlib/InfCodes.cs b/crypto/src/util/zlib/InfCodes.cs new file mode 100644 index 000000000..6fcafe458 --- /dev/null +++ b/crypto/src/util/zlib/InfCodes.cs @@ -0,0 +1,611 @@ +using System; +/* + * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + internal sealed class InfCodes{ + + private static readonly int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + private const int Z_OK=0; + private const int Z_STREAM_END=1; + private const int Z_NEED_DICT=2; + private const int Z_ERRNO=-1; + private const int Z_STREAM_ERROR=-2; + private const int Z_DATA_ERROR=-3; + private const int Z_MEM_ERROR=-4; + private const int Z_BUF_ERROR=-5; + private const int Z_VERSION_ERROR=-6; + + // waiting for "i:"=input, + // "o:"=output, + // "x:"=nothing + private const int START=0; // x: set up for LEN + private const int LEN=1; // i: get length/literal/eob next + private const int LENEXT=2; // i: getting length extra (have base) + private const int DIST=3; // i: get distance next + private const int DISTEXT=4;// i: getting distance extra + private const int COPY=5; // o: copying bytes in window, waiting for space + private const int LIT=6; // o: got literal, waiting for output space + private const int WASH=7; // o: got eob, possibly still output waiting + private const int END=8; // x: got eob and all data flushed + private const int BADCODE=9;// x: got error + + int mode; // current inflate_codes mode + + // mode dependent information + int len; + + int[] tree; // pointer into tree + int tree_index=0; + int need; // bits needed + + int lit; + + // if EXT or COPY, where and how much + int get; // bits to get for extra + int dist; // distance back to copy from + + byte lbits; // ltree bits decoded per branch + byte dbits; // dtree bits decoder per branch + int[] ltree; // literal/length/eob tree + int ltree_index; // literal/length/eob tree + int[] dtree; // distance tree + int dtree_index; // distance tree + + internal InfCodes(){ + } + internal void init(int bl, int bd, + int[] tl, int tl_index, + int[] td, int td_index, ZStream z){ + mode=START; + lbits=(byte)bl; + dbits=(byte)bd; + ltree=tl; + ltree_index=tl_index; + dtree = td; + dtree_index=td_index; + tree=null; + } + + internal int proc(InfBlocks s, ZStream z, int r){ + int j; // temporary storage + int tindex; // temporary pointer + int e; // extra bits or operation + int b=0; // bit buffer + int k=0; // bits in bit buffer + int p=0; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int f; // pointer to copy strings from + + // copy input/output information to locals (UPDATE macro restores) + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q= 258 && n >= 10){ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + r = inflate_fast(lbits, dbits, + ltree, ltree_index, + dtree, dtree_index, + s, z); + + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q>=(tree[tindex+1]); + k-=(tree[tindex+1]); + + e=tree[tindex]; + + if(e == 0){ // literal + lit = tree[tindex+2]; + mode = LIT; + break; + } + if((e & 16)!=0 ){ // length + get = e & 15; + len = tree[tindex+2]; + mode = LENEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3+tree[tindex+2]; + break; + } + if ((e & 32)!=0){ // end of block + mode = WASH; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(z,r); + + case LENEXT: // i: getting length extra (have base) + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(z,r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + need = dbits; + tree = dtree; + tree_index=dtree_index; + mode = DIST; + goto case DIST; + case DIST: // i: get distance next + j = need; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(z,r); + } + n--; b|=(z.next_in[p++]&0xff)<>=tree[tindex+1]; + k-=tree[tindex+1]; + + e = (tree[tindex]); + if((e & 16)!=0){ // distance + get = e & 15; + dist = tree[tindex+2]; + mode = DISTEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3 + tree[tindex+2]; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid distance code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(z,r); + + case DISTEXT: // i: getting distance extra + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(z,r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + mode = COPY; + goto case COPY; + case COPY: // o: copying bytes in window, waiting for space + f = q - dist; + while(f < 0){ // modulo window size-"while" instead + f += s.end; // of "if" handles invalid distances + } + while (len!=0){ + + if(m==0){ + if(q==s.end&&s.read!=0){q=0;m=q 7){ // return unused byte, if any + k -= 8; + n++; + p--; // can always return one + } + + s.write=q; r=s.inflate_flush(z,r); + q=s.write;m=q= 258 && n >= 10 + // get literal/length code + while(k<(20)){ // max bits for literal/length code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++] = (byte)tp[tp_index_t_3+2]; + m--; + continue; + } + do { + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + e &= 15; + c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]); + + b>>=e; k-=e; + + // decode distance base of block to copy + while(k<(15)){ // max bits for distance code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + // get extra bits to add to distance base + e &= 15; + while(k<(e)){ // get extra bits (up to 13) + n--; + b|=(z.next_in[p++]&0xff)<>=(e); k-=(e); + + // do the copy + m -= c; + if (q >= d){ // offset before dest + // just copy + r=q-d; + if(q-r>0 && 2>(q-r)){ + s.window[q++]=s.window[r++]; // minimum count is three, + s.window[q++]=s.window[r++]; // so unroll loop a little + c-=2; + } + else{ + System.Array.Copy(s.window, r, s.window, q, 2); + q+=2; r+=2; c-=2; + } + } + else{ // else offset after destination + r=q-d; + do{ + r+=s.end; // force pointer in window + }while(r<0); // covers invalid distances + e=s.end-r; + if(c>e){ // if source crosses, + c-=e; // wrapped copy + if(q-r>0 && e>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--e!=0); + } + else{ + System.Array.Copy(s.window, r, s.window, q, e); + q+=e; r+=e; e=0; + } + r = 0; // copy rest from start of window + } + + } + + // copy all or what's left + if(q-r>0 && c>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--c!=0); + } + else{ + System.Array.Copy(s.window, r, s.window, q, c); + q+=c; r+=c; c=0; + } + break; + } + else if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + e=tp[tp_index_t_3]; + } + else{ + z.msg = "invalid distance code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + break; + } + + if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + if((e=tp[tp_index_t_3])==0){ + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++]=(byte)tp[tp_index_t_3+2]; + m--; + break; + } + } + else if((e&32)!=0){ + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_STREAM_END; + } + else{ + z.msg="invalid literal/length code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + } + while(m>=258 && n>= 10); + + // not enough input or output--restore pointers and return + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_OK; + } + } +} \ No newline at end of file diff --git a/crypto/src/util/zlib/InfTree.cs b/crypto/src/util/zlib/InfTree.cs new file mode 100644 index 000000000..6ed7d1920 --- /dev/null +++ b/crypto/src/util/zlib/InfTree.cs @@ -0,0 +1,523 @@ +using System; +/* + * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + internal sealed class InfTree{ + + private const int MANY=1440; + + private const int Z_OK=0; + private const int Z_STREAM_END=1; + private const int Z_NEED_DICT=2; + private const int Z_ERRNO=-1; + private const int Z_STREAM_ERROR=-2; + private const int Z_DATA_ERROR=-3; + private const int Z_MEM_ERROR=-4; + private const int Z_BUF_ERROR=-5; + private const int Z_VERSION_ERROR=-6; + + private const int fixed_bl = 9; + private const int fixed_bd = 5; + + static readonly int[] fixed_tl = { + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,192, + 80,7,10, 0,8,96, 0,8,32, 0,9,160, + 0,8,0, 0,8,128, 0,8,64, 0,9,224, + 80,7,6, 0,8,88, 0,8,24, 0,9,144, + 83,7,59, 0,8,120, 0,8,56, 0,9,208, + 81,7,17, 0,8,104, 0,8,40, 0,9,176, + 0,8,8, 0,8,136, 0,8,72, 0,9,240, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,200, + 81,7,13, 0,8,100, 0,8,36, 0,9,168, + 0,8,4, 0,8,132, 0,8,68, 0,9,232, + 80,7,8, 0,8,92, 0,8,28, 0,9,152, + 84,7,83, 0,8,124, 0,8,60, 0,9,216, + 82,7,23, 0,8,108, 0,8,44, 0,9,184, + 0,8,12, 0,8,140, 0,8,76, 0,9,248, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,196, + 81,7,11, 0,8,98, 0,8,34, 0,9,164, + 0,8,2, 0,8,130, 0,8,66, 0,9,228, + 80,7,7, 0,8,90, 0,8,26, 0,9,148, + 84,7,67, 0,8,122, 0,8,58, 0,9,212, + 82,7,19, 0,8,106, 0,8,42, 0,9,180, + 0,8,10, 0,8,138, 0,8,74, 0,9,244, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,204, + 81,7,15, 0,8,102, 0,8,38, 0,9,172, + 0,8,6, 0,8,134, 0,8,70, 0,9,236, + 80,7,9, 0,8,94, 0,8,30, 0,9,156, + 84,7,99, 0,8,126, 0,8,62, 0,9,220, + 82,7,27, 0,8,110, 0,8,46, 0,9,188, + 0,8,14, 0,8,142, 0,8,78, 0,9,252, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,194, + 80,7,10, 0,8,97, 0,8,33, 0,9,162, + 0,8,1, 0,8,129, 0,8,65, 0,9,226, + 80,7,6, 0,8,89, 0,8,25, 0,9,146, + 83,7,59, 0,8,121, 0,8,57, 0,9,210, + 81,7,17, 0,8,105, 0,8,41, 0,9,178, + 0,8,9, 0,8,137, 0,8,73, 0,9,242, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,202, + 81,7,13, 0,8,101, 0,8,37, 0,9,170, + 0,8,5, 0,8,133, 0,8,69, 0,9,234, + 80,7,8, 0,8,93, 0,8,29, 0,9,154, + 84,7,83, 0,8,125, 0,8,61, 0,9,218, + 82,7,23, 0,8,109, 0,8,45, 0,9,186, + 0,8,13, 0,8,141, 0,8,77, 0,9,250, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,198, + 81,7,11, 0,8,99, 0,8,35, 0,9,166, + 0,8,3, 0,8,131, 0,8,67, 0,9,230, + 80,7,7, 0,8,91, 0,8,27, 0,9,150, + 84,7,67, 0,8,123, 0,8,59, 0,9,214, + 82,7,19, 0,8,107, 0,8,43, 0,9,182, + 0,8,11, 0,8,139, 0,8,75, 0,9,246, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,206, + 81,7,15, 0,8,103, 0,8,39, 0,9,174, + 0,8,7, 0,8,135, 0,8,71, 0,9,238, + 80,7,9, 0,8,95, 0,8,31, 0,9,158, + 84,7,99, 0,8,127, 0,8,63, 0,9,222, + 82,7,27, 0,8,111, 0,8,47, 0,9,190, + 0,8,15, 0,8,143, 0,8,79, 0,9,254, + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,193, + + 80,7,10, 0,8,96, 0,8,32, 0,9,161, + 0,8,0, 0,8,128, 0,8,64, 0,9,225, + 80,7,6, 0,8,88, 0,8,24, 0,9,145, + 83,7,59, 0,8,120, 0,8,56, 0,9,209, + 81,7,17, 0,8,104, 0,8,40, 0,9,177, + 0,8,8, 0,8,136, 0,8,72, 0,9,241, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,201, + 81,7,13, 0,8,100, 0,8,36, 0,9,169, + 0,8,4, 0,8,132, 0,8,68, 0,9,233, + 80,7,8, 0,8,92, 0,8,28, 0,9,153, + 84,7,83, 0,8,124, 0,8,60, 0,9,217, + 82,7,23, 0,8,108, 0,8,44, 0,9,185, + 0,8,12, 0,8,140, 0,8,76, 0,9,249, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,197, + 81,7,11, 0,8,98, 0,8,34, 0,9,165, + 0,8,2, 0,8,130, 0,8,66, 0,9,229, + 80,7,7, 0,8,90, 0,8,26, 0,9,149, + 84,7,67, 0,8,122, 0,8,58, 0,9,213, + 82,7,19, 0,8,106, 0,8,42, 0,9,181, + 0,8,10, 0,8,138, 0,8,74, 0,9,245, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,205, + 81,7,15, 0,8,102, 0,8,38, 0,9,173, + 0,8,6, 0,8,134, 0,8,70, 0,9,237, + 80,7,9, 0,8,94, 0,8,30, 0,9,157, + 84,7,99, 0,8,126, 0,8,62, 0,9,221, + 82,7,27, 0,8,110, 0,8,46, 0,9,189, + 0,8,14, 0,8,142, 0,8,78, 0,9,253, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,195, + 80,7,10, 0,8,97, 0,8,33, 0,9,163, + 0,8,1, 0,8,129, 0,8,65, 0,9,227, + 80,7,6, 0,8,89, 0,8,25, 0,9,147, + 83,7,59, 0,8,121, 0,8,57, 0,9,211, + 81,7,17, 0,8,105, 0,8,41, 0,9,179, + 0,8,9, 0,8,137, 0,8,73, 0,9,243, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,203, + 81,7,13, 0,8,101, 0,8,37, 0,9,171, + 0,8,5, 0,8,133, 0,8,69, 0,9,235, + 80,7,8, 0,8,93, 0,8,29, 0,9,155, + 84,7,83, 0,8,125, 0,8,61, 0,9,219, + 82,7,23, 0,8,109, 0,8,45, 0,9,187, + 0,8,13, 0,8,141, 0,8,77, 0,9,251, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,199, + 81,7,11, 0,8,99, 0,8,35, 0,9,167, + 0,8,3, 0,8,131, 0,8,67, 0,9,231, + 80,7,7, 0,8,91, 0,8,27, 0,9,151, + 84,7,67, 0,8,123, 0,8,59, 0,9,215, + 82,7,19, 0,8,107, 0,8,43, 0,9,183, + 0,8,11, 0,8,139, 0,8,75, 0,9,247, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,207, + 81,7,15, 0,8,103, 0,8,39, 0,9,175, + 0,8,7, 0,8,135, 0,8,71, 0,9,239, + 80,7,9, 0,8,95, 0,8,31, 0,9,159, + 84,7,99, 0,8,127, 0,8,63, 0,9,223, + 82,7,27, 0,8,111, 0,8,47, 0,9,191, + 0,8,15, 0,8,143, 0,8,79, 0,9,255 + }; + static readonly int[] fixed_td = { + 80,5,1, 87,5,257, 83,5,17, 91,5,4097, + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385, + 80,5,3, 88,5,513, 84,5,33, 92,5,8193, + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577, + 80,5,2, 87,5,385, 83,5,25, 91,5,6145, + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577, + 80,5,4, 88,5,769, 84,5,49, 92,5,12289, + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577 + }; + + // Tables for deflate from PKZIP's appnote.txt. + static readonly int[] cplens = { // Copy lengths for literal codes 257..285 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + + // see note #13 above about 258 + static readonly int[] cplext = { // Extra bits for literal codes 257..285 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid + }; + + static readonly int[] cpdist = { // Copy offsets for distance codes 0..29 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + static readonly int[] cpdext = { // Extra bits for distance codes + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + // If BMAX needs to be larger than 16, then h and x[] should be uLong. + const int BMAX=15; // maximum bit length of any code + + int[] hn = null; // hufts used in space + int[] v = null; // work area for huft_build + int[] c = null; // bit length count table + int[] r = null; // table entry for structure assignment + int[] u = null; // table stack + int[] x = null; // bit offsets, then code stack + + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX) + int bindex, + int n, // number of codes (assumed <= 288) + int s, // number of simple-valued codes (0..s-1) + int[] d, // list of base values for non-simple codes + int[] e, // list of extra bits for non-simple codes + int[] t, // result: starting table + int[] m, // maximum lookup bits, returns actual + int[] hp,// space for trees + int[] hn,// hufts used in space + int[] v // working area: values in order of bit length + ){ + // Given a list of code lengths and a maximum table size, make a set of + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + // if the given code set is incomplete (the tables are still built in this + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + // lengths), or Z_MEM_ERROR if not enough memory. + + int a; // counter for codes of length k + int f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + int i; // counter, current code + int j; // counter + int k; // number of bits in current code + int l; // bits per table (returned in m) + int mask; // (1 << w) - 1, to avoid cc -O bug on HP + int p; // pointer into c[], b[], or v[] + int q; // points to current table + int w; // bits before this table == (l * h) + int xp; // pointer into x + int y; // number of dummy codes added + int z; // number of entries in current table + + // Generate counts for each bit length + + p = 0; i = n; + do { + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX + }while(i!=0); + + if(c[0] == n){ // null input--all zero length codes + t[0] = -1; + m[0] = 0; + return Z_OK; + } + + // Find minimum and maximum length, bound *m by those + l = m[0]; + for (j = 1; j <= BMAX; j++) + if(c[j]!=0) break; + k = j; // minimum code length + if(l < j){ + l = j; + } + for (i = BMAX; i!=0; i--){ + if(c[i]!=0) break; + } + g = i; // maximum code length + if(l > i){ + l = i; + } + m[0] = l; + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1){ + if ((y -= c[j]) < 0){ + return Z_DATA_ERROR; + } + } + if ((y -= c[i]) < 0){ + return Z_DATA_ERROR; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = 1; xp = 2; + while (--i!=0) { // note that i == g from above + x[xp] = (j += c[p]); + xp++; + p++; + } + + // Make a table of values in order of bit lengths + i = 0; p = 0; + do { + if ((j = b[bindex+p]) != 0){ + v[x[j]++] = i; + } + p++; + } + while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = -l; // bits decoded == (l * h) + u[0] = 0; // just to keep compilers happy + q = 0; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++){ + a = c[k]; + while (a--!=0){ + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l){ + h++; + w += l; // previous table always l bits + // compute minimum size table less than or equal to l bits + z = g - w; + z = (z > l) ? l : z; // table size upper limit + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + if(j < z){ + while (++j < z){ // try smaller tables up to z bits + if((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + } + u[h] = q = /*hp+*/ hn[0]; // DEBUG + hn[0] += z; + + // connect to last table, if there is one + if(h!=0){ + x[h]=i; // save pattern for backing up + r[0]=(byte)j; // bits in this table + r[1]=(byte)l; // bits to dump before this table + j=i>>(w - l); + r[2] = (int)(q - u[h-1] - j); // offset to this table + System.Array.Copy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table + } + else{ + t[0] = q; // first table is returned result + } + } + + // set up table entry in r + r[1] = (byte)(k - w); + if (p >= n){ + r[0] = 128 + 64; // out of values--invalid code + } + else if (v[p] < s){ + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block + r[2] = v[p++]; // simple code is just the value + } + else{ + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists + r[2]=d[v[p++] - s]; + } + + // fill code-like entries with r + f=1<<(k-w); + for (j=i>>w;j>= 1){ + i ^= j; + } + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]){ + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; + } + } + } + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; + } + + internal int inflate_trees_bits(int[] c, // 19 code lengths + int[] bb, // bits tree desired/actual depth + int[] tb, // bits tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + initWorkArea(19); + hn[0]=0; + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); + + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed dynamic bit lengths tree"; + } + else if(result == Z_BUF_ERROR || bb[0] == 0){ + z.msg = "incomplete dynamic bit lengths tree"; + result = Z_DATA_ERROR; + } + return result; + } + + internal int inflate_trees_dynamic(int nl, // number of literal/length codes + int nd, // number of distance codes + int[] c, // that many (total) code lengths + int[] bl, // literal desired/actual bit depth + int[] bd, // distance desired/actual bit depth + int[] tl, // literal/length tree result + int[] td, // distance tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + + // build literal/length tree + initWorkArea(288); + hn[0]=0; + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); + if (result != Z_OK || bl[0] == 0){ + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed literal/length tree"; + } + else if (result != Z_MEM_ERROR){ + z.msg = "incomplete literal/length tree"; + result = Z_DATA_ERROR; + } + return result; + } + + // build distance tree + initWorkArea(288); + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); + + if (result != Z_OK || (bd[0] == 0 && nl > 257)){ + if (result == Z_DATA_ERROR){ + z.msg = "oversubscribed distance tree"; + } + else if (result == Z_BUF_ERROR) { + z.msg = "incomplete distance tree"; + result = Z_DATA_ERROR; + } + else if (result != Z_MEM_ERROR){ + z.msg = "empty distance tree with lengths"; + result = Z_DATA_ERROR; + } + return result; + } + + return Z_OK; + } + + internal static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth + int[] bd, //distance desired/actual bit depth + int[][] tl,//literal/length tree result + int[][] td,//distance tree result + ZStream z //for memory allocation + ){ + bl[0]=fixed_bl; + bd[0]=fixed_bd; + tl[0]=fixed_tl; + td[0]=fixed_td; + return Z_OK; + } + + private void initWorkArea(int vsize){ + if(hn==null){ + hn=new int[1]; + v=new int[vsize]; + c=new int[BMAX+1]; + r=new int[3]; + u=new int[BMAX]; + x=new int[BMAX+1]; + } + if(v.Lengthstate); + return Z_OK; + } + + internal int inflateInit(ZStream z, int w){ + z.msg = null; + blocks = null; + + // handle undocumented nowrap option (no zlib header or check) + nowrap = 0; + if(w < 0){ + w = - w; + nowrap = 1; + } + + // set window size + if(w<8 ||w>15){ + inflateEnd(z); + return Z_STREAM_ERROR; + } + wbits=w; + + z.istate.blocks=new InfBlocks(z, + z.istate.nowrap!=0 ? null : this, + 1<>4)+8>z.istate.wbits){ + z.istate.mode = BAD; + z.msg="invalid window size"; + z.istate.marker = 5; // can't try inflateSync + break; + } + z.istate.mode=FLAG; + goto case FLAG; + case FLAG: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + b = (z.next_in[z.next_in_index++])&0xff; + + if((((z.istate.method << 8)+b) % 31)!=0){ + z.istate.mode = BAD; + z.msg = "incorrect header check"; + z.istate.marker = 5; // can't try inflateSync + break; + } + + if((b&PRESET_DICT)==0){ + z.istate.mode = BLOCKS; + break; + } + z.istate.mode = DICT4; + goto case DICT4; + case DICT4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + z.istate.mode=DICT3; + goto case DICT3; + case DICT3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + z.istate.mode=DICT2; + goto case DICT2; + case DICT2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + z.istate.mode=DICT1; + goto case DICT1; + case DICT1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need += (z.next_in[z.next_in_index++]&0xffL); + z.adler = z.istate.need; + z.istate.mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z.istate.mode = BAD; + z.msg = "need dictionary"; + z.istate.marker = 0; // can try inflateSync + return Z_STREAM_ERROR; + case BLOCKS: + + r = z.istate.blocks.proc(z, r); + if(r == Z_DATA_ERROR){ + z.istate.mode = BAD; + z.istate.marker = 0; // can try inflateSync + break; + } + if(r == Z_OK){ + r = f; + } + if(r != Z_STREAM_END){ + return r; + } + r = f; + z.istate.blocks.reset(z, z.istate.was); + if(z.istate.nowrap!=0){ + z.istate.mode=DONE; + break; + } + z.istate.mode=CHECK4; + goto case CHECK4; + case CHECK4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + z.istate.mode=CHECK3; + goto case CHECK3; + case CHECK3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + z.istate.mode = CHECK2; + goto case CHECK2; + case CHECK2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + z.istate.mode = CHECK1; + goto case CHECK1; + case CHECK1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + z.istate.need+=(z.next_in[z.next_in_index++]&0xffL); + + if(((int)(z.istate.was[0])) != ((int)(z.istate.need))){ + z.istate.mode = BAD; + z.msg = "incorrect data check"; + z.istate.marker = 5; // can't try inflateSync + break; + } + + z.istate.mode = DONE; + goto case DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } + } + } + + + internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength){ + int index=0; + int length = dictLength; + if(z==null || z.istate == null|| z.istate.mode != DICT0) + return Z_STREAM_ERROR; + + if(z._adler.adler32(1L, dictionary, 0, dictLength)!=z.adler){ + return Z_DATA_ERROR; + } + + z.adler = z._adler.adler32(0, null, 0, 0); + + if(length >= (1<>7)]); + } + + internal short[] dyn_tree; // the dynamic tree + internal int max_code; // largest code with non zero frequency + internal StaticTree stat_desc; // the corresponding static tree + + // Compute the optimal bit lengths for a tree and update the total bit length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + internal void gen_bitlen(Deflate s){ + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int[] extra = stat_desc.extra_bits; + int based = stat_desc.extra_base; + int max_length = stat_desc.max_length; + int h; // heap index + int n, m; // iterate over the tree elements + int bits; // bit length + int xbits; // extra bits + short f; // frequency + int overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap + + for(h=s.heap_max+1; h max_length){ bits = max_length; overflow++; } + tree[n*2+1] = (short)bits; + // We overwrite tree[n*2+1] which is no longer needed + + if (n > max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= based) xbits = extra[n-based]; + f = tree[n*2]; + s.opt_len += f * (bits + xbits); + if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits); + } + if (overflow == 0) return; + + // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + do { + bits = max_length-1; + while(s.bl_count[bits]==0) bits--; + s.bl_count[bits]--; // move one leaf down the tree + s.bl_count[bits+1]+=2; // move one overflow item as its brother + s.bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } + while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) { + n = s.bl_count[bits]; + while (n != 0) { + m = s.heap[--h]; + if (m > max_code) continue; + if (tree[m*2+1] != bits) { + s.opt_len += (int)(((long)bits - (long)tree[m*2+1])*(long)tree[m*2]); + tree[m*2+1] = (short)bits; + } + n--; + } + } + } + + // Construct one Huffman tree and assigns the code bit strings and lengths. + // Update the total bit length for the current block. + // IN assertion: the field freq is set for all tree elements. + // OUT assertions: the fields len and code are set to the optimal bit length + // and corresponding code. The length opt_len is updated; static_len is + // also updated if stree is not null. The field max_code is set. + internal void build_tree(Deflate s){ + short[] tree=dyn_tree; + short[] stree=stat_desc.static_tree; + int elems=stat_desc.elems; + int n, m; // iterate over heap elements + int max_code=-1; // largest code with non zero frequency + int node; // new node being created + + // Construct the initial heap, with least frequent element in + // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + // heap[0] is not used. + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for(n=0; n=1; n--) + s.pqdownheap(tree, n); + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + node=elems; // next internal node of the tree + do{ + // n = node of least frequency + n=s.heap[1]; + s.heap[1]=s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m=s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + s.heap[--s.heap_max] = m; + + // Create a new node father of n and m + tree[node*2] = (short)(tree[n*2] + tree[m*2]); + s.depth[node] = (byte)(System.Math.Max(s.depth[n],s.depth[m])+1); + tree[n*2+1] = tree[m*2+1] = (short)node; + + // and insert the new node in the heap + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } + while(s.heap_len>=2); + + s.heap[--s.heap_max] = s.heap[1]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code, s.bl_count); + } + + // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + internal static void gen_codes(short[] tree, // the tree to decorate + int max_code, // largest code with non zero frequency + short[] bl_count // number of codes at each bit length + ){ + short[] next_code=new short[MAX_BITS+1]; // next code value for each bit length + short code = 0; // running code value + int bits; // bit index + int n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1); + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + //Assert (code + bl_count[MAX_BITS]-1 == (1<>=1; + res<<=1; + } + while(--len>0); + return res>>1; + } + } +} \ No newline at end of file diff --git a/crypto/src/util/zlib/ZDeflaterOutputStream.cs b/crypto/src/util/zlib/ZDeflaterOutputStream.cs new file mode 100644 index 000000000..1d88847bd --- /dev/null +++ b/crypto/src/util/zlib/ZDeflaterOutputStream.cs @@ -0,0 +1,151 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.Zlib { + /// + /// Summary description for DeflaterOutputStream. + /// + [Obsolete("Use 'ZOutputStream' instead")] + public class ZDeflaterOutputStream : Stream { + protected ZStream z=new ZStream(); + protected int flushLevel=JZlib.Z_NO_FLUSH; + private const int BUFSIZE = 4192; + protected byte[] buf=new byte[BUFSIZE]; + private byte[] buf1=new byte[1]; + + protected Stream outp; + + public ZDeflaterOutputStream(Stream outp) : this(outp, 6, false) { + } + + public ZDeflaterOutputStream(Stream outp, int level) : this(outp, level, false) { + } + + public ZDeflaterOutputStream(Stream outp, int level, bool nowrap) { + this.outp=outp; + z.deflateInit(level, nowrap); + } + + + public override bool CanRead { + get { + // TODO: Add DeflaterOutputStream.CanRead getter implementation + return false; + } + } + + public override bool CanSeek { + get { + // TODO: Add DeflaterOutputStream.CanSeek getter implementation + return false; + } + } + + public override bool CanWrite { + get { + // TODO: Add DeflaterOutputStream.CanWrite getter implementation + return true; + } + } + + public override long Length { + get { + // TODO: Add DeflaterOutputStream.Length getter implementation + return 0; + } + } + + public override long Position { + get { + // TODO: Add DeflaterOutputStream.Position getter implementation + return 0; + } + set { + // TODO: Add DeflaterOutputStream.Position setter implementation + } + } + + public override void Write(byte[] b, int off, int len) { + if(len==0) + return; + int err; + z.next_in=b; + z.next_in_index=off; + z.avail_in=len; + do{ + z.next_out=buf; + z.next_out_index=0; + z.avail_out=BUFSIZE; + err=z.deflate(flushLevel); + if(err!=JZlib.Z_OK) + throw new IOException("deflating: "+z.msg); + if (z.avail_out < BUFSIZE) + { + outp.Write(buf, 0, BUFSIZE-z.avail_out); + } + } + while(z.avail_in>0 || z.avail_out==0); + } + + public override long Seek(long offset, SeekOrigin origin) { + // TODO: Add DeflaterOutputStream.Seek implementation + return 0; + } + + public override void SetLength(long value) { + // TODO: Add DeflaterOutputStream.SetLength implementation + + } + + public override int Read(byte[] buffer, int offset, int count) { + // TODO: Add DeflaterOutputStream.Read implementation + return 0; + } + + public override void Flush() { + outp.Flush(); + } + + public override void WriteByte(byte b) { + buf1[0]=(byte)b; + Write(buf1, 0, 1); + } + + public void Finish() { + int err; + do{ + z.next_out=buf; + z.next_out_index=0; + z.avail_out=BUFSIZE; + err=z.deflate(JZlib.Z_FINISH); + if(err!=JZlib.Z_STREAM_END && err != JZlib.Z_OK) + throw new IOException("deflating: "+z.msg); + if(BUFSIZE-z.avail_out>0){ + outp.Write(buf, 0, BUFSIZE-z.avail_out); + } + } + while(z.avail_in>0 || z.avail_out==0); + Flush(); + } + + public void End() { + if(z==null) + return; + z.deflateEnd(); + z.free(); + z=null; + } + + public override void Close() { + try{ + try{Finish();} + catch (IOException) {} + } + finally{ + End(); + outp.Close(); + outp=null; + } + } + } +} diff --git a/crypto/src/util/zlib/ZInflaterInputStream.cs b/crypto/src/util/zlib/ZInflaterInputStream.cs new file mode 100644 index 000000000..5a3ff5aa6 --- /dev/null +++ b/crypto/src/util/zlib/ZInflaterInputStream.cs @@ -0,0 +1,127 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.Zlib { + /// + /// Summary description for DeflaterOutputStream. + /// + [Obsolete("Use 'ZInputStream' instead")] + public class ZInflaterInputStream : Stream { + protected ZStream z=new ZStream(); + protected int flushLevel=JZlib.Z_NO_FLUSH; + private const int BUFSIZE = 4192; + protected byte[] buf=new byte[BUFSIZE]; + private byte[] buf1=new byte[1]; + + protected Stream inp=null; + private bool nomoreinput=false; + + public ZInflaterInputStream(Stream inp) : this(inp, false) { + } + + public ZInflaterInputStream(Stream inp, bool nowrap) { + this.inp=inp; + z.inflateInit(nowrap); + z.next_in=buf; + z.next_in_index=0; + z.avail_in=0; + } + + public override bool CanRead { + get { + // TODO: Add DeflaterOutputStream.CanRead getter implementation + return true; + } + } + + public override bool CanSeek { + get { + // TODO: Add DeflaterOutputStream.CanSeek getter implementation + return false; + } + } + + public override bool CanWrite { + get { + // TODO: Add DeflaterOutputStream.CanWrite getter implementation + return false; + } + } + + public override long Length { + get { + // TODO: Add DeflaterOutputStream.Length getter implementation + return 0; + } + } + + public override long Position { + get { + // TODO: Add DeflaterOutputStream.Position getter implementation + return 0; + } + set { + // TODO: Add DeflaterOutputStream.Position setter implementation + } + } + + public override void Write(byte[] b, int off, int len) { + } + + public override long Seek(long offset, SeekOrigin origin) { + // TODO: Add DeflaterOutputStream.Seek implementation + return 0; + } + + public override void SetLength(long value) { + // TODO: Add DeflaterOutputStream.SetLength implementation + + } + + public override int Read(byte[] b, int off, int len) { + if(len==0) + return(0); + int err; + z.next_out=b; + z.next_out_index=off; + z.avail_out=len; + do { + if((z.avail_in==0)&&(!nomoreinput)) { // if buffer is empty and more input is avaiable, refill it + z.next_in_index=0; + z.avail_in=inp.Read(buf, 0, BUFSIZE);//(BUFSIZE 0) + { + output.Write(buf, 0, count); + } + } + while (z.avail_in > 0 || z.avail_out == 0); + + Flush(); + } + + public override void Flush() + { + output.Flush(); + } + + public virtual int FlushMode + { + get { return flushLevel; } + set { this.flushLevel = value; } + } + + public sealed override long Length { get { throw new NotSupportedException(); } } + public sealed override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } + public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } + public sealed override void SetLength(long value) { throw new NotSupportedException(); } + + public virtual long TotalIn + { + get { return z.total_in; } + } + + public virtual long TotalOut + { + get { return z.total_out; } + } + + public override void Write(byte[] b, int off, int len) + { + if (len == 0) + return; + + z.next_in = b; + z.next_in_index = off; + z.avail_in = len; + + do + { + z.next_out = buf; + z.next_out_index = 0; + z.avail_out = buf.Length; + + int err = compress + ? z.deflate(flushLevel) + : z.inflate(flushLevel); + + if (err != JZlib.Z_OK) + // TODO +// throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg); + throw new IOException((compress ? "de" : "in") + "flating: " + z.msg); + + output.Write(buf, 0, buf.Length - z.avail_out); + } + while (z.avail_in > 0 || z.avail_out == 0); + } + + public override void WriteByte(byte b) + { + buf1[0] = b; + Write(buf1, 0, 1); + } + } +} diff --git a/crypto/src/util/zlib/ZStream.cs b/crypto/src/util/zlib/ZStream.cs new file mode 100644 index 000000000..7ff961462 --- /dev/null +++ b/crypto/src/util/zlib/ZStream.cs @@ -0,0 +1,214 @@ +using System; +/* + * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $ + * +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +namespace Org.BouncyCastle.Utilities.Zlib { + + public sealed class ZStream{ + + private const int MAX_WBITS=15; // 32K LZ77 window + private const int DEF_WBITS=MAX_WBITS; + + private const int Z_NO_FLUSH=0; + private const int Z_PARTIAL_FLUSH=1; + private const int Z_SYNC_FLUSH=2; + private const int Z_FULL_FLUSH=3; + private const int Z_FINISH=4; + + private const int MAX_MEM_LEVEL=9; + + private const int Z_OK=0; + private const int Z_STREAM_END=1; + private const int Z_NEED_DICT=2; + private const int Z_ERRNO=-1; + private const int Z_STREAM_ERROR=-2; + private const int Z_DATA_ERROR=-3; + private const int Z_MEM_ERROR=-4; + private const int Z_BUF_ERROR=-5; + private const int Z_VERSION_ERROR=-6; + + public byte[] next_in; // next input byte + public int next_in_index; + public int avail_in; // number of bytes available at next_in + public long total_in; // total nb of input bytes read so far + + public byte[] next_out; // next output byte should be put there + public int next_out_index; + public int avail_out; // remaining free space at next_out + public long total_out; // total nb of bytes output so far + + public String msg; + + internal Deflate dstate; + internal Inflate istate; + + internal int data_type; // best guess about the data type: ascii or binary + + public long adler; + internal Adler32 _adler=new Adler32(); + + public int inflateInit(){ + return inflateInit(DEF_WBITS); + } + public int inflateInit(bool nowrap){ + return inflateInit(DEF_WBITS, nowrap); + } + public int inflateInit(int w){ + return inflateInit(w, false); + } + + public int inflateInit(int w, bool nowrap){ + istate=new Inflate(); + return istate.inflateInit(this, nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + return istate.inflate(this, f); + } + public int inflateEnd(){ + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(this); + istate = null; + return ret; + } + public int inflateSync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(this); + } + public int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(this, dictionary, dictLength); + } + + public int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + public int deflateInit(int level, bool nowrap){ + return deflateInit(level, MAX_WBITS, nowrap); + } + public int deflateInit(int level, int bits){ + return deflateInit(level, bits, false); + } + public int deflateInit(int level, int bits, bool nowrap){ + dstate=new Deflate(); + return dstate.deflateInit(this, level, nowrap?-bits:bits); + } + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + return dstate.deflate(this, flush); + } + public int deflateEnd(){ + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + return ret; + } + public int deflateParams(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(this, level, strategy); + } + public int deflateSetDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(this, dictionary, dictLength); + } + + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + internal void flush_pending(){ + int len=dstate.pending; + + if(len>avail_out) len=avail_out; + if(len==0) return; + + if(dstate.pending_buf.Length<=dstate.pending_out || + next_out.Length<=next_out_index || + dstate.pending_buf.Length<(dstate.pending_out+len) || + next_out.Length<(next_out_index+len)){ + // System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ + // ", "+next_out.length+", "+next_out_index+", "+len); + // System.out.println("avail_out="+avail_out); + } + + System.Array.Copy(dstate.pending_buf, dstate.pending_out, + next_out, next_out_index, len); + + next_out_index+=len; + dstate.pending_out+=len; + total_out+=len; + avail_out-=len; + dstate.pending-=len; + if(dstate.pending==0){ + dstate.pending_out=0; + } + } + + // Read a new buffer from the current input stream, update the adler32 + // and total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + internal int read_buf(byte[] buf, int start, int size) { + int len=avail_in; + + if(len>size) len=size; + if(len==0) return 0; + + avail_in-=len; + + if(dstate.noheader==0) { + adler=_adler.adler32(adler, next_in, next_in_index, len); + } + System.Array.Copy(next_in, next_in_index, buf, start, len); + next_in_index += len; + total_in += len; + return len; + } + + public void free(){ + next_in=null; + next_out=null; + msg=null; + _adler=null; + } + } +} \ No newline at end of file diff --git a/crypto/src/x509/AttributeCertificateHolder.cs b/crypto/src/x509/AttributeCertificateHolder.cs new file mode 100644 index 000000000..3a6af4c20 --- /dev/null +++ b/crypto/src/x509/AttributeCertificateHolder.cs @@ -0,0 +1,442 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.X509 +{ + /// + /// The Holder object. + ///
    + 	/// 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
    + 	/// }
    +	/// 
    + ///
    + public class AttributeCertificateHolder + //: CertSelector, Selector + : IX509Selector + { + internal readonly Holder holder; + + internal AttributeCertificateHolder( + Asn1Sequence seq) + { + holder = Holder.GetInstance(seq); + } + + public AttributeCertificateHolder( + X509Name issuerName, + BigInteger serialNumber) + { + holder = new Holder( + new IssuerSerial( + GenerateGeneralNames(issuerName), + new DerInteger(serialNumber))); + } + + public AttributeCertificateHolder( + X509Certificate cert) + { + X509Name name; + try + { + name = PrincipalUtilities.GetIssuerX509Principal(cert); + } + catch (Exception e) + { + throw new CertificateParsingException(e.Message); + } + + holder = new Holder(new IssuerSerial(GenerateGeneralNames(name), new DerInteger(cert.SerialNumber))); + } + + public AttributeCertificateHolder( + X509Name principal) + { + holder = new Holder(GenerateGeneralNames(principal)); + } + + /** + * Constructs a holder for v2 attribute certificates with a hash value for + * some type of object. + *

    + * digestedObjectType can be one of the following: + *

      + *
    • 0 - publicKey - A hash of the public key of the holder must be + * passed.
    • + *
    • 1 - publicKeyCert - A hash of the public key certificate of the + * holder must be passed.
    • + *
    • 2 - otherObjectDigest - A hash of some other object type must be + * passed. otherObjectTypeID must not be empty.
    • + *
    + *

    + *

    This cannot be used if a v1 attribute certificate is used.

    + * + * @param digestedObjectType The digest object type. + * @param digestAlgorithm The algorithm identifier for the hash. + * @param otherObjectTypeID The object type ID if + * digestedObjectType is + * otherObjectDigest. + * @param objectDigest The hash value. + */ + public AttributeCertificateHolder( + int digestedObjectType, + string digestAlgorithm, + string otherObjectTypeID, + byte[] objectDigest) + { + // TODO Allow 'objectDigest' to be null? + + holder = new Holder(new ObjectDigestInfo(digestedObjectType, otherObjectTypeID, + new AlgorithmIdentifier(digestAlgorithm), Arrays.Clone(objectDigest))); + } + + /** + * Returns the digest object type if an object digest info is used. + *

    + *

      + *
    • 0 - publicKey - A hash of the public key of the holder must be + * passed.
    • + *
    • 1 - publicKeyCert - A hash of the public key certificate of the + * holder must be passed.
    • + *
    • 2 - otherObjectDigest - A hash of some other object type must be + * passed. otherObjectTypeID must not be empty.
    • + *
    + *

    + * + * @return The digest object type or -1 if no object digest info is set. + */ + public int DigestedObjectType + { + get + { + ObjectDigestInfo odi = holder.ObjectDigestInfo; + + return odi == null + ? -1 + : odi.DigestedObjectType.Value.IntValue; + } + } + + /** + * Returns the other object type ID if an object digest info is used. + * + * @return The other object type ID or null if no object + * digest info is set. + */ + public string DigestAlgorithm + { + get + { + ObjectDigestInfo odi = holder.ObjectDigestInfo; + + return odi == null + ? null + : odi.DigestAlgorithm.ObjectID.Id; + } + } + + /** + * Returns the hash if an object digest info is used. + * + * @return The hash or null if no object digest info is set. + */ + public byte[] GetObjectDigest() + { + ObjectDigestInfo odi = holder.ObjectDigestInfo; + + return odi == null + ? null + : odi.ObjectDigest.GetBytes(); + } + + /** + * Returns the digest algorithm ID if an object digest info is used. + * + * @return The digest algorithm ID or null if no object + * digest info is set. + */ + public string OtherObjectTypeID + { + get + { + ObjectDigestInfo odi = holder.ObjectDigestInfo; + + return odi == null + ? null + : odi.OtherObjectTypeID.Id; + } + } + + private GeneralNames GenerateGeneralNames( + X509Name principal) + { +// return GeneralNames.GetInstance(new DerSequence(new GeneralName(principal))); + return new GeneralNames(new GeneralName(principal)); + } + + private bool MatchesDN( + X509Name subject, + GeneralNames targets) + { + GeneralName[] names = targets.GetNames(); + + for (int i = 0; i != names.Length; i++) + { + GeneralName gn = names[i]; + + if (gn.TagNo == GeneralName.DirectoryName) + { + try + { + if (X509Name.GetInstance(gn.Name).Equivalent(subject)) + { + return true; + } + } + catch (Exception) + { + } + } + } + + return false; + } + + private object[] GetNames( + GeneralName[] names) + { + int count = 0; + for (int i = 0; i != names.Length; i++) + { + if (names[i].TagNo == GeneralName.DirectoryName) + { + ++count; + } + } + + object[] result = new object[count]; + + int pos = 0; + for (int i = 0; i != names.Length; i++) + { + if (names[i].TagNo == GeneralName.DirectoryName) + { + result[pos++] = X509Name.GetInstance(names[i].Name); + } + } + + return result; + } + + private X509Name[] GetPrincipals( + GeneralNames names) + { + object[] p = this.GetNames(names.GetNames()); + + int count = 0; + + for (int i = 0; i != p.Length; i++) + { + if (p[i] is X509Name) + { + ++count; + } + } + + X509Name[] result = new X509Name[count]; + + int pos = 0; + for (int i = 0; i != p.Length; i++) + { + if (p[i] is X509Name) + { + result[pos++] = (X509Name)p[i]; + } + } + + return result; + } + + /** + * Return any principal objects inside the attribute certificate holder entity names field. + * + * @return an array of IPrincipal objects (usually X509Name), null if no entity names field is set. + */ + public X509Name[] GetEntityNames() + { + if (holder.EntityName != null) + { + return GetPrincipals(holder.EntityName); + } + + return null; + } + + /** + * Return the principals associated with the issuer attached to this holder + * + * @return an array of principals, null if no BaseCertificateID is set. + */ + public X509Name[] GetIssuer() + { + if (holder.BaseCertificateID != null) + { + return GetPrincipals(holder.BaseCertificateID.Issuer); + } + + return null; + } + + /** + * Return the serial number associated with the issuer attached to this holder. + * + * @return the certificate serial number, null if no BaseCertificateID is set. + */ + public BigInteger SerialNumber + { + get + { + if (holder.BaseCertificateID != null) + { + return holder.BaseCertificateID.Serial.Value; + } + + return null; + } + } + + public object Clone() + { + return new AttributeCertificateHolder((Asn1Sequence)holder.ToAsn1Object()); + } + + public bool Match( +// Certificate cert) + X509Certificate x509Cert) + { +// if (!(cert is X509Certificate)) +// { +// return false; +// } +// +// X509Certificate x509Cert = (X509Certificate)cert; + + try + { + if (holder.BaseCertificateID != null) + { + return holder.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber) + && MatchesDN(PrincipalUtilities.GetIssuerX509Principal(x509Cert), holder.BaseCertificateID.Issuer); + } + + if (holder.EntityName != null) + { + if (MatchesDN(PrincipalUtilities.GetSubjectX509Principal(x509Cert), holder.EntityName)) + { + return true; + } + } + + if (holder.ObjectDigestInfo != null) + { + IDigest md = null; + try + { + md = DigestUtilities.GetDigest(DigestAlgorithm); + } + catch (Exception) + { + return false; + } + + switch (DigestedObjectType) + { + case ObjectDigestInfo.PublicKey: + { + // TODO: DSA Dss-parms + + //byte[] b = x509Cert.GetPublicKey().getEncoded(); + // TODO Is this the right way to encode? + byte[] b = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( + x509Cert.GetPublicKey()).GetEncoded(); + md.BlockUpdate(b, 0, b.Length); + break; + } + + case ObjectDigestInfo.PublicKeyCert: + { + byte[] b = x509Cert.GetEncoded(); + md.BlockUpdate(b, 0, b.Length); + break; + } + + // TODO Default handler? + } + + // TODO Shouldn't this be the other way around? + if (!Arrays.AreEqual(DigestUtilities.DoFinal(md), GetObjectDigest())) + { + return false; + } + } + } + catch (CertificateEncodingException) + { + return false; + } + + return false; + } + + public override bool Equals( + object obj) + { + if (obj == this) + { + return true; + } + + if (!(obj is AttributeCertificateHolder)) + { + return false; + } + + AttributeCertificateHolder other = (AttributeCertificateHolder)obj; + + return this.holder.Equals(other.holder); + } + + public override int GetHashCode() + { + return this.holder.GetHashCode(); + } + + public bool Match( + object obj) + { + if (!(obj is X509Certificate)) + { + return false; + } + +// return Match((Certificate)obj); + return Match((X509Certificate)obj); + } + } +} diff --git a/crypto/src/x509/AttributeCertificateIssuer.cs b/crypto/src/x509/AttributeCertificateIssuer.cs new file mode 100644 index 000000000..7df1416d3 --- /dev/null +++ b/crypto/src/x509/AttributeCertificateIssuer.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.X509 +{ + /** + * Carrying class for an attribute certificate issuer. + */ + public class AttributeCertificateIssuer + //: CertSelector, Selector + : IX509Selector + { + internal readonly Asn1Encodable form; + + /** + * Set the issuer directly with the ASN.1 structure. + * + * @param issuer The issuer + */ + public AttributeCertificateIssuer( + AttCertIssuer issuer) + { + form = issuer.Issuer; + } + + public AttributeCertificateIssuer( + X509Name principal) + { +// form = new V2Form(GeneralNames.GetInstance(new DerSequence(new GeneralName(principal)))); + form = new V2Form(new GeneralNames(new GeneralName(principal))); + } + + private object[] GetNames() + { + GeneralNames name; + if (form is V2Form) + { + name = ((V2Form)form).IssuerName; + } + else + { + name = (GeneralNames)form; + } + + GeneralName[] names = name.GetNames(); + + int count = 0; + for (int i = 0; i != names.Length; i++) + { + if (names[i].TagNo == GeneralName.DirectoryName) + { + ++count; + } + } + + object[] result = new object[count]; + + int pos = 0; + for (int i = 0; i != names.Length; i++) + { + if (names[i].TagNo == GeneralName.DirectoryName) + { + result[pos++] = X509Name.GetInstance(names[i].Name); + } + } + + return result; + } + + /// Return any principal objects inside the attribute certificate issuer object. + /// An array of IPrincipal objects (usually X509Principal). + public X509Name[] GetPrincipals() + { + object[] p = this.GetNames(); + + int count = 0; + for (int i = 0; i != p.Length; i++) + { + if (p[i] is X509Name) + { + ++count; + } + } + + X509Name[] result = new X509Name[count]; + + int pos = 0; + for (int i = 0; i != p.Length; i++) + { + if (p[i] is X509Name) + { + result[pos++] = (X509Name)p[i]; + } + } + + return result; + } + + private bool MatchesDN( + X509Name subject, + GeneralNames targets) + { + GeneralName[] names = targets.GetNames(); + + for (int i = 0; i != names.Length; i++) + { + GeneralName gn = names[i]; + + if (gn.TagNo == GeneralName.DirectoryName) + { + try + { + if (X509Name.GetInstance(gn.Name).Equivalent(subject)) + { + return true; + } + } + catch (Exception) + { + } + } + } + + return false; + } + + public object Clone() + { + return new AttributeCertificateIssuer(AttCertIssuer.GetInstance(form)); + } + + public bool Match( +// Certificate cert) + X509Certificate x509Cert) + { +// if (!(cert is X509Certificate)) +// { +// return false; +// } +// +// X509Certificate x509Cert = (X509Certificate)cert; + + if (form is V2Form) + { + V2Form issuer = (V2Form) form; + if (issuer.BaseCertificateID != null) + { + return issuer.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber) + && MatchesDN(x509Cert.IssuerDN, issuer.BaseCertificateID.Issuer); + } + + return MatchesDN(x509Cert.SubjectDN, issuer.IssuerName); + } + + return MatchesDN(x509Cert.SubjectDN, (GeneralNames) form); + } + + public override bool Equals( + object obj) + { + if (obj == this) + { + return true; + } + + if (!(obj is AttributeCertificateIssuer)) + { + return false; + } + + AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj; + + return this.form.Equals(other.form); + } + + public override int GetHashCode() + { + return this.form.GetHashCode(); + } + + public bool Match( + object obj) + { + if (!(obj is X509Certificate)) + { + return false; + } + + //return Match((Certificate)obj); + return Match((X509Certificate)obj); + } + } +} diff --git a/crypto/src/x509/IX509AttributeCertificate.cs b/crypto/src/x509/IX509AttributeCertificate.cs new file mode 100644 index 000000000..9a3004e01 --- /dev/null +++ b/crypto/src/x509/IX509AttributeCertificate.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.X509 +{ + /// Interface for an X.509 Attribute Certificate. + public interface IX509AttributeCertificate + : IX509Extension + { + /// The version number for the certificate. + int Version { get; } + + /// The serial number for the certificate. + BigInteger SerialNumber { get; } + + /// The UTC DateTime before which the certificate is not valid. + DateTime NotBefore { get; } + + /// The UTC DateTime after which the certificate is not valid. + DateTime NotAfter { get; } + + /// The holder of the certificate. + AttributeCertificateHolder Holder { get; } + + /// The issuer details for the certificate. + AttributeCertificateIssuer Issuer { get; } + + /// Return the attributes contained in the attribute block in the certificate. + /// An array of attributes. + X509Attribute[] GetAttributes(); + + /// Return the attributes with the same type as the passed in oid. + /// The object identifier we wish to match. + /// An array of matched attributes, null if there is no match. + X509Attribute[] GetAttributes(string oid); + + bool[] GetIssuerUniqueID(); + + bool IsValidNow { get; } + bool IsValid(DateTime date); + + void CheckValidity(); + void CheckValidity(DateTime date); + + byte[] GetSignature(); + + void Verify(AsymmetricKeyParameter publicKey); + + /// Return an ASN.1 encoded byte array representing the attribute certificate. + /// An ASN.1 encoded byte array. + /// If the certificate cannot be encoded. + byte[] GetEncoded(); + } +} diff --git a/crypto/src/x509/IX509Extension.cs b/crypto/src/x509/IX509Extension.cs new file mode 100644 index 000000000..e861e8736 --- /dev/null +++ b/crypto/src/x509/IX509Extension.cs @@ -0,0 +1,27 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.X509 +{ + public interface IX509Extension + { + /// + /// Get all critical extension values, by oid + /// + /// IDictionary with string (OID) keys and Asn1OctetString values + ISet GetCriticalExtensionOids(); + + /// + /// Get all non-critical extension values, by oid + /// + /// IDictionary with string (OID) keys and Asn1OctetString values + ISet GetNonCriticalExtensionOids(); + + [Obsolete("Use version taking a DerObjectIdentifier instead")] + Asn1OctetString GetExtensionValue(string oid); + + Asn1OctetString GetExtensionValue(DerObjectIdentifier oid); + } +} diff --git a/crypto/src/x509/PEMParser.cs b/crypto/src/x509/PEMParser.cs new file mode 100644 index 000000000..8c117f323 --- /dev/null +++ b/crypto/src/x509/PEMParser.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.X509 +{ + class PemParser + { + private readonly string _header1; + private readonly string _header2; + private readonly string _footer1; + private readonly string _footer2; + + internal PemParser( + string type) + { + _header1 = "-----BEGIN " + type + "-----"; + _header2 = "-----BEGIN X509 " + type + "-----"; + _footer1 = "-----END " + type + "-----"; + _footer2 = "-----END X509 " + type + "-----"; + } + + private string ReadLine( + Stream inStream) + { + int c; + StringBuilder l = new StringBuilder(); + + do + { + while (((c = inStream.ReadByte()) != '\r') && c != '\n' && (c >= 0)) + { + if (c == '\r') + { + continue; + } + + l.Append((char)c); + } + } + while (c >= 0 && l.Length == 0); + + if (c < 0) + { + return null; + } + + return l.ToString(); + } + + internal Asn1Sequence ReadPemObject( + Stream inStream) + { + string line; + StringBuilder pemBuf = new StringBuilder(); + + while ((line = ReadLine(inStream)) != null) + { + if (line.StartsWith(_header1) || line.StartsWith(_header2)) + { + break; + } + } + + while ((line = ReadLine(inStream)) != null) + { + if (line.StartsWith(_footer1) || line.StartsWith(_footer2)) + { + break; + } + + pemBuf.Append(line); + } + + if (pemBuf.Length != 0) + { + Asn1Object o = Asn1Object.FromByteArray(Base64.Decode(pemBuf.ToString())); + + if (!(o is Asn1Sequence)) + { + throw new IOException("malformed PEM data encountered"); + } + + return (Asn1Sequence) o; + } + + return null; + } + } +} + diff --git a/crypto/src/x509/PrincipalUtil.cs b/crypto/src/x509/PrincipalUtil.cs new file mode 100644 index 000000000..0edc4a395 --- /dev/null +++ b/crypto/src/x509/PrincipalUtil.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; + +namespace Org.BouncyCastle.X509 +{ + /// + /// A utility class that will extract X509Principal objects from X.509 certificates. + ///

    + /// Use this in preference to trying to recreate a principal from a string, not all + /// DNs are what they should be, so it's best to leave them encoded where they + /// can be.

    + ///
    + public class PrincipalUtilities + { + /// Return the issuer of the given cert as an X509Principal. + public static X509Name GetIssuerX509Principal( + X509Certificate cert) + { + try + { + TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance( + Asn1Object.FromByteArray(cert.GetTbsCertificate())); + + return tbsCert.Issuer; + } + catch (Exception e) + { + throw new CertificateEncodingException("Could not extract issuer", e); + } + } + + /// Return the subject of the given cert as an X509Principal. + public static X509Name GetSubjectX509Principal( + X509Certificate cert) + { + try + { + TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance( + Asn1Object.FromByteArray(cert.GetTbsCertificate())); + + return tbsCert.Subject; + } + catch (Exception e) + { + throw new CertificateEncodingException("Could not extract subject", e); + } + } + + /// Return the issuer of the given CRL as an X509Principal. + public static X509Name GetIssuerX509Principal( + X509Crl crl) + { + try + { + TbsCertificateList tbsCertList = TbsCertificateList.GetInstance( + Asn1Object.FromByteArray(crl.GetTbsCertList())); + + return tbsCertList.Issuer; + } + catch (Exception e) + { + throw new CrlException("Could not extract issuer", e); + } + } + } +} diff --git a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs new file mode 100644 index 000000000..54ca78090 --- /dev/null +++ b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs @@ -0,0 +1,187 @@ +using System; +using System.IO; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509 +{ + /// + /// A factory to produce Public Key Info Objects. + /// + public sealed class SubjectPublicKeyInfoFactory + { + private SubjectPublicKeyInfoFactory() + { + } + + /// + /// Create a Subject Public Key Info object for a given public key. + /// + /// One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters + /// A subject public key info object. + /// Throw exception if object provided is not one of the above. + public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo( + AsymmetricKeyParameter key) + { + if (key == null) + throw new ArgumentNullException("key"); + if (key.IsPrivate) + throw new ArgumentException("Private key passed - public key expected.", "key"); + + if (key is ElGamalPublicKeyParameters) + { + ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key; + ElGamalParameters kp = _key.Parameters; + + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( + new AlgorithmIdentifier( + OiwObjectIdentifiers.ElGamalAlgorithm, + new ElGamalParameter(kp.P, kp.G).ToAsn1Object()), + new DerInteger(_key.Y)); + + return info; + } + + if (key is DsaPublicKeyParameters) + { + DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key; + DsaParameters kp = _key.Parameters; + Asn1Encodable ae = kp == null + ? null + : new DsaParameter(kp.P, kp.Q, kp.G).ToAsn1Object(); + + return new SubjectPublicKeyInfo( + new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, ae), + new DerInteger(_key.Y)); + } + + if (key is DHPublicKeyParameters) + { + DHPublicKeyParameters _key = (DHPublicKeyParameters) key; + DHParameters kp = _key.Parameters; + + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( + new AlgorithmIdentifier( + _key.AlgorithmOid, + new DHParameter(kp.P, kp.G, kp.L).ToAsn1Object()), + new DerInteger(_key.Y)); + + return info; + } // End of DH + + if (key is RsaKeyParameters) + { + RsaKeyParameters _key = (RsaKeyParameters) key; + + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( + new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance), + new RsaPublicKeyStructure(_key.Modulus, _key.Exponent).ToAsn1Object()); + + return info; + } // End of RSA. + + if (key is ECPublicKeyParameters) + { + ECPublicKeyParameters _key = (ECPublicKeyParameters) key; + + if (_key.AlgorithmName == "ECGOST3410") + { + if (_key.PublicKeyParamSet == null) + throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); + + ECPoint q = _key.Q; + BigInteger bX = q.X.ToBigInteger(); + BigInteger bY = q.Y.ToBigInteger(); + + byte[] encKey = new byte[64]; + ExtractBytes(encKey, 0, bX); + ExtractBytes(encKey, 32, bY); + + Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( + _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); + + AlgorithmIdentifier algID = new AlgorithmIdentifier( + CryptoProObjectIdentifiers.GostR3410x2001, + gostParams.ToAsn1Object()); + + return new SubjectPublicKeyInfo(algID, new DerOctetString(encKey)); + } + else + { + X962Parameters x962; + if (_key.PublicKeyParamSet == null) + { + ECDomainParameters kp = _key.Parameters; + X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed()); + + x962 = new X962Parameters(ecP); + } + else + { + x962 = new X962Parameters(_key.PublicKeyParamSet); + } + + Asn1OctetString p = (Asn1OctetString)(new X9ECPoint(_key.Q).ToAsn1Object()); + + AlgorithmIdentifier algID = new AlgorithmIdentifier( + X9ObjectIdentifiers.IdECPublicKey, x962.ToAsn1Object()); + + return new SubjectPublicKeyInfo(algID, p.GetOctets()); + } + } // End of EC + + if (key is Gost3410PublicKeyParameters) + { + Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key; + + if (_key.PublicKeyParamSet == null) + throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); + + byte[] keyEnc = _key.Y.ToByteArrayUnsigned(); + byte[] keyBytes = new byte[keyEnc.Length]; + + for (int i = 0; i != keyBytes.Length; i++) + { + keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian + } + + Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters( + _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); + + AlgorithmIdentifier algID = new AlgorithmIdentifier( + CryptoProObjectIdentifiers.GostR3410x94, + algParams.ToAsn1Object()); + + return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes)); + } + + throw new ArgumentException("Class provided no convertible: " + key.GetType().FullName); + } + + private static void ExtractBytes( + byte[] encKey, + int offset, + BigInteger bI) + { + byte[] val = bI.ToByteArray(); + int n = (bI.BitLength + 7) / 8; + + for (int i = 0; i < n; ++i) + { + encKey[offset + i] = val[val.Length - 1 - i]; + } + } + } +} diff --git a/crypto/src/x509/X509AttrCertParser.cs b/crypto/src/x509/X509AttrCertParser.cs new file mode 100644 index 000000000..a5c07362e --- /dev/null +++ b/crypto/src/x509/X509AttrCertParser.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.X509 +{ + public class X509AttrCertParser + { + private static readonly PemParser PemAttrCertParser = new PemParser("ATTRIBUTE CERTIFICATE"); + + private Asn1Set sData; + private int sDataObjectCount; + private Stream currentStream; + + private IX509AttributeCertificate ReadDerCertificate( + Asn1InputStream dIn) + { + Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject(); + + if (seq.Count > 1 && seq[0] is DerObjectIdentifier) + { + if (seq[0].Equals(PkcsObjectIdentifiers.SignedData)) + { + sData = SignedData.GetInstance( + Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates; + + return GetCertificate(); + } + } + +// return new X509V2AttributeCertificate(seq.getEncoded()); + return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq)); + } + + private IX509AttributeCertificate GetCertificate() + { + if (sData != null) + { + while (sDataObjectCount < sData.Count) + { + object obj = sData[sDataObjectCount++]; + + if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 2) + { + //return new X509V2AttributeCertificate( + // Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false).GetEncoded()); + return new X509V2AttributeCertificate( + AttributeCertificate.GetInstance( + Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false))); + } + } + } + + return null; + } + + private IX509AttributeCertificate ReadPemCertificate( + Stream inStream) + { + Asn1Sequence seq = PemAttrCertParser.ReadPemObject(inStream); + + return seq == null + ? null + //: new X509V2AttributeCertificate(seq.getEncoded()); + : new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq)); + } + + /// + /// Create loading data from byte array. + /// + /// + public IX509AttributeCertificate ReadAttrCert( + byte[] input) + { + return ReadAttrCert(new MemoryStream(input, false)); + } + + /// + /// Create loading data from byte array. + /// + /// + public ICollection ReadAttrCerts( + byte[] input) + { + return ReadAttrCerts(new MemoryStream(input, false)); + } + + /** + * Generates a certificate object and initializes it with the data + * read from the input stream inStream. + */ + public IX509AttributeCertificate ReadAttrCert( + Stream inStream) + { + if (inStream == null) + throw new ArgumentNullException("inStream"); + if (!inStream.CanRead) + throw new ArgumentException("inStream must be read-able", "inStream"); + + if (currentStream == null) + { + currentStream = inStream; + sData = null; + sDataObjectCount = 0; + } + else if (currentStream != inStream) // reset if input stream has changed + { + currentStream = inStream; + sData = null; + sDataObjectCount = 0; + } + + try + { + if (sData != null) + { + if (sDataObjectCount != sData.Count) + { + return GetCertificate(); + } + + sData = null; + sDataObjectCount = 0; + return null; + } + + PushbackStream pis = new PushbackStream(inStream); + int tag = pis.ReadByte(); + + if (tag < 0) + return null; + + pis.Unread(tag); + + if (tag != 0x30) // assume ascii PEM encoded. + { + return ReadPemCertificate(pis); + } + + return ReadDerCertificate(new Asn1InputStream(pis)); + } + catch (Exception e) + { + throw new CertificateException(e.ToString()); + } + } + + /** + * Returns a (possibly empty) collection view of the certificates + * read from the given input stream inStream. + */ + public ICollection ReadAttrCerts( + Stream inStream) + { + IX509AttributeCertificate attrCert; + IList attrCerts = Platform.CreateArrayList(); + + while ((attrCert = ReadAttrCert(inStream)) != null) + { + attrCerts.Add(attrCert); + } + + return attrCerts; + } + } +} \ No newline at end of file diff --git a/crypto/src/x509/X509Attribute.cs b/crypto/src/x509/X509Attribute.cs new file mode 100644 index 000000000..248d66cc4 --- /dev/null +++ b/crypto/src/x509/X509Attribute.cs @@ -0,0 +1,76 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.X509 +{ + /** + * Class for carrying the values in an X.509 Attribute. + */ + public class X509Attribute + : Asn1Encodable + { + private readonly AttributeX509 attr; + + /** + * @param at an object representing an attribute. + */ + internal X509Attribute( + Asn1Encodable at) + { + this.attr = AttributeX509.GetInstance(at); + } + + /** + * Create an X.509 Attribute with the type given by the passed in oid and + * the value represented by an ASN.1 Set containing value. + * + * @param oid type of the attribute + * @param value value object to go into the atribute's value set. + */ + public X509Attribute( + string oid, + Asn1Encodable value) + { + this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value)); + } + + /** + * Create an X.59 Attribute with the type given by the passed in oid and the + * value represented by an ASN.1 Set containing the objects in value. + * + * @param oid type of the attribute + * @param value vector of values to go in the attribute's value set. + */ + public X509Attribute( + string oid, + Asn1EncodableVector value) + { + this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value)); + } + + public string Oid + { + get { return attr.AttrType.Id; } + } + + public Asn1Encodable[] GetValues() + { + Asn1Set s = attr.AttrValues; + Asn1Encodable[] values = new Asn1Encodable[s.Count]; + + for (int i = 0; i != s.Count; i++) + { + values[i] = (Asn1Encodable)s[i]; + } + + return values; + } + + public override Asn1Object ToAsn1Object() + { + return attr.ToAsn1Object(); + } + } +} diff --git a/crypto/src/x509/X509CertPairParser.cs b/crypto/src/x509/X509CertPairParser.cs new file mode 100644 index 000000000..82612599b --- /dev/null +++ b/crypto/src/x509/X509CertPairParser.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.X509 +{ + public class X509CertPairParser + { + private Stream currentStream; + + private X509CertificatePair ReadDerCrossCertificatePair( + Stream inStream) + { + Asn1InputStream dIn = new Asn1InputStream(inStream);//, ProviderUtil.getReadLimit(in)); + Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject(); + CertificatePair pair = CertificatePair.GetInstance(seq); + return new X509CertificatePair(pair); + } + + /// + /// Create loading data from byte array. + /// + /// + public X509CertificatePair ReadCertPair( + byte[] input) + { + return ReadCertPair(new MemoryStream(input, false)); + } + + /// + /// Create loading data from byte array. + /// + /// + public ICollection ReadCertPairs( + byte[] input) + { + return ReadCertPairs(new MemoryStream(input, false)); + } + + public X509CertificatePair ReadCertPair( + Stream inStream) + { + if (inStream == null) + throw new ArgumentNullException("inStream"); + if (!inStream.CanRead) + throw new ArgumentException("inStream must be read-able", "inStream"); + + if (currentStream == null) + { + currentStream = inStream; + } + else if (currentStream != inStream) // reset if input stream has changed + { + currentStream = inStream; + } + + try + { + PushbackStream pis = new PushbackStream(inStream); + int tag = pis.ReadByte(); + + if (tag < 0) + return null; + + pis.Unread(tag); + + return ReadDerCrossCertificatePair(pis); + } + catch (Exception e) + { + throw new CertificateException(e.ToString()); + } + } + + public ICollection ReadCertPairs( + Stream inStream) + { + X509CertificatePair certPair; + IList certPairs = Platform.CreateArrayList(); + + while ((certPair = ReadCertPair(inStream)) != null) + { + certPairs.Add(certPair); + } + + return certPairs; + } + } +} diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs new file mode 100644 index 000000000..f156f3147 --- /dev/null +++ b/crypto/src/x509/X509Certificate.cs @@ -0,0 +1,595 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Misc; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509 +{ + /// + /// An Object representing an X509 Certificate. + /// Has static methods for loading Certificates encoded in many forms that return X509Certificate Objects. + /// + public class X509Certificate + : X509ExtensionBase +// , PKCS12BagAttributeCarrier + { + private readonly X509CertificateStructure c; +// private Hashtable pkcs12Attributes = new Hashtable(); +// private ArrayList pkcs12Ordering = new ArrayList(); + private readonly BasicConstraints basicConstraints; + private readonly bool[] keyUsage; + + private bool hashValueSet; + private int hashValue; + + protected X509Certificate() + { + } + + public X509Certificate( + X509CertificateStructure c) + { + this.c = c; + + try + { + Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.19")); + + if (str != null) + { + basicConstraints = BasicConstraints.GetInstance( + X509ExtensionUtilities.FromExtensionValue(str)); + } + } + catch (Exception e) + { + throw new CertificateParsingException("cannot construct BasicConstraints: " + e); + } + + try + { + Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.15")); + + if (str != null) + { + DerBitString bits = DerBitString.GetInstance( + X509ExtensionUtilities.FromExtensionValue(str)); + + byte[] bytes = bits.GetBytes(); + int length = (bytes.Length * 8) - bits.PadBits; + + keyUsage = new bool[(length < 9) ? 9 : length]; + + for (int i = 0; i != length; i++) + { +// keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; + keyUsage[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0; + } + } + else + { + keyUsage = null; + } + } + catch (Exception e) + { + throw new CertificateParsingException("cannot construct KeyUsage: " + e); + } + } + +// internal X509Certificate( +// Asn1Sequence seq) +// { +// this.c = X509CertificateStructure.GetInstance(seq); +// } + +// /// +// /// Load certificate from byte array. +// /// +// /// Byte array containing encoded X509Certificate. +// public X509Certificate( +// byte[] encoded) +// : this((Asn1Sequence) new Asn1InputStream(encoded).ReadObject()) +// { +// } +// +// /// +// /// Load certificate from Stream. +// /// Must be positioned at start of certificate. +// /// +// /// +// public X509Certificate( +// Stream input) +// : this((Asn1Sequence) new Asn1InputStream(input).ReadObject()) +// { +// } + + public virtual X509CertificateStructure CertificateStructure + { + get { return c; } + } + + /// + /// Return true if the current time is within the start and end times nominated on the certificate. + /// + /// true id certificate is valid for the current time. + public virtual bool IsValidNow + { + get { return IsValid(DateTime.UtcNow); } + } + + /// + /// Return true if the nominated time is within the start and end times nominated on the certificate. + /// + /// The time to test validity against. + /// True if certificate is valid for nominated time. + public virtual bool IsValid( + DateTime time) + { + return time.CompareTo(NotBefore) >= 0 && time.CompareTo(NotAfter) <= 0; + } + + /// + /// Checks if the current date is within certificate's validity period. + /// + public virtual void CheckValidity() + { + this.CheckValidity(DateTime.UtcNow); + } + + /// + /// Checks if the given date is within certificate's validity period. + /// + /// if the certificate is expired by given date + /// if the certificate is not yet valid on given date + public virtual void CheckValidity( + DateTime time) + { + if (time.CompareTo(NotAfter) > 0) + throw new CertificateExpiredException("certificate expired on " + c.EndDate.GetTime()); + if (time.CompareTo(NotBefore) < 0) + throw new CertificateNotYetValidException("certificate not valid until " + c.StartDate.GetTime()); + } + + /// + /// Return the certificate's version. + /// + /// An integer whose value Equals the version of the cerficate. + public virtual int Version + { + get { return c.Version; } + } + + /// + /// Return a BigInteger containing the serial number. + /// + /// The Serial number. + public virtual BigInteger SerialNumber + { + get { return c.SerialNumber.Value; } + } + + /// + /// Get the Issuer Distinguished Name. (Who signed the certificate.) + /// + /// And X509Object containing name and value pairs. +// public IPrincipal IssuerDN + public virtual X509Name IssuerDN + { + get { return c.Issuer; } + } + + /// + /// Get the subject of this certificate. + /// + /// An X509Name object containing name and value pairs. +// public IPrincipal SubjectDN + public virtual X509Name SubjectDN + { + get { return c.Subject; } + } + + /// + /// The time that this certificate is valid from. + /// + /// A DateTime object representing that time in the local time zone. + public virtual DateTime NotBefore + { + get { return c.StartDate.ToDateTime(); } + } + + /// + /// The time that this certificate is valid up to. + /// + /// A DateTime object representing that time in the local time zone. + public virtual DateTime NotAfter + { + get { return c.EndDate.ToDateTime(); } + } + + /// + /// Return the Der encoded TbsCertificate data. + /// This is the certificate component less the signature. + /// To Get the whole certificate call the GetEncoded() member. + /// + /// A byte array containing the Der encoded Certificate component. + public virtual byte[] GetTbsCertificate() + { + return c.TbsCertificate.GetDerEncoded(); + } + + /// + /// The signature. + /// + /// A byte array containg the signature of the certificate. + public virtual byte[] GetSignature() + { + return c.Signature.GetBytes(); + } + + /// + /// A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA) + /// + /// A sting representing the signature algorithm. + public virtual string SigAlgName + { + get { return SignerUtilities.GetEncodingName(c.SignatureAlgorithm.ObjectID); } + } + + /// + /// Get the Signature Algorithms Object ID. + /// + /// A string containg a '.' separated object id. + public virtual string SigAlgOid + { + get { return c.SignatureAlgorithm.ObjectID.Id; } + } + + /// + /// Get the signature algorithms parameters. (EG DSA Parameters) + /// + /// A byte array containing the Der encoded version of the parameters or null if there are none. + public virtual byte[] GetSigAlgParams() + { + if (c.SignatureAlgorithm.Parameters != null) + { + return c.SignatureAlgorithm.Parameters.GetDerEncoded(); + } + + return null; + } + + /// + /// Get the issuers UID. + /// + /// A DerBitString. + public virtual DerBitString IssuerUniqueID + { + get { return c.TbsCertificate.IssuerUniqueID; } + } + + /// + /// Get the subjects UID. + /// + /// A DerBitString. + public virtual DerBitString SubjectUniqueID + { + get { return c.TbsCertificate.SubjectUniqueID; } + } + + /// + /// Get a key usage guidlines. + /// + public virtual bool[] GetKeyUsage() + { + return keyUsage == null ? null : (bool[]) keyUsage.Clone(); + } + + // TODO Replace with something that returns a list of DerObjectIdentifier + public virtual IList GetExtendedKeyUsage() + { + Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.37")); + + if (str == null) + return null; + + try + { + Asn1Sequence seq = Asn1Sequence.GetInstance( + X509ExtensionUtilities.FromExtensionValue(str)); + + IList list = Platform.CreateArrayList(); + + foreach (DerObjectIdentifier oid in seq) + { + list.Add(oid.Id); + } + + return list; + } + catch (Exception e) + { + throw new CertificateParsingException("error processing extended key usage extension", e); + } + } + + public virtual int GetBasicConstraints() + { + if (basicConstraints != null && basicConstraints.IsCA()) + { + if (basicConstraints.PathLenConstraint == null) + { + return int.MaxValue; + } + + return basicConstraints.PathLenConstraint.IntValue; + } + + return -1; + } + + public virtual ICollection GetSubjectAlternativeNames() + { + return GetAlternativeNames("2.5.29.17"); + } + + public virtual ICollection GetIssuerAlternativeNames() + { + return GetAlternativeNames("2.5.29.18"); + } + + protected virtual ICollection GetAlternativeNames( + string oid) + { + Asn1OctetString altNames = GetExtensionValue(new DerObjectIdentifier(oid)); + + if (altNames == null) + return null; + + Asn1Object asn1Object = X509ExtensionUtilities.FromExtensionValue(altNames); + + GeneralNames gns = GeneralNames.GetInstance(asn1Object); + + IList result = Platform.CreateArrayList(); + foreach (GeneralName gn in gns.GetNames()) + { + IList entry = Platform.CreateArrayList(); + entry.Add(gn.TagNo); + entry.Add(gn.Name.ToString()); + result.Add(entry); + } + return result; + } + + protected override X509Extensions GetX509Extensions() + { + return c.Version == 3 + ? c.TbsCertificate.Extensions + : null; + } + + /// + /// Get the public key of the subject of the certificate. + /// + /// The public key parameters. + public virtual AsymmetricKeyParameter GetPublicKey() + { + return PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo); + } + + /// + /// Return a Der encoded version of this certificate. + /// + /// A byte array. + public virtual byte[] GetEncoded() + { + return c.GetDerEncoded(); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + X509Certificate other = obj as X509Certificate; + + if (other == null) + return false; + + return c.Equals(other.c); + + // NB: May prefer this implementation of Equals if more than one certificate implementation in play +// return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded()); + } + + public override int GetHashCode() + { + lock (this) + { + if (!hashValueSet) + { + hashValue = c.GetHashCode(); + hashValueSet = true; + } + } + + return hashValue; + } + +// public void setBagAttribute( +// DERObjectIdentifier oid, +// DEREncodable attribute) +// { +// pkcs12Attributes.put(oid, attribute); +// pkcs12Ordering.addElement(oid); +// } +// +// public DEREncodable getBagAttribute( +// DERObjectIdentifier oid) +// { +// return (DEREncodable)pkcs12Attributes.get(oid); +// } +// +// public Enumeration getBagAttributeKeys() +// { +// return pkcs12Ordering.elements(); +// } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string nl = Platform.NewLine; + + buf.Append(" [0] Version: ").Append(this.Version).Append(nl); + buf.Append(" SerialNumber: ").Append(this.SerialNumber).Append(nl); + buf.Append(" IssuerDN: ").Append(this.IssuerDN).Append(nl); + buf.Append(" Start Date: ").Append(this.NotBefore).Append(nl); + buf.Append(" Final Date: ").Append(this.NotAfter).Append(nl); + buf.Append(" SubjectDN: ").Append(this.SubjectDN).Append(nl); + buf.Append(" Public Key: ").Append(this.GetPublicKey()).Append(nl); + buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).Append(nl); + + byte[] sig = this.GetSignature(); + buf.Append(" Signature: ").Append(Hex.ToHexString(sig, 0, 20)).Append(nl); + + for (int i = 20; i < sig.Length; i += 20) + { + int len = System.Math.Min(20, sig.Length - i); + buf.Append(" ").Append(Hex.ToHexString(sig, i, len)).Append(nl); + } + + X509Extensions extensions = c.TbsCertificate.Extensions; + + if (extensions != null) + { + IEnumerator e = extensions.ExtensionOids.GetEnumerator(); + + if (e.MoveNext()) + { + buf.Append(" Extensions: \n"); + } + + do + { + DerObjectIdentifier oid = (DerObjectIdentifier)e.Current; + X509Extension ext = extensions.GetExtension(oid); + + if (ext.Value != null) + { + byte[] octs = ext.Value.GetOctets(); + Asn1Object obj = Asn1Object.FromByteArray(octs); + buf.Append(" critical(").Append(ext.IsCritical).Append(") "); + try + { + if (oid.Equals(X509Extensions.BasicConstraints)) + { + buf.Append(BasicConstraints.GetInstance(obj)); + } + else if (oid.Equals(X509Extensions.KeyUsage)) + { + buf.Append(KeyUsage.GetInstance(obj)); + } + else if (oid.Equals(MiscObjectIdentifiers.NetscapeCertType)) + { + buf.Append(new NetscapeCertType((DerBitString) obj)); + } + else if (oid.Equals(MiscObjectIdentifiers.NetscapeRevocationUrl)) + { + buf.Append(new NetscapeRevocationUrl((DerIA5String) obj)); + } + else if (oid.Equals(MiscObjectIdentifiers.VerisignCzagExtension)) + { + buf.Append(new VerisignCzagExtension((DerIA5String) obj)); + } + else + { + buf.Append(oid.Id); + buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj)); + //buf.Append(" value = ").Append("*****").Append(nl); + } + } + catch (Exception) + { + buf.Append(oid.Id); + //buf.Append(" value = ").Append(new string(Hex.encode(ext.getValue().getOctets()))).Append(nl); + buf.Append(" value = ").Append("*****"); + } + } + + buf.Append(nl); + } + while (e.MoveNext()); + } + + return buf.ToString(); + } + + /// + /// Verify the certificate's signature using the nominated public key. + /// + /// An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters + /// True if the signature is valid. + /// If key submitted is not of the above nominated types. + public virtual void Verify( + AsymmetricKeyParameter key) + { + string sigName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm); + ISigner signature = SignerUtilities.GetSigner(sigName); + + CheckSignature(key, signature); + } + + protected virtual void CheckSignature( + AsymmetricKeyParameter publicKey, + ISigner signature) + { + if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature)) + throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); + + Asn1Encodable parameters = c.SignatureAlgorithm.Parameters; + + X509SignatureUtilities.SetSignatureParameters(signature, parameters); + + signature.Init(false, publicKey); + + byte[] b = this.GetTbsCertificate(); + signature.BlockUpdate(b, 0, b.Length); + + byte[] sig = this.GetSignature(); + if (!signature.VerifySignature(sig)) + { + throw new InvalidKeyException("Public key presented not for certificate signature"); + } + } + + private static bool IsAlgIDEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2) + { + if (!id1.ObjectID.Equals(id2.ObjectID)) + return false; + + Asn1Encodable p1 = id1.Parameters; + Asn1Encodable p2 = id2.Parameters; + + if ((p1 == null) == (p2 == null)) + return Platform.Equals(p1, p2); + + // Exactly one of p1, p2 is null at this point + return p1 == null + ? p2.ToAsn1Object() is Asn1Null + : p1.ToAsn1Object() is Asn1Null; + } + } +} diff --git a/crypto/src/x509/X509CertificatePair.cs b/crypto/src/x509/X509CertificatePair.cs new file mode 100644 index 000000000..fbeba4dc6 --- /dev/null +++ b/crypto/src/x509/X509CertificatePair.cs @@ -0,0 +1,123 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509 +{ + /// + /// This class contains a cross certificate pair. Cross certificates pairs may + /// contain two cross signed certificates from two CAs. A certificate from the + /// other CA to this CA is contained in the forward certificate, the certificate + /// from this CA to the other CA is contained in the reverse certificate. + /// + public class X509CertificatePair + { + private readonly X509Certificate forward; + private readonly X509Certificate reverse; + + /// Constructor + /// Certificate from the other CA to this CA. + /// Certificate from this CA to the other CA. + public X509CertificatePair( + X509Certificate forward, + X509Certificate reverse) + { + this.forward = forward; + this.reverse = reverse; + } + + /// Constructor from a ASN.1 CertificatePair structure. + /// The CertificatePair ASN.1 object. + public X509CertificatePair( + CertificatePair pair) + { + if (pair.Forward != null) + { + this.forward = new X509Certificate(pair.Forward); + } + if (pair.Reverse != null) + { + this.reverse = new X509Certificate(pair.Reverse); + } + } + + public byte[] GetEncoded() + { + try + { + X509CertificateStructure f = null, r = null; + + if (forward != null) + { + f = X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(forward.GetEncoded())); + + if (f == null) + throw new CertificateEncodingException("unable to get encoding for forward"); + } + + if (reverse != null) + { + r = X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(reverse.GetEncoded())); + + if (r == null) + throw new CertificateEncodingException("unable to get encoding for reverse"); + } + + return new CertificatePair(f, r).GetDerEncoded(); + } + catch (Exception e) + { + // TODO +// throw new ExtCertificateEncodingException(e.toString(), e); + throw new CertificateEncodingException(e.Message, e); + } + } + + /// Returns the certificate from the other CA to this CA. + public X509Certificate Forward + { + get { return forward; } + } + + /// Returns the certificate from this CA to the other CA. + public X509Certificate Reverse + { + get { return reverse; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + X509CertificatePair other = obj as X509CertificatePair; + + if (other == null) + return false; + + return Platform.Equals(this.forward, other.forward) + && Platform.Equals(this.reverse, other.reverse); + } + + public override int GetHashCode() + { + int hash = -1; + if (forward != null) + { + hash ^= forward.GetHashCode(); + } + if (reverse != null) + { + hash *= 17; + hash ^= reverse.GetHashCode(); + } + return hash; + } + } +} diff --git a/crypto/src/x509/X509CertificateParser.cs b/crypto/src/x509/X509CertificateParser.cs new file mode 100644 index 000000000..8f0e7406c --- /dev/null +++ b/crypto/src/x509/X509CertificateParser.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.X509 +{ + /** + * class for dealing with X509 certificates. + *

    + * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----" + * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7 + * objects.

    + */ + public class X509CertificateParser + { + private static readonly PemParser PemCertParser = new PemParser("CERTIFICATE"); + + private Asn1Set sData; + private int sDataObjectCount; + private Stream currentStream; + + private X509Certificate ReadDerCertificate( + Asn1InputStream dIn) + { + Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject(); + + if (seq.Count > 1 && seq[0] is DerObjectIdentifier) + { + if (seq[0].Equals(PkcsObjectIdentifiers.SignedData)) + { + sData = SignedData.GetInstance( + Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates; + + return GetCertificate(); + } + } + + return CreateX509Certificate(X509CertificateStructure.GetInstance(seq)); + } + + private X509Certificate GetCertificate() + { + if (sData != null) + { + while (sDataObjectCount < sData.Count) + { + object obj = sData[sDataObjectCount++]; + + if (obj is Asn1Sequence) + { + return CreateX509Certificate( + X509CertificateStructure.GetInstance(obj)); + } + } + } + + return null; + } + + private X509Certificate ReadPemCertificate( + Stream inStream) + { + Asn1Sequence seq = PemCertParser.ReadPemObject(inStream); + + return seq == null + ? null + : CreateX509Certificate(X509CertificateStructure.GetInstance(seq)); + } + + protected virtual X509Certificate CreateX509Certificate( + X509CertificateStructure c) + { + return new X509Certificate(c); + } + + /// + /// Create loading data from byte array. + /// + /// + public X509Certificate ReadCertificate( + byte[] input) + { + return ReadCertificate(new MemoryStream(input, false)); + } + + /// + /// Create loading data from byte array. + /// + /// + public ICollection ReadCertificates( + byte[] input) + { + return ReadCertificates(new MemoryStream(input, false)); + } + + /** + * Generates a certificate object and initializes it with the data + * read from the input stream inStream. + */ + public X509Certificate ReadCertificate( + Stream inStream) + { + if (inStream == null) + throw new ArgumentNullException("inStream"); + if (!inStream.CanRead) + throw new ArgumentException("inStream must be read-able", "inStream"); + + if (currentStream == null) + { + currentStream = inStream; + sData = null; + sDataObjectCount = 0; + } + else if (currentStream != inStream) // reset if input stream has changed + { + currentStream = inStream; + sData = null; + sDataObjectCount = 0; + } + + try + { + if (sData != null) + { + if (sDataObjectCount != sData.Count) + { + return GetCertificate(); + } + + sData = null; + sDataObjectCount = 0; + return null; + } + + PushbackStream pis = new PushbackStream(inStream); + int tag = pis.ReadByte(); + + if (tag < 0) + return null; + + pis.Unread(tag); + + if (tag != 0x30) // assume ascii PEM encoded. + { + return ReadPemCertificate(pis); + } + + return ReadDerCertificate(new Asn1InputStream(pis)); + } + catch (Exception e) + { + throw new CertificateException("Failed to read certificate", e); + } + } + + /** + * Returns a (possibly empty) collection view of the certificates + * read from the given input stream inStream. + */ + public ICollection ReadCertificates( + Stream inStream) + { + X509Certificate cert; + IList certs = Platform.CreateArrayList(); + + while ((cert = ReadCertificate(inStream)) != null) + { + certs.Add(cert); + } + + return certs; + } + } +} diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs new file mode 100644 index 000000000..7d0e7aa72 --- /dev/null +++ b/crypto/src/x509/X509Crl.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509 +{ + /** + * The following extensions are listed in RFC 2459 as relevant to CRLs + * + * Authority Key Identifier + * Issuer Alternative Name + * CRL Number + * Delta CRL Indicator (critical) + * Issuing Distribution Point (critical) + */ + public class X509Crl + : X509ExtensionBase + // TODO Add interface Crl? + { + private readonly CertificateList c; + private readonly string sigAlgName; + private readonly byte[] sigAlgParams; + private readonly bool isIndirect; + + public X509Crl( + CertificateList c) + { + this.c = c; + + try + { + this.sigAlgName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm); + + if (c.SignatureAlgorithm.Parameters != null) + { + this.sigAlgParams = ((Asn1Encodable)c.SignatureAlgorithm.Parameters).GetDerEncoded(); + } + else + { + this.sigAlgParams = null; + } + + this.isIndirect = IsIndirectCrl; + } + catch (Exception e) + { + throw new CrlException("CRL contents invalid: " + e); + } + } + + protected override X509Extensions GetX509Extensions() + { + return Version == 2 + ? c.TbsCertList.Extensions + : null; + } + + public virtual byte[] GetEncoded() + { + try + { + return c.GetDerEncoded(); + } + catch (Exception e) + { + throw new CrlException(e.ToString()); + } + } + + public virtual void Verify( + AsymmetricKeyParameter publicKey) + { + if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature)) + { + throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList."); + } + + ISigner sig = SignerUtilities.GetSigner(SigAlgName); + sig.Init(false, publicKey); + + byte[] encoded = this.GetTbsCertList(); + sig.BlockUpdate(encoded, 0, encoded.Length); + + if (!sig.VerifySignature(this.GetSignature())) + { + throw new SignatureException("CRL does not verify with supplied public key."); + } + } + + public virtual int Version + { + get { return c.Version; } + } + + public virtual X509Name IssuerDN + { + get { return c.Issuer; } + } + + public virtual DateTime ThisUpdate + { + get { return c.ThisUpdate.ToDateTime(); } + } + + public virtual DateTimeObject NextUpdate + { + get + { + return c.NextUpdate == null + ? null + : new DateTimeObject(c.NextUpdate.ToDateTime()); + } + } + + private ISet LoadCrlEntries() + { + ISet entrySet = new HashSet(); + IEnumerable certs = c.GetRevokedCertificateEnumeration(); + + X509Name previousCertificateIssuer = IssuerDN; + foreach (CrlEntry entry in certs) + { + X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer); + entrySet.Add(crlEntry); + previousCertificateIssuer = crlEntry.GetCertificateIssuer(); + } + + return entrySet; + } + + public virtual X509CrlEntry GetRevokedCertificate( + BigInteger serialNumber) + { + IEnumerable certs = c.GetRevokedCertificateEnumeration(); + + X509Name previousCertificateIssuer = IssuerDN; + foreach (CrlEntry entry in certs) + { + X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer); + + if (serialNumber.Equals(entry.UserCertificate.Value)) + { + return crlEntry; + } + + previousCertificateIssuer = crlEntry.GetCertificateIssuer(); + } + + return null; + } + + public virtual ISet GetRevokedCertificates() + { + ISet entrySet = LoadCrlEntries(); + + if (entrySet.Count > 0) + { + return entrySet; // TODO? Collections.unmodifiableSet(entrySet); + } + + return null; + } + + public virtual byte[] GetTbsCertList() + { + try + { + return c.TbsCertList.GetDerEncoded(); + } + catch (Exception e) + { + throw new CrlException(e.ToString()); + } + } + + public virtual byte[] GetSignature() + { + return c.Signature.GetBytes(); + } + + public virtual string SigAlgName + { + get { return sigAlgName; } + } + + public virtual string SigAlgOid + { + get { return c.SignatureAlgorithm.ObjectID.Id; } + } + + public virtual byte[] GetSigAlgParams() + { + return Arrays.Clone(sigAlgParams); + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + X509Crl other = obj as X509Crl; + + if (other == null) + return false; + + return c.Equals(other.c); + + // NB: May prefer this implementation of Equals if more than one certificate implementation in play + //return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded()); + } + + public override int GetHashCode() + { + return c.GetHashCode(); + } + + /** + * Returns a string representation of this CRL. + * + * @return a string representation of this CRL. + */ + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string nl = Platform.NewLine; + + buf.Append(" Version: ").Append(this.Version).Append(nl); + buf.Append(" IssuerDN: ").Append(this.IssuerDN).Append(nl); + buf.Append(" This update: ").Append(this.ThisUpdate).Append(nl); + buf.Append(" Next update: ").Append(this.NextUpdate).Append(nl); + buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).Append(nl); + + byte[] sig = this.GetSignature(); + + buf.Append(" Signature: "); + buf.Append(Hex.ToHexString(sig, 0, 20)).Append(nl); + + for (int i = 20; i < sig.Length; i += 20) + { + int count = System.Math.Min(20, sig.Length - i); + buf.Append(" "); + buf.Append(Hex.ToHexString(sig, i, count)).Append(nl); + } + + X509Extensions extensions = c.TbsCertList.Extensions; + + if (extensions != null) + { + IEnumerator e = extensions.ExtensionOids.GetEnumerator(); + + if (e.MoveNext()) + { + buf.Append(" Extensions: ").Append(nl); + } + + do + { + DerObjectIdentifier oid = (DerObjectIdentifier) e.Current; + X509Extension ext = extensions.GetExtension(oid); + + if (ext.Value != null) + { + Asn1Object asn1Value = X509ExtensionUtilities.FromExtensionValue(ext.Value); + + buf.Append(" critical(").Append(ext.IsCritical).Append(") "); + try + { + if (oid.Equals(X509Extensions.CrlNumber)) + { + buf.Append(new CrlNumber(DerInteger.GetInstance(asn1Value).PositiveValue)).Append(nl); + } + else if (oid.Equals(X509Extensions.DeltaCrlIndicator)) + { + buf.Append( + "Base CRL: " + + new CrlNumber(DerInteger.GetInstance( + asn1Value).PositiveValue)) + .Append(nl); + } + else if (oid.Equals(X509Extensions.IssuingDistributionPoint)) + { + buf.Append(IssuingDistributionPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl); + } + else if (oid.Equals(X509Extensions.CrlDistributionPoints)) + { + buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl); + } + else if (oid.Equals(X509Extensions.FreshestCrl)) + { + buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl); + } + else + { + buf.Append(oid.Id); + buf.Append(" value = ").Append( + Asn1Dump.DumpAsString(asn1Value)) + .Append(nl); + } + } + catch (Exception) + { + buf.Append(oid.Id); + buf.Append(" value = ").Append("*****").Append(nl); + } + } + else + { + buf.Append(nl); + } + } + while (e.MoveNext()); + } + + ISet certSet = GetRevokedCertificates(); + if (certSet != null) + { + foreach (X509CrlEntry entry in certSet) + { + buf.Append(entry); + buf.Append(nl); + } + } + + return buf.ToString(); + } + + /** + * Checks whether the given certificate is on this CRL. + * + * @param cert the certificate to check for. + * @return true if the given certificate is on this CRL, + * false otherwise. + */ +// public bool IsRevoked( +// Certificate cert) +// { +// if (!cert.getType().Equals("X.509")) +// { +// throw new RuntimeException("X.509 CRL used with non X.509 Cert"); +// } + public virtual bool IsRevoked( + X509Certificate cert) + { + CrlEntry[] certs = c.GetRevokedCertificates(); + + if (certs != null) + { +// BigInteger serial = ((X509Certificate)cert).SerialNumber; + BigInteger serial = cert.SerialNumber; + + for (int i = 0; i < certs.Length; i++) + { + if (certs[i].UserCertificate.Value.Equals(serial)) + { + return true; + } + } + } + + return false; + } + + protected virtual bool IsIndirectCrl + { + get + { + Asn1OctetString idp = GetExtensionValue(X509Extensions.IssuingDistributionPoint); + bool isIndirect = false; + + try + { + if (idp != null) + { + isIndirect = IssuingDistributionPoint.GetInstance( + X509ExtensionUtilities.FromExtensionValue(idp)).IsIndirectCrl; + } + } + catch (Exception e) + { + // TODO +// throw new ExtCrlException("Exception reading IssuingDistributionPoint", e); + throw new CrlException("Exception reading IssuingDistributionPoint" + e); + } + + return isIndirect; + } + } + } +} diff --git a/crypto/src/x509/X509CrlEntry.cs b/crypto/src/x509/X509CrlEntry.cs new file mode 100644 index 000000000..caca29470 --- /dev/null +++ b/crypto/src/x509/X509CrlEntry.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509 +{ + /** + * The following extensions are listed in RFC 2459 as relevant to CRL Entries + * + * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer + * (critical) + */ + public class X509CrlEntry + : X509ExtensionBase + { + private CrlEntry c; + private bool isIndirect; + private X509Name previousCertificateIssuer; + private X509Name certificateIssuer; + + public X509CrlEntry( + CrlEntry c) + { + this.c = c; + this.certificateIssuer = loadCertificateIssuer(); + } + + /** + * Constructor for CRLEntries of indirect CRLs. If isIndirect + * is false {@link #getCertificateIssuer()} will always + * return null, previousCertificateIssuer is + * ignored. If this isIndirect is specified and this CrlEntry + * has no certificate issuer CRL entry extension + * previousCertificateIssuer is returned by + * {@link #getCertificateIssuer()}. + * + * @param c + * TbsCertificateList.CrlEntry object. + * @param isIndirect + * true if the corresponding CRL is a indirect + * CRL. + * @param previousCertificateIssuer + * Certificate issuer of the previous CrlEntry. + */ + public X509CrlEntry( + CrlEntry c, + bool isIndirect, + X509Name previousCertificateIssuer) + { + this.c = c; + this.isIndirect = isIndirect; + this.previousCertificateIssuer = previousCertificateIssuer; + this.certificateIssuer = loadCertificateIssuer(); + } + + private X509Name loadCertificateIssuer() + { + if (!isIndirect) + { + return null; + } + + Asn1OctetString ext = GetExtensionValue(X509Extensions.CertificateIssuer); + if (ext == null) + { + return previousCertificateIssuer; + } + + try + { + GeneralName[] names = GeneralNames.GetInstance( + X509ExtensionUtilities.FromExtensionValue(ext)).GetNames(); + + for (int i = 0; i < names.Length; i++) + { + if (names[i].TagNo == GeneralName.DirectoryName) + { + return X509Name.GetInstance(names[i].Name); + } + } + } + catch (Exception) + { + } + + return null; + } + + public X509Name GetCertificateIssuer() + { + return certificateIssuer; + } + + protected override X509Extensions GetX509Extensions() + { + return c.Extensions; + } + + public byte[] GetEncoded() + { + try + { + return c.GetDerEncoded(); + } + catch (Exception e) + { + throw new CrlException(e.ToString()); + } + } + + public BigInteger SerialNumber + { + get { return c.UserCertificate.Value; } + } + + public DateTime RevocationDate + { + get { return c.RevocationDate.ToDateTime(); } + } + + public bool HasExtensions + { + get { return c.Extensions != null; } + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + string nl = Platform.NewLine; + + buf.Append(" userCertificate: ").Append(this.SerialNumber).Append(nl); + buf.Append(" revocationDate: ").Append(this.RevocationDate).Append(nl); + buf.Append(" certificateIssuer: ").Append(this.GetCertificateIssuer()).Append(nl); + + X509Extensions extensions = c.Extensions; + + if (extensions != null) + { + IEnumerator e = extensions.ExtensionOids.GetEnumerator(); + if (e.MoveNext()) + { + buf.Append(" crlEntryExtensions:").Append(nl); + + do + { + DerObjectIdentifier oid = (DerObjectIdentifier)e.Current; + X509Extension ext = extensions.GetExtension(oid); + + if (ext.Value != null) + { + Asn1Object obj = Asn1Object.FromByteArray(ext.Value.GetOctets()); + + buf.Append(" critical(") + .Append(ext.IsCritical) + .Append(") "); + try + { + if (oid.Equals(X509Extensions.ReasonCode)) + { + buf.Append(new CrlReason(DerEnumerated.GetInstance(obj))); + } + else if (oid.Equals(X509Extensions.CertificateIssuer)) + { + buf.Append("Certificate issuer: ").Append( + GeneralNames.GetInstance((Asn1Sequence)obj)); + } + else + { + buf.Append(oid.Id); + buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj)); + } + buf.Append(nl); + } + catch (Exception) + { + buf.Append(oid.Id); + buf.Append(" value = ").Append("*****").Append(nl); + } + } + else + { + buf.Append(nl); + } + } + while (e.MoveNext()); + } + } + + return buf.ToString(); + } + } +} diff --git a/crypto/src/x509/X509CrlParser.cs b/crypto/src/x509/X509CrlParser.cs new file mode 100644 index 000000000..d830bb9a6 --- /dev/null +++ b/crypto/src/x509/X509CrlParser.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.X509 +{ + public class X509CrlParser + { + private static readonly PemParser PemCrlParser = new PemParser("CRL"); + + private readonly bool lazyAsn1; + + private Asn1Set sCrlData; + private int sCrlDataObjectCount; + private Stream currentCrlStream; + + public X509CrlParser() + : this(false) + { + } + + public X509CrlParser( + bool lazyAsn1) + { + this.lazyAsn1 = lazyAsn1; + } + + private X509Crl ReadPemCrl( + Stream inStream) + { + Asn1Sequence seq = PemCrlParser.ReadPemObject(inStream); + + return seq == null + ? null + : CreateX509Crl(CertificateList.GetInstance(seq)); + } + + private X509Crl ReadDerCrl( + Asn1InputStream dIn) + { + Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject(); + + if (seq.Count > 1 && seq[0] is DerObjectIdentifier) + { + if (seq[0].Equals(PkcsObjectIdentifiers.SignedData)) + { + sCrlData = SignedData.GetInstance( + Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Crls; + + return GetCrl(); + } + } + + return CreateX509Crl(CertificateList.GetInstance(seq)); + } + + private X509Crl GetCrl() + { + if (sCrlData == null || sCrlDataObjectCount >= sCrlData.Count) + { + return null; + } + + return CreateX509Crl( + CertificateList.GetInstance( + sCrlData[sCrlDataObjectCount++])); + } + + protected virtual X509Crl CreateX509Crl( + CertificateList c) + { + return new X509Crl(c); + } + + /// + /// Create loading data from byte array. + /// + /// + public X509Crl ReadCrl( + byte[] input) + { + return ReadCrl(new MemoryStream(input, false)); + } + + /// + /// Create loading data from byte array. + /// + /// + public ICollection ReadCrls( + byte[] input) + { + return ReadCrls(new MemoryStream(input, false)); + } + + /** + * Generates a certificate revocation list (CRL) object and initializes + * it with the data read from the input stream inStream. + */ + public X509Crl ReadCrl( + Stream inStream) + { + if (inStream == null) + throw new ArgumentNullException("inStream"); + if (!inStream.CanRead) + throw new ArgumentException("inStream must be read-able", "inStream"); + + if (currentCrlStream == null) + { + currentCrlStream = inStream; + sCrlData = null; + sCrlDataObjectCount = 0; + } + else if (currentCrlStream != inStream) // reset if input stream has changed + { + currentCrlStream = inStream; + sCrlData = null; + sCrlDataObjectCount = 0; + } + + try + { + if (sCrlData != null) + { + if (sCrlDataObjectCount != sCrlData.Count) + { + return GetCrl(); + } + + sCrlData = null; + sCrlDataObjectCount = 0; + return null; + } + + PushbackStream pis = new PushbackStream(inStream); + int tag = pis.ReadByte(); + + if (tag < 0) + return null; + + pis.Unread(tag); + + if (tag != 0x30) // assume ascii PEM encoded. + { + return ReadPemCrl(pis); + } + + Asn1InputStream asn1 = lazyAsn1 + ? new LazyAsn1InputStream(pis) + : new Asn1InputStream(pis); + + return ReadDerCrl(asn1); + } + catch (CrlException e) + { + throw e; + } + catch (Exception e) + { + throw new CrlException(e.ToString()); + } + } + + /** + * Returns a (possibly empty) collection view of the CRLs read from + * the given input stream inStream. + * + * The inStream may contain a sequence of DER-encoded CRLs, or + * a PKCS#7 CRL set. This is a PKCS#7 SignedData object, with the + * only significant field being crls. In particular the signature + * and the contents are ignored. + */ + public ICollection ReadCrls( + Stream inStream) + { + X509Crl crl; + IList crls = Platform.CreateArrayList(); + + while ((crl = ReadCrl(inStream)) != null) + { + crls.Add(crl); + } + + return crls; + } + } +} diff --git a/crypto/src/x509/X509ExtensionBase.cs b/crypto/src/x509/X509ExtensionBase.cs new file mode 100644 index 000000000..aaf6695c0 --- /dev/null +++ b/crypto/src/x509/X509ExtensionBase.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.X509 +{ + public abstract class X509ExtensionBase + : IX509Extension + { + protected abstract X509Extensions GetX509Extensions(); + + protected virtual ISet GetExtensionOids( + bool critical) + { + X509Extensions extensions = GetX509Extensions(); + if (extensions != null) + { + HashSet set = new HashSet(); + foreach (DerObjectIdentifier oid in extensions.ExtensionOids) + { + X509Extension ext = extensions.GetExtension(oid); + if (ext.IsCritical == critical) + { + set.Add(oid.Id); + } + } + + return set; + } + + return null; + } + + /// + /// Get non critical extensions. + /// + /// A set of non critical extension oids. + public virtual ISet GetNonCriticalExtensionOids() + { + return GetExtensionOids(false); + } + + /// + /// Get any critical extensions. + /// + /// A sorted list of critical entension. + public virtual ISet GetCriticalExtensionOids() + { + return GetExtensionOids(true); + } + + /// + /// Get the value of a given extension. + /// + /// The object ID of the extension. + /// An Asn1OctetString object if that extension is found or null if not. + [Obsolete("Use version taking a DerObjectIdentifier instead")] + public Asn1OctetString GetExtensionValue( + string oid) + { + return GetExtensionValue(new DerObjectIdentifier(oid)); + } + + public virtual Asn1OctetString GetExtensionValue( + DerObjectIdentifier oid) + { + X509Extensions exts = GetX509Extensions(); + if (exts != null) + { + X509Extension ext = exts.GetExtension(oid); + if (ext != null) + { + return ext.Value; + } + } + + return null; + } + } +} diff --git a/crypto/src/x509/X509KeyUsage.cs b/crypto/src/x509/X509KeyUsage.cs new file mode 100644 index 000000000..e0a7b4939 --- /dev/null +++ b/crypto/src/x509/X509KeyUsage.cs @@ -0,0 +1,59 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.X509 +{ + /** + * A holding class for constructing an X509 Key Usage extension. + * + *
    +	 *    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) }
    +	 * 
    + */ + public class X509KeyUsage + : Asn1Encodable + { + public const int DigitalSignature = 1 << 7; + public const int NonRepudiation = 1 << 6; + public const int KeyEncipherment = 1 << 5; + public const int DataEncipherment = 1 << 4; + public const int KeyAgreement = 1 << 3; + public const int KeyCertSign = 1 << 2; + public const int CrlSign = 1 << 1; + public const int EncipherOnly = 1 << 0; + public const int DecipherOnly = 1 << 15; + + private readonly int usage; + + /** + * Basic constructor. + * + * @param usage - the bitwise OR of the Key Usage flags giving the + * allowed uses for the key. + * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment) + */ + public X509KeyUsage( + int usage) + { + this.usage = usage; + } + + public override Asn1Object ToAsn1Object() + { + return new KeyUsage(usage); + } + } +} diff --git a/crypto/src/x509/X509SignatureUtil.cs b/crypto/src/x509/X509SignatureUtil.cs new file mode 100644 index 000000000..7a4ab1448 --- /dev/null +++ b/crypto/src/x509/X509SignatureUtil.cs @@ -0,0 +1,128 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.X509 +{ + internal class X509SignatureUtilities + { + private static readonly Asn1Null derNull = DerNull.Instance; + + internal static void SetSignatureParameters( + ISigner signature, + Asn1Encodable parameters) + { + if (parameters != null && !derNull.Equals(parameters)) + { + // TODO Put back in +// AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm()); +// +// try +// { +// sigParams.Init(parameters.ToAsn1Object().GetDerEncoded()); +// } +// catch (IOException e) +// { +// throw new SignatureException("IOException decoding parameters: " + e.Message); +// } +// +// if (signature.getAlgorithm().EndsWith("MGF1")) +// { +// try +// { +// signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class)); +// } +// catch (GeneralSecurityException e) +// { +// throw new SignatureException("Exception extracting parameters: " + e.Message); +// } +// } + } + } + + internal static string GetSignatureName( + AlgorithmIdentifier sigAlgId) + { + Asn1Encodable parameters = sigAlgId.Parameters; + + if (parameters != null && !derNull.Equals(parameters)) + { + if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss)) + { + RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters); + + return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1"; + } + if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2)) + { + Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters); + + return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA"; + } + } + + return sigAlgId.ObjectID.Id; + } + + /** + * Return the digest algorithm using one of the standard JCA string + * representations rather than the algorithm identifier (if possible). + */ + private static string GetDigestAlgName( + DerObjectIdentifier digestAlgOID) + { + if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID)) + { + return "MD5"; + } + else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID)) + { + return "SHA1"; + } + else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID)) + { + return "SHA224"; + } + else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID)) + { + return "SHA256"; + } + else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID)) + { + return "SHA384"; + } + else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID)) + { + return "SHA512"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID)) + { + return "RIPEMD128"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID)) + { + return "RIPEMD160"; + } + else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID)) + { + return "RIPEMD256"; + } + else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID)) + { + return "GOST3411"; + } + else + { + return digestAlgOID.Id; + } + } + } +} diff --git a/crypto/src/x509/X509Utilities.cs b/crypto/src/x509/X509Utilities.cs new file mode 100644 index 000000000..52a122c21 --- /dev/null +++ b/crypto/src/x509/X509Utilities.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.X509 +{ + internal class X509Utilities + { + private static readonly IDictionary algorithms = Platform.CreateHashtable(); + private static readonly IDictionary exParams = Platform.CreateHashtable(); + private static readonly ISet noParams = new HashSet(); + + static X509Utilities() + { + algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption); + algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption); + algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption); + algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption); + algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption); + algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption); + algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption); + algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption); + algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption); + algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption); + algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss); + algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160); + algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128); + algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256); + algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1); + algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1); + algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224); + algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256); + algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384); + algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512); + algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1); + algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + + // + // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. + // The parameters field SHALL be NULL for RSA based signature algorithms. + // + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384); + noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512); + noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1); + noParams.Add(NistObjectIdentifiers.DsaWithSha224); + noParams.Add(NistObjectIdentifiers.DsaWithSha256); + noParams.Add(NistObjectIdentifiers.DsaWithSha384); + noParams.Add(NistObjectIdentifiers.DsaWithSha512); + + // + // RFC 4491 + // + noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94); + noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001); + + // + // explicit params + // + AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); + exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20)); + + AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance); + exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28)); + + AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance); + exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32)); + + AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance); + exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48)); + + AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance); + exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64)); + } + + private static RsassaPssParameters CreatePssParams( + AlgorithmIdentifier hashAlgId, + int saltSize) + { + return new RsassaPssParameters( + hashAlgId, + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId), + new DerInteger(saltSize), + new DerInteger(1)); + } + + internal static DerObjectIdentifier GetAlgorithmOid( + string algorithmName) + { + algorithmName = Platform.ToUpperInvariant(algorithmName); + + if (algorithms.Contains(algorithmName)) + { + return (DerObjectIdentifier) algorithms[algorithmName]; + } + + return new DerObjectIdentifier(algorithmName); + } + + internal static AlgorithmIdentifier GetSigAlgID( + DerObjectIdentifier sigOid, + string algorithmName) + { + if (noParams.Contains(sigOid)) + { + return new AlgorithmIdentifier(sigOid); + } + + algorithmName = Platform.ToUpperInvariant(algorithmName); + + if (exParams.Contains(algorithmName)) + { + return new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]); + } + + return new AlgorithmIdentifier(sigOid, DerNull.Instance); + } + + internal static IEnumerable GetAlgNames() + { + return new EnumerableProxy(algorithms.Keys); + } + + internal static byte[] GetSignatureForObject( + DerObjectIdentifier sigOid, // TODO Redundant now? + string sigName, + AsymmetricKeyParameter privateKey, + SecureRandom random, + Asn1Encodable ae) + { + if (sigOid == null) + throw new ArgumentNullException("sigOid"); + + ISigner sig = SignerUtilities.GetSigner(sigName); + + if (random != null) + { + sig.Init(true, new ParametersWithRandom(privateKey, random)); + } + else + { + sig.Init(true, privateKey); + } + + byte[] encoded = ae.GetDerEncoded(); + sig.BlockUpdate(encoded, 0, encoded.Length); + + return sig.GenerateSignature(); + } + } +} diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs new file mode 100644 index 000000000..02b58a198 --- /dev/null +++ b/crypto/src/x509/X509V1CertificateGenerator.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; + +namespace Org.BouncyCastle.X509 +{ + /// + /// Class to Generate X509V1 Certificates. + /// + public class X509V1CertificateGenerator + { + private V1TbsCertificateGenerator tbsGen; + private DerObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private string signatureAlgorithm; + + /// + /// Default Constructor. + /// + public X509V1CertificateGenerator() + { + tbsGen = new V1TbsCertificateGenerator(); + } + + /// + /// Reset the generator. + /// + public void Reset() + { + tbsGen = new V1TbsCertificateGenerator(); + } + + /// + /// Set the certificate's serial number. + /// + /// Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data. + /// You will be surprised how ugly a serial number collision can get. + /// The serial number. + public void SetSerialNumber( + BigInteger serialNumber) + { + if (serialNumber.SignValue <= 0) + { + throw new ArgumentException("serial number must be a positive integer", "serialNumber"); + } + + tbsGen.SetSerialNumber(new DerInteger(serialNumber)); + } + + /// + /// Set the issuer distinguished name. + /// The issuer is the entity whose private key is used to sign the certificate. + /// + /// The issuers DN. + public void SetIssuerDN( + X509Name issuer) + { + tbsGen.SetIssuer(issuer); + } + + /// + /// Set the date that this certificate is to be valid from. + /// + /// + public void SetNotBefore( + DateTime date) + { + tbsGen.SetStartDate(new Time(date)); + } + + /// + /// Set the date after which this certificate will no longer be valid. + /// + /// + public void SetNotAfter( + DateTime date) + { + tbsGen.SetEndDate(new Time(date)); + } + + /// + /// Set the subject distinguished name. + /// The subject describes the entity associated with the public key. + /// + /// + public void SetSubjectDN( + X509Name subject) + { + tbsGen.SetSubject(subject); + } + + /// + /// Set the public key that this certificate identifies. + /// + /// + public void SetPublicKey( + AsymmetricKeyParameter publicKey) + { + try + { + tbsGen.SetSubjectPublicKeyInfo( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey)); + } + catch (Exception e) + { + throw new ArgumentException("unable to process key - " + e.ToString()); + } + } + + /// + /// Set the signature algorithm that will be used to sign this certificate. + /// This can be either a name or an OID, names are treated as case insensitive. + /// + /// string representation of the algorithm name + public void SetSignatureAlgorithm( + string signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm); + } + catch (Exception) + { + throw new ArgumentException("Unknown signature type requested", "signatureAlgorithm"); + } + + sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm); + + tbsGen.SetSignature(sigAlgId); + } + + /// + /// Generate a new X509Certificate. + /// + /// The private key of the issuer used to sign this certificate. + /// An X509Certificate. + public X509Certificate Generate( + AsymmetricKeyParameter privateKey) + { + return Generate(privateKey, null); + } + + /// + /// Generate a new X509Certificate specifying a SecureRandom instance that you would like to use. + /// + /// The private key of the issuer used to sign this certificate. + /// The Secure Random you want to use. + /// An X509Certificate. + public X509Certificate Generate( + AsymmetricKeyParameter privateKey, + SecureRandom random) + { + TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate(); + byte[] signature; + + try + { + signature = X509Utilities.GetSignatureForObject( + sigOID, signatureAlgorithm, privateKey, random, tbsCert); + } + catch (Exception e) + { + // TODO +// throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + throw new CertificateEncodingException("exception encoding TBS cert", e); + } + + try + { + return GenerateJcaObject(tbsCert, signature); + } + catch (CertificateParsingException e) + { + // TODO + // throw new ExtCertificateEncodingException("exception producing certificate object", e); + throw new CertificateEncodingException("exception producing certificate object", e); + } + } + + private X509Certificate GenerateJcaObject( + TbsCertificateStructure tbsCert, + byte[] signature) + { + return new X509Certificate( + new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature))); + } + + /// + /// Allows enumeration of the signature names supported by the generator. + /// + public IEnumerable SignatureAlgNames + { + get { return X509Utilities.GetAlgNames(); } + } + } +} diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs new file mode 100644 index 000000000..117ac4cc2 --- /dev/null +++ b/crypto/src/x509/X509V2AttributeCertificate.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509 +{ + /// An implementation of a version 2 X.509 Attribute Certificate. + public class X509V2AttributeCertificate + : X509ExtensionBase, IX509AttributeCertificate + { + private readonly AttributeCertificate cert; + private readonly DateTime notBefore; + private readonly DateTime notAfter; + + private static AttributeCertificate GetObject(Stream input) + { + try + { + return AttributeCertificate.GetInstance(Asn1Object.FromStream(input)); + } + catch (IOException e) + { + throw e; + } + catch (Exception e) + { + throw new IOException("exception decoding certificate structure", e); + } + } + + public X509V2AttributeCertificate( + Stream encIn) + : this(GetObject(encIn)) + { + } + + public X509V2AttributeCertificate( + byte[] encoded) + : this(new MemoryStream(encoded, false)) + { + } + + internal X509V2AttributeCertificate( + AttributeCertificate cert) + { + this.cert = cert; + + try + { + this.notAfter = cert.ACInfo.AttrCertValidityPeriod.NotAfterTime.ToDateTime(); + this.notBefore = cert.ACInfo.AttrCertValidityPeriod.NotBeforeTime.ToDateTime(); + } + catch (Exception e) + { + throw new IOException("invalid data structure in certificate!", e); + } + } + + public virtual int Version + { + get { return cert.ACInfo.Version.Value.IntValue + 1; } + } + + public virtual BigInteger SerialNumber + { + get { return cert.ACInfo.SerialNumber.Value; } + } + + public virtual AttributeCertificateHolder Holder + { + get + { + return new AttributeCertificateHolder((Asn1Sequence)cert.ACInfo.Holder.ToAsn1Object()); + } + } + + public virtual AttributeCertificateIssuer Issuer + { + get + { + return new AttributeCertificateIssuer(cert.ACInfo.Issuer); + } + } + + public virtual DateTime NotBefore + { + get { return notBefore; } + } + + public virtual DateTime NotAfter + { + get { return notAfter; } + } + + public virtual bool[] GetIssuerUniqueID() + { + DerBitString id = cert.ACInfo.IssuerUniqueID; + + if (id != null) + { + byte[] bytes = id.GetBytes(); + bool[] boolId = new bool[bytes.Length * 8 - id.PadBits]; + + for (int i = 0; i != boolId.Length; i++) + { + //boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; + boolId[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0; + } + + return boolId; + } + + return null; + } + + public virtual bool IsValidNow + { + get { return IsValid(DateTime.UtcNow); } + } + + public virtual bool IsValid( + DateTime date) + { + return date.CompareTo(NotBefore) >= 0 && date.CompareTo(NotAfter) <= 0; + } + + public virtual void CheckValidity() + { + this.CheckValidity(DateTime.UtcNow); + } + + public virtual void CheckValidity( + DateTime date) + { + if (date.CompareTo(NotAfter) > 0) + throw new CertificateExpiredException("certificate expired on " + NotAfter); + if (date.CompareTo(NotBefore) < 0) + throw new CertificateNotYetValidException("certificate not valid until " + NotBefore); + } + + public virtual byte[] GetSignature() + { + return cert.SignatureValue.GetBytes(); + } + + public virtual void Verify( + AsymmetricKeyParameter publicKey) + { + if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature)) + { + throw new CertificateException("Signature algorithm in certificate info not same as outer certificate"); + } + + ISigner signature = SignerUtilities.GetSigner(cert.SignatureAlgorithm.ObjectID.Id); + + signature.Init(false, publicKey); + + try + { + byte[] b = cert.ACInfo.GetEncoded(); + signature.BlockUpdate(b, 0, b.Length); + } + catch (IOException e) + { + throw new SignatureException("Exception encoding certificate info object", e); + } + + if (!signature.VerifySignature(this.GetSignature())) + { + throw new InvalidKeyException("Public key presented not for certificate signature"); + } + } + + public virtual byte[] GetEncoded() + { + return cert.GetEncoded(); + } + + protected override X509Extensions GetX509Extensions() + { + return cert.ACInfo.Extensions; + } + + public virtual X509Attribute[] GetAttributes() + { + Asn1Sequence seq = cert.ACInfo.Attributes; + X509Attribute[] attrs = new X509Attribute[seq.Count]; + + for (int i = 0; i != seq.Count; i++) + { + attrs[i] = new X509Attribute((Asn1Encodable)seq[i]); + } + + return attrs; + } + + public virtual X509Attribute[] GetAttributes( + string oid) + { + Asn1Sequence seq = cert.ACInfo.Attributes; + IList list = Platform.CreateArrayList(); + + for (int i = 0; i != seq.Count; i++) + { + X509Attribute attr = new X509Attribute((Asn1Encodable)seq[i]); + if (attr.Oid.Equals(oid)) + { + list.Add(attr); + } + } + + if (list.Count < 1) + { + return null; + } + + X509Attribute[] result = new X509Attribute[list.Count]; + for (int i = 0; i < list.Count; ++i) + { + result[i] = (X509Attribute)list[i]; + } + return result; + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + X509V2AttributeCertificate other = obj as X509V2AttributeCertificate; + + if (other == null) + return false; + + return cert.Equals(other.cert); + + // NB: May prefer this implementation of Equals if more than one certificate implementation in play + //return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded()); + } + + public override int GetHashCode() + { + return cert.GetHashCode(); + } + } +} diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs new file mode 100644 index 000000000..a683d5e20 --- /dev/null +++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509 +{ + /// Class to produce an X.509 Version 2 AttributeCertificate. + public class X509V2AttributeCertificateGenerator + { + private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator(); + + private V2AttributeCertificateInfoGenerator acInfoGen; + private DerObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private string signatureAlgorithm; + + public X509V2AttributeCertificateGenerator() + { + acInfoGen = new V2AttributeCertificateInfoGenerator(); + } + + /// Reset the generator + public void Reset() + { + acInfoGen = new V2AttributeCertificateInfoGenerator(); + extGenerator.Reset(); + } + + /// Set the Holder of this Attribute Certificate. + public void SetHolder( + AttributeCertificateHolder holder) + { + acInfoGen.SetHolder(holder.holder); + } + + /// Set the issuer. + public void SetIssuer( + AttributeCertificateIssuer issuer) + { + acInfoGen.SetIssuer(AttCertIssuer.GetInstance(issuer.form)); + } + + /// Set the serial number for the certificate. + public void SetSerialNumber( + BigInteger serialNumber) + { + acInfoGen.SetSerialNumber(new DerInteger(serialNumber)); + } + + public void SetNotBefore( + DateTime date) + { + acInfoGen.SetStartDate(new DerGeneralizedTime(date)); + } + + public void SetNotAfter( + DateTime date) + { + acInfoGen.SetEndDate(new DerGeneralizedTime(date)); + } + + /// + /// Set the signature algorithm. This can be either a name or an OID, names + /// are treated as case insensitive. + /// + /// The algorithm name. + public void SetSignatureAlgorithm( + string signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm); + } + catch (Exception) + { + throw new ArgumentException("Unknown signature type requested"); + } + + sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm); + + acInfoGen.SetSignature(sigAlgId); + } + + /// Add an attribute. + public void AddAttribute( + X509Attribute attribute) + { + acInfoGen.AddAttribute(AttributeX509.GetInstance(attribute.ToAsn1Object())); + } + + public void SetIssuerUniqueId( + bool[] iui) + { + // TODO convert bool array to bit string + //acInfoGen.SetIssuerUniqueID(iui); + throw Platform.CreateNotImplementedException("SetIssuerUniqueId()"); + } + + /// Add a given extension field for the standard extensions tag. + public void AddExtension( + string oid, + bool critical, + Asn1Encodable extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); + } + + /// + /// Add a given extension field for the standard extensions tag. + /// The value parameter becomes the contents of the octet string associated + /// with the extension. + /// + public void AddExtension( + string oid, + bool critical, + byte[] extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); + } + + /// + /// Generate an X509 certificate, based on the current issuer and subject. + /// + public IX509AttributeCertificate Generate( + AsymmetricKeyParameter publicKey) + { + return Generate(publicKey, null); + } + + /// + /// Generate an X509 certificate, based on the current issuer and subject, + /// using the supplied source of randomness, if required. + /// + public IX509AttributeCertificate Generate( + AsymmetricKeyParameter publicKey, + SecureRandom random) + { + if (!extGenerator.IsEmpty) + { + acInfoGen.SetExtensions(extGenerator.Generate()); + } + + AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo(); + + Asn1EncodableVector v = new Asn1EncodableVector(); + + v.Add(acInfo, sigAlgId); + + try + { + v.Add(new DerBitString(X509Utilities.GetSignatureForObject(sigOID, signatureAlgorithm, publicKey, random, acInfo))); + + return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(new DerSequence(v))); + } + catch (Exception e) + { + // TODO +// throw new ExtCertificateEncodingException("constructed invalid certificate", e); + throw new CertificateEncodingException("constructed invalid certificate", e); + } + } + + /// + /// Allows enumeration of the signature names supported by the generator. + /// + public IEnumerable SignatureAlgNames + { + get { return X509Utilities.GetAlgNames(); } + } + } +} diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs new file mode 100644 index 000000000..a2293b333 --- /dev/null +++ b/crypto/src/x509/X509V2CRLGenerator.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Collections; + +namespace Org.BouncyCastle.X509 +{ + /** + * class to produce an X.509 Version 2 CRL. + */ + public class X509V2CrlGenerator + { + private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator(); + + private V2TbsCertListGenerator tbsGen; + private DerObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private string signatureAlgorithm; + + public X509V2CrlGenerator() + { + tbsGen = new V2TbsCertListGenerator(); + } + + /** + * reset the generator + */ + public void Reset() + { + tbsGen = new V2TbsCertListGenerator(); + extGenerator.Reset(); + } + + /** + * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the + * certificate. + */ + public void SetIssuerDN( + X509Name issuer) + { + tbsGen.SetIssuer(issuer); + } + + public void SetThisUpdate( + DateTime date) + { + tbsGen.SetThisUpdate(new Time(date)); + } + + public void SetNextUpdate( + DateTime date) + { + tbsGen.SetNextUpdate(new Time(date)); + } + + /** + * Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise + * or 0 if CrlReason is not to be used + **/ + public void AddCrlEntry( + BigInteger userCertificate, + DateTime revocationDate, + int reason) + { + tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason); + } + + /** + * Add a CRL entry with an Invalidity Date extension as well as a CrlReason extension. + * Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise + * or 0 if CrlReason is not to be used + **/ + public void AddCrlEntry( + BigInteger userCertificate, + DateTime revocationDate, + int reason, + DateTime invalidityDate) + { + tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason, new DerGeneralizedTime(invalidityDate)); + } + + /** + * Add a CRL entry with extensions. + **/ + public void AddCrlEntry( + BigInteger userCertificate, + DateTime revocationDate, + X509Extensions extensions) + { + tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), extensions); + } + + /** + * Add the CRLEntry objects contained in a previous CRL. + * + * @param other the X509Crl to source the other entries from. + */ + public void AddCrl( + X509Crl other) + { + if (other == null) + throw new ArgumentNullException("other"); + + ISet revocations = other.GetRevokedCertificates(); + + if (revocations != null) + { + foreach (X509CrlEntry entry in revocations) + { + try + { + tbsGen.AddCrlEntry( + Asn1Sequence.GetInstance( + Asn1Object.FromByteArray(entry.GetEncoded()))); + } + catch (IOException e) + { + throw new CrlException("exception processing encoding of CRL", e); + } + } + } + } + + /** + * Set the signature algorithm. This can be either a name or an oid, names + * are treated as case insensitive. + * + * @param signatureAlgorithm string representation of the algorithm name. + */ + public void SetSignatureAlgorithm( + string signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm); + } + catch (Exception e) + { + throw new ArgumentException("Unknown signature type requested", e); + } + + sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm); + + tbsGen.SetSignature(sigAlgId); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void AddExtension( + string oid, + bool critical, + Asn1Encodable extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + Asn1Encodable extensionValue) + { + extGenerator.AddExtension(oid, critical, extensionValue); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void AddExtension( + string oid, + bool critical, + byte[] extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue)); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + byte[] extensionValue) + { + extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue)); + } + + /// Generate an X509 CRL, based on the current issuer and subject. + /// The key used for signing. + public X509Crl Generate( + AsymmetricKeyParameter privateKey) + { + return Generate(privateKey, null); + } + + /// Generate an X509 CRL, based on the current issuer and subject. + /// The key used for signing. + /// A user-defined source of randomness. + public X509Crl Generate( + AsymmetricKeyParameter privateKey, + SecureRandom random) + { + TbsCertificateList tbsCrl = GenerateCertList(); + byte[] signature; + + try + { + signature = X509Utilities.GetSignatureForObject( + sigOID, signatureAlgorithm, privateKey, random, tbsCrl); + } + catch (IOException e) + { + // TODO +// throw new ExtCrlException("cannot generate CRL encoding", e); + throw new CrlException("cannot generate CRL encoding", e); + } + + return GenerateJcaObject(tbsCrl, signature); + } + + private TbsCertificateList GenerateCertList() + { + if (!extGenerator.IsEmpty) + { + tbsGen.SetExtensions(extGenerator.Generate()); + } + + return tbsGen.GenerateTbsCertList(); + } + + private X509Crl GenerateJcaObject( + TbsCertificateList tbsCrl, + byte[] signature) + { + return new X509Crl( + CertificateList.GetInstance( + new DerSequence(tbsCrl, sigAlgId, new DerBitString(signature)))); + } + + /// + /// Allows enumeration of the signature names supported by the generator. + /// + public IEnumerable SignatureAlgNames + { + get { return X509Utilities.GetAlgNames(); } + } + } +} diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs new file mode 100644 index 000000000..bb0dd9cbc --- /dev/null +++ b/crypto/src/x509/X509V3CertificateGenerator.cs @@ -0,0 +1,346 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509 +{ + /// + /// A class to Generate Version 3 X509Certificates. + /// + public class X509V3CertificateGenerator + { + private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator(); + + private V3TbsCertificateGenerator tbsGen; + private DerObjectIdentifier sigOid; + private AlgorithmIdentifier sigAlgId; + private string signatureAlgorithm; + + public X509V3CertificateGenerator() + { + tbsGen = new V3TbsCertificateGenerator(); + } + + /// + /// Reset the Generator. + /// + public void Reset() + { + tbsGen = new V3TbsCertificateGenerator(); + extGenerator.Reset(); + } + + /// + /// Set the certificate's serial number. + /// + /// Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data. + /// You will be surprised how ugly a serial number collision can Get. + /// The serial number. + public void SetSerialNumber( + BigInteger serialNumber) + { + if (serialNumber.SignValue <= 0) + { + throw new ArgumentException("serial number must be a positive integer", "serialNumber"); + } + + tbsGen.SetSerialNumber(new DerInteger(serialNumber)); + } + + /// + /// Set the distinguished name of the issuer. + /// The issuer is the entity which is signing the certificate. + /// + /// The issuer's DN. + public void SetIssuerDN( + X509Name issuer) + { + tbsGen.SetIssuer(issuer); + } + + /// + /// Set the date that this certificate is to be valid from. + /// + /// + public void SetNotBefore( + DateTime date) + { + tbsGen.SetStartDate(new Time(date)); + } + + /// + /// Set the date after which this certificate will no longer be valid. + /// + /// + public void SetNotAfter( + DateTime date) + { + tbsGen.SetEndDate(new Time(date)); + } + + /// + /// Set the DN of the entity that this certificate is about. + /// + /// + public void SetSubjectDN( + X509Name subject) + { + tbsGen.SetSubject(subject); + } + + /// + /// Set the public key that this certificate identifies. + /// + /// + public void SetPublicKey( + AsymmetricKeyParameter publicKey) + { + tbsGen.SetSubjectPublicKeyInfo(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey)); + } + + /// + /// Set the signature algorithm that will be used to sign this certificate. + /// + /// + public void SetSignatureAlgorithm( + string signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOid = X509Utilities.GetAlgorithmOid(signatureAlgorithm); + } + catch (Exception) + { + throw new ArgumentException("Unknown signature type requested: " + signatureAlgorithm); + } + + sigAlgId = X509Utilities.GetSigAlgID(sigOid, signatureAlgorithm); + + tbsGen.SetSignature(sigAlgId); + } + + /// + /// Set the subject unique ID - note: it is very rare that it is correct to do this. + /// + /// + public void SetSubjectUniqueID( + bool[] uniqueID) + { + tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID)); + } + + /// + /// Set the issuer unique ID - note: it is very rare that it is correct to do this. + /// + /// + public void SetIssuerUniqueID( + bool[] uniqueID) + { + tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID)); + } + + private DerBitString booleanToBitString( + bool[] id) + { + byte[] bytes = new byte[(id.Length + 7) / 8]; + + for (int i = 0; i != id.Length; i++) + { + if (id[i]) + { + bytes[i / 8] |= (byte)(1 << ((7 - (i % 8)))); + } + } + + int pad = id.Length % 8; + + if (pad == 0) + { + return new DerBitString(bytes); + } + + return new DerBitString(bytes, 8 - pad); + } + + /// + /// Add a given extension field for the standard extensions tag (tag 3). + /// + /// string containing a dotted decimal Object Identifier. + /// Is it critical. + /// The value. + public void AddExtension( + string oid, + bool critical, + Asn1Encodable extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); + } + + /// + /// Add an extension to this certificate. + /// + /// Its Object Identifier. + /// Is it critical. + /// The value. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + Asn1Encodable extensionValue) + { + extGenerator.AddExtension(oid, critical, extensionValue); + } + + /// + /// Add an extension using a string with a dotted decimal OID. + /// + /// string containing a dotted decimal Object Identifier. + /// Is it critical. + /// byte[] containing the value of this extension. + public void AddExtension( + string oid, + bool critical, + byte[] extensionValue) + { + extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue)); + } + + /// + /// Add an extension to this certificate. + /// + /// Its Object Identifier. + /// Is it critical. + /// byte[] containing the value of this extension. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + byte[] extensionValue) + { + extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue)); + } + + /// + /// Add a given extension field for the standard extensions tag (tag 3), + /// copying the extension value from another certificate. + /// + public void CopyAndAddExtension( + string oid, + bool critical, + X509Certificate cert) + { + CopyAndAddExtension(new DerObjectIdentifier(oid), critical, cert); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * copying the extension value from another certificate. + * @throws CertificateParsingException if the extension cannot be extracted. + */ + public void CopyAndAddExtension( + DerObjectIdentifier oid, + bool critical, + X509Certificate cert) + { + Asn1OctetString extValue = cert.GetExtensionValue(oid); + + if (extValue == null) + { + throw new CertificateParsingException("extension " + oid + " not present"); + } + + try + { + Asn1Encodable value = X509ExtensionUtilities.FromExtensionValue(extValue); + + this.AddExtension(oid, critical, value); + } + catch (Exception e) + { + throw new CertificateParsingException(e.Message, e); + } + } + + /// + /// Generate an X509Certificate. + /// + /// The private key of the issuer that is signing this certificate. + /// An X509Certificate. + public X509Certificate Generate( + AsymmetricKeyParameter privateKey) + { + return Generate(privateKey, null); + } + + /// + /// Generate an X509Certificate using your own SecureRandom. + /// + /// The private key of the issuer that is signing this certificate. + /// You Secure Random instance. + /// An X509Certificate. + public X509Certificate Generate( + AsymmetricKeyParameter privateKey, + SecureRandom random) + { + TbsCertificateStructure tbsCert = GenerateTbsCert(); + byte[] signature; + + try + { + signature = X509Utilities.GetSignatureForObject( + sigOid, signatureAlgorithm, privateKey, random, tbsCert); + } + catch (Exception e) + { + // TODO +// throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + throw new CertificateEncodingException("exception encoding TBS cert", e); + } + + try + { + return GenerateJcaObject(tbsCert, signature); + } + catch (CertificateParsingException e) + { + // TODO + // throw new ExtCertificateEncodingException("exception producing certificate object", e); + throw new CertificateEncodingException("exception producing certificate object", e); + } + } + + private TbsCertificateStructure GenerateTbsCert() + { + if (!extGenerator.IsEmpty) + { + tbsGen.SetExtensions(extGenerator.Generate()); + } + + return tbsGen.GenerateTbsCertificate(); + } + + private X509Certificate GenerateJcaObject( + TbsCertificateStructure tbsCert, + byte[] signature) + { + return new X509Certificate( + new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature))); + } + + /// + /// Allows enumeration of the signature names supported by the generator. + /// + public IEnumerable SignatureAlgNames + { + get { return X509Utilities.GetAlgNames(); } + } + } +} diff --git a/crypto/src/x509/extension/AuthorityKeyIdentifierStructure.cs b/crypto/src/x509/extension/AuthorityKeyIdentifierStructure.cs new file mode 100644 index 000000000..006dc009b --- /dev/null +++ b/crypto/src/x509/extension/AuthorityKeyIdentifierStructure.cs @@ -0,0 +1,102 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; + +namespace Org.BouncyCastle.X509.Extension +{ + /// A high level authority key identifier. + public class AuthorityKeyIdentifierStructure + : AuthorityKeyIdentifier + { + /** + * Constructor which will take the byte[] returned from getExtensionValue() + * + * @param encodedValue a DER octet encoded string with the extension structure in it. + * @throws IOException on parsing errors. + */ + // TODO Add a functional constructor from byte[]? + public AuthorityKeyIdentifierStructure( + Asn1OctetString encodedValue) + : base((Asn1Sequence) X509ExtensionUtilities.FromExtensionValue(encodedValue)) + { + } + + private static Asn1Sequence FromCertificate( + X509Certificate certificate) + { + try + { + GeneralName genName = new GeneralName( + PrincipalUtilities.GetIssuerX509Principal(certificate)); + + if (certificate.Version == 3) + { + Asn1OctetString ext = certificate.GetExtensionValue(X509Extensions.SubjectKeyIdentifier); + + if (ext != null) + { + Asn1OctetString str = (Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(ext); + + return (Asn1Sequence) new AuthorityKeyIdentifier( + str.GetOctets(), new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object(); + } + } + + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( + certificate.GetPublicKey()); + + return (Asn1Sequence) new AuthorityKeyIdentifier( + info, new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object(); + } + catch (Exception e) + { + throw new CertificateParsingException("Exception extracting certificate details", e); + } + } + + private static Asn1Sequence FromKey( + AsymmetricKeyParameter pubKey) + { + try + { + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey); + + return (Asn1Sequence) new AuthorityKeyIdentifier(info).ToAsn1Object(); + } + catch (Exception e) + { + throw new InvalidKeyException("can't process key: " + e); + } + } + + /** + * Create an AuthorityKeyIdentifier using the passed in certificate's public + * key, issuer and serial number. + * + * @param certificate the certificate providing the information. + * @throws CertificateParsingException if there is a problem processing the certificate + */ + public AuthorityKeyIdentifierStructure( + X509Certificate certificate) + : base(FromCertificate(certificate)) + { + } + + /** + * Create an AuthorityKeyIdentifier using just the hash of the + * public key. + * + * @param pubKey the key to generate the hash from. + * @throws InvalidKeyException if there is a problem using the key. + */ + public AuthorityKeyIdentifierStructure( + AsymmetricKeyParameter pubKey) + : base(FromKey(pubKey)) + { + } + } +} diff --git a/crypto/src/x509/extension/SubjectKeyIdentifierStructure.cs b/crypto/src/x509/extension/SubjectKeyIdentifierStructure.cs new file mode 100644 index 000000000..4c7b79ab8 --- /dev/null +++ b/crypto/src/x509/extension/SubjectKeyIdentifierStructure.cs @@ -0,0 +1,49 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security.Certificates; + +namespace Org.BouncyCastle.X509.Extension +{ + /** + * A high level subject key identifier. + */ + public class SubjectKeyIdentifierStructure + : SubjectKeyIdentifier + { + /** + * Constructor which will take the byte[] returned from getExtensionValue() + * + * @param encodedValue a DER octet encoded string with the extension structure in it. + * @throws IOException on parsing errors. + */ + public SubjectKeyIdentifierStructure( + Asn1OctetString encodedValue) + : base((Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(encodedValue)) + { + } + + private static Asn1OctetString FromPublicKey( + AsymmetricKeyParameter pubKey) + { + try + { + SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey); + + return (Asn1OctetString) new SubjectKeyIdentifier(info).ToAsn1Object(); + } + catch (Exception e) + { + throw new CertificateParsingException("Exception extracting certificate details: " + e.ToString()); + } + } + + public SubjectKeyIdentifierStructure( + AsymmetricKeyParameter pubKey) + : base(FromPublicKey(pubKey)) + { + } + } +} diff --git a/crypto/src/x509/extension/X509ExtensionUtil.cs b/crypto/src/x509/extension/X509ExtensionUtil.cs new file mode 100644 index 000000000..845a87bad --- /dev/null +++ b/crypto/src/x509/extension/X509ExtensionUtil.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509.Extension +{ + public class X509ExtensionUtilities + { + public static Asn1Object FromExtensionValue( + Asn1OctetString extensionValue) + { + return Asn1Object.FromByteArray(extensionValue.GetOctets()); + } + + public static ICollection GetIssuerAlternativeNames( + X509Certificate cert) + { + Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.IssuerAlternativeName); + + return GetAlternativeName(extVal); + } + + public static ICollection GetSubjectAlternativeNames( + X509Certificate cert) + { + Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.SubjectAlternativeName); + + return GetAlternativeName(extVal); + } + + private static ICollection GetAlternativeName( + Asn1OctetString extVal) + { + IList temp = Platform.CreateArrayList(); + + if (extVal != null) + { + try + { + Asn1Sequence seq = DerSequence.GetInstance(FromExtensionValue(extVal)); + + foreach (GeneralName genName in seq) + { + IList list = Platform.CreateArrayList(); + list.Add(genName.TagNo); + + switch (genName.TagNo) + { + case GeneralName.EdiPartyName: + case GeneralName.X400Address: + case GeneralName.OtherName: + list.Add(genName.Name.ToAsn1Object()); + break; + case GeneralName.DirectoryName: + list.Add(X509Name.GetInstance(genName.Name).ToString()); + break; + case GeneralName.DnsName: + case GeneralName.Rfc822Name: + case GeneralName.UniformResourceIdentifier: + list.Add(((IAsn1String)genName.Name).GetString()); + break; + case GeneralName.RegisteredID: + list.Add(DerObjectIdentifier.GetInstance(genName.Name).Id); + break; + case GeneralName.IPAddress: + list.Add(DerOctetString.GetInstance(genName.Name).GetOctets()); + break; + default: + throw new IOException("Bad tag number: " + genName.TagNo); + } + + temp.Add(list); + } + } + catch (Exception e) + { + throw new CertificateParsingException(e.Message); + } + } + + return temp; + } + } +} diff --git a/crypto/src/x509/store/IX509Selector.cs b/crypto/src/x509/store/IX509Selector.cs new file mode 100644 index 000000000..09f6f1849 --- /dev/null +++ b/crypto/src/x509/store/IX509Selector.cs @@ -0,0 +1,15 @@ +using System; + +namespace Org.BouncyCastle.X509.Store +{ + public interface IX509Selector +#if !SILVERLIGHT + : ICloneable +#endif + { +#if SILVERLIGHT + object Clone(); +#endif + bool Match(object obj); + } +} diff --git a/crypto/src/x509/store/IX509Store.cs b/crypto/src/x509/store/IX509Store.cs new file mode 100644 index 000000000..e5c3a462a --- /dev/null +++ b/crypto/src/x509/store/IX509Store.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections; + +namespace Org.BouncyCastle.X509.Store +{ + public interface IX509Store + { +// void Init(IX509StoreParameters parameters); + ICollection GetMatches(IX509Selector selector); + } +} diff --git a/crypto/src/x509/store/IX509StoreParameters.cs b/crypto/src/x509/store/IX509StoreParameters.cs new file mode 100644 index 000000000..aee3036c2 --- /dev/null +++ b/crypto/src/x509/store/IX509StoreParameters.cs @@ -0,0 +1,8 @@ +using System; + +namespace Org.BouncyCastle.X509.Store +{ + public interface IX509StoreParameters + { + } +} diff --git a/crypto/src/x509/store/NoSuchStoreException.cs b/crypto/src/x509/store/NoSuchStoreException.cs new file mode 100644 index 000000000..02c593245 --- /dev/null +++ b/crypto/src/x509/store/NoSuchStoreException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.X509.Store +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class NoSuchStoreException + : X509StoreException + { + public NoSuchStoreException() + { + } + + public NoSuchStoreException( + string message) + : base(message) + { + } + + public NoSuchStoreException( + string message, + Exception e) + : base(message, e) + { + } + } +} diff --git a/crypto/src/x509/store/X509AttrCertStoreSelector.cs b/crypto/src/x509/store/X509AttrCertStoreSelector.cs new file mode 100644 index 000000000..9f1dc20d1 --- /dev/null +++ b/crypto/src/x509/store/X509AttrCertStoreSelector.cs @@ -0,0 +1,376 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509.Store +{ + /** + * This class is an Selector like implementation to select + * attribute certificates from a given set of criteria. + * + * @see org.bouncycastle.x509.X509AttributeCertificate + * @see org.bouncycastle.x509.X509Store + */ + public class X509AttrCertStoreSelector + : IX509Selector + { + // TODO: name constraints??? + + private IX509AttributeCertificate attributeCert; + private DateTimeObject attributeCertificateValid; + private AttributeCertificateHolder holder; + private AttributeCertificateIssuer issuer; + private BigInteger serialNumber; + private ISet targetNames = new HashSet(); + private ISet targetGroups = new HashSet(); + + public X509AttrCertStoreSelector() + { + } + + private X509AttrCertStoreSelector( + X509AttrCertStoreSelector o) + { + this.attributeCert = o.attributeCert; + this.attributeCertificateValid = o.attributeCertificateValid; + this.holder = o.holder; + this.issuer = o.issuer; + this.serialNumber = o.serialNumber; + this.targetGroups = new HashSet(o.targetGroups); + this.targetNames = new HashSet(o.targetNames); + } + + /// + /// Decides if the given attribute certificate should be selected. + /// + /// The attribute certificate to be checked. + /// true if the object matches this selector. + public bool Match( + object obj) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + IX509AttributeCertificate attrCert = obj as IX509AttributeCertificate; + + if (attrCert == null) + return false; + + if (this.attributeCert != null && !this.attributeCert.Equals(attrCert)) + return false; + + if (serialNumber != null && !attrCert.SerialNumber.Equals(serialNumber)) + return false; + + if (holder != null && !attrCert.Holder.Equals(holder)) + return false; + + if (issuer != null && !attrCert.Issuer.Equals(issuer)) + return false; + + if (attributeCertificateValid != null && !attrCert.IsValid(attributeCertificateValid.Value)) + return false; + + if (targetNames.Count > 0 || targetGroups.Count > 0) + { + Asn1OctetString targetInfoExt = attrCert.GetExtensionValue( + X509Extensions.TargetInformation); + + if (targetInfoExt != null) + { + TargetInformation targetinfo; + try + { + targetinfo = TargetInformation.GetInstance( + X509ExtensionUtilities.FromExtensionValue(targetInfoExt)); + } + catch (Exception) + { + return false; + } + + Targets[] targetss = targetinfo.GetTargetsObjects(); + + if (targetNames.Count > 0) + { + bool found = false; + + for (int i = 0; i < targetss.Length && !found; i++) + { + Target[] targets = targetss[i].GetTargets(); + + for (int j = 0; j < targets.Length; j++) + { + GeneralName targetName = targets[j].TargetName; + + if (targetName != null && targetNames.Contains(targetName)) + { + found = true; + break; + } + } + } + if (!found) + { + return false; + } + } + + if (targetGroups.Count > 0) + { + bool found = false; + + for (int i = 0; i < targetss.Length && !found; i++) + { + Target[] targets = targetss[i].GetTargets(); + + for (int j = 0; j < targets.Length; j++) + { + GeneralName targetGroup = targets[j].TargetGroup; + + if (targetGroup != null && targetGroups.Contains(targetGroup)) + { + found = true; + break; + } + } + } + + if (!found) + { + return false; + } + } + } + } + + return true; + } + + public object Clone() + { + return new X509AttrCertStoreSelector(this); + } + + /// The attribute certificate which must be matched. + /// If null is given, any will do. + public IX509AttributeCertificate AttributeCert + { + get { return attributeCert; } + set { this.attributeCert = value; } + } + + [Obsolete("Use AttributeCertificateValid instead")] + public DateTimeObject AttribueCertificateValid + { + get { return attributeCertificateValid; } + set { this.attributeCertificateValid = value; } + } + + /// The criteria for validity + /// If null is given any will do. + public DateTimeObject AttributeCertificateValid + { + get { return attributeCertificateValid; } + set { this.attributeCertificateValid = value; } + } + + /// The holder. + /// If null is given any will do. + public AttributeCertificateHolder Holder + { + get { return holder; } + set { this.holder = value; } + } + + /// The issuer. + /// If null is given any will do. + public AttributeCertificateIssuer Issuer + { + get { return issuer; } + set { this.issuer = value; } + } + + /// The serial number. + /// If null is given any will do. + public BigInteger SerialNumber + { + get { return serialNumber; } + set { this.serialNumber = value; } + } + + /** + * Adds a target name criterion for the attribute certificate to the target + * information extension criteria. The X509AttributeCertificate + * must contain at least one of the specified target names. + *

    + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + *

    + * + * @param name The name as a GeneralName (not null) + */ + public void AddTargetName( + GeneralName name) + { + targetNames.Add(name); + } + + /** + * Adds a target name criterion for the attribute certificate to the target + * information extension criteria. The X509AttributeCertificate + * must contain at least one of the specified target names. + *

    + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + *

    + * + * @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName + * @throws IOException if a parsing error occurs. + */ + public void AddTargetName( + byte[] name) + { + AddTargetName(GeneralName.GetInstance(Asn1Object.FromByteArray(name))); + } + + /** + * Adds a collection with target names criteria. If null is + * given any will do. + *

    + * The collection consists of either GeneralName objects or byte[] arrays representing + * DER encoded GeneralName structures. + *

    + * + * @param names A collection of target names. + * @throws IOException if a parsing error occurs. + * @see #AddTargetName(byte[]) + * @see #AddTargetName(GeneralName) + */ + public void SetTargetNames( + IEnumerable names) + { + targetNames = ExtractGeneralNames(names); + } + + /** + * Gets the target names. The collection consists of Lists + * made up of an Integer in the first entry and a DER encoded + * byte array or a String in the second entry. + *

    The returned collection is immutable.

    + * + * @return The collection of target names + * @see #setTargetNames(Collection) + */ + public IEnumerable GetTargetNames() + { + return new EnumerableProxy(targetNames); + } + + /** + * Adds a target group criterion for the attribute certificate to the target + * information extension criteria. The X509AttributeCertificate + * must contain at least one of the specified target groups. + *

    + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + *

    + * + * @param group The group as GeneralName form (not null) + */ + public void AddTargetGroup( + GeneralName group) + { + targetGroups.Add(group); + } + + /** + * Adds a target group criterion for the attribute certificate to the target + * information extension criteria. The X509AttributeCertificate + * must contain at least one of the specified target groups. + *

    + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + *

    + * + * @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName + * @throws IOException if a parsing error occurs. + */ + public void AddTargetGroup( + byte[] name) + { + AddTargetGroup(GeneralName.GetInstance(Asn1Object.FromByteArray(name))); + } + + /** + * Adds a collection with target groups criteria. If null is + * given any will do. + *

    + * The collection consists of GeneralName objects or byte[] + * representing DER encoded GeneralNames. + *

    + * + * @param names A collection of target groups. + * @throws IOException if a parsing error occurs. + * @see #AddTargetGroup(byte[]) + * @see #AddTargetGroup(GeneralName) + */ + public void SetTargetGroups( + IEnumerable names) + { + targetGroups = ExtractGeneralNames(names); + } + + /** + * Gets the target groups. The collection consists of Lists + * made up of an Integer in the first entry and a DER encoded + * byte array or a String in the second entry. + *

    The returned collection is immutable.

    + * + * @return The collection of target groups. + * @see #setTargetGroups(Collection) + */ + public IEnumerable GetTargetGroups() + { + return new EnumerableProxy(targetGroups); + } + + private ISet ExtractGeneralNames( + IEnumerable names) + { + ISet result = new HashSet(); + + if (names != null) + { + foreach (object o in names) + { + if (o is GeneralName) + { + result.Add(o); + } + else + { + result.Add(GeneralName.GetInstance(Asn1Object.FromByteArray((byte[]) o))); + } + } + } + + return result; + } + } +} diff --git a/crypto/src/x509/store/X509CertPairStoreSelector.cs b/crypto/src/x509/store/X509CertPairStoreSelector.cs new file mode 100644 index 000000000..2796971c7 --- /dev/null +++ b/crypto/src/x509/store/X509CertPairStoreSelector.cs @@ -0,0 +1,92 @@ +using System; + +namespace Org.BouncyCastle.X509.Store +{ + /// + /// This class is an IX509Selector implementation to select + /// certificate pairs, which are e.g. used for cross certificates. The set of + /// criteria is given from two X509CertStoreSelector objects, + /// each of which, if present, must match the respective component of a pair. + /// + public class X509CertPairStoreSelector + : IX509Selector + { + private static X509CertStoreSelector CloneSelector( + X509CertStoreSelector s) + { + return s == null ? null : (X509CertStoreSelector) s.Clone(); + } + + private X509CertificatePair certPair; + private X509CertStoreSelector forwardSelector; + private X509CertStoreSelector reverseSelector; + + public X509CertPairStoreSelector() + { + } + + private X509CertPairStoreSelector( + X509CertPairStoreSelector o) + { + this.certPair = o.CertPair; + this.forwardSelector = o.ForwardSelector; + this.reverseSelector = o.ReverseSelector; + } + + /// The certificate pair which is used for testing on equality. + public X509CertificatePair CertPair + { + get { return certPair; } + set { this.certPair = value; } + } + + /// The certificate selector for the forward part. + public X509CertStoreSelector ForwardSelector + { + get { return CloneSelector(forwardSelector); } + set { this.forwardSelector = CloneSelector(value); } + } + + /// The certificate selector for the reverse part. + public X509CertStoreSelector ReverseSelector + { + get { return CloneSelector(reverseSelector); } + set { this.reverseSelector = CloneSelector(value); } + } + + /// + /// Decides if the given certificate pair should be selected. If + /// obj is not a X509CertificatePair, this method + /// returns false. + /// + /// The X509CertificatePair to be tested. + /// true if the object matches this selector. + public bool Match( + object obj) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + X509CertificatePair pair = obj as X509CertificatePair; + + if (pair == null) + return false; + + if (certPair != null && !certPair.Equals(pair)) + return false; + + if (forwardSelector != null && !forwardSelector.Match(pair.Forward)) + return false; + + if (reverseSelector != null && !reverseSelector.Match(pair.Reverse)) + return false; + + return true; + } + + public object Clone() + { + return new X509CertPairStoreSelector(this); + } + } +} diff --git a/crypto/src/x509/store/X509CertStoreSelector.cs b/crypto/src/x509/store/X509CertStoreSelector.cs new file mode 100644 index 000000000..3874edf1d --- /dev/null +++ b/crypto/src/x509/store/X509CertStoreSelector.cs @@ -0,0 +1,337 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509.Store +{ + public class X509CertStoreSelector + : IX509Selector + { + // TODO Missing criteria? + + private byte[] authorityKeyIdentifier; + private int basicConstraints = -1; + private X509Certificate certificate; + private DateTimeObject certificateValid; + private ISet extendedKeyUsage; + private X509Name issuer; + private bool[] keyUsage; + private ISet policy; + private DateTimeObject privateKeyValid; + private BigInteger serialNumber; + private X509Name subject; + private byte[] subjectKeyIdentifier; + private SubjectPublicKeyInfo subjectPublicKey; + private DerObjectIdentifier subjectPublicKeyAlgID; + + public X509CertStoreSelector() + { + } + + public X509CertStoreSelector( + X509CertStoreSelector o) + { + this.authorityKeyIdentifier = o.AuthorityKeyIdentifier; + this.basicConstraints = o.BasicConstraints; + this.certificate = o.Certificate; + this.certificateValid = o.CertificateValid; + this.extendedKeyUsage = o.ExtendedKeyUsage; + this.issuer = o.Issuer; + this.keyUsage = o.KeyUsage; + this.policy = o.Policy; + this.privateKeyValid = o.PrivateKeyValid; + this.serialNumber = o.SerialNumber; + this.subject = o.Subject; + this.subjectKeyIdentifier = o.SubjectKeyIdentifier; + this.subjectPublicKey = o.SubjectPublicKey; + this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID; + } + + public virtual object Clone() + { + return new X509CertStoreSelector(this); + } + + public byte[] AuthorityKeyIdentifier + { + get { return Arrays.Clone(authorityKeyIdentifier); } + set { authorityKeyIdentifier = Arrays.Clone(value); } + } + + public int BasicConstraints + { + get { return basicConstraints; } + set + { + if (value < -2) + throw new ArgumentException("value can't be less than -2", "value"); + + basicConstraints = value; + } + } + + public X509Certificate Certificate + { + get { return certificate; } + set { this.certificate = value; } + } + + public DateTimeObject CertificateValid + { + get { return certificateValid; } + set { certificateValid = value; } + } + + public ISet ExtendedKeyUsage + { + get { return CopySet(extendedKeyUsage); } + set { extendedKeyUsage = CopySet(value); } + } + + public X509Name Issuer + { + get { return issuer; } + set { issuer = value; } + } + + [Obsolete("Avoid working with X509Name objects in string form")] + public string IssuerAsString + { + get { return issuer != null ? issuer.ToString() : null; } + } + + public bool[] KeyUsage + { + get { return CopyBoolArray(keyUsage); } + set { keyUsage = CopyBoolArray(value); } + } + + /// + /// An ISet of DerObjectIdentifier objects. + /// + public ISet Policy + { + get { return CopySet(policy); } + set { policy = CopySet(value); } + } + + public DateTimeObject PrivateKeyValid + { + get { return privateKeyValid; } + set { privateKeyValid = value; } + } + + public BigInteger SerialNumber + { + get { return serialNumber; } + set { serialNumber = value; } + } + + public X509Name Subject + { + get { return subject; } + set { subject = value; } + } + + public string SubjectAsString + { + get { return subject != null ? subject.ToString() : null; } + } + + public byte[] SubjectKeyIdentifier + { + get { return Arrays.Clone(subjectKeyIdentifier); } + set { subjectKeyIdentifier = Arrays.Clone(value); } + } + + public SubjectPublicKeyInfo SubjectPublicKey + { + get { return subjectPublicKey; } + set { subjectPublicKey = value; } + } + + public DerObjectIdentifier SubjectPublicKeyAlgID + { + get { return subjectPublicKeyAlgID; } + set { subjectPublicKeyAlgID = value; } + } + + public virtual bool Match( + object obj) + { + X509Certificate c = obj as X509Certificate; + + if (c == null) + return false; + + if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier)) + return false; + + if (basicConstraints != -1) + { + int bc = c.GetBasicConstraints(); + + if (basicConstraints == -2) + { + if (bc != -1) + return false; + } + else + { + if (bc < basicConstraints) + return false; + } + } + + if (certificate != null && !certificate.Equals(c)) + return false; + + if (certificateValid != null && !c.IsValid(certificateValid.Value)) + return false; + + if (extendedKeyUsage != null) + { + IList eku = c.GetExtendedKeyUsage(); + + // Note: if no extended key usage set, all key purposes are implicitly allowed + + if (eku != null) + { + foreach (DerObjectIdentifier oid in extendedKeyUsage) + { + if (!eku.Contains(oid.Id)) + return false; + } + } + } + + if (issuer != null && !issuer.Equivalent(c.IssuerDN, true)) + return false; + + if (keyUsage != null) + { + bool[] ku = c.GetKeyUsage(); + + // Note: if no key usage set, all key purposes are implicitly allowed + + if (ku != null) + { + for (int i = 0; i < 9; ++i) + { + if (keyUsage[i] && !ku[i]) + return false; + } + } + } + + if (policy != null) + { + Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies); + if (extVal == null) + return false; + + Asn1Sequence certPolicies = Asn1Sequence.GetInstance( + X509ExtensionUtilities.FromExtensionValue(extVal)); + + if (policy.Count < 1 && certPolicies.Count < 1) + return false; + + bool found = false; + foreach (PolicyInformation pi in certPolicies) + { + if (policy.Contains(pi.PolicyIdentifier)) + { + found = true; + break; + } + } + + if (!found) + return false; + } + + if (privateKeyValid != null) + { + Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod); + if (extVal == null) + return false; + + PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance( + X509ExtensionUtilities.FromExtensionValue(extVal)); + + DateTime dt = privateKeyValid.Value; + DateTime notAfter = pkup.NotAfter.ToDateTime(); + DateTime notBefore = pkup.NotBefore.ToDateTime(); + + if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0) + return false; + } + + if (serialNumber != null && !serialNumber.Equals(c.SerialNumber)) + return false; + + if (subject != null && !subject.Equivalent(c.SubjectDN, true)) + return false; + + if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier)) + return false; + + if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c))) + return false; + + if (subjectPublicKeyAlgID != null + && !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID)) + return false; + + return true; + } + + internal static bool IssuersMatch( + X509Name a, + X509Name b) + { + return a == null ? b == null : a.Equivalent(b, true); + } + + private static bool[] CopyBoolArray( + bool[] b) + { + return b == null ? null : (bool[]) b.Clone(); + } + + private static ISet CopySet( + ISet s) + { + return s == null ? null : new HashSet(s); + } + + private static SubjectPublicKeyInfo GetSubjectPublicKey( + X509Certificate c) + { + return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey()); + } + + private static bool MatchExtension( + byte[] b, + X509Certificate c, + DerObjectIdentifier oid) + { + if (b == null) + return true; + + Asn1OctetString extVal = c.GetExtensionValue(oid); + + if (extVal == null) + return false; + + return Arrays.AreEqual(b, extVal.GetOctets()); + } + } +} diff --git a/crypto/src/x509/store/X509CollectionStore.cs b/crypto/src/x509/store/X509CollectionStore.cs new file mode 100644 index 000000000..92173140b --- /dev/null +++ b/crypto/src/x509/store/X509CollectionStore.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509.Store +{ + /** + * A simple collection backed store. + */ + internal class X509CollectionStore + : IX509Store + { + private ICollection _local; + + /** + * Basic constructor. + * + * @param collection - initial contents for the store, this is copied. + */ + internal X509CollectionStore( + ICollection collection) + { + _local = Platform.CreateArrayList(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 ICollection GetMatches( + IX509Selector selector) + { + if (selector == null) + { + return Platform.CreateArrayList(_local); + } + + IList result = Platform.CreateArrayList(); + foreach (object obj in _local) + { + if (selector.Match(obj)) + result.Add(obj); + } + + return result; + } + } +} diff --git a/crypto/src/x509/store/X509CollectionStoreParameters.cs b/crypto/src/x509/store/X509CollectionStoreParameters.cs new file mode 100644 index 000000000..7fd047a47 --- /dev/null +++ b/crypto/src/x509/store/X509CollectionStoreParameters.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509.Store +{ + /// This class contains a collection for collection based X509Stores. + public class X509CollectionStoreParameters + : IX509StoreParameters + { + private readonly IList collection; + + /// + /// Constructor. + ///

    + /// The collection is copied. + ///

    + ///
    + /// The collection containing X.509 object types. + /// If collection is null. + public X509CollectionStoreParameters( + ICollection collection) + { + if (collection == null) + throw new ArgumentNullException("collection"); + + this.collection = Platform.CreateArrayList(collection); + } + + // TODO Do we need to be able to Clone() these, and should it really be shallow? +// /** +// * Returns a shallow clone. The returned contents are not copied, so adding +// * or removing objects will effect this. +// * +// * @return a shallow clone. +// */ +// public object Clone() +// { +// return new X509CollectionStoreParameters(collection); +// } + + /// Returns a copy of the ICollection. + public ICollection GetCollection() + { + return Platform.CreateArrayList(collection); + } + + /// Returns a formatted string describing the parameters. + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("X509CollectionStoreParameters: [\n"); + sb.Append(" collection: " + collection + "\n"); + sb.Append("]"); + return sb.ToString(); + } + } +} diff --git a/crypto/src/x509/store/X509CrlStoreSelector.cs b/crypto/src/x509/store/X509CrlStoreSelector.cs new file mode 100644 index 000000000..c4b0062c1 --- /dev/null +++ b/crypto/src/x509/store/X509CrlStoreSelector.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.X509.Store +{ + public class X509CrlStoreSelector + : IX509Selector + { + // TODO Missing criteria? + + private X509Certificate certificateChecking; + private DateTimeObject dateAndTime; + private ICollection issuers; + private BigInteger maxCrlNumber; + private BigInteger minCrlNumber; + + private IX509AttributeCertificate attrCertChecking; + private bool completeCrlEnabled; + private bool deltaCrlIndicatorEnabled; + private byte[] issuingDistributionPoint; + private bool issuingDistributionPointEnabled; + private BigInteger maxBaseCrlNumber; + + public X509CrlStoreSelector() + { + } + + public X509CrlStoreSelector( + X509CrlStoreSelector o) + { + this.certificateChecking = o.CertificateChecking; + this.dateAndTime = o.DateAndTime; + this.issuers = o.Issuers; + this.maxCrlNumber = o.MaxCrlNumber; + this.minCrlNumber = o.MinCrlNumber; + + this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled; + this.completeCrlEnabled = o.CompleteCrlEnabled; + this.maxBaseCrlNumber = o.MaxBaseCrlNumber; + this.attrCertChecking = o.AttrCertChecking; + this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled; + this.issuingDistributionPoint = o.IssuingDistributionPoint; + } + + public virtual object Clone() + { + return new X509CrlStoreSelector(this); + } + + public X509Certificate CertificateChecking + { + get { return certificateChecking; } + set { certificateChecking = value; } + } + + public DateTimeObject DateAndTime + { + get { return dateAndTime; } + set { dateAndTime = value; } + } + + /// + /// An ICollection of X509Name objects + /// + public ICollection Issuers + { + get { return Platform.CreateArrayList(issuers); } + set { issuers = Platform.CreateArrayList(value); } + } + + public BigInteger MaxCrlNumber + { + get { return maxCrlNumber; } + set { maxCrlNumber = value; } + } + + public BigInteger MinCrlNumber + { + get { return minCrlNumber; } + set { minCrlNumber = value; } + } + + /** + * The attribute certificate being checked. This is not a criterion. + * Rather, it is optional information that may help a {@link X509Store} find + * CRLs that would be relevant when checking revocation for the specified + * attribute certificate. If null is specified, then no such + * optional information is provided. + * + * @param attrCert the IX509AttributeCertificate being checked (or + * null) + * @see #getAttrCertificateChecking() + */ + public IX509AttributeCertificate AttrCertChecking + { + get { return attrCertChecking; } + set { this.attrCertChecking = value; } + } + + /** + * If true only complete CRLs are returned. Defaults to + * false. + * + * @return true if only complete CRLs are returned. + */ + public bool CompleteCrlEnabled + { + get { return completeCrlEnabled; } + set { this.completeCrlEnabled = value; } + } + + /** + * Returns if this selector must match CRLs with the delta CRL indicator + * extension set. Defaults to false. + * + * @return Returns true if only CRLs with the delta CRL + * indicator extension are selected. + */ + public bool DeltaCrlIndicatorEnabled + { + get { return deltaCrlIndicatorEnabled; } + set { this.deltaCrlIndicatorEnabled = value; } + } + + /** + * The issuing distribution point. + *

    + * The issuing distribution point extension is a CRL extension which + * identifies the scope and the distribution point of a CRL. The scope + * contains among others information about revocation reasons contained in + * the CRL. Delta CRLs and complete CRLs must have matching issuing + * distribution points.

    + *

    + * The byte array is cloned to protect against subsequent modifications.

    + *

    + * You must also enable or disable this criteria with + * {@link #setIssuingDistributionPointEnabled(bool)}.

    + * + * @param issuingDistributionPoint The issuing distribution point to set. + * This is the DER encoded OCTET STRING extension value. + * @see #getIssuingDistributionPoint() + */ + public byte[] IssuingDistributionPoint + { + get { return Arrays.Clone(issuingDistributionPoint); } + set { this.issuingDistributionPoint = Arrays.Clone(value); } + } + + /** + * Whether the issuing distribution point criteria should be applied. + * Defaults to false. + *

    + * You may also set the issuing distribution point criteria if not a missing + * issuing distribution point should be assumed.

    + * + * @return Returns if the issuing distribution point check is enabled. + */ + public bool IssuingDistributionPointEnabled + { + get { return issuingDistributionPointEnabled; } + set { this.issuingDistributionPointEnabled = value; } + } + + /** + * The maximum base CRL number. Defaults to null. + * + * @return Returns the maximum base CRL number. + * @see #setMaxBaseCRLNumber(BigInteger) + */ + public BigInteger MaxBaseCrlNumber + { + get { return maxBaseCrlNumber; } + set { this.maxBaseCrlNumber = value; } + } + + public virtual bool Match( + object obj) + { + X509Crl c = obj as X509Crl; + + if (c == null) + return false; + + if (dateAndTime != null) + { + DateTime dt = dateAndTime.Value; + DateTime tu = c.ThisUpdate; + DateTimeObject nu = c.NextUpdate; + + if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0) + return false; + } + + if (issuers != null) + { + X509Name i = c.IssuerDN; + + bool found = false; + + foreach (X509Name issuer in issuers) + { + if (issuer.Equivalent(i, true)) + { + found = true; + break; + } + } + + if (!found) + return false; + } + + if (maxCrlNumber != null || minCrlNumber != null) + { + Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber); + if (extVal == null) + return false; + + BigInteger cn = CrlNumber.GetInstance( + X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue; + + if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0) + return false; + + if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0) + return false; + } + + DerInteger dci = null; + try + { + Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator); + if (bytes != null) + { + dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes)); + } + } + catch (Exception) + { + return false; + } + + if (dci == null) + { + if (DeltaCrlIndicatorEnabled) + return false; + } + else + { + if (CompleteCrlEnabled) + return false; + + if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0) + return false; + } + + if (issuingDistributionPointEnabled) + { + Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint); + if (issuingDistributionPoint == null) + { + if (idp != null) + return false; + } + else + { + if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint)) + return false; + } + } + + return true; + } + } +} diff --git a/crypto/src/x509/store/X509StoreException.cs b/crypto/src/x509/store/X509StoreException.cs new file mode 100644 index 000000000..f781291e2 --- /dev/null +++ b/crypto/src/x509/store/X509StoreException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.X509.Store +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class X509StoreException + : Exception + { + public X509StoreException() + { + } + + public X509StoreException( + string message) + : base(message) + { + } + + public X509StoreException( + string message, + Exception e) + : base(message, e) + { + } + } +} diff --git a/crypto/src/x509/store/X509StoreFactory.cs b/crypto/src/x509/store/X509StoreFactory.cs new file mode 100644 index 000000000..96f22be3f --- /dev/null +++ b/crypto/src/x509/store/X509StoreFactory.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.X509.Store +{ + public sealed class X509StoreFactory + { + private X509StoreFactory() + { + } + + public static IX509Store Create( + string type, + IX509StoreParameters parameters) + { + if (type == null) + throw new ArgumentNullException("type"); + + string[] parts = Platform.ToUpperInvariant(type).Split('/'); + + if (parts.Length < 2) + throw new ArgumentException("type"); + + if (parts[1] != "COLLECTION") + throw new NoSuchStoreException("X.509 store type '" + type + "' not available."); + + X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters; + ICollection coll = p.GetCollection(); + + switch (parts[0]) + { + case "ATTRIBUTECERTIFICATE": + checkCorrectType(coll, typeof(IX509AttributeCertificate)); + break; + case "CERTIFICATE": + checkCorrectType(coll, typeof(X509Certificate)); + break; + case "CERTIFICATEPAIR": + checkCorrectType(coll, typeof(X509CertificatePair)); + break; + case "CRL": + checkCorrectType(coll, typeof(X509Crl)); + break; + default: + throw new NoSuchStoreException("X.509 store type '" + type + "' not available."); + } + + return new X509CollectionStore(coll); + } + + private static void checkCorrectType(ICollection coll, Type t) + { + foreach (object o in coll) + { + if (!t.IsInstanceOfType(o)) + throw new InvalidCastException("Can't cast object to type: " + t.FullName); + } + } + } +} diff --git a/crypto/test/data/PKITS/README.txt b/crypto/test/data/PKITS/README.txt new file mode 100644 index 000000000..00a124b65 --- /dev/null +++ b/crypto/test/data/PKITS/README.txt @@ -0,0 +1,3 @@ +PKITS test data from http://csrc.nist.gov/pki/testing/x509paths.html + +For more details please check the website above. diff --git a/crypto/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt b/crypto/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt new file mode 100644 index 000000000..6c40491f2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt b/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt new file mode 100644 index 000000000..41b6d15b2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt b/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt new file mode 100644 index 000000000..9210106f5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt b/crypto/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt new file mode 100644 index 000000000..a7f9d22b0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/AnyPolicyTest14EE.crt b/crypto/test/data/PKITS/certs/AnyPolicyTest14EE.crt new file mode 100644 index 000000000..b5961c75f Binary files /dev/null and b/crypto/test/data/PKITS/certs/AnyPolicyTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt b/crypto/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt new file mode 100644 index 000000000..6afe5ddd0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BadCRLSignatureCACert.crt b/crypto/test/data/PKITS/certs/BadCRLSignatureCACert.crt new file mode 100644 index 000000000..bfac8a406 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BadCRLSignatureCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BadSignedCACert.crt b/crypto/test/data/PKITS/certs/BadSignedCACert.crt new file mode 100644 index 000000000..abf7f319c Binary files /dev/null and b/crypto/test/data/PKITS/certs/BadSignedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BadnotAfterDateCACert.crt b/crypto/test/data/PKITS/certs/BadnotAfterDateCACert.crt new file mode 100644 index 000000000..d8babc267 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BadnotAfterDateCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BadnotBeforeDateCACert.crt b/crypto/test/data/PKITS/certs/BadnotBeforeDateCACert.crt new file mode 100644 index 000000000..9b4cd824a Binary files /dev/null and b/crypto/test/data/PKITS/certs/BadnotBeforeDateCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt new file mode 100644 index 000000000..41881148c Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt new file mode 100644 index 000000000..7c1b13952 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt new file mode 100644 index 000000000..b4ccbe84f Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt new file mode 100644 index 000000000..336a1caa0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt new file mode 100644 index 000000000..78953d66f Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt b/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt new file mode 100644 index 000000000..853dc0613 Binary files /dev/null and b/crypto/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt b/crypto/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt new file mode 100644 index 000000000..8bc703698 Binary files /dev/null and b/crypto/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DSACACert.crt b/crypto/test/data/PKITS/certs/DSACACert.crt new file mode 100644 index 000000000..a1f9e05f6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/DSACACert.crt differ diff --git a/crypto/test/data/PKITS/certs/DSAParametersInheritedCACert.crt b/crypto/test/data/PKITS/certs/DSAParametersInheritedCACert.crt new file mode 100644 index 000000000..7eae4863e Binary files /dev/null and b/crypto/test/data/PKITS/certs/DSAParametersInheritedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt new file mode 100644 index 000000000..6aa6ae5cd Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt new file mode 100644 index 000000000..8cd24ec7e Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt new file mode 100644 index 000000000..6af794d89 Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt new file mode 100644 index 000000000..43150466b Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt new file mode 100644 index 000000000..8caf46a33 Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt new file mode 100644 index 000000000..f49721d7e Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt b/crypto/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt new file mode 100644 index 000000000..49a38a558 Binary files /dev/null and b/crypto/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt b/crypto/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt new file mode 100644 index 000000000..c22228aa0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/GoodCACert.crt b/crypto/test/data/PKITS/certs/GoodCACert.crt new file mode 100644 index 000000000..5aecbc0cf Binary files /dev/null and b/crypto/test/data/PKITS/certs/GoodCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/GoodsubCACert.crt b/crypto/test/data/PKITS/certs/GoodsubCACert.crt new file mode 100644 index 000000000..09c98aad6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/GoodsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt b/crypto/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt new file mode 100644 index 000000000..2540cd45d Binary files /dev/null and b/crypto/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt new file mode 100644 index 000000000..749f7cc0f Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt b/crypto/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt new file mode 100644 index 000000000..3c4d2cbe2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt new file mode 100644 index 000000000..7919115d2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt new file mode 100644 index 000000000..b242bad64 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt new file mode 100644 index 000000000..e75d97865 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt new file mode 100644 index 000000000..ed3000124 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt new file mode 100644 index 000000000..8d337bddf Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt new file mode 100644 index 000000000..6f6748d07 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt new file mode 100644 index 000000000..e7b01de4d Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt new file mode 100644 index 000000000..3f86eefe0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt new file mode 100644 index 000000000..805205b29 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt new file mode 100644 index 000000000..eff3779d3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt b/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt new file mode 100644 index 000000000..7c1dd9cb2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt b/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt new file mode 100644 index 000000000..bdf08adcb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt new file mode 100644 index 000000000..5ff84a45b Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt new file mode 100644 index 000000000..11ec10fe8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt new file mode 100644 index 000000000..08c3050d1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt new file mode 100644 index 000000000..28ab46587 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt new file mode 100644 index 000000000..56e42d0f1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt new file mode 100644 index 000000000..f9f53b932 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt new file mode 100644 index 000000000..15fbe8faa Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt new file mode 100644 index 000000000..8daf2f2a6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt new file mode 100644 index 000000000..52cd9993e Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt new file mode 100644 index 000000000..799760b5f Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt new file mode 100644 index 000000000..d874621eb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt new file mode 100644 index 000000000..18314bd01 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt new file mode 100644 index 000000000..bcc900cf4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt b/crypto/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt new file mode 100644 index 000000000..e21461e37 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt new file mode 100644 index 000000000..46269d05e Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt new file mode 100644 index 000000000..f1bf1d1a4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt b/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt new file mode 100644 index 000000000..31965f628 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt b/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt new file mode 100644 index 000000000..b9b87a6c1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt b/crypto/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt new file mode 100644 index 000000000..1c84dce0e Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt b/crypto/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt new file mode 100644 index 000000000..49aab726e Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt new file mode 100644 index 000000000..0a56c5e0d Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt new file mode 100644 index 000000000..7af5ce5aa Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt new file mode 100644 index 000000000..f5d8703c3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt new file mode 100644 index 000000000..9c40a3391 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt new file mode 100644 index 000000000..f7ae3b0e8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt b/crypto/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt new file mode 100644 index 000000000..2d323b4df Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt b/crypto/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt new file mode 100644 index 000000000..858db72d6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt new file mode 100644 index 000000000..ef227b8ea Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt new file mode 100644 index 000000000..58ace916a Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt new file mode 100644 index 000000000..c0dd555d5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt new file mode 100644 index 000000000..d8134e0a6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt new file mode 100644 index 000000000..b71c6a377 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt new file mode 100644 index 000000000..0ffdf26fa Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt b/crypto/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt new file mode 100644 index 000000000..65a0a1ab4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt b/crypto/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt new file mode 100644 index 000000000..80ea4d3f5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt new file mode 100644 index 000000000..21c32e976 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt new file mode 100644 index 000000000..d57f0cb52 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt new file mode 100644 index 000000000..577998c4f Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt new file mode 100644 index 000000000..621c325eb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt new file mode 100644 index 000000000..98f8160cb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt new file mode 100644 index 000000000..b80277286 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt new file mode 100644 index 000000000..9fba63afb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt new file mode 100644 index 000000000..a1b58ffaa Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt new file mode 100644 index 000000000..108f38c5f Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt b/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt new file mode 100644 index 000000000..8671cc6f5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt b/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt new file mode 100644 index 000000000..b8faa4acc Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt b/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt new file mode 100644 index 000000000..5313fc96d Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt b/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt new file mode 100644 index 000000000..81fd01db7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt b/crypto/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt new file mode 100644 index 000000000..6170daef8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt new file mode 100644 index 000000000..8c8dfc0d8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt b/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt new file mode 100644 index 000000000..83c1b6af4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt new file mode 100644 index 000000000..65c7a68ec Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt new file mode 100644 index 000000000..206892ceb Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt new file mode 100644 index 000000000..25b925a28 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt b/crypto/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt new file mode 100644 index 000000000..5d8f86320 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt new file mode 100644 index 000000000..1cb9f595d Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt new file mode 100644 index 000000000..7e08a55d3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt new file mode 100644 index 000000000..ec020a1a4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt new file mode 100644 index 000000000..b309b809b Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt new file mode 100644 index 000000000..257daab5a Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt new file mode 100644 index 000000000..30e49a4ec Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt new file mode 100644 index 000000000..d60e4f698 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt new file mode 100644 index 000000000..27ce111ae Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt new file mode 100644 index 000000000..a7edcf890 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt new file mode 100644 index 000000000..0e247f2ab Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt new file mode 100644 index 000000000..e5b34e4ac Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt new file mode 100644 index 000000000..c61a6460a Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt new file mode 100644 index 000000000..531033234 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt new file mode 100644 index 000000000..9236346ee Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt new file mode 100644 index 000000000..3520f6a3f Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt new file mode 100644 index 000000000..5982bb6a2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt new file mode 100644 index 000000000..b6fe66182 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt new file mode 100644 index 000000000..e6a924a1a Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt new file mode 100644 index 000000000..20c40a497 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt new file mode 100644 index 000000000..03c8a3208 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt new file mode 100644 index 000000000..f028a76ff Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt new file mode 100644 index 000000000..3393af56c Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt new file mode 100644 index 000000000..374681425 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt new file mode 100644 index 000000000..9f7eafa22 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt b/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt new file mode 100644 index 000000000..888f7e2ae Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt b/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt new file mode 100644 index 000000000..43b0d9587 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt new file mode 100644 index 000000000..fbfb4c4e4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt b/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt new file mode 100644 index 000000000..a9da41446 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt b/crypto/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt new file mode 100644 index 000000000..60e0f7dbf Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt b/crypto/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt new file mode 100644 index 000000000..c0ada1281 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt b/crypto/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt new file mode 100644 index 000000000..acf119985 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt new file mode 100644 index 000000000..45460ee00 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt new file mode 100644 index 000000000..b82e84e61 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt new file mode 100644 index 000000000..d29a9ff08 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt new file mode 100644 index 000000000..431d60071 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt new file mode 100644 index 000000000..68bf8f9ab Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt new file mode 100644 index 000000000..788389d3e Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt new file mode 100644 index 000000000..01ea4d0b7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt new file mode 100644 index 000000000..231641608 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt new file mode 100644 index 000000000..7164f04fe Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt new file mode 100644 index 000000000..eec5f9de1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt new file mode 100644 index 000000000..6a063a61d Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt b/crypto/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt new file mode 100644 index 000000000..634a08e51 Binary files /dev/null and b/crypto/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt b/crypto/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt new file mode 100644 index 000000000..88916af6f Binary files /dev/null and b/crypto/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt b/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt new file mode 100644 index 000000000..38f98e475 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt b/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt new file mode 100644 index 000000000..ca3ea17b8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/LongSerialNumberCACert.crt b/crypto/test/data/PKITS/certs/LongSerialNumberCACert.crt new file mode 100644 index 000000000..6aaf3d0a4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/LongSerialNumberCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/Mapping1to2CACert.crt b/crypto/test/data/PKITS/certs/Mapping1to2CACert.crt new file mode 100644 index 000000000..a458115a3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/Mapping1to2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt b/crypto/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt new file mode 100644 index 000000000..812da596d Binary files /dev/null and b/crypto/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/MappingToanyPolicyCACert.crt b/crypto/test/data/PKITS/certs/MappingToanyPolicyCACert.crt new file mode 100644 index 000000000..42effeb79 Binary files /dev/null and b/crypto/test/data/PKITS/certs/MappingToanyPolicyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt b/crypto/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt new file mode 100644 index 000000000..17ebf2523 Binary files /dev/null and b/crypto/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/NameOrderingCACert.crt b/crypto/test/data/PKITS/certs/NameOrderingCACert.crt new file mode 100644 index 000000000..6b744db06 Binary files /dev/null and b/crypto/test/data/PKITS/certs/NameOrderingCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/NegativeSerialNumberCACert.crt b/crypto/test/data/PKITS/certs/NegativeSerialNumberCACert.crt new file mode 100644 index 000000000..57fc93300 Binary files /dev/null and b/crypto/test/data/PKITS/certs/NegativeSerialNumberCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/NoCRLCACert.crt b/crypto/test/data/PKITS/certs/NoCRLCACert.crt new file mode 100644 index 000000000..acd908c6f Binary files /dev/null and b/crypto/test/data/PKITS/certs/NoCRLCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/NoPoliciesCACert.crt b/crypto/test/data/PKITS/certs/NoPoliciesCACert.crt new file mode 100644 index 000000000..5e2a3fc70 Binary files /dev/null and b/crypto/test/data/PKITS/certs/NoPoliciesCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt b/crypto/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt new file mode 100644 index 000000000..bf4f8140f Binary files /dev/null and b/crypto/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt b/crypto/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt new file mode 100644 index 000000000..c9fb043b8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt b/crypto/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt new file mode 100644 index 000000000..56d136cfd Binary files /dev/null and b/crypto/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/P12Mapping1to3CACert.crt b/crypto/test/data/PKITS/certs/P12Mapping1to3CACert.crt new file mode 100644 index 000000000..f9ed7b756 Binary files /dev/null and b/crypto/test/data/PKITS/certs/P12Mapping1to3CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/P12Mapping1to3subCACert.crt b/crypto/test/data/PKITS/certs/P12Mapping1to3subCACert.crt new file mode 100644 index 000000000..2029d6ba7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/P12Mapping1to3subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt b/crypto/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt new file mode 100644 index 000000000..50e7fcd26 Binary files /dev/null and b/crypto/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/P1Mapping1to234CACert.crt b/crypto/test/data/PKITS/certs/P1Mapping1to234CACert.crt new file mode 100644 index 000000000..d7b3028d6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/P1Mapping1to234CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/P1Mapping1to234subCACert.crt b/crypto/test/data/PKITS/certs/P1Mapping1to234subCACert.crt new file mode 100644 index 000000000..8648ddec9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/P1Mapping1to234subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt b/crypto/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt new file mode 100644 index 000000000..85e39feaa Binary files /dev/null and b/crypto/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt b/crypto/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt new file mode 100644 index 000000000..5abbb788d Binary files /dev/null and b/crypto/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP1234CACert.crt b/crypto/test/data/PKITS/certs/PoliciesP1234CACert.crt new file mode 100644 index 000000000..9a5eb5b73 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP1234CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt new file mode 100644 index 000000000..9b385455d Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt new file mode 100644 index 000000000..4990a9b9d Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP123CACert.crt b/crypto/test/data/PKITS/certs/PoliciesP123CACert.crt new file mode 100644 index 000000000..03509d172 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP123CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt new file mode 100644 index 000000000..0009819fa Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt new file mode 100644 index 000000000..669c18190 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt new file mode 100644 index 000000000..faa7516b7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt new file mode 100644 index 000000000..44346d5c2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP12CACert.crt b/crypto/test/data/PKITS/certs/PoliciesP12CACert.crt new file mode 100644 index 000000000..27bf52414 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP12CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt new file mode 100644 index 000000000..9a24328a7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt new file mode 100644 index 000000000..49cc0ed6d Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt b/crypto/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt new file mode 100644 index 000000000..ccbedc695 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP2subCACert.crt b/crypto/test/data/PKITS/certs/PoliciesP2subCACert.crt new file mode 100644 index 000000000..ce66a79b5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP2subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/PoliciesP3CACert.crt b/crypto/test/data/PKITS/certs/PoliciesP3CACert.crt new file mode 100644 index 000000000..90c4d266e Binary files /dev/null and b/crypto/test/data/PKITS/certs/PoliciesP3CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt b/crypto/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt new file mode 100644 index 000000000..fa0e1c8f4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt b/crypto/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt new file mode 100644 index 000000000..973373b10 Binary files /dev/null and b/crypto/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/RevokedsubCACert.crt b/crypto/test/data/PKITS/certs/RevokedsubCACert.crt new file mode 100644 index 000000000..edbd547f0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/RevokedsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt b/crypto/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt new file mode 100644 index 000000000..658f20cf5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt new file mode 100644 index 000000000..67135a6c0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt differ diff --git a/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt new file mode 100644 index 000000000..c05f92c3b Binary files /dev/null and b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt new file mode 100644 index 000000000..8c7200f87 Binary files /dev/null and b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt differ diff --git a/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt new file mode 100644 index 000000000..10deedd4f Binary files /dev/null and b/crypto/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/TrustAnchorRootCertificate.crt b/crypto/test/data/PKITS/certs/TrustAnchorRootCertificate.crt new file mode 100644 index 000000000..21f520ee5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/TrustAnchorRootCertificate.crt differ diff --git a/crypto/test/data/PKITS/certs/TwoCRLsCACert.crt b/crypto/test/data/PKITS/certs/TwoCRLsCACert.crt new file mode 100644 index 000000000..c6389d36a Binary files /dev/null and b/crypto/test/data/PKITS/certs/TwoCRLsCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UIDCACert.crt b/crypto/test/data/PKITS/certs/UIDCACert.crt new file mode 100644 index 000000000..d852bc095 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UIDCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt b/crypto/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt new file mode 100644 index 000000000..c59715d5e Binary files /dev/null and b/crypto/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt b/crypto/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt new file mode 100644 index 000000000..68d49e021 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt b/crypto/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt new file mode 100644 index 000000000..8c81c3744 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt b/crypto/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt new file mode 100644 index 000000000..db7d39e59 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt new file mode 100644 index 000000000..e912cdfa9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt differ diff --git a/crypto/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt new file mode 100644 index 000000000..ec04e1f3d Binary files /dev/null and b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt differ diff --git a/crypto/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt new file mode 100644 index 000000000..f78a47d6a Binary files /dev/null and b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt differ diff --git a/crypto/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt new file mode 100644 index 000000000..cc5cf5a77 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt differ diff --git a/crypto/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt new file mode 100644 index 000000000..3df534a98 Binary files /dev/null and b/crypto/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt new file mode 100644 index 000000000..034de7fe0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt new file mode 100644 index 000000000..199afb768 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt new file mode 100644 index 000000000..d4323162e Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt new file mode 100644 index 000000000..b54a8b0f4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt b/crypto/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt new file mode 100644 index 000000000..26985c9f6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt b/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt new file mode 100644 index 000000000..ec7d43d46 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt b/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt new file mode 100644 index 000000000..ed88860ba Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt b/crypto/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt new file mode 100644 index 000000000..73759dca2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt new file mode 100644 index 000000000..1af47ba80 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt new file mode 100644 index 000000000..ff249f051 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt new file mode 100644 index 000000000..b658d671b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt new file mode 100644 index 000000000..f4e2b8448 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt new file mode 100644 index 000000000..4c86f9b77 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt new file mode 100644 index 000000000..beb401360 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt new file mode 100644 index 000000000..b68b6f7ca Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt new file mode 100644 index 000000000..9aff6e874 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt b/crypto/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt new file mode 100644 index 000000000..8fe2af452 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt b/crypto/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt new file mode 100644 index 000000000..5b1cbc827 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt b/crypto/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt new file mode 100644 index 000000000..a22f2e6c1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt b/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt new file mode 100644 index 000000000..15689c18c Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt b/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt new file mode 100644 index 000000000..385bb1eaa Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt new file mode 100644 index 000000000..6706cf1c3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt new file mode 100644 index 000000000..bea72fe2b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt new file mode 100644 index 000000000..994c90ad6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt b/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt new file mode 100644 index 000000000..11ba787ab Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt b/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt new file mode 100644 index 000000000..75504db35 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt b/crypto/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt new file mode 100644 index 000000000..5b633871e Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt b/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt new file mode 100644 index 000000000..2aef73cfc Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt b/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt new file mode 100644 index 000000000..6890cdd85 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt b/crypto/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt new file mode 100644 index 000000000..3cddea4a2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt b/crypto/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt new file mode 100644 index 000000000..139a086d8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt b/crypto/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt new file mode 100644 index 000000000..bd8ca38b0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt new file mode 100644 index 000000000..9d19ad192 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt new file mode 100644 index 000000000..76b9fe52c Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt new file mode 100644 index 000000000..7db330523 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt new file mode 100644 index 000000000..57bf42655 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt new file mode 100644 index 000000000..436cb9e02 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt new file mode 100644 index 000000000..c835b0b24 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt new file mode 100644 index 000000000..faaeb9e46 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt new file mode 100644 index 000000000..2cd443323 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt new file mode 100644 index 000000000..4debc2942 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt b/crypto/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt new file mode 100644 index 000000000..c3e977666 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt b/crypto/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt new file mode 100644 index 000000000..f33c9d509 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt new file mode 100644 index 000000000..743e9eb9a Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt new file mode 100644 index 000000000..f8703ed8d Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt new file mode 100644 index 000000000..e89ae7f80 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt b/crypto/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt new file mode 100644 index 000000000..924d2f60a Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt new file mode 100644 index 000000000..2e7e99546 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt new file mode 100644 index 000000000..764024716 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt new file mode 100644 index 000000000..b4b282d99 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt new file mode 100644 index 000000000..0bad35f76 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt new file mode 100644 index 000000000..1535ef864 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt b/crypto/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt new file mode 100644 index 000000000..781ce0d38 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt b/crypto/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt new file mode 100644 index 000000000..fda18197b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt b/crypto/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt new file mode 100644 index 000000000..e04433ad2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt b/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt new file mode 100644 index 000000000..b554f91e6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt b/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt new file mode 100644 index 000000000..8b1f00f21 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt b/crypto/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt new file mode 100644 index 000000000..8a9d0ca82 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt b/crypto/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt new file mode 100644 index 000000000..c901690b8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt b/crypto/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt new file mode 100644 index 000000000..6ee8d1e3b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt b/crypto/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt new file mode 100644 index 000000000..543710fda Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt new file mode 100644 index 000000000..1448aa4a3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt new file mode 100644 index 000000000..ec442e1b1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt new file mode 100644 index 000000000..2dc236766 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt new file mode 100644 index 000000000..65b28440d Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt new file mode 100644 index 000000000..0d24df052 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt new file mode 100644 index 000000000..2bdaaf21e Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt new file mode 100644 index 000000000..3f6792194 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt new file mode 100644 index 000000000..65861281c Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt b/crypto/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt new file mode 100644 index 000000000..487cc2f9a Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt b/crypto/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt new file mode 100644 index 000000000..3782e79a8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt b/crypto/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt new file mode 100644 index 000000000..07a8c494a Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt b/crypto/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt new file mode 100644 index 000000000..948f37fb9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt b/crypto/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt new file mode 100644 index 000000000..dc61d5231 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt b/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt new file mode 100644 index 000000000..fc432a1d4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt b/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt new file mode 100644 index 000000000..dce692769 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt b/crypto/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt new file mode 100644 index 000000000..bddbb9a26 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt b/crypto/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt new file mode 100644 index 000000000..f35f5de2a Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt b/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt new file mode 100644 index 000000000..7c0e1dedc Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt b/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt new file mode 100644 index 000000000..f3a811c1b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt new file mode 100644 index 000000000..dcf88340d Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt new file mode 100644 index 000000000..66fe25647 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt new file mode 100644 index 000000000..5f689eaf7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt new file mode 100644 index 000000000..2357bebf1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt differ diff --git a/crypto/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt b/crypto/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt new file mode 100644 index 000000000..5a6149927 Binary files /dev/null and b/crypto/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt new file mode 100644 index 000000000..10399269e Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt new file mode 100644 index 000000000..451c2d81d Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt differ diff --git a/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt new file mode 100644 index 000000000..a2fa2f12b Binary files /dev/null and b/crypto/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt differ diff --git a/crypto/test/data/PKITS/certs/WrongCRLCACert.crt b/crypto/test/data/PKITS/certs/WrongCRLCACert.crt new file mode 100644 index 000000000..4cc51952a Binary files /dev/null and b/crypto/test/data/PKITS/certs/WrongCRLCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/anyPolicyCACert.crt b/crypto/test/data/PKITS/certs/anyPolicyCACert.crt new file mode 100644 index 000000000..4d9fb79b2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/anyPolicyCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt b/crypto/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt new file mode 100644 index 000000000..12a8b5037 Binary files /dev/null and b/crypto/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt b/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt new file mode 100644 index 000000000..8f9da1eb1 Binary files /dev/null and b/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt b/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt new file mode 100644 index 000000000..ca61262ec Binary files /dev/null and b/crypto/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/deltaCRLCA1Cert.crt b/crypto/test/data/PKITS/certs/deltaCRLCA1Cert.crt new file mode 100644 index 000000000..47f74eb40 Binary files /dev/null and b/crypto/test/data/PKITS/certs/deltaCRLCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/deltaCRLCA2Cert.crt b/crypto/test/data/PKITS/certs/deltaCRLCA2Cert.crt new file mode 100644 index 000000000..a99dd4030 Binary files /dev/null and b/crypto/test/data/PKITS/certs/deltaCRLCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/deltaCRLCA3Cert.crt b/crypto/test/data/PKITS/certs/deltaCRLCA3Cert.crt new file mode 100644 index 000000000..eeaaa36e4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/deltaCRLCA3Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt b/crypto/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt new file mode 100644 index 000000000..5ec06b3d6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/distributionPoint1CACert.crt b/crypto/test/data/PKITS/certs/distributionPoint1CACert.crt new file mode 100644 index 000000000..1e74bed04 Binary files /dev/null and b/crypto/test/data/PKITS/certs/distributionPoint1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/distributionPoint2CACert.crt b/crypto/test/data/PKITS/certs/distributionPoint2CACert.crt new file mode 100644 index 000000000..a6d37be90 Binary files /dev/null and b/crypto/test/data/PKITS/certs/distributionPoint2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA1Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA1Cert.crt new file mode 100644 index 000000000..ef079f653 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA2Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA2Cert.crt new file mode 100644 index 000000000..4bfc0b5ed Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA3Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA3Cert.crt new file mode 100644 index 000000000..f0787f0c5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA3Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt new file mode 100644 index 000000000..f8089937b Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA4Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA4Cert.crt new file mode 100644 index 000000000..6ebe43ce5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA4Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt new file mode 100644 index 000000000..0468b0866 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA5Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA5Cert.crt new file mode 100644 index 000000000..90ba7d7e5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA5Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/indirectCRLCA6Cert.crt b/crypto/test/data/PKITS/certs/indirectCRLCA6Cert.crt new file mode 100644 index 000000000..3c5781e96 Binary files /dev/null and b/crypto/test/data/PKITS/certs/indirectCRLCA6Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt new file mode 100644 index 000000000..474968979 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt new file mode 100644 index 000000000..8d35b0e67 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt new file mode 100644 index 000000000..0362dde87 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt new file mode 100644 index 000000000..1d24bc194 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt new file mode 100644 index 000000000..af02467cd Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt new file mode 100644 index 000000000..e8590f72e Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt new file mode 100644 index 000000000..75bc59e4a Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt new file mode 100644 index 000000000..cbf40ff09 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt new file mode 100644 index 000000000..3765f6e38 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt new file mode 100644 index 000000000..f75006d1e Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt new file mode 100644 index 000000000..f2898ea06 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt b/crypto/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt new file mode 100644 index 000000000..850d6499f Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt new file mode 100644 index 000000000..b4934e898 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt new file mode 100644 index 000000000..79f45b82b Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt new file mode 100644 index 000000000..57dd683c6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt new file mode 100644 index 000000000..1e6bd7006 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt new file mode 100644 index 000000000..e68346842 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt new file mode 100644 index 000000000..f73f4d299 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt new file mode 100644 index 000000000..fe32edafb Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt new file mode 100644 index 000000000..b3bff4667 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt new file mode 100644 index 000000000..399bd824f Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt new file mode 100644 index 000000000..cd2ce9448 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt new file mode 100644 index 000000000..31d9af5dd Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt new file mode 100644 index 000000000..13e78f0cc Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt new file mode 100644 index 000000000..86ea42633 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt new file mode 100644 index 000000000..788622cb9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt new file mode 100644 index 000000000..d4a025e32 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt new file mode 100644 index 000000000..2c0e6e888 Binary files /dev/null and b/crypto/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt b/crypto/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt new file mode 100644 index 000000000..a50545a1e Binary files /dev/null and b/crypto/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt b/crypto/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 000000000..f6824d3a2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt b/crypto/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt new file mode 100644 index 000000000..344f7d90a Binary files /dev/null and b/crypto/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt b/crypto/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt new file mode 100644 index 000000000..c02d6f491 Binary files /dev/null and b/crypto/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt b/crypto/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 000000000..b9c46b5b8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN1CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN1CACert.crt new file mode 100644 index 000000000..5379f1fbb Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt new file mode 100644 index 000000000..75f1f7e60 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt new file mode 100644 index 000000000..670291b8e Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt new file mode 100644 index 000000000..a010eee16 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt new file mode 100644 index 000000000..b31c28a6f Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN2CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN2CACert.crt new file mode 100644 index 000000000..3aab55b46 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN3CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN3CACert.crt new file mode 100644 index 000000000..f1af18eac Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN3CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt new file mode 100644 index 000000000..e40c5f06b Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt new file mode 100644 index 000000000..94247454d Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN4CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN4CACert.crt new file mode 100644 index 000000000..141eb7264 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN4CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDN5CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDN5CACert.crt new file mode 100644 index 000000000..a0d06284a Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDN5CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt new file mode 100644 index 000000000..10f0b35d2 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt new file mode 100644 index 000000000..83fabc569 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt new file mode 100644 index 000000000..07fcc37a5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt new file mode 100644 index 000000000..2001bfa39 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt new file mode 100644 index 000000000..e3723693b Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsURI1CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsURI1CACert.crt new file mode 100644 index 000000000..d0dbca5ee Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsURI1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/nameConstraintsURI2CACert.crt b/crypto/test/data/PKITS/certs/nameConstraintsURI2CACert.crt new file mode 100644 index 000000000..bf988e6d6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/nameConstraintsURI2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt b/crypto/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt new file mode 100644 index 000000000..6855fbe46 Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlyContainsCACertsCACert.crt b/crypto/test/data/PKITS/certs/onlyContainsCACertsCACert.crt new file mode 100644 index 000000000..055d8aace Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlyContainsCACertsCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt b/crypto/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt new file mode 100644 index 000000000..f8fc85e7a Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt b/crypto/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt new file mode 100644 index 000000000..26ee389ad Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt b/crypto/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt new file mode 100644 index 000000000..3c444e1e6 Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt b/crypto/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt new file mode 100644 index 000000000..3b0969977 Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt b/crypto/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt new file mode 100644 index 000000000..4889d5ce8 Binary files /dev/null and b/crypto/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint0CACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint0CACert.crt new file mode 100644 index 000000000..73c9433c4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint0CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt new file mode 100644 index 000000000..f66228e11 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt new file mode 100644 index 000000000..c5cdea3df Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint0subCACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint0subCACert.crt new file mode 100644 index 000000000..c51de222e Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint0subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint1CACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint1CACert.crt new file mode 100644 index 000000000..b1da15b82 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint1CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt new file mode 100644 index 000000000..02aeffa91 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt new file mode 100644 index 000000000..0a94f5f4f Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint1subCACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint1subCACert.crt new file mode 100644 index 000000000..a84fb534a Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint1subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6CACert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6CACert.crt new file mode 100644 index 000000000..d89052bd9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt new file mode 100644 index 000000000..4b220169b Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt new file mode 100644 index 000000000..b25ba34cb Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt new file mode 100644 index 000000000..ca87ee8bf Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt new file mode 100644 index 000000000..2b88eb6d7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt new file mode 100644 index 000000000..de511c4d9 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt new file mode 100644 index 000000000..c6e6096b0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt new file mode 100644 index 000000000..9c9dc4e15 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt differ diff --git a/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt new file mode 100644 index 000000000..2729261cc Binary files /dev/null and b/crypto/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt differ diff --git a/crypto/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt b/crypto/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt new file mode 100644 index 000000000..1a79b8158 Binary files /dev/null and b/crypto/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt new file mode 100644 index 000000000..0eb93be3f Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt new file mode 100644 index 000000000..f96129ec7 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt new file mode 100644 index 000000000..c0d9b49c0 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt new file mode 100644 index 000000000..497d53a8b Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt new file mode 100644 index 000000000..b3406b122 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt new file mode 100644 index 000000000..1544bbb75 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt new file mode 100644 index 000000000..0166d99f3 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt new file mode 100644 index 000000000..8018f6afa Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt new file mode 100644 index 000000000..7ec4e4944 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt new file mode 100644 index 000000000..285a05c72 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt new file mode 100644 index 000000000..f29b37f27 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt new file mode 100644 index 000000000..a1f20a3a5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt new file mode 100644 index 000000000..c2a9c464f Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt new file mode 100644 index 000000000..9f9ea5bff Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt new file mode 100644 index 000000000..3d0f27852 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt new file mode 100644 index 000000000..a14f9d474 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt new file mode 100644 index 000000000..ef2010b4d Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt new file mode 100644 index 000000000..99d31d162 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt new file mode 100644 index 000000000..99afa4d14 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt new file mode 100644 index 000000000..9abe48ddd Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt new file mode 100644 index 000000000..cac6bb62e Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt new file mode 100644 index 000000000..d55d884c5 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt new file mode 100644 index 000000000..1c9aec850 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt differ diff --git a/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt new file mode 100644 index 000000000..ecd5f45a4 Binary files /dev/null and b/crypto/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt differ diff --git a/crypto/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl b/crypto/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl new file mode 100644 index 000000000..d4871b55f Binary files /dev/null and b/crypto/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BadCRLSignatureCACRL.crl b/crypto/test/data/PKITS/crls/BadCRLSignatureCACRL.crl new file mode 100644 index 000000000..b1658c34f Binary files /dev/null and b/crypto/test/data/PKITS/crls/BadCRLSignatureCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BadSignedCACRL.crl b/crypto/test/data/PKITS/crls/BadSignedCACRL.crl new file mode 100644 index 000000000..e0ded9b4c Binary files /dev/null and b/crypto/test/data/PKITS/crls/BadSignedCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BadnotAfterDateCACRL.crl b/crypto/test/data/PKITS/crls/BadnotAfterDateCACRL.crl new file mode 100644 index 000000000..1ec2a0e81 Binary files /dev/null and b/crypto/test/data/PKITS/crls/BadnotAfterDateCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl b/crypto/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl new file mode 100644 index 000000000..1a96d0f76 Binary files /dev/null and b/crypto/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl b/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl new file mode 100644 index 000000000..fed48645b Binary files /dev/null and b/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl b/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl new file mode 100644 index 000000000..053471f83 Binary files /dev/null and b/crypto/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl b/crypto/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl new file mode 100644 index 000000000..7370ed295 Binary files /dev/null and b/crypto/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl b/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl new file mode 100644 index 000000000..dee61837e Binary files /dev/null and b/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl b/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl new file mode 100644 index 000000000..4e7e0145b Binary files /dev/null and b/crypto/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/DSACACRL.crl b/crypto/test/data/PKITS/crls/DSACACRL.crl new file mode 100644 index 000000000..46463c8a2 Binary files /dev/null and b/crypto/test/data/PKITS/crls/DSACACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl b/crypto/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl new file mode 100644 index 000000000..5bf724527 Binary files /dev/null and b/crypto/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl b/crypto/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl new file mode 100644 index 000000000..40387d3cf Binary files /dev/null and b/crypto/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/GoodCACRL.crl b/crypto/test/data/PKITS/crls/GoodCACRL.crl new file mode 100644 index 000000000..2fdc3cc1a Binary files /dev/null and b/crypto/test/data/PKITS/crls/GoodCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/GoodsubCACRL.crl b/crypto/test/data/PKITS/crls/GoodsubCACRL.crl new file mode 100644 index 000000000..963d7033b Binary files /dev/null and b/crypto/test/data/PKITS/crls/GoodsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl b/crypto/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl new file mode 100644 index 000000000..9c5d1b278 Binary files /dev/null and b/crypto/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/LongSerialNumberCACRL.crl b/crypto/test/data/PKITS/crls/LongSerialNumberCACRL.crl new file mode 100644 index 000000000..55f39b844 Binary files /dev/null and b/crypto/test/data/PKITS/crls/LongSerialNumberCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/Mapping1to2CACRL.crl b/crypto/test/data/PKITS/crls/Mapping1to2CACRL.crl new file mode 100644 index 000000000..36e07e1e3 Binary files /dev/null and b/crypto/test/data/PKITS/crls/Mapping1to2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl b/crypto/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl new file mode 100644 index 000000000..025b6bbba Binary files /dev/null and b/crypto/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl b/crypto/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl new file mode 100644 index 000000000..99f12535d Binary files /dev/null and b/crypto/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl b/crypto/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl new file mode 100644 index 000000000..f91729cc1 Binary files /dev/null and b/crypto/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/NameOrderCACRL.crl b/crypto/test/data/PKITS/crls/NameOrderCACRL.crl new file mode 100644 index 000000000..4cd201583 Binary files /dev/null and b/crypto/test/data/PKITS/crls/NameOrderCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl b/crypto/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl new file mode 100644 index 000000000..99514d7a4 Binary files /dev/null and b/crypto/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/NoPoliciesCACRL.crl b/crypto/test/data/PKITS/crls/NoPoliciesCACRL.crl new file mode 100644 index 000000000..b77586bc6 Binary files /dev/null and b/crypto/test/data/PKITS/crls/NoPoliciesCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl b/crypto/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl new file mode 100644 index 000000000..c7d5b1d63 Binary files /dev/null and b/crypto/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl b/crypto/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl new file mode 100644 index 000000000..f121dff3d Binary files /dev/null and b/crypto/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P12Mapping1to3CACRL.crl b/crypto/test/data/PKITS/crls/P12Mapping1to3CACRL.crl new file mode 100644 index 000000000..451d1986e Binary files /dev/null and b/crypto/test/data/PKITS/crls/P12Mapping1to3CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl b/crypto/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl new file mode 100644 index 000000000..b063e6bce Binary files /dev/null and b/crypto/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl b/crypto/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl new file mode 100644 index 000000000..6dcdf05d9 Binary files /dev/null and b/crypto/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P1Mapping1to234CACRL.crl b/crypto/test/data/PKITS/crls/P1Mapping1to234CACRL.crl new file mode 100644 index 000000000..70febec74 Binary files /dev/null and b/crypto/test/data/PKITS/crls/P1Mapping1to234CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl b/crypto/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl new file mode 100644 index 000000000..8ee779929 Binary files /dev/null and b/crypto/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl b/crypto/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl new file mode 100644 index 000000000..8cf52dc8f Binary files /dev/null and b/crypto/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl b/crypto/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl new file mode 100644 index 000000000..51482debf Binary files /dev/null and b/crypto/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP1234CACRL.crl b/crypto/test/data/PKITS/crls/PoliciesP1234CACRL.crl new file mode 100644 index 000000000..48c6b1a6f Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP1234CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl new file mode 100644 index 000000000..aa8426312 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl new file mode 100644 index 000000000..ae1a01941 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP123CACRL.crl b/crypto/test/data/PKITS/crls/PoliciesP123CACRL.crl new file mode 100644 index 000000000..deb37062e Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP123CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl new file mode 100644 index 000000000..ecd65f87b Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl new file mode 100644 index 000000000..51f09f6d7 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl new file mode 100644 index 000000000..5d6fb365d Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl new file mode 100644 index 000000000..07908f67d Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP12CACRL.crl b/crypto/test/data/PKITS/crls/PoliciesP12CACRL.crl new file mode 100644 index 000000000..5b090b05b Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP12CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl new file mode 100644 index 000000000..d2f29b792 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl new file mode 100644 index 000000000..bd4cf7576 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl b/crypto/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl new file mode 100644 index 000000000..774bc7325 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP2subCACRL.crl b/crypto/test/data/PKITS/crls/PoliciesP2subCACRL.crl new file mode 100644 index 000000000..7d7ba76b0 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP2subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/PoliciesP3CACRL.crl b/crypto/test/data/PKITS/crls/PoliciesP3CACRL.crl new file mode 100644 index 000000000..9d81c6da9 Binary files /dev/null and b/crypto/test/data/PKITS/crls/PoliciesP3CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl b/crypto/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl new file mode 100644 index 000000000..63ed6556f Binary files /dev/null and b/crypto/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl b/crypto/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl new file mode 100644 index 000000000..e088ab148 Binary files /dev/null and b/crypto/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/RevokedsubCACRL.crl b/crypto/test/data/PKITS/crls/RevokedsubCACRL.crl new file mode 100644 index 000000000..c77ffa358 Binary files /dev/null and b/crypto/test/data/PKITS/crls/RevokedsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl b/crypto/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl new file mode 100644 index 000000000..c7f5c7acd Binary files /dev/null and b/crypto/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl b/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl new file mode 100644 index 000000000..a85f99f7c Binary files /dev/null and b/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl b/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl new file mode 100644 index 000000000..4d159dd45 Binary files /dev/null and b/crypto/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/TrustAnchorRootCRL.crl b/crypto/test/data/PKITS/crls/TrustAnchorRootCRL.crl new file mode 100644 index 000000000..3ba3df615 Binary files /dev/null and b/crypto/test/data/PKITS/crls/TrustAnchorRootCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/TwoCRLsCABadCRL.crl b/crypto/test/data/PKITS/crls/TwoCRLsCABadCRL.crl new file mode 100644 index 000000000..fba92fae4 Binary files /dev/null and b/crypto/test/data/PKITS/crls/TwoCRLsCABadCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl b/crypto/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl new file mode 100644 index 000000000..fcb7488a6 Binary files /dev/null and b/crypto/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/UIDCACRL.crl b/crypto/test/data/PKITS/crls/UIDCACRL.crl new file mode 100644 index 000000000..0da091a66 Binary files /dev/null and b/crypto/test/data/PKITS/crls/UIDCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl b/crypto/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl new file mode 100644 index 000000000..9ee2a2354 Binary files /dev/null and b/crypto/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl b/crypto/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl new file mode 100644 index 000000000..3d7de0022 Binary files /dev/null and b/crypto/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl b/crypto/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl new file mode 100644 index 000000000..efbdae412 Binary files /dev/null and b/crypto/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl b/crypto/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl new file mode 100644 index 000000000..de7111393 Binary files /dev/null and b/crypto/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/WrongCRLCACRL.crl b/crypto/test/data/PKITS/crls/WrongCRLCACRL.crl new file mode 100644 index 000000000..3ba3df615 Binary files /dev/null and b/crypto/test/data/PKITS/crls/WrongCRLCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/anyPolicyCACRL.crl b/crypto/test/data/PKITS/crls/anyPolicyCACRL.crl new file mode 100644 index 000000000..8506ea112 Binary files /dev/null and b/crypto/test/data/PKITS/crls/anyPolicyCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl b/crypto/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl new file mode 100644 index 000000000..15a7e3d10 Binary files /dev/null and b/crypto/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl b/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl new file mode 100644 index 000000000..9e5ac6215 Binary files /dev/null and b/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl b/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl new file mode 100644 index 000000000..dfbbec9f8 Binary files /dev/null and b/crypto/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA1CRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA1CRL.crl new file mode 100644 index 000000000..fb562aaa6 Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl new file mode 100644 index 000000000..9a76c5cf1 Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA2CRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA2CRL.crl new file mode 100644 index 000000000..36d66fe6d Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl new file mode 100644 index 000000000..713d54a4c Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA3CRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA3CRL.crl new file mode 100644 index 000000000..4527c9a8f Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA3CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl b/crypto/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl new file mode 100644 index 000000000..bfb3c1d63 Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl b/crypto/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl new file mode 100644 index 000000000..b9a591e1a Binary files /dev/null and b/crypto/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/distributionPoint1CACRL.crl b/crypto/test/data/PKITS/crls/distributionPoint1CACRL.crl new file mode 100644 index 000000000..1be74de20 Binary files /dev/null and b/crypto/test/data/PKITS/crls/distributionPoint1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/distributionPoint2CACRL.crl b/crypto/test/data/PKITS/crls/distributionPoint2CACRL.crl new file mode 100644 index 000000000..5bdc14914 Binary files /dev/null and b/crypto/test/data/PKITS/crls/distributionPoint2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/indirectCRLCA1CRL.crl b/crypto/test/data/PKITS/crls/indirectCRLCA1CRL.crl new file mode 100644 index 000000000..6eed456cb Binary files /dev/null and b/crypto/test/data/PKITS/crls/indirectCRLCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/indirectCRLCA3CRL.crl b/crypto/test/data/PKITS/crls/indirectCRLCA3CRL.crl new file mode 100644 index 000000000..02be17931 Binary files /dev/null and b/crypto/test/data/PKITS/crls/indirectCRLCA3CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl b/crypto/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl new file mode 100644 index 000000000..166a457ea Binary files /dev/null and b/crypto/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl b/crypto/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl new file mode 100644 index 000000000..b870a7fa5 Binary files /dev/null and b/crypto/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/indirectCRLCA5CRL.crl b/crypto/test/data/PKITS/crls/indirectCRLCA5CRL.crl new file mode 100644 index 000000000..25c2e8145 Binary files /dev/null and b/crypto/test/data/PKITS/crls/indirectCRLCA5CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl new file mode 100644 index 000000000..301f7456a Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl new file mode 100644 index 000000000..ab1364573 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl new file mode 100644 index 000000000..46c0e0c00 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl new file mode 100644 index 000000000..1ee4b77ea Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl new file mode 100644 index 000000000..af4fff09e Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl new file mode 100644 index 000000000..3b6b35c33 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl new file mode 100644 index 000000000..07f5e3de2 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl new file mode 100644 index 000000000..373bdebbe Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl new file mode 100644 index 000000000..e56b61c9a Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl new file mode 100644 index 000000000..1ebad7097 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl new file mode 100644 index 000000000..e3f4f9712 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl new file mode 100644 index 000000000..5291d66d1 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl new file mode 100644 index 000000000..9c155a976 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl new file mode 100644 index 000000000..dc7fe6836 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl new file mode 100644 index 000000000..9fcab42c6 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl new file mode 100644 index 000000000..ebcdc5bb7 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl new file mode 100644 index 000000000..36c2b7918 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl new file mode 100644 index 000000000..1fa7ac98f Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl new file mode 100644 index 000000000..3b1ac99ff Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl new file mode 100644 index 000000000..a19deb75f Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl new file mode 100644 index 000000000..c3ef69116 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl new file mode 100644 index 000000000..45df218ac Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl new file mode 100644 index 000000000..3ca93d4d0 Binary files /dev/null and b/crypto/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl b/crypto/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl new file mode 100644 index 000000000..6f02f8089 Binary files /dev/null and b/crypto/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl b/crypto/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl new file mode 100644 index 000000000..4abda7660 Binary files /dev/null and b/crypto/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl b/crypto/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl new file mode 100644 index 000000000..358e4e6a0 Binary files /dev/null and b/crypto/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl b/crypto/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl new file mode 100644 index 000000000..707c73c2c Binary files /dev/null and b/crypto/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl b/crypto/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl new file mode 100644 index 000000000..5e817b640 Binary files /dev/null and b/crypto/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl new file mode 100644 index 000000000..10c7389ed Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl new file mode 100644 index 000000000..9d33b7c9f Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl new file mode 100644 index 000000000..7a3949e5a Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl new file mode 100644 index 000000000..22aa2f9b1 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl new file mode 100644 index 000000000..da6fe6f80 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl new file mode 100644 index 000000000..83fd3a5e1 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl new file mode 100644 index 000000000..8c6fb506d Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl new file mode 100644 index 000000000..1797663c3 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl new file mode 100644 index 000000000..ae9f73a86 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl new file mode 100644 index 000000000..46dbb8812 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl new file mode 100644 index 000000000..94fa45e45 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl new file mode 100644 index 000000000..214093179 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl new file mode 100644 index 000000000..a4b047314 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl new file mode 100644 index 000000000..2042f6fc8 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl new file mode 100644 index 000000000..8f207e51e Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl new file mode 100644 index 000000000..b19c9de77 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl b/crypto/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl new file mode 100644 index 000000000..3dbc011d4 Binary files /dev/null and b/crypto/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl b/crypto/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl new file mode 100644 index 000000000..0993754a2 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl b/crypto/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl new file mode 100644 index 000000000..621dfa9bc Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl b/crypto/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl new file mode 100644 index 000000000..1aee7c2ba Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl new file mode 100644 index 000000000..3d5ff65da Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl new file mode 100644 index 000000000..83cce82f0 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl new file mode 100644 index 000000000..eb408f271 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl new file mode 100644 index 000000000..e333d2650 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl new file mode 100644 index 000000000..6837068b2 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl new file mode 100644 index 000000000..ef4ee3e05 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl new file mode 100644 index 000000000..45fcc0bbd Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl b/crypto/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl new file mode 100644 index 000000000..0fca68195 Binary files /dev/null and b/crypto/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint0CACRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint0CACRL.crl new file mode 100644 index 000000000..1e52e650f Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint0CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl new file mode 100644 index 000000000..69488c7ba Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl new file mode 100644 index 000000000..00295797c Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint1CACRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint1CACRL.crl new file mode 100644 index 000000000..9c069801e Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint1CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl new file mode 100644 index 000000000..61d007640 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6CACRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6CACRL.crl new file mode 100644 index 000000000..779c2b785 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl new file mode 100644 index 000000000..30fee13e3 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl new file mode 100644 index 000000000..71eafbb42 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl new file mode 100644 index 000000000..8d14b0c8a Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl new file mode 100644 index 000000000..24ecdde93 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl new file mode 100644 index 000000000..51b4ab70e Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl new file mode 100644 index 000000000..9e4e18181 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl new file mode 100644 index 000000000..5891e6308 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl new file mode 100644 index 000000000..217e5e57e Binary files /dev/null and b/crypto/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl differ diff --git a/crypto/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl b/crypto/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl new file mode 100644 index 000000000..6315186f4 Binary files /dev/null and b/crypto/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl new file mode 100644 index 000000000..5ac2d2764 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl new file mode 100644 index 000000000..569ff3e26 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl new file mode 100644 index 000000000..c614cbb1d Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl new file mode 100644 index 000000000..910c035ff Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl new file mode 100644 index 000000000..7bfbf7634 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl new file mode 100644 index 000000000..bc4845d41 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl new file mode 100644 index 000000000..802a6520d Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl new file mode 100644 index 000000000..6f84d3972 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl new file mode 100644 index 000000000..e14cdaa0b Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl new file mode 100644 index 000000000..883091750 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl new file mode 100644 index 000000000..c6817a34a Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl new file mode 100644 index 000000000..d1f5ad1e4 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl new file mode 100644 index 000000000..7203b19af Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl new file mode 100644 index 000000000..467e00472 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl new file mode 100644 index 000000000..96848db79 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl new file mode 100644 index 000000000..8bb7c1dbb Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl new file mode 100644 index 000000000..143dab515 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl new file mode 100644 index 000000000..8a9c8b363 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl new file mode 100644 index 000000000..43870fb63 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl new file mode 100644 index 000000000..48c70c0fa Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl new file mode 100644 index 000000000..3808af657 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl differ diff --git a/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl new file mode 100644 index 000000000..4ed5b0a13 Binary files /dev/null and b/crypto/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl differ diff --git a/crypto/test/data/asn1/masterlist-content.data b/crypto/test/data/asn1/masterlist-content.data new file mode 100644 index 000000000..d462f0d8d Binary files /dev/null and b/crypto/test/data/asn1/masterlist-content.data differ diff --git a/crypto/test/data/cms/sigs/PSSSignData.data b/crypto/test/data/cms/sigs/PSSSignData.data new file mode 100644 index 000000000..ab51e847c --- /dev/null +++ b/crypto/test/data/cms/sigs/PSSSignData.data @@ -0,0 +1 @@ +This is a test message \ No newline at end of file diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA1.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA1.sig new file mode 100644 index 000000000..1ecfd010c Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA1.sig differ diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA1Enc.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA1Enc.sig new file mode 100644 index 000000000..2f7e7b677 Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA1Enc.sig differ diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA256.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA256.sig new file mode 100644 index 000000000..114c592d7 Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA256.sig differ diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA256Enc.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA256Enc.sig new file mode 100644 index 000000000..28bb81108 Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA256Enc.sig differ diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA512.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA512.sig new file mode 100644 index 000000000..eb3429ba8 Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA512.sig differ diff --git a/crypto/test/data/cms/sigs/PSSSignDataSHA512Enc.sig b/crypto/test/data/cms/sigs/PSSSignDataSHA512Enc.sig new file mode 100644 index 000000000..91556c681 Binary files /dev/null and b/crypto/test/data/cms/sigs/PSSSignDataSHA512Enc.sig differ diff --git a/crypto/test/data/cms/sigs/counterSig.p7m b/crypto/test/data/cms/sigs/counterSig.p7m new file mode 100644 index 000000000..7d82b99c6 Binary files /dev/null and b/crypto/test/data/cms/sigs/counterSig.p7m differ diff --git a/crypto/test/data/hc256/hc128/ecrypt_HC-128.txt b/crypto/test/data/hc256/hc128/ecrypt_HC-128.txt new file mode 100644 index 000000000..fbc2fbd38 --- /dev/null +++ b/crypto/test/data/hc256/hc128/ecrypt_HC-128.txt @@ -0,0 +1,2337 @@ +******************************************************************************** +* ECRYPT Stream Cipher Project * +******************************************************************************** + +Primitive Name: HC-128 +====================== +Profile: S3___ +Key size: 128 bits +IV size: 128 bits + +Test vectors -- set 1 +===================== + +(stream is generated by encrypting 512 zero bytes) + +Set 1, vector# 0: + key = 80000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 378602B98F32A74847515654AE0DE7ED + 8F72BC34776A065103E51595521FFE47 + F9AF0A4CB47999CFA26D33BF80954598 + 9D53DEBFE7A9EFD8B9109CA6EFADDF83 + stream[192..255] = E7F8DCC6A1D42ECF6A49651F7C610657 + B1DF6E58FBEF6A246D6D4CAA83858839 + 86325BE2B4185B4D63D4BF766C5F4B73 + 0B89C3CD66018155DFE9D37B6F5C1251 + stream[256..319] = 6D21763B2FEBADB212AC71388FF93586 + 48AA1A0E874D3B6932D7F80A5657F88D + A44BDC16AA21E531E3E473CFE6FCA9EE + 20739339CE4F2DAC793210C8CC20897F + stream[448..511] = 5BB39DF39C64BFA13F2AAE924D3DF4FA + 22899838ADB609806C022C36180A3E46 + A547CFF7F4DE1151A81AED3646B2D86E + 1F0F3C22C92D3459593ED599D1A535DF + xor-digest = 1EFC3423B31F67D397923613A1169F54 + A35193C9A31484D48204A8380D19984A + AB3C53E44D0511C1CA13A3823A0B2C24 + 7602797C533F0D5251CD5FF60D4A4F5E + +Set 1, vector# 9: + key = 00400000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 80978AC0647C7C5E3716B3B3DD9A3FD6 + EE0EC133F29A0F2F92E3F7AEFFE8CAD2 + 789DB433255F7A9F2A9D0873B8932032 + A7FD7EE6D07C903738B78E88DC173674 + stream[192..255] = E314E449A75D8CD4FB0BF8BB133915EF + 0471D3824CCB9CF828F2086EED1E09EF + 78E510E0D7362275CFECE3F2D79F5B37 + 8C8F21D3817083098E1D3918DC49EB13 + stream[256..319] = BD9BD906D4AC9B0A0A68C1371DDD0BAB + 7D36784577856634034D9A7BAF3A8B06 + 1C29904A896A82526CCAED7899FCBCE2 + 619E6AEDA6D79B55C6EE7C97353486F0 + stream[448..511] = 163E7EDB8F4A866A0E1C991883B2A966 + 0DF6C547BA4C3E2D59AC014170872C73 + 220303B5AB4D7321CA0C25DF3E18D5D9 + 1D6B52A5C2369F4F764B7E4649674F89 + xor-digest = 2F1B2356F1149C6EE7694E217332E4CA + 33E47D0DB237E71D542A4BFDE033137D + C8085B39215AF06840E542E501FC0584 + 257B7F6DCD6297CABF03026A95A6E27D + +Set 1, vector# 18: + key = 00002000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 94DAB13AE0D2F9A65283C6AE98733110 + 1C4EE45EC812AD67DDF3D1F026B51B17 + 2D366C7E3B2D55E5AE7010A279D35B03 + 83B77E96C6B2434C3E6DDC2401D64AEC + stream[192..255] = 8199B6243A278FA6C07B430B6FFAAD83 + C2A40A1115DEB693B446504AD35615CD + C4881D06F2EC1EC5C189BC37C0F6AABC + C349FD461023A1B840C40B7E96A481E4 + stream[256..319] = A2FF8C499364E1E900EAE72A98399585 + 6C609132B14C83B191D49BF251E73EE2 + 0FC48469A1E72416F803CCB7C933A880 + F8343A8DE2AB9492190E86194680B21C + stream[448..511] = C442F7A0791CCC0F7E8D4CC454829E6C + 26811BE74AF8BC70276C4901277753CF + E44FACC0ECB82E9E5803CD08A316D9EE + 5B0A016185BEEF9FE94A3E64C8BCB161 + xor-digest = 53170F85C0661EBB8E0C595C6405CE21 + B9F19433C791DB8A71883E4E6BA31656 + 2268C2110CCF228AF6634A80599B6A0E + 24106DBA30C3098EE57A10B1604511E7 + +Set 1, vector# 27: + key = 00000010000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 0D3549E38106BC69495957DE0722C36F + B3362CB8BB2ECAAB49C99AA5455C4DC7 + 363E990AE7FCAB1F4648413DDC698D79 + 294F3FF36FD83C299AEE2772D34D057F + stream[192..255] = 3239C047E0DA62024EC64B1D8E8A5E0F + 6E89062774AB24D2B69A17FC7F4C6EA8 + 85F71AEEF1B7A36A559EEE29D422CD4E + 98733C99CF47472F1E4A406EC58A80EA + stream[256..319] = 1B1F13FBB383683E26371ECB23F49D0D + E3B0A224D96A1A87D63A6737614F0415 + DBAA27AE8107DA06E5BB62D96FE4502D + 7B92EB6B5AF180CE8C2373920C77292B + stream[448..511] = CDA9A705E95B0656600EE8CC654127ED + 0A8E362FACAC68B18C0C25CA57929F2B + 1761F0706FCB0E066338507BD04C7F62 + 0FC91BB6AD77D569E30547959578216A + xor-digest = 6D339778DCB212787325D09BA20110C9 + A9CAE09E5915DFB1F74BA59E9C610FEC + 7989F18AF4CE86AC3D135659F46DB2D3 + 59C08FC80B14E10AEC6B6701F661E86B + +Set 1, vector# 36: + key = 00000000080000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = A4E7B46F89DD8205C71F6453B1ED3924 + 5D7FBB100E7EBE4D1D27E69047AF47DB + 3575B3A580FB9591A5F794306CDFA3E1 + A0A61905827D5ED980F49932A5ABA561 + stream[192..255] = 364556E21E20C5816ED375B9C12C0603 + B680F2A4972EDA77AF198A2F015ECEA4 + 7171028016B99EEABE1DAA2131711466 + 6D3C1558218D95A8068E1780BF738C2D + stream[256..319] = 84F5E62E1E8D4AD21DFE9B3537172D6E + 3F4539DD15B5A55B38373E9787F0A4DE + 5F4D90B0D56C0E1F8A5F9C282A1F5567 + 342BF864960F27E5311A4FBE3B85CDF8 + stream[448..511] = FB062A1FD5E64D97489F24A4F12193CA + 9C6F4711C993C13742EEF14D88009DCD + FA40D295DB8959D1562DE734ED1AEF4C + 90D136852F37A4115757F21F40977025 + xor-digest = FB8B62297F1B5E510091057F075AD348 + 54FD949E9E35712E2F455D25AA7EC559 + D55FFCC3D6832865EBDA17EEF34A2CCE + C6758E6449BDE9D70B5071B2A1D5094D + +Set 1, vector# 45: + key = 00000000000400000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = DFAB6AB2296BDEB8D8B3F6A790F3885F + 093BAD3BE4E0BD63E43F69535F5E77CA + DBA06B447471B03D6A47D6BCB5AE4D40 + 03B8AF7738AB8EB4D5B9C6040A434A71 + stream[192..255] = 9313979FA86022D65C61D902DC0D4F9F + 98C1D026B710B03123812FEABEE5C0ED + 8973F8B97CF7E281EEE0A5135A01F0B1 + 4C6DC27B352CB349273EE5E34541C518 + stream[256..319] = B53E875AA400CB453C7DBF5CEEEE4D69 + 31763C844FEDD960E5410FC3A5E51B19 + 7D252502EDBE71D457461A9D0033E26E + C7F78BD9C39580695914941737645754 + stream[448..511] = DED32F71701CB0AB10C3062F1A15571A + E70F2E3AC7A533CF7C962B2F4C256A9E + 12EA7D7F7DEA955DE6C7CA512A7EB4B1 + 80CE31FDD1F38BD486EF438D52B791A8 + xor-digest = B0EBC9D8BCC2DC7E20BBB7063FA84B6C + 109A619BE7EC9DF5C9C6182AD692DED1 + 0F24329DA2E5C346A659F2DF60BA0F2F + E0169D173C4C75D26363A0D7DB40A195 + +Set 1, vector# 54: + key = 00000000000002000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 9D5E9AA4795B8B5E97E415BD1F14E697 + 3D5E1D148EC12743699A48DADD6EF61A + 4643E9A7C2D2F88D50A8B9A63E003367 + ADDD8DCC464EB1C0FA6C23D244E725C9 + stream[192..255] = 8DC91C4A6B3E6B88EB7EE1E0F7345718 + 6C80BCCEED7197FC98CB118EE13D9AE5 + 3EC8C6917F38FEE09C5C6F08E475E058 + 51D1E7D4EF0B24AB263F0AB5656E3E82 + stream[256..319] = BC2875569BEA6623C7E16A6A87C972C1 + 1EE3782148A48D51F6D9E32CFB42812A + 2D20A318F0D699C9E760159F591EB9DC + 9EF3429A2613FD30EF2C839FFFAC5D0C + stream[448..511] = 6733FAE7B9AE358748DCD6937D494F21 + 46315B363CC50E362C5F585FD350C462 + BD99DD69F2644043100A9E690302CF26 + 4436B96CC818B659555DE0ABCBCB911F + xor-digest = ECCE54CD5721D18E47CAE60E30741660 + 1F03D46F90A1110614728849445E66B9 + ADA53954F9E8DCB746CC4BCD4D82EA34 + 30767E2CF9BE6BF81E19382DB5A7677E + +Set 1, vector# 63: + key = 00000000000000010000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = A88EADE3DE0EB0BA73CE09E995540BF3 + B8DF7485F028B1C3C15D1F813E2C5413 + 5B004E1804EB6FD248505C998B5F2CCD + B3EC043B40FE7A532981F932D107776F + stream[192..255] = D81CAE569DEC3E6D22C83F043B64FC88 + 0B04116A646BBADC38B28848D17028D3 + 11535C1AE172CD85A9B2D3ED4D728FCD + 0A5289DA14D823578E5B8984AEE42671 + stream[256..319] = 18FF81D6F5D7678998B48A51CF0D024F + 5872A5C1084E20182A8C255938339D34 + 6798356AD957663C089939F896330C12 + 747C08E2BF752B4103661B98229FB5CF + stream[448..511] = 9B797430B254C3F4DDB6AA211254ED75 + 13A7403B62D5D1E2452E43DBCC7B50C8 + 266F82A5155D405A5B7E15E921AD8154 + 362799FFE25F1E7ADE3434B0862E9D10 + xor-digest = 983E10E11689266E4569A99855A4F642 + 9094FAEBEBCD68434BD771C8528FDC62 + D357A379A0D6D78B9543E9A4CCAA42CD + DC719C3C880A358B409477D670F55EBF + +Set 1, vector# 72: + key = 00000000000000000080000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 7ECBBF2FD6D7E521A15DD022D0988F7E + 319AC64A9ED55C72E2817AD91F778221 + 98A55A9E9BFC9D01C0BF8BCD9828001A + 18AED8C48E3F6633FA541B74A1799C62 + stream[192..255] = 1BC71E27C8EAF24C12E78A4F9FC8E000 + 625AE2FA2AB74483C8EE3ABB69C77B13 + 7DF6C9213A1EA8D6557F0C1688154B87 + BE22F1B87AEE346AF7AFDE02C4C2C776 + stream[256..319] = D2AF220214395745FA09AF2FBBCDB112 + 0A588713476B29479F48B92F278BF39B + 3048630F0EC091D1188E7CEFD4C6F8D2 + 709187581999E5DEE22745D21C03BCA3 + stream[448..511] = 995534950559F7F3D01A718891ABC639 + 3D64688DE7FDA76C1DCF2B81F6934EE9 + 4BE1DE90F720E073DB9E54DC101BF513 + 5ED06CA4684A73A506553CB8713E4FEC + xor-digest = 2E87F43F3622E1A512D0E540939727EA + A035F7D7C136FFD565BF639C00165F7B + 6C33B969DDD106EC9D4CFAB1FA0D5618 + FD17C64CC68E94DAF7DB9791B7DE16A9 + +Set 1, vector# 81: + key = 00000000000000000000400000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 2AAC5C088CC1EC5D579779B7EEEB7F9D + AEC2DF6224B8E39F9E74511E4E8CAD0E + 59E0BEFCFCFA73DA661B53350A470887 + 11B1ADC5304481515256C94204EAD340 + stream[192..255] = AA9240B5E98DD28D7CC6FDF07C61E536 + 069C5D4B818A96DFF41939A57DF9FE45 + 32F384A624B236064C1AFF1A37C8CE01 + 23B87B7903EBB91D6D83C69C684090B5 + stream[256..319] = FD816941100F6CCA2EFF27C275753702 + 8B371BB985E878229621CA3D0B4E6BF9 + 1F74BAF0C05F661C93B819092CF475E0 + C61EE25FC5FF6CC9BE274834E718EDC1 + stream[448..511] = 0A2B3B21DE9AE621B9DA45091AA26213 + EE2E560D32FA4CB8ADC6DD1AF7EA11DE + B4905EAC39580A5A89A68F85BED6CFFE + 820A79E20265488FBC9E266ADA0C4CFA + xor-digest = 60ABAD1341AA90112B53568014827D64 + A4A39E7CCCD78943018C685D0CC4DEB7 + EE7A203B7C88ED8996EA7B2EEBBECC7D + 86E53A4B5E0646BA59CA88144B032C9F + +Set 1, vector# 90: + key = 00000000000000000000002000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = CB3DF6C584DC8826BAD57EC5B98D644D + AFE6C749F0463744EE1CB03EC81DDEC4 + 4B4948C634552BF4760A0976C67BB2D4 + C53F7A7805FDCC68C3ADB7ADBDF9B509 + stream[192..255] = 0ABC3A02DEDCEE79E8C26D3667B085C5 + 30FD86A2CAB845CCD323075D7D6FD7A7 + 05E7532A5F630BDC205B1DE61DC29243 + A2DDC2750F9AF32EF0CD794EC074AA83 + stream[256..319] = FC4AD0FCAB98C2F3379E3A3D1B35DEE3 + 93B60A327A41BD5147DD17F315DBB5F6 + 625D67ACCF9A460C2CFDAD84403D4163 + EFF59D1356C144E6237A09044BCFF8CB + stream[448..511] = EFDAD499C277519887424DBEFAD5DB2C + 97C97CE5E512871B5CA81D9408F59B39 + 9E23B24AA57DC934C2F539CBCC6A9EE9 + 750B3A5D08ACEAFDED87C325D01CE866 + xor-digest = 7D8E173BD06363238A383D72422F5FAB + 941BA41199C462C2110E29E62350C9AD + 15780C3BC2B9092641A4702B9A696430 + E38F7D0F6FFD1AE59B82787A3A69CA0E + +Set 1, vector# 99: + key = 00000000000000000000000010000000 + IV = 00000000000000000000000000000000 + stream[0..63] = EBF5E178FA8E2E45F53B73AB15C2D54F + A48DEAC9529BDA434E857A809CC7C0F9 + D8F372BAE323FBF79874EC53EAD3928E + DB203A64C601A99BEE4C07473DDD3B23 + stream[192..255] = D461188EA8C5F22E8649B6FA7B68274C + D97EF513C81DA77CBAC826D9D20D9968 + 716FBDA415BBF064DBFCB7D5AE12F72D + 4DD1FC3670A553EE6F23CFDA400F6D9A + stream[256..319] = 031589CA9A8B0C09BD0CB167D3D49C2F + 873AA718E0C9B3A3A515A9D196C5382F + BB6CA5E3190FC20084F5A4D22DD92095 + 8E3A1883E30F7BFB55B40747B495FD49 + stream[448..511] = CF106A7EB0FD339B8EB67F09E2A27AFE + A4117C472AA64CF1A41850062266B48F + 92CB46600E87E811121959B19999BFE9 + 1C68A664A4C28ACC8AE5E6EA477D0A2F + xor-digest = 2480D3C1DCD26EE2B05D964B3CD526C8 + 4E39E6FF48EC793FB82F4AF928073D1D + 80887F9AED832951D4AB2FDB518B548F + EB5A42FE6454C19FCC101019B598A808 + +Set 1, vector#108: + key = 00000000000000000000000000080000 + IV = 00000000000000000000000000000000 + stream[0..63] = 2EABC4033A51B3901B6340BE32F808EE + A319582F21A7CF6633570E82AC879B60 + 3E438847D9E3719EAB71F8E3247FEFA5 + C07B2282AA2FA80CEFFA8E076304FEBA + stream[192..255] = F178E16CCB405A8025FA50215B109BFC + 9CE3A655DAD91BCC64D89BE115D4BC84 + 261DC0E440DAF6028D3AFEA13C9D53B1 + C38E2AA48153CCF3DD9791563E45A98C + stream[256..319] = 284E211A092241828DB7204310536167 + 653D66987537E004201DFF6290CD8C37 + 84AA31D76477908455CD4E1C51F907AC + 69893D7FD3D626989526F4E6891E82A0 + stream[448..511] = 043F1740552381D9A01C882DD0D542B4 + 8EE86ECF6B5D2A23B8EAECCA55224664 + 5702B29F7CAB606417CDCCAFD9B63ACB + CEC56E95C945B72DC457103B2C378A28 + xor-digest = 1A56CC2BC61F1A802CDF26A84BD37A9C + 86F903637E5A1BB21B5829994628B000 + 2A356A4D150DC529907786BAABD0C733 + 4500BE0DDC9D487EC6356B2ACD65946E + +Set 1, vector#117: + key = 00000000000000000000000000000400 + IV = 00000000000000000000000000000000 + stream[0..63] = BA81D9884075FC9E2F9938392EB10354 + 1AD1D4A599A6DAC3E33EEC59235C3559 + 4448E3DAB3B5A5F56DAF7B86B63EF376 + 3728193CCE74807DC7E26087D87BF7D8 + stream[192..255] = 1F91ECF0B6E889D6FD6FA97510D2EE3F + 91552978AC896D69B10A923F6F5CCA67 + 8320765AA5CDD2ABB4A5FB3CAF86C76E + 12280CABB4E74C8543C9D5B1D9B8268C + stream[256..319] = 31BF924BBD38F9FE050E17E50EB66C45 + 081DC5CF49F0F02610828A91F31D0B29 + AAB0D6123D69347ADA5CFB37C8AE5E70 + 38453B5194EA285F798179A875F75E70 + stream[448..511] = 78F5C37A21EEBAB00F7A80656D72AE39 + 5566B8114BA6EC8BCFE8C46D0CEB4C6A + BDE4E4F0F131BAC671F8186821CA01E8 + 69FAB184E938B93B56D1AA3C1D68D3AB + xor-digest = EFA43D76919EF92EED6AA30B4FD2E37D + 461D4377618426C2912493665FBB004E + 0C92A654CB660FB709681F460DD61825 + C7A7089737F5F5DA10023049A0595DBE + +Set 1, vector#126: + key = 00000000000000000000000000000002 + IV = 00000000000000000000000000000000 + stream[0..63] = 23C1F447C5496B37512923D74B61CF71 + 015A25988370C0F4E0E48194E4C3B72D + 0C9519F6A88D8AE9DD319A3C9160A6B5 + 51FFBAF27D374B3E6F624344D06BD06B + stream[192..255] = 019E730A2D0DD92CB417B1FCF42D2352 + 058F3B059E1FA4C489909E0B9B90944D + 9816E45E992893244CDEB5EA6AF79703 + F70CEC7C3E770D2A8310127B3EEA9026 + stream[256..319] = 3BA682C375554002E718ECEAE6768648 + 2442D9643AEB6E4D518A5146263B6BEC + 0577A4A0CCD7995F10B7F1312926C613 + B4BCFA28D37B85C7FE6CC64A26DBCD47 + stream[448..511] = 41D18A4275E2E4DBACDD91D3F79A186F + 6B2F48BBB64D47186C32910E86914BB8 + 74688AEE59998D8CF7635DDED58EA9E5 + C51DF64956C951C1F9123DC1C97A4027 + xor-digest = E7A40A98E52ACDD2CAD780E71312F128 + 8A73CDDD2CABD28EB767A045871861B7 + 680C64DE4986F508E8CAA04B49630B3B + DF931CAF478B2C3470E483F3D2EA71A8 + +Test vectors -- set 2 +===================== + +Set 2, vector# 0: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 82001573A003FD3B7FD72FFB0EAF63AA + C62F12DEB629DCA72785A66268EC758B + 1EDB36900560898178E0AD009ABF1F49 + 1330DC1C246E3D6CB264F6900271D59C + stream[192..255] = 76F5E28163A6F72F4AB72FCD90C69EED + EF6D5C73539F14E7CA0BF6A9F229F12D + 1492EFCFDAD11EE26DE44F0E843178D2 + C989D4F21FE9B53C03C12874E83A7026 + stream[256..319] = 3CDC1D88EDA836767090FB77DAE5ECC0 + 0F5BF5CA8879733FAC19E8DE5C725636 + 7E39E8C9C4EFCDD75DFA9660BBBEB584 + B5593DFF4566EAC37E857D9B9E21FF06 + stream[448..511] = 713B389BD7E1651A450C051B77F83A96 + DA277A370FCEBC4303A18AB1C5FF5342 + B319F0593A67F2BE6DE7D256CEC89F65 + 61FF60B8AB8621B6720206975269023F + xor-digest = 4943A339E572249ED48A06F45BD60AC5 + 26F1ED970617DC9DB29EFE99ACEC6C7B + 82C8F548503C3DC16E79C4D7D7B7C6C6 + 08CE84DC170A72286CEA1148D180A7BD + +Set 2, vector# 9: + key = 09090909090909090909090909090909 + IV = 00000000000000000000000000000000 + stream[0..63] = 4C76978E4BC79261F8608B3E5327AEB4 + 4F2F0305D5F6B6326E0127F00C50DEDB + 85F5915ED2D70C9BECA2866AEBE6D154 + A4CCD80AC88588CAF24FC805974C96A7 + stream[192..255] = 5875CA142FA9AC13170031C71A3619EA + ECC3D6E0692AC276E2CA29864643D364 + 56DFA39E1782D487F49402AE32CB739F + AE267CFC438495B292D21E6B4A21774B + stream[256..319] = 8CEB212AE637E8DE29AD64E7D0719338 + F41AFEB1F1022F30BE485B348722B7F5 + A57DE6F253C6B0828C6FB1EF6C59EEC5 + FAC3D7FCBAB8C6BDAE2310CE77ECA503 + stream[448..511] = 4810F2AEA6804ED4820E5B9E7ADD1F44 + 37EF320686F108947B42991ACC7C4887 + 635E57E9AA90EF29F831D7959936DD95 + 0F466666BB84280764F5557582FAC149 + xor-digest = 7EA2FDE204E339B9C85051F22A46587B + 3619F4F9AE11426F5470D9EAA1629476 + FF156BF2727CB6306E62BABB4A68E9AF + 610D50C8034C5D4E23BCAC487F3DCA03 + +Set 2, vector# 18: + key = 12121212121212121212121212121212 + IV = 00000000000000000000000000000000 + stream[0..63] = 38F35C0172088DC537AE80089719655F + E8671884235DB1F6477D776B8DD158A6 + F6914C168E9EDF0B1020C63EA1851D2E + FE1A343C98ED4B4B23E52451B9BDC3D6 + stream[192..255] = E88226EA0CA8B620A68402F83A1475C2 + 54C875FD5D27C935130FDE6DCE3EA050 + 4F121A7EBF6B572D6EB41240A65CD001 + 5007AFF6C2A8827CC0841A6170C08467 + stream[256..319] = 0ECB78E446AB9C763315031C95E570B5 + 5A5D89BA13A228B80D86797BE378D766 + 59B47D48AF0FDB4C3D439311963B0A0E + 1311E6FA792B089EE4797D9AD023FF5A + stream[448..511] = 44C71180BEDC7E3CD29F80B9922C1733 + 5D815207E848FD528572CF61612A42E0 + AD4AEC01D042461A8C30ED194940F82F + A442DFD9061C03A1B72592894A0C73BA + xor-digest = 127E8501304A0632B8FA27A23BB97321 + BCD67F699D39A35A4324D5E8AD368E0D + CF134D13FBBADE2FA930AFCA7D15FEC0 + B2682F0B09AAB3373069F6DAB9EA112C + +Set 2, vector# 27: + key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + IV = 00000000000000000000000000000000 + stream[0..63] = B90DA1C325244BDA08C319AA6B4ED7E8 + 3DEF56BF03ADFB2A46E9041F4498BE2C + 4B9F76E7AF98697B2835F2F4D4585320 + 36844D8FA3F34121D9BF624556A52BCB + stream[192..255] = ED912457955FE3EDB032F4E7C452A13D + 52361DAA3154A756B1C00B0079DBF782 + AD089F2C090691BF7B66695538402EFF + 893D27969913F25177C01F4CA2FF5195 + stream[256..319] = 0127342854571D0640F2C283104FD6E4 + 4FF9B9198492414C1803E36F01A2E79E + 3EF76F350542EFEA11419692B6A708F2 + 0A6D938306E9212B8F047207E7C5782D + stream[448..511] = B297A467A6D2770B2609C7DC1EA505F8 + 3A36223731550282001144B4DF3363BD + 49802CCDF59D22FC7C2CB7913B4FEFB9 + 49128A2BED699B55D24E5B26C52BE674 + xor-digest = 711ED121D562F49A3D3F66FE95540DC1 + A58F5703108A7C484A53EDC9FA7455D0 + D356D9EA792AC30009754E94CF63493A + 8AA3BEADC0E7D671DAC10390C841F9EE + +Set 2, vector# 36: + key = 24242424242424242424242424242424 + IV = 00000000000000000000000000000000 + stream[0..63] = 38D294B5B1ED0A38C5430A355A5A5949 + 0137741305AD7EB6159A1B97A956648F + B27C16F507D5D5FF8E2B779BFF22CFD8 + DB4C7CF7FA78CBB20445D2F94518174E + stream[192..255] = FE70A06921BC304689079DDFB4CD4BBE + FC64B0C8E014A65F6D84A804E8F8F1A1 + 371D470977F033ADCA960346B189E848 + C899CD90446D5074C3C1EE48DD40F0C9 + stream[256..319] = C9B90ED55AD83A8DE0547000ABD0A633 + 653ED5D3B62EB16D2C3E176952786205 + AA702C32FC37DCDB714D8BB81E488438 + 43B805F2FF5ECE2E6C0A4A4BA5746561 + stream[448..511] = 396490C2E87DDA2FC2F9FD4D2E468A91 + A826ED3FB2AEE07DAB6E33EBB5D657B3 + 2488B38BEE6E316DEA6439979112CC62 + 0989E9907AD83A9479DF253A75FC6683 + xor-digest = 5478F54C1B95FFD16C6C873F900181F4 + EE33E5CB58CD28259E19645FF36B4419 + FF92A289E9C355E769D0CF6F004BB256 + E5134627E4E99459CA3916BC1216312E + +Set 2, vector# 45: + key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + IV = 00000000000000000000000000000000 + stream[0..63] = 0188DFBDAB2AA5D4996601E8CBC5AEE1 + 5254491641DCF5DEB7414FC751D52E56 + C253A98157200CE0C142C355AB961015 + 04991380F77C287212145552C000CFA2 + stream[192..255] = 6957E2069E8F1042C6A46AC8ECAD2439 + 0DB5739043E911FB9BBE4A7071A88B14 + 2867E45971D7C19BAAC4333BC176230A + A67A081EA89728380B00F5173E866B89 + stream[256..319] = B47E8222962EDF8B3CF7E4DF469C81F0 + 40431EE27D2CCC1C5D2B048C6E986681 + 9656F8E23714A227341795A9B881A776 + 9434923C01D25B4B2D60D0EA89580F82 + stream[448..511] = 89E48ABDB1A7F5BF17EC7304A951B1E5 + D152EA7EE181DD9866ABD782C7FCF238 + 66871D0B1EA30527CC178D0FBB0E6D8A + C5CDAFB27F01B7B6AA68413B3E7DCA6D + xor-digest = DFB99C93E6B26D2F079414A370EFCA10 + 5468E93AB8983DE0AAA1AEE3F8FCD068 + 3C20753931A9B13F48F10C9F71F99638 + 1AACA39469AD3EC6BC8B2ACB1DB9ECC9 + +Set 2, vector# 54: + key = 36363636363636363636363636363636 + IV = 00000000000000000000000000000000 + stream[0..63] = 6EC768666ADE02892FF522A9422F5B3D + D802727755D64C602C5BE156DCCC690D + D0237CF95B191BD29BEE5E030E1EB4B2 + CA981BED69F2F4FEBA39C9658450D21A + stream[192..255] = D62AED496AD8BC9EAE570843460EFF9F + 8CAA155E3B1619341D43D416A89C85EF + 2186E398467C6763C6B38AE8AC642391 + 39FC7D77C5DE1BF0304237527ECEF79E + stream[256..319] = FD2A2505BC2484CD26A953A460D43EB3 + 500DB0572509C1409AFB25DAF7A08E96 + 8C45901DD9943AC3558FE2D956045AFA + EC7FE93AFA7AC461E348A6FF67DFD8B9 + stream[448..511] = 1A9AAF97AD789E4003BF48E9B723EBCE + F2DB13513398FF8161D929F64C5603BE + 2D0B89D1B94E2C4A91468EF743C2A745 + 98093DC6EB5069213A1423FBD5526B80 + xor-digest = 93DD39B5F82C8B105C9A1D3CA17AEB09 + 21E77AF3235E3DC1F626D690D9306698 + 60DB7382B38C6F3EE0F250DBB67E8001 + 078938ACC2DCDFE3DC5E2F33FB4EEE51 + +Set 2, vector# 63: + key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + IV = 00000000000000000000000000000000 + stream[0..63] = 6D05510EF24AC345594E94F58E6F5024 + 1B40AA1CD6A62F35BC303CACBB263253 + CDDF54462EC606D6969E4CC5FB719A7C + 107DB872A5119566BF72FE37363E60E8 + stream[192..255] = A1626164C36C6AB010B9A2B944ED8839 + 13A3B9522F66429A75F5E30A03961871 + 26AF86AEF382E3944B0414B274859B4A + 93881386E6A3E780802B0E6894739442 + stream[256..319] = CBC22EEB532BE4B8B80D7F10A00FFFC6 + 22A02B7426DBF648AF398444B8F8D2FD + E4265F1B50CB43B003DDB0256D9E0A10 + 99BCDBDE162E8AA37B107B316B9673C3 + stream[448..511] = A7F2D829EF3BEADAE6D84CA26C81E618 + 6F70F3D9DA4E208754EFAA5A0441D87C + 7AE36AF993E7225A9C68764C87B5DA4C + C08B54A245A296EBF399B91331A6F286 + xor-digest = 55A30CB34036E3A22AAE25981272C8F3 + 6392347B5FCE8101A66023C5B324867B + 783EA103A714E749F14375CE64985A0B + 8ACECA137560D12E941228D04A968513 + +Set 2, vector# 72: + key = 48484848484848484848484848484848 + IV = 00000000000000000000000000000000 + stream[0..63] = 89C61A1182BC868BEDA3FE4A76CD679D + A3DF3A656AAD3AF83BB55C0F0455AFCA + 1B3FBAD0B91F7B1F209E5F74FDBD700D + 9417BF9B4A22BD3B7C94317C20ACCFE6 + stream[192..255] = 1C312223B46A20BAB52F110E04AB324A + 068E6DBDB1EABEA92CDC5063E38B7EB9 + A7DB50FC4CC626761CC00B7D821EB0E2 + D40F7C8DD10F5A975A14689151B38B77 + stream[256..319] = B38D45E3CEC551950D662FAE4241E3BC + 5FC8FFA67A472B1048F45D594EA0715A + 5B1DE277264D72251A3C5024C914A0A8 + 14747D714F8CC583105013382518A0F5 + stream[448..511] = 42D47BDA13625C17FC6E972E68F3AA7C + F8F9F12B900AB9E474C0295B48879DCC + 0832FD53C3C90B641454AB4BA90DD7D4 + 1748F4AACC9AB1E1CDA8007B3B18B1F1 + xor-digest = 131A1E29ACA16C3A409ED6E201559CF3 + 3CD05312376DBF6796D39E2877D23255 + F3308D3419CBEA800F1F2E9DF7AA36CD + 03AC3D6BD228A165A885824941D764C6 + +Set 2, vector# 81: + key = 51515151515151515151515151515151 + IV = 00000000000000000000000000000000 + stream[0..63] = 70977581BC650C5D03F1B3A02672C384 + 250692C2AC94EA0F4A43723E88FE587C + 00B5319F87223F6817C36F21FB852995 + 5CCCAE243D65792A55D6F047DDE1999E + stream[192..255] = C00B41DD0BE80054F46ECE559526ED5F + A87E7196A3A20698F5048183F91ABACC + 9E50AB64D437F05375CE78D75469EB7D + 478810E1C792CE3BA0C253FB1E549A0C + stream[256..319] = C95C6CE222392307CABC95202CE59EEB + 160A25C482F4608616C80B50A9D0B771 + 732262DA67BE8319486F73E4B1FE3DBD + 1B7C97516F0ED02F1F4ABE9141329925 + stream[448..511] = 93984394395B47A34FBEDD96E50A1F67 + 7DCFB1845CFAFEB7DD83A9A7BFA35C7E + 48E44C38F9D33B3CFBB763A79048F6F7 + B6F32386329AC979F7EDF8828734A116 + xor-digest = DF2A33DFE7C90E76DB4E4F2D9AE2AB69 + EA16664B5E0031D800913B6572E1E2C9 + AD4A31D6BB088AA082195F8B4DA56605 + D32A19916474C042F755AB11EE56F6E1 + +Set 2, vector# 90: + key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + IV = 00000000000000000000000000000000 + stream[0..63] = A266B810953284ECAD69E960C9AC8FC7 + 0B94798E55BF7D2EF54EE50319574C28 + 7DF798958FD653B5E5BBAC0519D3F40C + 4372DB7204A3FFF89F6E70BE245C30B4 + stream[192..255] = 72979FA8747EC91B68EECED4820CE7F3 + 8EF0F20240D8E04C5004D10880BBE17F + 673A427D0FD62E8331BA633890D062CD + FE584ECEB2884AB4086E3AD04F9C1137 + stream[256..319] = 77E9FD26E216E6F22D32AA89E4D02C33 + 482570BE05C0E1FAD59DCDC5A3F1315D + B2FE99C4863DE4512EDBBF45DDF51CB2 + EF472481D6BB7EF8C7AA09E45B03F45F + stream[448..511] = 0386E999B6EDB2E52F86B3792A8BD15A + FBC40B44D6EAFAA0D562C6FB2BD16BAA + 3F77F968925DA020D36A109A67ECEFA1 + CC278F022B93169006D79C0F56351DEC + xor-digest = 35BCB2796B3AD76E59C2BDA7EBD7B47D + C99236FAF5F2186188114C1A958185C6 + 48BA837A3B839CCCF55FBA67B21DB031 + D7BAB7AF52A98676CFE3EE4249A530DA + +Set 2, vector# 99: + key = 63636363636363636363636363636363 + IV = 00000000000000000000000000000000 + stream[0..63] = 14F782FCF5C88052A93AEF40492669AF + 7C92F72147C2AB2C18217144055C9868 + 3E2FBB80775B54D119A9A06AE72EEFAB + 999E85F3AE12804FABCAE539A8585492 + stream[192..255] = 663FFAE38877EF1898973355FA27E9E7 + 0BC0034A88C1ABBD2847C46335C18113 + 47F42E18C1295D07D5F75909F0B1C0AB + 45EEBED3356A930E018E262655074944 + stream[256..319] = 6ECB3BB43DC1C4A3FFE0EAECE58B07B7 + 1CB5C7763DF420859853C7973778F63B + 10EB1B854BB8CF1DA0D5DCE6EA0D5816 + BA0508E7A1694ABDE04A706A008252D8 + stream[448..511] = A68ECAAD1CF25C78522FB75D08C8CFEE + 561C2CAA9E0D44EEDB121228F4809F50 + 996B9DB89E2E2F8547578F83015C55F4 + ABE82F371A5E02CC97FC35FE7DA49AD3 + xor-digest = 83F0BDBDF9A82287A650BC70A0C8F38D + 92868DF38D150E4268526A0A51D3A9A6 + FDA27D6FDE8A1A55E856DC891B35ECA9 + 1D583E0470419BAB5C0B9ED4886342B4 + +Set 2, vector#108: + key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + IV = 00000000000000000000000000000000 + stream[0..63] = 359B9D751379BECE129238C22647B90F + A849534C9395EDFA5F2121963D2F0B68 + D9C6469AC8A192FACBA7C27762B22D8E + 39171D3D01D6BB41CC4F2AC318407D65 + stream[192..255] = BB4795A89BA6AC0869B2BBA5891FC1E6 + 890F13DCDE5CBBCB22A85014E554BF10 + DCB0873D79A79438F39DB467E23EE1E6 + 2D2A549DC86B89FA3DF53BA5E5195718 + stream[256..319] = 7AD5CF48C01B51572FFE4E0D23FF158E + 46941F1B1BB5D7DED2BFE80BCC48A6CF + 3DBB186AD1D3F911ACD8426B2A1219A3 + 032104E3EE70717FA7D547014FD334AC + stream[448..511] = 6320933C389A66B5BD72DD69BA492432 + 01861F3524C529DC2869127BA41DEEEC + FCA5D5BA7521DED5166E70FCEC72A564 + 545FE45F29A2DA9DCCD5AB80DFD119D1 + xor-digest = 9E1E8A8A4FE661C660DA51134D1C8A65 + 3824DC5A99715E88F17245436F07E283 + E481D9B0A314B2DC9821930C80F8A184 + 2F33F4219525F3DD063CB9C32D9AAC60 + +Set 2, vector#117: + key = 75757575757575757575757575757575 + IV = 00000000000000000000000000000000 + stream[0..63] = CD479075E614524CA0B4A73BA48632FB + 01C8E9DA532912094D14606F08B81C0A + CD7556942CC4FE4900C4419E8F618AED + B53261B5B97603DC21F5FC8D57887F0E + stream[192..255] = E69AFA41D5DCC57CEE46FFF86551AE30 + D7A4B7CD2082BA8B9F446BA1A8E01B55 + D924E0D788A01D7C75B819D8B88C4074 + E97E1781061DDB3AF084A45E5A2D67D7 + stream[256..319] = 27F75AB01FE45DBF6E661D39159A8727 + 15AB7D7CB1275A11AA3C8CD55708A67A + DCBE98FD8E1DF1F787F099881C87A3C2 + A0135088B99B21631AD115A8247BD280 + stream[448..511] = A75C019250930742A65637B2E60A43E4 + 1891CE1252082CA86891A684C19304EB + 7D57EAA4F8DF4686D05E886C5496C37F + C224455AAE45F071FA654FC88CCBE17D + xor-digest = F5C14A26F22546515005E433E1F825E3 + 6395F5B59566C11C79F0435389DD7745 + 793F8C925E68A9836B6E7B03C0639FCC + CCBB3C1758E28E9DBAB1D9F733AEE7DD + +Set 2, vector#126: + key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + IV = 00000000000000000000000000000000 + stream[0..63] = 1AFC41EB0B3A1AE62127B62AE3B7219F + C34C0A9D904D21F071424A7D07A55E4A + 69AB9FB401909372445844A367C2ED44 + 69C12FFED293DE61619AF98FC5F159AC + stream[192..255] = 48080F88453788279BEAAD61B24BA5EE + 28F0044B5AAEBA5DD6844E2F57A0F3A7 + AF19BE8E7F6DF5BA7D74DEEF01CD5B09 + C928410B02532F66C19A3E677B04AFEB + stream[256..319] = 5D493BE7C17B1D6075F0CFF7C738CDAE + 8B5BB6126A1FDD8ED2FAD3A1502BBA0E + CAD26485BD94EC5FA852AC74FBABB070 + FBC0604F69C11F5725F644FD14E5D001 + stream[448..511] = 7D3D74044FEC8DF49C8A505CF1E5413F + A63F53ED43F4B90DB3CAB6EC08E65821 + F1384E84490C6E5631B021145565D234 + 67010AD6C9A5C729C774BFCAE2D43DC0 + xor-digest = E2B8D71D68ABBFA49D04DFC8A3DFC390 + FAFFCED207BCEB9EC4B6C435A9757AF4 + ADAF3E0734268365C82DE978634696B8 + D61EF69FAF3EF62CFCE89672F1CA7497 + +Set 2, vector#135: + key = 87878787878787878787878787878787 + IV = 00000000000000000000000000000000 + stream[0..63] = DFD7B8D57A6AE51A401FA8DF38395B37 + 17507AF28A9A771149C034F3361E0203 + ECE88C484F44DEB8370D9E77994EBE6B + E05CA8E05E3DCF545EFBA53859C2FBF3 + stream[192..255] = 42996981385309DC8884D65CF2103D64 + F76567EC51266A6DE5BEBC362529B782 + C95D92A17CF4567454422BC72D20BA56 + 9DBCCA81DCD694B2B3DD88A988004875 + stream[256..319] = 43C31B1EEAA67D7506A6CAE07CF9EB0C + 838C72494C14012F58B80D0F4D159379 + 68C860E32A029B3B0CA040AAEE262CE2 + 9C50046E1CE83FF36120D3CE81EA3BB6 + stream[448..511] = BA8D089901F2F5C83E1CD485BC178F12 + 88D1B700A7EE749DDA9A96910529EB5F + 057BC8FCBCD0D542FC3781E0FA742C3E + C616578C8ED918E8F104EDC142BC7B7B + xor-digest = C9D6AB2D64CC7BDB01F89F08047749AC + 38856667B53C87F8B501CBB5F18DDB84 + 820D409D5A44FBEF505213981D86241D + 279C6749D1D0B756BAE39390D754AB21 + +Set 2, vector#144: + key = 90909090909090909090909090909090 + IV = 00000000000000000000000000000000 + stream[0..63] = C60205FE3662A0905EA10CE1D17527A2 + 7565D227C895A8C9426069A9F0F48894 + A96AB80039477BD604762F5F2CB2903C + 7642EA714B27B365DFBFAF60A6E249BD + stream[192..255] = 88DC912DB28D5A2700EB74CE8011A307 + E2A0B8FA2E9B50E38899B4AF1A0F3BA1 + 79CF4DFE87DA0BCC1E76D9A56DB789FB + 18E439849D6B8B6850D0CF8A17726FEF + stream[256..319] = 2247A96C32B9BDC5DB41E7670DEC0A51 + 73EFD83F345DE71CE0A2192354395576 + 4101D73BCB2051C08DA70CA5100C7194 + D22A6C3DADF313369CAF8E545E97E25A + stream[448..511] = 83089E1CCDEF294EDAC0006D6CF49475 + E93324D10A6EA635B2C19D285B58226F + AE271B6166A5818C6C567CDDE508B9C5 + 264C2A6D5A8A4C7D6754CD11A58A6588 + xor-digest = 2B89AACFAAFFFCC15076A79EA8D983CF + FA2CBE2BBAB4BC70464E9801B585FA23 + 618864E62E573F51F1119D32E509A507 + 458DB29422896E0A29E44D2A96FC0B64 + +Set 2, vector#153: + key = 99999999999999999999999999999999 + IV = 00000000000000000000000000000000 + stream[0..63] = A6A3260212BC1A9FCD7336F1DEA05D75 + A48B1B1662F61B1CF1589A91AA66EB82 + 25F58E77BFE7DB10AC31F318ABBDA7B2 + FBA88A57CA8AAFB83A3ACD0D78AE9944 + stream[192..255] = C960FEA579A48D263C514DC4D7173B8C + A325A16B02C87086EFC38F3271087B48 + BC51FC4B8FE936BB87336D54D35E8B60 + F8300334D0A78B48D2E97751CA571ADC + stream[256..319] = DB1859630B7E5D59366E95EE9F680F48 + 1EEB9B880A3E82C85046552A844E5784 + 3D4BBBC50923E806A1E2B03499C4F869 + 9035913D5993757A5CE2A94311A22C17 + stream[448..511] = 792B3AFBA5A9EC89C8119FB8F1CD552D + 6ADFCD61B70481760EB52878CB907367 + B2A5082FD963F56ACCD0F5FE6B67ED48 + EE81ACCBF066DD4178D39E001A6A2027 + xor-digest = 45E67FC4B7FCCEE700CDDE0404160E21 + DBFA6280DCFDAD3865FEC930EFF1B3FD + 799161C8812EB27F6A24985298994FD6 + 5605325D0979CD798F0ECE18886C6E8B + +Set 2, vector#162: + key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + IV = 00000000000000000000000000000000 + stream[0..63] = 94DF00B66C81CEF99E47BCB9AA6B2E48 + CCB408E20D878C56A9328D2422F1436B + CCB7C8B04F8AA12BCF1DEE965EF098F3 + F78540213E755C86FA33B6117BE9E81F + stream[192..255] = DB745EADFB31EAE7A699A84FCD41EF80 + DCDC25334225F7B3E5D49FF58503C60A + 2FD73212719EA17F61F60271C9347E19 + 3A894816DBD39A313AEA33F56311309F + stream[256..319] = 75410B6F256D7E9D2C4DEA9F24766E0D + 1FC3EBC67A5EEC72BD45140C41C3ACF7 + C517E9D8BE1B0AA06668012FB1C388F8 + 098FA03173EC61CCF0252F793E42B4F5 + stream[448..511] = E41DEDE3241806F3ACE001D8ABA5C290 + 8C8D3DCC7E33A4031571D6F5BCAEBDBD + 0DA77831AFE34A4300B5677EC615FC18 + 00A2CA80FEC9CB40AA33DAA1D20D80F6 + xor-digest = 8A80F6234BB7430D1EA7C6A6998D03C7 + CBBEBEA27F9C329012E19B0B62BC5077 + CB64AF18099DFB4113C6430B842BF529 + 0DDE3BC0DF45CF836D766D03B6CDD43E + +Set 2, vector#171: + key = ABABABABABABABABABABABABABABABAB + IV = 00000000000000000000000000000000 + stream[0..63] = 77BAAA833D320DD2E8C8D36D4C1025BA + 07DB396F663C2E50CBC43E640EF93977 + 97ABF342CF471B758DC6A1472C817068 + BC7E30B49004DED1F763DE141C33A0BE + stream[192..255] = 018E53C65112E8C3CD374B892B21C1EA + 80408F1A21AF4EF02AC7CA5A6A55D130 + 0B947E0A93D8980BC2070B082EFC3125 + E37F2A7D1A5BF0A8C8D154B84D6FC933 + stream[256..319] = 0EA8A2C53BCFCD5350B3CC2CA07C0041 + 53B4AEC461D18419071470D8F4BC7404 + F34FB030DCBC4E01B98DEEFEDAC031A9 + 41C395538E95867A13EAC71EBCDADBDB + stream[448..511] = 1832583CC5A02147E6CB3FC2E5157A83 + 3BD5513D14333DE552B5E1517527E4BA + 7069DE68F47D7A28CD2DD2808DF110AE + 1F53353B654E4ADD055032D8323FE829 + xor-digest = 14C12CE94857C60659ACC9DB6FFA02AF + 11840A7E2859DB05FA6436D7B3E9779F + D21CA43BBDB9F721B5164485FEBE4034 + 7CA303DF12630D6E967C0DFD7653ABFE + +Set 2, vector#180: + key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + IV = 00000000000000000000000000000000 + stream[0..63] = 1C1BA750879B3BC214CB843962A0006F + 54E3B0F682FBDD7AECC21EDC208994F7 + E738B69FDDE5E90964CCE34D7351188B + B3D788F435747FAA13EE208030893252 + stream[192..255] = F358238286724199C183D8C960D730C7 + 2058248249104960DD2899886625C5AB + 4844D768FB2594F2CCB751280478364D + C78E631B5ED11343A104338AB8E28958 + stream[256..319] = 0AF1A0C7A000092FB1CDA9CE6D145DDF + C37D1078C00008392BE73C2F34DC05B9 + 9FC4954071AAB16AEBA5A0D8498D411B + 5C1DAE961DC2A74B8FC992DAEFBAD292 + stream[448..511] = CF358444795D941D450F2A6F86811CBC + 2492263D5964C4A45A26AEE228739BDE + 3BC223FE507EB5B9AC6983E213F529D7 + 86473A4DB0764DCA5A27AB7B011A5393 + xor-digest = 78714C06C8C4C206EC238D4E679D96CE + 4C258C46C1EAB4E23D2E55A0061CD767 + 9AFC8C85AB4862D39768DFFB3A0FC583 + 0BD203F66B03BE4FD491E1FE0DD83FFD + +Set 2, vector#189: + key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + IV = 00000000000000000000000000000000 + stream[0..63] = AA10D434183C285709EC2706371DCE5D + 5F8C6FF0CA2B01281550AFE875413B25 + 14D34846E658F9F11BED0F93A427FD96 + 8C62380A46FE8E3F7E023318E989BF31 + stream[192..255] = 2AB885D3EA66AEDC476DC5C59C3D4888 + 2D39907B51878917B7DCF351CDD30963 + 6AD8614DA701B89EC9B141696F77E815 + F95B15AD77B96513E5ED6C7F10EDE616 + stream[256..319] = 39270D1BAC8A3028E55097217ABAA158 + 1C0B8874A21E42533720F0F4350CAA8F + 1940A83B17D328BF0FD50BF8E62EDBD9 + 5DF959FA4CEE952B6098D48277968AB0 + stream[448..511] = 21DD7B64EBEF256536E95403EE0CCD20 + B062193EBCD72EDDCB1B0DE9308D048C + B3F3C653DD93D01F3B266252B11F32A1 + 59AFE3B00369FDA024DBF392921FD1CE + xor-digest = 1A748746F13675F5125F0151D0AD6349 + 7D23517B99000CB5479645F19889E407 + FC770983F7537AF86564F5B323E0DFCB + FAEAA53AF258F151C871C83B5BEB7AE7 + +Set 2, vector#198: + key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + IV = 00000000000000000000000000000000 + stream[0..63] = D4CE9B9AB39183E530A347FE5B435895 + 4899F18A43A1AD9F249522F7B8243359 + EB61ACCC30BB40203D3B5730736D38BE + 057C15D6A2DCCD005395C16CEF85FADC + stream[192..255] = 459CA305A8F73AA0931A56D914A51CCB + 3C6B22C1C35392464BD2BCDA1FB37050 + E2181510546024C753222E678A7CCDB0 + 77DC88DD7C947210897021A72E437DBD + stream[256..319] = 8537F62AC5AD1CDC7C6C910D45111165 + 5219E461238002391B54E7A8BD6BF323 + 1E2CE93AA581D9A8E755B33A382FE56E + 9FAC3D9F3370226EFB99701B4D0668B1 + stream[448..511] = 192691D070C8E3966467F1DAD89D5D8A + E345230E9828C9BECF681DC7AC0B7AE9 + 88656C7333BE93F103D7EE505F05C5C1 + FD8CEA2D27407EE265CD59F6BB5ED7F8 + xor-digest = 41A75368279FA64F63FC895FDC49DF18 + 1EB48E780AAE9C2F548C825BBB276803 + A4479CBFF22E79E35701B24B47B45777 + 26B5455C804E802B62704655B77D20F9 + +Set 2, vector#207: + key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + IV = 00000000000000000000000000000000 + stream[0..63] = 430EEE25DFCA972E12DF2FA3FD1F9A61 + CA16B3EA67C5131D701360C9BBF2ABCB + F2431D01590B300CF462A68FEC3C6E9F + 1F6A5BBB416EE0A098D2995711C9772C + stream[192..255] = 97D49334BC2482B1BEF901BA4A91738C + F6DD9F917862984616DA7C2FA3F9BEE5 + 1329AAADFD5B88A224C7B4EECF1BDAD2 + EE33E2C7060C1EE0E8A4E21D78D08942 + stream[256..319] = 79C06E2806BB38FE558E926E4A2C11DA + 903DC06D384D033984D2F7516ECB2657 + 4D5B5629B79C8D38E71F9A01B9526EB1 + 7E3FDB48B37B6338BCCBC914B7804935 + stream[448..511] = DA2A78E621FE1D105DBD0F7CD45AFD51 + 366533D03C446005EF100DFCD9789C5A + 06A00A7379A4D45AAEC1CC337F61C532 + DE26B1D028E72C399097A04FD7FF087C + xor-digest = F3833AF5AD9FF9AC9B227B1C9D0EF385 + 0B22FF5A0F307EB25654BFB63C61E802 + 2134A69091E5C5DC1E04C56BA2009B97 + DC9D02339578603D8EE4F50D1320247D + +Set 2, vector#216: + key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + IV = 00000000000000000000000000000000 + stream[0..63] = 7960EC96803829CE052CCF5B8205D09E + A417C075068FE91982283DA19533A61B + EAB72F7CC93AEB22AF97AA3B4A5B337D + 36C96BCBB23A073F57F2F378B7309758 + stream[192..255] = CABCE57DB1AFA7127A13498FE1FF87BF + DF1C40DC7F8D69D46EF62996C2AADE35 + 526377F4A09FB10B4260EF7B5E700470 + 1729CD1F0732748CDAFFC14AB6910617 + stream[256..319] = 01898230BE3F6E682480C8333700A2C5 + 1FD38AD27EBBF60CF2DF71B22C827708 + 3A1476E7FCF3348FD5E4E9EEE6CE61EB + 818DED1BA0C09FB96C5B7C799C1656F7 + stream[448..511] = E49D27417583CC79299ECD18751AA540 + C7831C3A0252292EEA8242590714DFF9 + 4833393BCC56403144E68A6BB08AAF35 + 2F71C6AEA9256EB5AB5250DED6366AA8 + xor-digest = E6D998D7F3BF7EEBE45844EFD7EEA371 + 4405D07D6EBF2D5F7F5435E4F557AB4F + 7571015CEBDC2CE0A199D7FF8B0DCAB2 + B9BACAEABE852E667EFD2E82A219FFC3 + +Set 2, vector#225: + key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + IV = 00000000000000000000000000000000 + stream[0..63] = E9AB7EE17B4734823A1522F5D78EBFC7 + 2F8112F67325BC5C12778C6F8302ED9F + BB545EF47EBF2B12380935AD8048B90D + 4B7DBC7759E27C205C94202EB64F8E0A + stream[192..255] = 5B775277917681D67800B3249E7A82EF + C5500F49E7507CFA0696D94FFB021CF4 + EC6955663CC37F9B2FF7A0345A71FEFF + 3712836C66A05C3C6FB9A03EC3D52260 + stream[256..319] = 11ECB0057615CC8244B2251E87449CCF + 0CE7805F669C762F46EF54E8E992737A + BC668204D49ADA49E51E592B79B34BEE + 248CE41C72E8A60366C9951B74986FA2 + stream[448..511] = 3BD82780875577B7ED9C603A240F1944 + 5C3090E36926793F769B11E3C6C8C993 + 697E2A0C1793AC4F39DEC882DACE3375 + D17B72FE40B82FB95575F9B7A17B24A0 + xor-digest = 996E394453A2CDE7CF809216337D1ECA + FF5FFA7414AAACEFFFFFD30CCDA5E424 + 2223AD119B3EA56D50248E7E7C0BE002 + 9640304D08A2B3D44386CEA0098D6738 + +Set 2, vector#234: + key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + IV = 00000000000000000000000000000000 + stream[0..63] = 79D2D1270B77A586ED9C3897C2875842 + 16498EA183465A96FA1D783BF1B1B070 + B46091CC3879E9ABF97ED22A72FBFF2F + F8C72DF9A3832C927FFDE6FD43D6C1BB + stream[192..255] = 4CB1C6953204F5F279F9F334AE8BE696 + 26201C8EBD488E6204DCC9823E022A15 + 23DADDA98E6A1A19BD42B37047A2906D + 19EF12702530DF4B7E597367B4463DA3 + stream[256..319] = 51500A31B349274BBF9A6E324773E5A4 + 2E91DA8482D306C7F13EE3E1975F7BC0 + D9006964367F4D8B28B389652455951C + 402AB51A4ABD06262E0E3A7A8FA3A7AE + stream[448..511] = 01F28C4729556AE8227B306930175707 + C75BF589B3711AACAD836615D666A66D + 255B40302E0DD5021EC4A15BCCAACA95 + 565BF3FB68BCF02D265F911ACDF6BA0E + xor-digest = 3B5FF103A75AFD640DEA7B686359CBBB + A888AB60348CE2FDF301267E415129BE + 46D088D9222139E96DA8D804DA3691FC + C546981BF65265FE04366053229BD030 + +Set 2, vector#243: + key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + IV = 00000000000000000000000000000000 + stream[0..63] = D8AA78A091BFB8D90FCA94705DD86B4D + FBB2673A5ACCBDC4F69A21C3B06A0594 + F470F70DCCA273A2A72C167659B7E0A2 + 76CC3BCC20AB889E682D4E2B70BEC4A9 + stream[192..255] = FD6974FE135C1E11DDC82F2DCF5CBB27 + AF0A8A55084407C3315B47FA41D2C240 + 372C7C4B03F8F90C3201B2269D18CFF4 + C70A13722F46FFC34727779CEDD17FA8 + stream[256..319] = 6433E61D5773ECF30ECF8DA06F8F11BB + 717B268E2C283FDC7B2F7841040EEEF8 + 29216193392BA5D99405A744FB571B6A + 71A6EA188B3BF5CDF9D601ABE3312FA6 + stream[448..511] = B238D39267ED812D37AC81E6D2B29D21 + 45F9337A6E2CB426C8B43BC795832FA7 + 8D94B5E1E83C19D40D3C2B4B670F3C1A + D504DA82D6E83A71BC5E431152B485EC + xor-digest = DE1C9B7BAE92989BCDC7AD0D527CC6D9 + 4F138C8C2A1A06C1AE28405C867191CF + 444F45770CC216226ACB13D2A0A2B8DF + FD81B93AAB20EE7C19E631D9635AD0B9 + +Set 2, vector#252: + key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + IV = 00000000000000000000000000000000 + stream[0..63] = F61BEE71B1353E8E198E9300CC720C88 + 977F23274ABF7F9DEF298B97EF43FFA5 + CDFEB51DAC7224EE6DE64CE0966B358C + 9786762BE880BF00BD48FB1D3D1FCB99 + stream[192..255] = 019B52D05CEC5CFC74F2D26ADA3D2F18 + B4B44D3EC9359A132AE18B33510C249E + D56D0AA2BE16C6213BE2ED47514B70A4 + DD5FB07C317757F5981009F70EEDCF39 + stream[256..319] = 4221E9421F2C68EC8B59660512EA0442 + 64FF35D22DEC65E1ED18E3D8BA359A78 + 92FB5566DA0DA25CD5A3409EF6A6F020 + 59DD632A793886C0032864F16D827A36 + stream[448..511] = 71330EEACEE6E27994023E212D1B8A42 + 045C29F141E4C696F74A0E7500B45E82 + A0ED1F4DF8C78A93D8D6033B780BC22A + F4D8029B82AB447E0D5EEE3405EB0D22 + xor-digest = AB84F0A0D9D1E8D810E76517E5A0B80D + 0B2832EE12AEC48B5DA48B78DC4D2278 + 710DF7664ADD91B1FAF3F14F3951344F + 08515E7D43F8EB677B5CF18C487A697F + +Test vectors -- set 3 +===================== + +Set 3, vector# 0: + key = 000102030405060708090A0B0C0D0E0F + IV = 00000000000000000000000000000000 + stream[0..63] = CCF2DFC47B94B1C67DA07BE50ECBEBE5 + 9F470BFA68058E55529EC8041EAA2107 + A15DBCFF20B1E54B36ADEDB49356FE2D + 4BA86FA2C6FE08DD1E260D7D20A3D93C + stream[192..255] = E5EE7048E8EC8C7904138C6E355D3956 + 1D8A1B824D62DD5267918237E9225416 + 2A192BD543327B9D786F973479F88DDF + 152974B2FCD44DF9B77E1E9D8595F29E + stream[256..319] = ABEDDC8F46C83EF0B3D159B3A1BC6E1A + 4535744E20D82A2013A3013F864D4B43 + 01C54F2BB0F03C775738875C1116642F + 4E6BC1D551145D40A8F978207F44BF89 + stream[448..511] = 804C09F0973A24FAD6B4E7398C57B11D + E670AB2AEAA63822D70C7109E2E1CA58 + 42E2251424C23525980A7E7132BA889C + C2604FCD9F443A1A194646730FE349E7 + xor-digest = ADBA33559432364C670A33CBBDA0C0D6 + D75C6C986D073C473C96286F5058ECB9 + 5B78052C26C5BCDD6138334201B05458 + 135B363B8ADA8CDB3AE0C565C9235646 + +Set 3, vector# 9: + key = 090A0B0C0D0E0F101112131415161718 + IV = 00000000000000000000000000000000 + stream[0..63] = 759D5A8381CB183CB0A01B4A85FBD793 + EC9580339CECC9BDF7DC52F67D8D635F + 1F590575EFB26F906424962D99880E45 + AF25D68181C9652EFA590E8B1E0FA578 + stream[192..255] = 3FA014E6416459F15B5527380E5B513A + CC38193B9A26CC24C59CD6866EFE8010 + 30C950DC2D55B70495D4C11296D9609D + 670E41CCC20EA01349E28A2651318A1E + stream[256..319] = 675B1A11D7F20A18C137EEEB2D3593F1 + 7D1A284A076E4E18BF8B622738962236 + C3F07D4AB453EB4FF0E3A0BD89E21AE5 + CD17432F149B386CD29011D6864B3B83 + stream[448..511] = C2C4385B74B6A38A18590A5A596DBDA7 + 294C4DE7B15EE36F4481E275AE2C11A8 + 17181DA10309BE5B366852035C227BBB + C61F001560F03F2B361B5B8E0FADE6F9 + xor-digest = 26A33A713972455A92FF0E6D65C7A7C8 + 537BD0D9F8EEC96E03C3B39C5F9307FE + F8956D1EC10BEAF467BA86A26E846ECE + F4F330FBD9D6DAF5306DE538F0F76C0E + +Set 3, vector# 18: + key = 12131415161718191A1B1C1D1E1F2021 + IV = 00000000000000000000000000000000 + stream[0..63] = 27D21507A4F5E2C39050B1D752574ECD + 5BDC31D6E8708D1AD950E3E48C53A059 + 9FE6F7B5CD7A6AB95AB9C3FE0EF154E9 + 68882B10A2613A283C9310579F444F19 + stream[192..255] = CFD6E486D72760DD5FD1D246C5C150BD + 622052B7F1938C3EA510F3D0EE47B494 + FE8854A833EBB2C7E579EE3925B19AE9 + EED77434CF7B7AA00833904A78AED517 + stream[256..319] = C6FDE37C40A1FF7B4EA3A8DD64E7A1D0 + 7C4F25C04CE05A3C09F6EE012B458A9F + 93FF21C9EDE67FF06918CA541DD24C87 + 19931323F1C87EBC38F56308A2F5E076 + stream[448..511] = 1E9D3E112C8CCCE11ABA19E941E48173 + EAC5840A3025A88EE79DF2514EDCFBD1 + 3A581C507EA3769FC0498EFC7447C0D8 + 9135E602E06512D25EC773A20C4D1F2B + xor-digest = 122C8ABB06E644953AE81EF78CF4EF6C + A1322AF81186B8C27EB199B5EA7814EF + E6F0C6EF98781CC12FF7A988F135F3C3 + 28BB53B6D2612B1786D4B24D63BCAD01 + +Set 3, vector# 27: + key = 1B1C1D1E1F202122232425262728292A + IV = 00000000000000000000000000000000 + stream[0..63] = B98764C4BEE54B7CE1722955D29F7265 + 74D3B6D2A7F51847A8A5F2BD78218DD4 + 13BAE5A9B76EB7C2140E6D728D430CE3 + EE77FA5446B53D887A600B8C2A954DFC + stream[192..255] = CA3AD141894C09B6DF333C6C42729339 + 45AA6F7F13EA64C1E3043F2AB64FA18B + A3CF16B35E853FC98A67DEB1A9A60B1F + EFF93767C87E583C8B50BA0B80B69AEF + stream[256..319] = 0D03AEE4BC0E4260B48C43614AE1327B + 4FAA2F0813F188DA28C3CF15C433EE59 + 881DD500A53768C5A1231991386E1470 + 2295243CF3E18638B60CCC4513C83077 + stream[448..511] = 4E190889B78B6CECDDCC675FCD336592 + 8D01D945C8B9737CEDC144005A7E2E6C + 921256F89098BB560D39BEAF700CA5DA + 4F4535ACCE3439D9223E357DAD2983A5 + xor-digest = 2261129A59B37D3C9FA15E35B9DA02E8 + B6044084F0EEDA1A62641BD8BEAE9293 + A57E89120CEF2CBE5594C47F96E46C5A + E6FADA330126A4EDE047E40153D5A182 + +Set 3, vector# 36: + key = 2425262728292A2B2C2D2E2F30313233 + IV = 00000000000000000000000000000000 + stream[0..63] = F8088D4E53936A40E21B3AAC1E6D975F + 13BCA7E4D6CF7D926F6B9AAC562790D8 + E2B66C05A075737B75F8E171C70E1507 + 94437B818F59052FE5ED87BBADFAD509 + stream[192..255] = 19686CA73474C6F626390DA198824970 + 9FE43AD003953D102437DFE11DFDBC64 + 432929F934A0758B2964EC3B7CFB8C1A + BE23C6B12132B155D3922719DF28ACC6 + stream[256..319] = 55EA041FDC9CD8438EB7B9C2C5381785 + 57E53ACC75CA512B88D8531E07DF4C15 + 35F60851AC242CD46F56DD35241D51AC + 6DA52A3BEF555E2844DD4EAFAFE3CE63 + stream[448..511] = FDFB1D76CEA5E3FD0C5EE1FDA1717684 + 2120C48956F28A583B291712DEFC158E + FA26FC4A833D31B0EB59F61D942E99D4 + AF4BB42D0C0448CF8CDDBEB336738414 + xor-digest = E49BAC9E963F83F3AE70026DA7DA496A + 0764267F7F5A8A23F7AB32EA0F54D459 + 32367E47527DF738F7255CC890F15FF5 + 8160EC0C1A27260856A822810AE63F2C + +Set 3, vector# 45: + key = 2D2E2F303132333435363738393A3B3C + IV = 00000000000000000000000000000000 + stream[0..63] = 67F1B4269C402D69FFB8B84559E60033 + 07B153631D650E01A3B265739130F184 + 4F6126FA1F957C7FF5AAD71C2E3BDE25 + 94DB87780773B4A4DB3E44D231D46AE2 + stream[192..255] = 5BF80BBE842FA08B4B2EDEEE74626A19 + 69CDEF41D1E731FDCFC906F320A2CAC2 + 8B79B585B0F70A5AB48CBC5C9478E5EC + B14A387D5DB8E60E4EFC86785274E437 + stream[256..319] = 5DC02CB76EAE6800980E204AD9A315F7 + A65C57E2F38DEFCC29FB1153E7A4586B + E9FB7FEA650E326A5593568957BCD278 + A93FEC168D48372068B9A2E41EE10C61 + stream[448..511] = 61D55EB5278689230193C990EC5E65A1 + DDA93955026C14BC32E80036055A31BA + 118911DAFA9FA9160D4C37524F5EFFD1 + 2D575FF005967C3EACFDCC9D8889A198 + xor-digest = 9B327699C5FB098D15CFF2AAE321D095 + A569B6D87AB1BD20FC8FD94AABFCDF2C + 521D3D5657857A6E197B55F371351525 + 171D23F4DC242408730057CE67BE8E58 + +Set 3, vector# 54: + key = 363738393A3B3C3D3E3F404142434445 + IV = 00000000000000000000000000000000 + stream[0..63] = D9B96EA262807FB3F5A8675D81B1A006 + 1D717D345EB2B91F607B853A5A38DB2B + ECDD26626A33477BF07BF9C57FE95100 + A1F142F70DA7DC86E063A58AEB090B2A + stream[192..255] = 597883FB531AA34A2EDB6D83AB2A304A + FE522A9EA6914C556618B3094874E021 + 2316FA67BEAF7ECE4BCF350A817DEA50 + FEF5B76E72E2596A149D99B6971B069B + stream[256..319] = 6090A1AF397F2BC3ED551450EF28472A + F60EE5F2B4BEC18A8B1ADF21A6A476F6 + 8C11F76405ED62ABB7BC585BEA4B0A47 + 988A09A1D93CE2CE95B82C9C1B60E650 + stream[448..511] = 49F88E9C5E53BF43EA422682ECA42968 + 6D794754E65DCE9306D3D9FF206BDAC6 + 442655D27EF6166CB095DA4C301FB7EE + F1F5FA0225EB84CE61BF3856062A4EF1 + xor-digest = A71B962E13E66A678C5B56E19099CED2 + A15480838832FA6361C3C0B5BF47C1C0 + DC954A7CA8D7484D7889FC760227B418 + 73EB611B5AD62FB622F5FB75FE412A44 + +Set 3, vector# 63: + key = 3F404142434445464748494A4B4C4D4E + IV = 00000000000000000000000000000000 + stream[0..63] = CF11B1510C81A296CB185B1BA6436112 + 832AD2EB68B70E52CD68F9D394F5165B + 94DE467FFDE4EBAB6AFB180EE7A2116A + 1E73AB81AE4528273D0D93DD05025D70 + stream[192..255] = 26E9F1C007EA49793D701F21696FDE8D + B72D317BB958F86A35E7BBAC80D62CE7 + 0879213503B04FEB1FBF3987847745F9 + DDA9310DB36AB8F485FEBE9FA6C1C7FB + stream[256..319] = 25C98B6441F90615C6078D82B5D72F61 + 828ACCFC365CD5EC17D5CEE488A51192 + 8826B334A1D7BEFAD7528BC5CFD32B82 + 87F4EC603E21F528B51999F222817DF0 + stream[448..511] = E2CB68B1CFB640B76DBFC5CDFD192AD0 + A7E8BE14ECDF6E20F1C8FD444D073108 + 6932BFEF0EFBCB7F64E5CE79CA4AAD15 + 846081CB229C74013CA0D498DDC69703 + xor-digest = 4BB7025AEEE0FC3ADE977F13A0853FBD + 9F43393A6A0B7C91534F5F2A47009D63 + 79D0B9440D5A36A82974EE70BCF3634D + 131E754FC6BFB8DA62A05B3F4D1E9FED + +Set 3, vector# 72: + key = 48494A4B4C4D4E4F5051525354555657 + IV = 00000000000000000000000000000000 + stream[0..63] = 0CD34EBF2677F222A589B77FC7284567 + C3CD391D85E3CBD04F43DCCFF830F0D9 + 5C9C97371376B180AC2235DE4EF2E377 + 8242ECD6A257FA02F2055CC7116A006E + stream[192..255] = 0CEA97153979B13DFBFC3F04D311D677 + 9380FCA517161003A82CF5E00CAD8438 + 18341CAF98A5BB7CC4D4E487A5878A3E + F0D490EFD4834ACB92EE0FBAA3144270 + stream[256..319] = 700797B741FF36DD80F72A889696436B + A900033C957BEBA6BB3EE71AE3D79A83 + FB4EF28F39B0B3A0E36719059774E6AB + CDB4447CB3CE6CF78E30EE239F537140 + stream[448..511] = 44EE572970D5AB8C094D434DF6489171 + B657A51C610D370EE9517370780D81CF + 47A666A1556AC7B254DBFCB2D1352365 + F62B950D9457E4E364EA980C3832AF75 + xor-digest = C794C46A6A1C155D6922A7CCF4327038 + B48618EE29326A7555AC2A00122D4E83 + A4F17AB72F9A133F48750BF43344D561 + E71C69844840FE83889B542FC83D5132 + +Set 3, vector# 81: + key = 5152535455565758595A5B5C5D5E5F60 + IV = 00000000000000000000000000000000 + stream[0..63] = AA9A1800F63A3D6EE6FAAE48B615175F + F4EC441EFAADB6273B38087417E9528E + BB3E9A8D9E81C6B7863D26C24CACF50D + BAE956DD15EE335C99CDC981B4182545 + stream[192..255] = 6F8CB1506073F5BF7E656C25BB46A689 + 73EFED2E87229204BDB09910180C279F + 23341A1FBB0C40705C1EDCDE8E1BD8D5 + AF9F503901071A857F8315ED2F963114 + stream[256..319] = 3EB29DC8A63E3B61A6EB1062F189BD53 + 54A7DDBB22A6C3B7857D80E5A761836C + 4A91EC1C994FBAF781AC65B1840DD892 + 2A82AF4D6DCE1004B3FDCDE790018C31 + stream[448..511] = 00A6E02F4DCAEEE2FC77318AB9619246 + 64E1DF835DD62629D035C44A1E147D6B + 809D6C60983B9767B92A10E35A651786 + B0B0E1B8FE8BCBBEF4D02BC625E5B402 + xor-digest = CBF02F452CCC84F5D8D3556876B7902F + 324BB22F3C676D3D5C5FEA182A4582EC + 57BB18419D8F82CC8C43737F3B356C73 + CC9452557FDE07F9CB3BCC06041C4279 + +Set 3, vector# 90: + key = 5A5B5C5D5E5F60616263646566676869 + IV = 00000000000000000000000000000000 + stream[0..63] = E5605A67C46B013408F53D1D8A583699 + 389267A63163901506FDB6150CAB719E + D591787D8CEEBF1EB13E73F6A5D3DBCA + CC916D41738008C5453132A472931D9D + stream[192..255] = 0D04AC34DE63ACD3D554E568B4E423D9 + 76B22FD4C32464BBA143163B225AE996 + 4658EF46C19E5C95CA14D9677098C303 + 7C37E77446E8878A5F8794E00FD2E0F8 + stream[256..319] = 1915755636B9E8CFDF50F532F6FD6C66 + 60CA7E53C6037A532A39E56E61C6067F + 99C864B32049F95CC142B019BAA37720 + 1A0C28D747CAAB42E81073F14818EF1E + stream[448..511] = 820E743AC49AF76E030EACE4D0BD568E + 781B2AB82257DF8C407C159CFFC13D12 + 7B869E6E48C5A6BE72A5F1A9877564E3 + CE22D770D9FFE839BA4BFB8D297D3795 + xor-digest = F98873945A95030C43B22CE430D520EE + F6E4F2FF30F2545693C7765D5EB19AC7 + A096799EDB90D661B1379264D5B42729 + E2CB5479FE63BA9B8D409AB98696248C + +Set 3, vector# 99: + key = 636465666768696A6B6C6D6E6F707172 + IV = 00000000000000000000000000000000 + stream[0..63] = 2ACCA4B94538608F318E142FA9DA9DAE + F2DA0FE10DC27C804C0DCEA927CBFBFC + 4F9AF87F67D962130A2DE073D4CBD1C2 + 70A836BE81FF2EFA6CF910E6F558485A + stream[192..255] = 586AC09D4C7285B3CC8A49BBF978D086 + C628229659DA298476EBED38C7FCD86B + 59FEE45D41F480258A44C0615DBA2DA5 + E64B178A2E7EE3B02A316245152F72CE + stream[256..319] = 1988E499CFD61EC2699181A520C1C829 + 3F0AE76B30C4BD0279C937D53054F646 + B318B13703EA193F63BC83BCD501C083 + D31B8E2DCBCAA5CB4B9ACF15EE740010 + stream[448..511] = 797DB54E1E718B6ECAB6F928C3CF507A + A8E58832933F404CE1331FD469643E78 + 3F8BC3004AC7AFC5EF036F8B5D4DB5EE + 16BA7F94C39A39237EF93BAE10E427D1 + xor-digest = 75197D3AF308890C381051938649CF93 + 157F5E1200E87F7A0CCE920B1A378415 + F1DBF671C49324EF517ACDE52BDDA9DB + BACFB24EB2DDA3582DFF0F0DA9A7CC8D + +Set 3, vector#108: + key = 6C6D6E6F707172737475767778797A7B + IV = 00000000000000000000000000000000 + stream[0..63] = 5B1C1C98D5EC2E066FE163A010AB06CB + D81E8E237F4486C3C57C7DDFE9CC4E2B + 6C0C016EB38630B09823CFE1804D969B + 3CF93666F785BF5EED450D6CCAA1ECAC + stream[192..255] = 5519D71CA1AD10191586664DDFF26BCA + 7CEE6FA4C728BC0487FFF71236DD947C + C7F84A9ADE9ACBDDB04CA4576AA11CD1 + 19F676BC908335BE454957280423AB9C + stream[256..319] = BCBAFB8D31351D748DAEB21A4927FCC0 + D206C0DFD1EF6CE6425808BCBEAEE26D + DF29CD37EF61A6C186E33E432298CB7E + 94A598588A7649C3639D3EEA43A4EFD9 + stream[448..511] = 6FED1CDB9C109AC353D8F0A92B8DE388 + EF089BB8805D6622CBF93F4E70939039 + 536C12BB7952550B4A9F62B8F99A3522 + FE12D79D52456E5E2B58D899CCC0A683 + xor-digest = 9A528A131B2DC7999743397DD1191EF6 + 306AC8B7D333276AA11FC5F952DA12C4 + 890509B6B3324B57117736A2FE462B97 + 3676D4AB0F9EC5F40389BD1631DA30C2 + +Set 3, vector#117: + key = 75767778797A7B7C7D7E7F8081828384 + IV = 00000000000000000000000000000000 + stream[0..63] = 19DD8D2D6FED84E4C8983761323019B5 + 6EFBFDDE9D0DD65ACF8EA7064D876159 + 34CA7A8690CD9B688A3A7E2739C0DD40 + 87E931669B47FAE65582F217B703F744 + stream[192..255] = 118247263D78B35C87001EE80D0855A5 + 4BB82A2538BDC4CE4E0508BA9C1AFF2D + F6E3BD124EE8EBBE9C5F8CFF809B22C7 + EC14FADC932266458D049847E4BBDA57 + stream[256..319] = 3ED5D1F9FC223FAF7C35165CB00DC41A + 948089FE364B824970DB5C8EEB277D5F + E1D7EBE4133BC0B5C9AA277360AB3D59 + D990F5F7F8FB2D4839F8DF8F91BC8CD5 + stream[448..511] = CA652B9B5179E5FD45CDD84F778BCA9F + A5E029B0D5F8F8DC9F6848EC6FB90CB8 + B5D6D1F65BAF94B02FAD8F432901B2C8 + 1DF0A7BE680810CBAC3FAEA492EB49C7 + xor-digest = 1D54E85686E20E556FF40B2C310505C8 + B3E341EE7DB6BEE6761CF0FF87D56DE0 + 3C08007AC388112D542875E0F56BC435 + EF698DE5F550B2E6DADB7CF899C670C7 + +Set 3, vector#126: + key = 7E7F808182838485868788898A8B8C8D + IV = 00000000000000000000000000000000 + stream[0..63] = A865C1EC58AEB098342D771FD9DC8CC6 + 257144135060E17F794154163B5B50E0 + C175DADFE996D8D9EDC24F528B403EBD + 31B181DA7621E80465F5609656D2F6BE + stream[192..255] = 6E369A08D533239B1813FB1E64FE4016 + D5A168E7B082AC17782FD536B1614EEF + 9B96114431A8A20901442B17D359AA8A + 616CDFF610EB376A01A5424443724BC5 + stream[256..319] = A6A4AAC9510367507B3ACD133FF4621F + EF8117A2F74CE892273D852801F6B788 + 3B4CFA27124C42D424131AFFF2890AF9 + B7EB6F70917407991169997C9014C6B8 + stream[448..511] = 54DA1A3C64310F07888F043684AC5081 + B35962F34CF46D8B1BF8CB9079A0CB7C + 3AE2998F6A247D758D7C435F2A509E9A + 164A0CB7F1D9FCF1DFF99D2C7074198C + xor-digest = 44F37D188FB59A4BB0BBD69BE1592797 + 65135A26C7EC258CB2FFCA9BCCFDC005 + E9971F4128215E73D9EAD8C6B0465C98 + DFB9065DCD07E83DEC0001A737CF8DFD + +Set 3, vector#135: + key = 8788898A8B8C8D8E8F90919293949596 + IV = 00000000000000000000000000000000 + stream[0..63] = 0707B0C6C7CFDB502FBA27A9179AC77A + 8EC79404E4DF30E46B0512EAE40876BA + A0129C7C6A7D61A264654AD3C7822B68 + 80AAEF7CEAB7CDC898F11F217BF705BE + stream[192..255] = FE4ED3B451213FDF4847305FEB8E9FE1 + 2C359E24DC7AC0957DF2558D300FB0CE + D38A9983F6CA936514983BD48F80A596 + A2CE35993ACA48ABC500BE4E766699FD + stream[256..319] = C5BF4DC95100E2D7F6792F6AF5F31371 + 53D418611ED358EB8646CC359FF18770 + 93C18CF26FC4DD646ECA8C4A199539C6 + 64C92D30F2F3D652DD2E4CF66A6F1725 + stream[448..511] = 588425C16BD8DDA6D1D34950A40E35C1 + 2CBC1F62542B3D3F6AE4069DA42CFE09 + 8B36BAFC94356A4EFFA655EF8DFC281D + F47FA499717D95FF7CA81EA175E2D6FE + xor-digest = 4F543EF4ACADF04EDCEAB6841B794C70 + B9CA52B336CA4D6696E5AF632271367C + 29815CA30CB0528546FAB08A6AF9016A + 9B25460BD71FC1D00C516961D3A0B448 + +Set 3, vector#144: + key = 909192939495969798999A9B9C9D9E9F + IV = 00000000000000000000000000000000 + stream[0..63] = C95BF1BBEAC136B08DB163D8A12CC5D1 + 53D2C485C257E16BB5EAD3B93BA84D32 + 352DD608CE457C3BBC55864B1FAE0296 + 1180FA7063C3E9AA05A471F89E9E8C92 + stream[192..255] = 112D3B048885FE87290E91C2288A605C + 669795CAB3F78FE8C6E15204E0FEFB5C + 9D0C690C2CC57882AA3C276E94414DE9 + 376531151D9BE1DAC6D784E95FB196B5 + stream[256..319] = A073295F2907C05C3CC3A17B8E404338 + 0BC74C10864FE1EC6F043DDEA356CB48 + 4159EF66A944668B55131F4BE61D7F4B + 4EDA1CCC0CDFBDFFD79B9A37D4E0DD01 + stream[448..511] = 42834D089F1518A4E6167174E844E51F + C31BE2238B7C2F306F1DCC3FF7DD30E6 + E9B0CD089B9F9280EE40D3416339E1D3 + 47F0E29593168593203825261191D02E + xor-digest = 86960034091CFB6A6767B53B66713632 + C6272B95347CB92D8D084E8794984516 + 4AA48669D26826E2C84907C2CEA78727 + B0D3C9E240A361FFA661F00670C3060D + +Set 3, vector#153: + key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8 + IV = 00000000000000000000000000000000 + stream[0..63] = FB01986DB035CCE47390DB060C6A31D8 + 3C9E93F728E785ECECE34E41D81133A2 + 69C5917545B1FF479F4C45BD1F6AA46F + 3F9591C54F3D67A8BA7AB6DD9D7D07FC + stream[192..255] = A056ECB565EEEE24B5C42C501D78882D + A9AF1A9B5BE4DAD286E695A23D516D52 + CA83FEDE7CA0853C01D8043CDEE992FA + 1F71C90DD5C3C95ADD5FED24575A4DDC + stream[256..319] = FBDC6515174B6E51F3A9804AA2C34DD6 + C03F0EB5202CC36D5602D58A2630390B + C9D7A452680F152767F4558B3160BFBC + EFD49175AB0FCF62D2FCB8E78E1CECA6 + stream[448..511] = 774009D68AE972386F6F4D0467963670 + 3E08B4CA05B801C5FC84376343B505F3 + 37B9052F7280733BDCC026529F48BDA4 + 765D1FB436CDB3DA0FB69F148894E8A9 + xor-digest = 41CCA3720EF5CE5F8EFABE447C3BEC9E + DA338E5ED14ED24B21F66BC010077475 + 16C61E91AC9E3501F2E8D9DE2E619ECD + F995AFBA554A8AF21E89EAAD9FBE9913 + +Set 3, vector#162: + key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1 + IV = 00000000000000000000000000000000 + stream[0..63] = 0DB9C95EF6FA9E4F256789098C2F589E + F5F2C63E8F38F81661A22842C4058E42 + D62675CF0F435C6441A905C46A5E2B55 + 98D87AA7483D5036DBC6DA6F795B95F6 + stream[192..255] = A195496ABF83B1EA9BAC8FD119F0514D + 5C01B2A262090DC52DD00AE0689DA3E7 + D9AD502FA2F3740EA254E8542296A3C9 + DD4D7ED40EBDAF2237157BB197887DCC + stream[256..319] = D5E1BC7E5C9B1F47FE69662C94D2C83A + 8B92217E877379F8BAB56CDBD5406CF8 + C18E1E2F223226EB9ED272BB66F7AD60 + ECEE3CA6C84A5E1BBA1DA733066C0D6F + stream[448..511] = C79F97FE9EEC3023430857F95A1541EC + BEEA487C1C072F81736CF02AE97D1A77 + 2C81A69FD2C58D85976DE47F09958BCD + 4382435A952C27B45EC6E387EB0A0333 + xor-digest = 65E3A3C2314794333A620A28C23D5EBE + 884D04CCEC9F7EC8892535B5E937C9F1 + D2B993451DC35047872F562C9ED5EBA8 + AD36B8B67325032A2C135495CF8A1683 + +Set 3, vector#171: + key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA + IV = 00000000000000000000000000000000 + stream[0..63] = 505F4C9084D6F5C640C214EFED9E2DF0 + 8EEF8241ACAE98072B5B3EDB72F1687D + 586B2569DC7F58DED2C2BCD134CB6CF3 + D80A7A879D7878C080A5BAD5ABA1DCCF + stream[192..255] = F38E694DB538EA115B3F765694B7F647 + BD16B1E50C927528B13FA2EB811E8E8A + B7A56FCACD80B1E7861733E0F8289E5B + 3C461080A858FCAFC85748DC11CA007B + stream[256..319] = DEE9825C69B6F6210381ED04A152A029 + A7ABC8D6C23D2895B968142E3A9C4D16 + 8059A067F309C2E9491426BD0953E4B5 + A6E545EE62D4E9363205FA50ADECE92E + stream[448..511] = E2C07AC69B0D646D013AB6129A979A80 + 0977C0B2E3505CD4DB4CCB4C2D02A936 + DDE87099B8F69301CB8A441A1CE6EEB7 + 9EB73A32F54D1B3AA1A5FAFAAEB0BFF5 + xor-digest = 58B7C17AF5B37A6806E8019BBC243F2F + 779B2961C0FF27B78EA54587FDA31F4D + 43AA70643AEB9BA547F814C57107B760 + 8D3DD6B06C6CA5BC0FE55A31274B4B5B + +Set 3, vector#180: + key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3 + IV = 00000000000000000000000000000000 + stream[0..63] = F43EB3DC7366C02A6EAA1BA286589786 + 3A2221D8679C3F0399B2119FB09D2717 + 8C262A1CAA0711E961209288EB03BC19 + FF9FF74773B10AC28295FF3BEF1E2B70 + stream[192..255] = 453BA5A1529349A29B1CC75B9835E642 + 9587A1E06F96A5E575BEDFC7CB6E6C79 + C7174D10F908C1688E9CDF6973971A89 + 2764D7412F054D772BF3B97B194717B0 + stream[256..319] = B2353310A194E71847B541FA5A301E56 + 6678FF7148960C4C2EE2139A338EDC4F + 082A79EC59E094AE01E3D9585033350F + 7E7255838EA448658ACD1D1B56546188 + stream[448..511] = 647B02009ED90BB30849D5136432AD33 + 759097A5BB30DAA7D768FD7F7F5FFCE8 + 513975CE19501ECD4E194A1C172F7A01 + E75BE6598CB0BBE4DEE6E1C364BF9C36 + xor-digest = 890A2D288B3BDE3AB9B9214DDFA6BB03 + 390FDC8925358A0C99C44543C8EAF224 + 64635D46AE1FCE0CA494A6BC7F127F23 + 2B8EC742C518A73F6B2DE22F2F564749 + +Set 3, vector#189: + key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC + IV = 00000000000000000000000000000000 + stream[0..63] = 17638771CE9C92633C8820B9FF9A7D20 + C0BB3ADE5D49E16EE463A6F768D0191F + F624A8E1E36DBE1F35EDB6EBA4587DA0 + AD633F1E6CA8072A3871C580037F202C + stream[192..255] = 36358F7049F57244EEF847ECC80803B4 + A9EDB8B97CF098F87B047D02FAE2043A + B4370B7C4E87777E049A79CA833A2F40 + DF221E8B34B710591A24937D19F39BDA + stream[256..319] = EC6A73C4A816CA1C3D1DC0B2A1AE5409 + AFEA32DD3B961BCE9F27FDF8B46E8300 + 28C2C75C0596D1394E579BB4239FBAD7 + 258C7BC7FB9E1C5465439177E454FA6E + stream[448..511] = 1A5ED8E740246F0744218C31668F081D + 333CB2C4416504584CA1AB6E7C56C82C + AEACD22E01CCC23C1A9E8BE94AF90C7E + DEEE590D8F75C9A1EB2134CC1A44AE0A + xor-digest = 2D664EC9400F9864BFB1CECE43DF3971 + B8EEECEFE3507CE09F6572A9C9743EB8 + 58B433A6FD2DF24605BB505B4D732050 + 8C89F38BAD818FB3893383DE2C1ABE08 + +Set 3, vector#198: + key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5 + IV = 00000000000000000000000000000000 + stream[0..63] = AECDF83CEAFC62A35AAE0B56DB5E6608 + 3ED8144A470316E5768F898741181B39 + BE1B44248B79446A2B8551A7F71009F3 + 4BA3799E8967A961169A2949979698BF + stream[192..255] = 1162529D235C48CBA87E0FAED1209825 + 4F0C650835F5A0C44B01FC1AB0A53ACE + 496709D34D632E42A98CDA3A14E033AC + F01E869A8263D0921619C26D3EC150EA + stream[256..319] = 30F569D183A30142A2C85002A7768DB1 + 1B12025C41B0331458BE45DC53608B11 + 63E130EC0D6940C2DA7BCB40881270F1 + 1D79B941B6DBD4B53A093CDB9DC3BB08 + stream[448..511] = 6170D203CCDDB9E93F3BBA8E195214E2 + 485BCD5E96031B5848C433D2BAF4AD4E + 2050902F0E6F0D71D034909B58EF6E3A + D8D72DFF40449A96F9DB8A2691FA02ED + xor-digest = 8D8C29A1126A2C135938D456B61C1C22 + 88F42EA3CC4AE32C2D9AF46A3393EA9D + 13719D95D2EE3F62D261807FBD4B504A + A189EF6CEDF6DE1CBD0C9223DC485044 + +Set 3, vector#207: + key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE + IV = 00000000000000000000000000000000 + stream[0..63] = 03FA3028E50F89A3A26FE0C9A59D4D8F + CD4F6664621464876D0DD0070C3C4A4F + BEA73FCF1858F583277C9A8AB098DBD2 + CE9DC0BD491A0069D48812B45D99BF6D + stream[192..255] = 4BFA1D3877F91E02E7B59C2BA54E80EE + 88FD0217E82EDB379B54F8AAD1B87308 + E908A3740DD0A6BED98D95A89579E18D + B12960A3E8C2DCF39F84BFE48CD9D8EF + stream[256..319] = DF87530FE64F198DE0F5685C24E6F752 + 776A64B5355FDCC7A734A195350A05EF + A9BCBDC50D12A81CB89F49F330EB2796 + F3C0EC3A2AA823AB1787B4AE2E9F4B84 + stream[448..511] = B62D2660AF636D037FF77CB2DA14EEED + 1DA4C10E4C34C3A170F00753256F021C + 6B8058A71680B8AC68F0E7B73D491E77 + 21CB13DA097FBA6630DC814920993501 + xor-digest = BFCA05D3C5A76AF3016B56245C890022 + F173D207ABFA1355C4AC75CD44440227 + 40BDF92FA07711FFFB49C3FE49F63375 + F242014728E308CE8261AB6971D82EBD + +Set 3, vector#216: + key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7 + IV = 00000000000000000000000000000000 + stream[0..63] = 3FF2373E4F64EA27FD8C86D971D6C497 + 9AA558C47B291B686BA3EB4C848320B4 + C2614E739FC890F78FBAF82DDD01EFE8 + D93CF5A5068A0BCC4FE41F87B4FE82D7 + stream[192..255] = 7BD47D4550A516BA255A572D948C143F + 8B46F2FDEE81E80D21E9A64A27A89FC6 + B00BF842251F5094326BA41055D83D75 + 3A7A4DC88643BB8D8207CF4E6B5D6360 + stream[256..319] = 9EC176E21634E97E52F5D8D42BEC590A + 5F4A6D0671BE640B7AC3C790AC521911 + 3862151C7EE904BBA1B1254CA5FF8A72 + 83EE9F0A3CBA3A0A38F3CBCECA7AC751 + stream[448..511] = B87FC33D6F13852603A069DD88143790 + 4922F8B3B98D383B7082257077DCDD01 + 1B2B0390F6B680719D91B815A0421DBD + 5F3687097C63BD0AB1B59EBC12441A43 + xor-digest = 819FEAE72A30198453E6B7E0566459FA + 3A325C59B0B1BEC7B1311FEABEFAFD0A + F7EA6A01603CD81DE8E338740573C01D + 94D57B04AC8F4D5CF26DDCFB7A9A85CA + +Set 3, vector#225: + key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0 + IV = 00000000000000000000000000000000 + stream[0..63] = B378200C66DABE0FB33FFC336DB91F9F + 25F65CE152EC1D11738AE1DFA2B419AC + 31AA2F559A63CE39B8829E2E880437F5 + 7D83E3680EB41CF262A6F8025EC8E733 + stream[192..255] = 739C9F273A1A8312214B4B3FFD58615D + AF751344F8D36BBD79A11BBA93BD0AA3 + 34CA56667A6B4A98B6209F0765D9E4A5 + 163756D6AC6861A8DE65777B9B5F4950 + stream[256..319] = E7C1F35E0596EAAF7954E0C7F0423C54 + 60E23A0106FEC3F1C4EBC571AE016BD4 + B232C2E0A8C079EA1A5DE6A2D18B1B79 + 5E69ED4DE32AE2011805A439493223DC + stream[448..511] = 91D8B977B8BD9F8E84C097AB9454FFE7 + 794908D3B1D98729036CF2DB77056F10 + 582C1D1EB084EC97943117FA428C5B9A + 7ED1736E05BCBB55E9E0ED1FD0113860 + xor-digest = B05B91E712072C9FE4AE5C4BCFF3AAFC + 954380E58A9F264458EE46ACE1194032 + 2B1CAAF21117E26A6B490A1C93761A49 + 92982F4277E36ED3C4B74D31D3BB2ABA + +Set 3, vector#234: + key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9 + IV = 00000000000000000000000000000000 + stream[0..63] = 77D958F664235976A8696CDBF0A3362C + BCF3EA19D524F379B02D403F79F9A067 + BBE8F1365B0BCE68699E0A0DA273F117 + 2EDA63B4558B062EF10743740825665C + stream[192..255] = 99B50E13CEA45209DB8FF0F3FFDB568C + 7EFDB1E021435065668313F23A57DD75 + 0676F550EB7C5C5FDD65EBA84B00AA02 + E41039EBCB5AF806339054EC8E9C9567 + stream[256..319] = 64CAF7DF8BDAA26D9BC8B49F99CAA94A + 0ABCD947E23AD676E3CFC95B4461CA78 + C17DF55D2ED805AF80B24BB57E3372A5 + 4F7BD4B4A1A0F65581BF0D409198199F + stream[448..511] = 98595F685F9884606A085383B2437A8F + 8D8B7536D30C693B13FDE9F19DB847E5 + 22B1C305A9BBDBB1F0D402A7794460E8 + DF5A4E719CDF48986C7E0B91A801742F + xor-digest = 54D02F27FFB007DF1686027BFE0F4978 + 01C265DAFA66F72EA530F37F82E8F25B + 35B6D7E2BBEB36F4DCB98C7526A727F1 + 452296BB074B8BCFB878A5299E052B9B + +Set 3, vector#243: + key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102 + IV = 00000000000000000000000000000000 + stream[0..63] = CCFFAD20ADF1C4B744BC6B2EC9CB29B9 + 12F5577164F188BEAD1B8F5884619756 + 350C6514969354F92C33DBEB3553E546 + D00B7321409CF15C2B1BF1D30E1B808E + stream[192..255] = 5D2AB87447F536F42DC3423A3F5E0C3D + 354B648D49A1D613E741FCA61E450D7F + 4777CB7F19557AFB0E3A49E8005255A3 + EF71C5389A5455AAD803CAA30C75E263 + stream[256..319] = 53764B5DDEF40B7C66414E2855FB5D70 + BCE612CB71A7478D3C8D6B42918BB8E1 + 4B12B5D48BF8C464B60214CE96E1CB2B + 6055A167B6BC4BEC2FE87B4C31441CAC + stream[448..511] = 2E4FCCA6545573B051885454D384B365 + 546DE212F89E14DFF2B27A97FA3D5CD3 + BA797DAE4815E8E01629F4A95321E1B1 + ACAE5AFBB2E1FF74D0FA5A31E09A76BF + xor-digest = 4DCE3E84B2FB36C6A268933805F307D3 + 6B9F8B2ED75BDFA9528F14E96CDCD7EF + 77AD88BB08CD19BEA854C1F66216EB4F + CF23FEC02A128FFBE7219244A72FF66C + +Set 3, vector#252: + key = FCFDFEFF000102030405060708090A0B + IV = 00000000000000000000000000000000 + stream[0..63] = 87E3FC12C86A001AD83DC4B364F49F3A + 331C286890826198B6D4937E6804F17E + A9701A1AE8BD09185C1803649959AF65 + 1726A25C54533924E6112F923056F09E + stream[192..255] = D6E5A2371EC564FD24213259599665D7 + 9A31404C3493E005F611116C7F7B48FA + CC6A949BB1746BC5EFE93D6114A1AD5D + 444A9A0391368106BEC2D5DAB96343D2 + stream[256..319] = DBB63AE5E1B11D8A014CDECDE7B03DE9 + D59A473563285D52DBAD3E7E4C1E99BE + C455E7CAE251B3AF52234CD9DE49BA55 + 2B19E5A721C994EA57AFF2239B42C0F1 + stream[448..511] = 339B85580D35BA903A85D2B45249FC31 + 182D7E1B894DE9584906C2E210319EA1 + 168E2E9C582CEBFCD96BEAD69E22CAD1 + E9C5AD2D5E3B708DC1F6B7E36F6E65EE + xor-digest = B3DA36B9D7E12E6761A1C7F8533370F1 + E1D4C4EBA89ACFCE4F24FAC989A7BA87 + A1E0E61BD5A89895C04513D4813FE066 + 6542738B77319BC7282D3209CE08CEF0 + +Test vectors -- set 4 +===================== + +Set 4, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 00000000000000000000000000000000 + stream[0..63] = B1B7CB35C1FFBE7A34E645B05C98501F + 2364C719BD94186DCD66351EDEDB5179 + 169D2EFD6BF03AE1B149DA229BE5C961 + 37C10C3210F8FF34B51A366E437DE0F3 + stream[65472..65535] = 5610AC7C3006ABADD3E0AB13B3D7E945 + 586A00964AD6DF9939835FD46D8B2327 + 15E447AA5D5CC4BAD03A495DC38BBF1A + 5C86A7D608D397694BCCCB029ACD1883 + stream[65536..65599] = 1D7469F8EC3D021C5FB418A0D46A19C4 + A632A7C1BF298B500ACC2D5C39384F5E + 7837C964465FBF3990602BE3381FF556 + 38114E41DC091B0AC1BC51FC6E70F98E + stream[131008..131071] = 5F1A8DD0D98D377C1378785F9EA7A3E4 + B17C9625EFE2650D845A4BAC7723B193 + A3AAC199A1950D7CB1D66380A566A8BE + BBCEB0DD7A700C5ED74E55E29933FC6F + xor-digest = 3E9A70E4A49AE98473313B957F781F09 + 237A172CEFC9068D4F95CABB57358B7F + 40839FFF4258C8BEB466A975B4261753 + 02BD1F4B9D4621436213703A3B99A719 + +Set 4, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 00000000000000000000000000000000 + stream[0..63] = 54182309BD782DEE44FB59B0EC694920 + 2B372AF8D715271A96D87867E65A067F + A5E52B455B76D400537B5D47C4AC318E + EE4C2ABE29F56107C213071C85828605 + stream[65472..65535] = F7D1475B3FA625D86467D4C24915038C + 43D9B81A13E7A08B333B8232D7F849B3 + 1442C014F49EC5814E15B607F11A73A9 + 61C04D305B2F71B7B22DB9D6055B7371 + stream[65536..65599] = CA286F0F05CD6C3BDDDE6108C8A0AECB + F6ED3FE2A39A976D7970FD100A242464 + 42D867162B87DF26EC2B04A990AA7305 + 94C8072994E80B2D6426B90AD0873B61 + stream[131008..131071] = B1FE56B55C9BB460B8EF4F9157B227DE + AACACFAE9009C61C16754EDC913AE3D0 + BEB00C99095C48A12F4485E9AD56BE6A + 6F9C214ED11E94086F32F945C0C3F6EF + xor-digest = 4667B465D4CD7E215B6594B648B05EE4 + 7D2770A69F5FB3A49AD66C1C823F2E6A + AAEAF0680A232F35EA7CAE919F477301 + 0AE66193179E51600ED840D5047F5493 + +Set 4, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 00000000000000000000000000000000 + stream[0..63] = 203C7A9050F5E4F98CB72D913B8E7FB9 + BB2635F8ECCDBFCD231B4EDCA96A24A9 + 9F71BDD76CE42B982228ADCF9385C702 + C2A767488DF42D5DBD8DF2884225367B + stream[65472..65535] = 94E590E29B3A371E5638E55DA4AAA1D2 + F2369CF9EF69EAA0331B4AB01FC1D7E4 + D27A41EEF2C15C51256EA111933BB71B + 5E948DE575258966A03ADC426A3AE9E1 + stream[65536..65599] = BCE13EAD9E39CCB67374B7D845B1B347 + DAF7C440162CEA622CCA3E34E9BFE35E + 10828358DB1F595C19A0A0CD16C127AC + D49903A5159564038BDA4EF156F9D004 + stream[131008..131071] = A4300187C3E146EC1C0F3568C147D668 + D00BAF2EF5E1F71686DC491745C6FC68 + 27F54AFEF7B2DBF9F65D5FE549B96919 + 4BDA10595556840647DD2A4BA22EAB63 + xor-digest = C575DB999E785911A2AEAEA074EA0CD9 + 2BA978DA488A3657341572F1B33E8009 + 07977C738874012CE18E487514FBBFFC + A2E645EB4632862812B7596ABAF1ACE6 + +Set 4, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 00000000000000000000000000000000 + stream[0..63] = 4A82E7937D7C52907515CDDDC1E8445F + D0ECAD783B25079AEDF9D694CE70B723 + 792E33F6FFFD438EECFD3DF933AB48CA + 7EFBB13A31C1E3E86249B8F9D188B7A3 + stream[65472..65535] = FD302A0A44AE5D3BD5554C508BD70D8C + A1803BE72ED426B8D57CC13F899A846E + 5A7A326AB25645EE27A84973BDDB82EC + 103AB97C16080C5FB117E10A8E252A4A + stream[65536..65599] = FAF43B81BC56F7E44BF5FD5F49581FC3 + 51244ED84492382D28A591C022073350 + 4F7B0267105D68566E9FCE5B52B7EC5F + 12A9131FACDC489279F8AA8E9E8E0A2A + stream[131008..131071] = 37C98A0BB719D5E166BF79AD35EBA109 + 9560BFD07144560F4BB91C88B34C008D + E7665BCA98D7B65562B57CED509684C2 + 6AE9011D0A9D674F30E7F9DC37E680D1 + xor-digest = 7139AAF66BE2A8CF28852D9FEDDF47AE + E1E229905F11F191AD60CDD2E1C9433F + 41F1D4BC92B10C8B988824C86B04100A + EFF77A48980691C5636814E04F1A656E + +Test vectors -- set 5 +===================== + +Set 5, vector# 0: + key = 00000000000000000000000000000000 + IV = 80000000000000000000000000000000 + stream[0..63] = 337F8611C6ED615FC2E7D28C6DAAAF1B + 2382AE24592D1E61218220A3775F529A + 7F050B7D4262E3600940F167742FBE4C + B0C147B3C0592523B890E76F59AFA3A8 + stream[192..255] = 47B4B94D6032E42E28BA280B06863134 + 0E65EF25AAE97BCFF5CA83096477B186 + 352757FAF40E7DC007FAF51484B54651 + 2B089A7BD3359258F3E8C0E3DE07C316 + stream[256..319] = CAC4ED541686A3BA14A68CAE81C0B1D0 + D973129F8FD712F1E344CC7815614B23 + 4412F351202D4FC7B622D905B8AC50D6 + 59613FD8799443F89A8E403EB46F7492 + stream[448..511] = 5C4ED1241AB7210EF543DC2732594AD5 + CC5A18AA3AB2CCB9B2BF17CAC28F6105 + 1152291EB8674493A12C0B3CC2C7EE09 + F1A258C5E078080F5EA70F3F587BEC5A + xor-digest = 4EF4B4DCF35FB72D210AE0546DD4A3FD + 9FE632736122E80559A32FC165E9166B + 59E2BB15A066307C88DD32611EC849E2 + A54DA4B47C5E52AC26375D2585EBE798 + +Set 5, vector# 9: + key = 00000000000000000000000000000000 + IV = 00400000000000000000000000000000 + stream[0..63] = 982727CC7FECD8C15B09E6967B624366 + FC902BBFBF9C608B240626B735C6009B + B6969A8D40EFD0546B056B181561034F + B51A6D7C7BCB34447CF5CC560824BAA3 + stream[192..255] = E8E61B734A6EC0DDCB4DF3248749B14B + 6CCCDADB8F24A090B7E5A49603C475AE + 8B6F8353E12FE7D8CB3EDA81E6DE9778 + 2C52BDA59FCF4CFB2BBAB2D196E08C85 + stream[256..319] = 06594AA97EDE3ABCD9458DEF29A7FEEE + 91965BACFA6A272B31BB644596DC5C66 + 8F93AAF38F1EFA50D88A9517DFB4B409 + 9E91F5A1B07C9CA8F36330840A6FCF76 + stream[448..511] = 32784F6FB85DB3ECA696DD98D75A5031 + B3ACD087ABEB6489F20429EBBADF8D87 + B0D7C4D54A8A80FA835B5FCDB901CF32 + E60269C5DE89409A61ABAAB00B7D8B79 + xor-digest = D696A18B23B0927FCA5B766F8C19CE2D + C98F40963485D0A77D92D0096334B9F3 + 834491F8FB7C5D8BEC499F28A37B7DB3 + 8E8A6291C1A6F73938B7AF2B74425996 + +Set 5, vector# 18: + key = 00000000000000000000000000000000 + IV = 00002000000000000000000000000000 + stream[0..63] = B3EC726B0BD04F969BB34A0DFB1AF9A0 + 880ED66663BC845BEC2CEA9BDDCB0E3C + E6FD6CFE389D544D863AD6B55F45F4BB + 14BA866A72D63E4FA83246498EF685FE + stream[192..255] = 549E7B93702F139AA76FFF7CBB04EAD4 + C091015E6455A9855E3EBE4AB1A80737 + 9E3E9C9418B909CC26E53470CD323FCD + ECE6BAF53D45BA80C4F03A412FF160C6 + stream[256..319] = 9599223B02F81DF5D31CE7FC6FD92D70 + 71ADB8985B61709E6769EF5065905E46 + B0AE83DEF7EAEEF01A49D5D855035AF8 + 6AC78AF9C14A3F8409773252EAC28D4D + stream[448..511] = 2C58AF08679A8AE28AF30688B33C417A + 392A6E8D6658D262EE24B479CBC4BA4A + C5DCA537CCE7B110489817F9D2858D95 + E006D338BA92D7FD664F9CC773AB67D3 + xor-digest = E52013C82C2088C5B76988031F0A0930 + 6322244F357700E3D3BDC71A2385B4BA + F6894A2B177F7BA78D5935521CDB5689 + 31F7706AE3413B10128CB903D7E27160 + +Set 5, vector# 27: + key = 00000000000000000000000000000000 + IV = 00000010000000000000000000000000 + stream[0..63] = 6727DB24106CABD6C3A14001BC9E3B5F + 90A47B78181576CF5398D8F190CEFC10 + 6615BDE30159225DD3E14A2F827DA07D + C230D11AFEE96855EE06FB02D23998D9 + stream[192..255] = 7B9AD4C2472D5816B963BC168F725083 + 0E900C4E4994711DF7FA494A04A7CB58 + C9CAD5513E8C554B47060D9256B4F276 + 2CD9790666A3C831FE1A9250C2C1F1B2 + stream[256..319] = F8B0EF0C84EC8375A17C8C36B9F75690 + 30D6D04687514709215F79B102304807 + 3FA3F284155CD677B30FEDE6EE33DA7E + 5B35636C0F8E981AACF01CFA4E7B00C8 + stream[448..511] = 023E93B9B5A526DA400CA8A818E506A9 + F5B0438F91264727C4FD5CA2FD4A845F + 3F2A6E0617A5619CCB0B691C2AE2F459 + A7F4764CFEBB22D8FC6AE8E28B08DD4E + xor-digest = A6BB0A1FA9D79299B2FCD3AB9DFE04C7 + 9BD7B88BB1A49AA7227E9BBD0A211677 + 283EE5CF808DB24D05227305E67915E8 + 74CB03402736AC8FFCD746B5AA4DD032 + +Set 5, vector# 36: + key = 00000000000000000000000000000000 + IV = 00000000080000000000000000000000 + stream[0..63] = 4BBA6A59AD3C1A7298CB38F244AEB7AB + 431AC1FEC2D091C4952794AAE9DA762B + 0873BEBD04FE1CD68D08654F1DFDD956 + 59EF5E09238984D834F2631D67E16EB1 + stream[192..255] = 945C61BFC21691064FDA05A6162869E6 + 82800A1DB8E19818C2AB13A9280C8CCD + BF9508894CCDE69ABC8A3F0CB2BA545D + 3A6D6E7D6E8B5E53683DC3E0018BE954 + stream[256..319] = CD87390C68404079BCE794A554FC4DE9 + 695AA78E626CF79094CF0374765C1ADF + 8C4054AD4B76535008F8466C806D1775 + 1987361A852DB77F2CDDDDB34D00A15B + stream[448..511] = 319081F4D93C649E6D1D8C4999E0A03C + F4AB23E4EB796B337C84898D6D9F083E + 70038515611FA040E686B893D89E28DB + 862C6D36F791F27EE05ED97AC636E836 + xor-digest = 1B86F56D5C6DDA97E2909873A042A48A + C3C102D22F88E8648C0A7DAB5C34C98F + CDF03CD03B6106095E3BA34969B67886 + 8AB4D93CF24042F52DB659591D72D0C7 + +Set 5, vector# 45: + key = 00000000000000000000000000000000 + IV = 00000000000400000000000000000000 + stream[0..63] = 2DD3C3CF5E6965EA02C31ED6FC539EEC + E0B8D48345113E978230ACFE35089F9C + D8EC821843DBC90E54010C16A8AEB245 + 5881FC16B5CC21032958DAD18EF55469 + stream[192..255] = B9299DC95D2F192F1C53FF23432158DC + 2746F64242CF9368D90FA217289BF31E + 6F08692251CCF86B2DEB7ADDD14D8E37 + 0E4D877637A2D499924146D89CB77F44 + stream[256..319] = A6F9EDFBA2E22CEF8E14BFE5B31ECD14 + 4114A045BAAF0458BF149F073DF191E7 + 022A9E518212876F7D6C99F1DDFACCD7 + 8E0DE69FD43FFD26EBB7E240B5F4B864 + stream[448..511] = AD29FD814401DB358AC8B2A911E743A7 + A594C9781D4F6560E29D8B67AB38D8E1 + 67AC71AA3855D5BE67998E0B797A64BB + 1B26558FD861B845E9B08FA071DDCD75 + xor-digest = 2DE49729E28C8B4585BAFB291E77B7FA + 6CA9E489C437133EABC613D0893822FD + 70A8F88BF6A3D29BA6503F17F055A003 + A42605780A79501BB62C35C922DFB1C5 + +Set 5, vector# 54: + key = 00000000000000000000000000000000 + IV = 00000000000002000000000000000000 + stream[0..63] = 8D3CF6CD521B43CF76A6ACA2A036B791 + 7E06F44E8DE525306C6508C1FE2E3C29 + 50A53F63B11B57596B76E97C1EB01612 + 3D33B57CF93E839A169AC49207BB42A2 + stream[192..255] = C009E0DECD6948B8F29A72F1A2BCAAFF + 04043B6B76B623CF977679D74186BB4A + B1C3529D94A5DD5CCDC20AAEC056492E + 7B9F9A9EE087187C52C7651F890A0DBA + stream[256..319] = DF5DAAFC6D650B0A47AFDD7BEF56634D + 13AC2D1442AA1F082715882F9D303170 + 8D338A7CFB14B100E3D3C645334C5D4C + BA9534475D4BA687956B00E8EAB587AA + stream[448..511] = FB2CB04310DC73C7B7312C840123FB0A + 783F10FB63F507EEBB012E19A0FBEA30 + C324904C02E301F4CE2CC2A1198C0C14 + A725FAB705C5176CF19EB2184DF9825A + xor-digest = 3B3136B100FF460D92A0FDEFE864662B + 324D7B8C7C3DAA46EBF02F8BD0960345 + A1FA8F9B7AB8DF16BC7FDF6B6AA0C61F + FB1C7A599A6474A916A8BB9E4FAB9856 + +Set 5, vector# 63: + key = 00000000000000000000000000000000 + IV = 00000000000000010000000000000000 + stream[0..63] = CF1667BC6BF8ECCC72ED756D4623E979 + 6A8E559E27ECE3DE4FD85DAA60757C33 + 0C33EE95AFEE6A53D730671F695C0B04 + B5968DC2501F48D9A2DB7E20CCEEF297 + stream[192..255] = BE8163A51FB1FD786E1E5197B5F3FA74 + 900AE8111592D24733B562187D399B95 + 79D5F751D722784832AA471C4445FA5E + F2725E23A251EDAE66D60203CB862095 + stream[256..319] = 8592AA7309D37B63AC539BE5B997AD26 + 3F6C38DD169535E7BFB1C19965919F55 + F4502C5995FF7DEF3021D07A37B9E7C0 + FA5E8AD9AECF2B072EE1DE2F2E26DB1A + stream[448..511] = F05E64D5CF14CF99154EF83E27CFA2F9 + 2B269E8E164F1B563F4AFC48C40B5FF8 + F40BFC7E59EF0F0B923F7474F30AC114 + 95EBE3EE8630A214776286D01A20DA23 + xor-digest = 46136E7DE5C7186F1F3D04FAA100B991 + 8FE7E8E02B36C72A92E5650F93F5D936 + 5675B0D3BD84E5C3E7F5CA7E70ED55FD + 027C83E1CB1AF8BDBD1FF1905A6EB596 + +Set 5, vector# 72: + key = 00000000000000000000000000000000 + IV = 00000000000000000080000000000000 + stream[0..63] = 583E7BA16D617DAD9F2A4A6A7BCB630E + 4248E8368A6F45F6BE8CF22C65964D34 + 49A7AC0EDE8957127CDCCD3AFD666426 + B8BD2391698525CD3620558076F61EC5 + stream[192..255] = 8CE8D0EAF9944E68D7EEA0F83ED86CBF + F87B99C8D87C40FBDA48E777976FB669 + CF6A68533BA7875DAD0BCDEEDBD4D136 + DCA8A9C9C1C6B30C5CB7B7C5846755BE + stream[256..319] = 534AD0B12F8CD7797CAC9E23B1618AA1 + B707F28D000422CA73196498C86D51FD + A63DFC791446094F4E146EA451F60B3B + C2711F81B137FF4C0521F94447A486E7 + stream[448..511] = 540F0CF1CAA5D5CA270FB71BE97FCF9F + F1F30C2F454BA29561F7B7C2D8ABF189 + 30D107F71560B26CB7E9E416F90604E8 + 510D29FC0AAFD94EEF254F0F4C0C43C8 + xor-digest = 0986B6D195197767683FB8221A50BCA4 + A375BC5989C24422855F465CE537FDB3 + 3894E7383CE580D8204694DD1E82D623 + 774AD356957E36042735848BBA9649A8 + +Set 5, vector# 81: + key = 00000000000000000000000000000000 + IV = 00000000000000000000400000000000 + stream[0..63] = FF9484C54337D0F0CB2342A7E73B21E8 + BA933A679CAA5549AE6218B7E0FCC88F + CEB6CF2158E19C1D30F4E0B0A2D5E052 + E4C73F2F2FF423417E67F49F45BEA7C2 + stream[192..255] = 6AA4E5586B608D3F0E4A394AC7818949 + E538604293010925AB3D69AFCD1979C8 + A8289CC46776E762452246B54C6C7D3F + E7BA43B8D901D2B55F2F7CE520DF99DB + stream[256..319] = AF841581E66BCB36AEEE07534A83B519 + 60D0DE9740D320D1ED3C542B64FB122F + 506B6F573F40AF29A61DC42FE183EEB3 + A5D55D0272659028B9B5B353A6292105 + stream[448..511] = 3E463ED75242C21811F9C2492A71D6B3 + E5B2BE3E50151A990F841EF0350259B6 + 9C727194154288C62DF02075AEEB2598 + 577A5C0B134EC1206F66AA96233D1BF0 + xor-digest = 0C45BDB39F8C038AC8E2E3C41A80FBF7 + 7B74C948861E7D58F7A89ACCCB4A2D04 + 7D370BD42B65DE42293C58BDFBC003EE + 58D71CA3D01313E8A74C7BEF66CAAC76 + +Set 5, vector# 90: + key = 00000000000000000000000000000000 + IV = 00000000000000000000002000000000 + stream[0..63] = 8C4921B72A3D11BE4DF4E326B9BF85C7 + 351CF85FE98039D5BFDB889DC5721B17 + C02EFE07FACD2F43E95D6EC63F4001EC + FE7355EB565B6E2CEAC64A995324DABC + stream[192..255] = 933FFDF78D118A083FB7CE405D042D3F + 9173B28879BF4A37A878EF2351622F42 + 80D218DE417B8503954E991A31BDF73E + B26903D1F7C7361F34D7F01656243B58 + stream[256..319] = 88E77D9A5FA78C7E348DFE0A66AF1B92 + FF564670DCEC867E24AC78CAC005DAF1 + 5953DEAEAF2C476C2DA514CF79A474DC + D4E68AAA0D52394762953A8A63A0B3A1 + stream[448..511] = 5FF4F24F6BC7585D16582944166C453D + 59A3CA9F9625A5946EE81F561CA183F4 + F6D5258F138E994DF848F532F613092E + 89FD262FA4899091596A1031913C6C5E + xor-digest = 4770E4B7DB5C5FF7F64BAB6334A13E4F + 9DA6686EB2945463852513C770ED64DA + 4A0C3D96403F4CD1E96B7FA6495BE23E + 15506374CE556E7B50D3ED8A92A643E6 + +Set 5, vector# 99: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000010000000 + stream[0..63] = A59AA0661087A6F3498D18BA156FD4EC + E5709F5CF1FF25B006382B250E4481FD + 050F68B95D56E1EAF77C619914F30269 + 4FC8C2461200D9AD357F21E9DA08F489 + stream[192..255] = 941E849E313B8E214DD6CD1C10FD8D18 + 05C1892B15623CE0724A3028F978215F + 7B6264D4D5CBBEFE12920BCCFD204134 + 1AF60D460B73D9493BA2AE7B314CAA41 + stream[256..319] = 2F27FA6FC61D2D84C008DE836B0CDB1A + EB0E62D5E327F88B8A62BFBE70789189 + 9E1335D20E495D2181253647B0333CA6 + 6833552B89571E3BC25190C791341940 + stream[448..511] = 9DACDBDBC8258B52C41788ABA3A7D08E + 5D7919C0B583F6AE89036A4EBFFB3AC9 + 7CD9E9B15E8C811EB6F2BDC7713115A4 + 5291C4BCA5DE179ECC779093B30870A0 + xor-digest = 2C7C5D79F8BC2D8E7B62DCE74340120A + EAEFEA33114403A970F1A51AD9EC9F9F + 63F630E74DD83AE5C6824089982685E4 + 28FF20C49689DAA995D7AF2E80502425 + +Set 5, vector#108: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000080000 + stream[0..63] = 869923A0917A8FBD8F45FF074E83FA79 + D665A9A44C769CC200A66C254B2D4B98 + 7D34D66E52EF7A9C7ABFDD7548F08631 + 49C7CE742F6CA599ECD0BFEB55CC8B6A + stream[192..255] = 75386882B941CDA70FDB6D02F165B3C3 + B0C7B0A8E4ECB161BBC745EA1AFBF382 + C0C09725D0DAE6316C7B956577EE7F97 + C4A102B04437F24D2090FDB00B78523F + stream[256..319] = 04FBECD2FDE606BC32E46FD0B9950F93 + A742DC2534886A3B17C8EEC5CDD28B04 + 5A03E7C5764EC92C1DC8AAC5F9D5483E + A9890C7322739BC7C73CF8158619F669 + stream[448..511] = FC322AC5E5635C8DC56895BAFD43A01D + 77807CC8CE57DAA306E7DDCC58B24309 + 4497AFBA51F8EA62922C697FC2EE8945 + 4926D4975219A40B2D6C9A9620634741 + xor-digest = D2E239BDF9A2E04082567893D06DCFB0 + 4FE50753793F21380F6A91354836C508 + 837A15527F914190F6F97BA87510180D + 67B13994803013B2E4D4A307D80E8EC0 + +Set 5, vector#117: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000400 + stream[0..63] = F350AB2F8E1B96AC93F1FAAED04BFB0A + 59EC1F7B95383E44878AFFBC5CA7D4AF + 2EE76CEFB67906469C9FAA59F4DDD24E + D16796DCAE66011584E8A4B139E016ED + stream[192..255] = 48D1D8F4583937C77BDC1757C3DFF07F + D0CD430F3667E37A6D4CE89217729AA5 + E480DEF30227A363C800A3153617B04B + 50322B06B795B0EEEA039A796C7B6664 + stream[256..319] = 4DE5C06008FBF0D54EE2E2052AF4EFB1 + 94AEE33EE7F133F225CDCF2C504AD2AE + AFBB2A2AC50D7F27022DA8D83D6B44F8 + 4545E8BD15E33CE531C3A7E076B39BED + stream[448..511] = 837C91FB8773A4DE4FE79D163FFBD186 + 2A361B96D79AADDE5AE964A62B3D9CCD + 1DDF29D845EB581C33E3ECF1CAC4AE15 + 3C75E0C5ABAA960389FF0C92205CF575 + xor-digest = 29B708C591EA72969C5EAF624B943D55 + 3A55CD66F13E5E762D6808F5A58D77E8 + 8CE91C0A7EABDEE8F30C05F4D48C0257 + 9B38612376DB9E26AE70591760E395AB + +Set 5, vector#126: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000002 + stream[0..63] = 073CD91D0183F07259608257E8267FA7 + 8799B748A5FEDA25FD40B463F15639E4 + CBA06A504C5D4E80A542366DDFDA8EEE + B21BE97CC2FFDFD5FC93792A7CF1C2F7 + stream[192..255] = D310A845416E7E187D3404B763B46BFA + 7EB62B04A06DFD0AC6E9871EB8D74F32 + 73D7488C8D2197515DBF84ED8EBD3F24 + A4B3B69DABB27A3CDA6DEECF2F58EEB7 + stream[256..319] = A8058C140D6692480614EAEE7AD97DA5 + F4423B249C2F0413DF35530CDC40417D + FA6D5007FB9488A073F0631AEC501E15 + A94EEF50A2744693EDF07273C5621056 + stream[448..511] = 44220A7B36E147C5C3F41FD72FD88F50 + ECCC2364563085D3409C5508DEE719CE + 327EBEEF70917036C37A534B764A4DBB + 39B77EDE8C115448096C7E2BF2EC6720 + xor-digest = 07C9AF7BD2DBDE982D011798BCF014FE + F9334DAF537AF14589BF2328C45D327A + 755F902A389BE04970AF515D5718C891 + A77AA50A46D1DD737489E298182BA245 + +Test vectors -- set 6 +===================== + +Set 6, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 0D74DB42A91077DE45AC137AE148AF16 + stream[0..63] = 2E1ED12A8551C05AF41FF39D8F9DF933 + 122B5235D48FC2A6F20037E69BDBBCE8 + 05782EFC16C455A4B3FF06142317535E + F876104C32445138CB26EBC2F88A684C + stream[65472..65535] = 1D92C4EBF6A256F0D0B0365160D72E90 + CA10D7086C58BE13E9325A5088F447D1 + 572466248CD275A736B83674739899CA + 3146963E00E170C6B9DC8B2BE912A5C2 + stream[65536..65599] = 878A21CA440BA0D659F24A5C986D6CF0 + 3EA0DD962337935BA0932FAD9599EF61 + D805800038AFE4208394C73AA044262C + 18490F742A2B7424ED56EF3D1B0F53AF + stream[131008..131071] = 99387AFF42EE8C9D4D8400808322114C + F4DF77CDAA363B0E4AFD0D8FF17D3D2C + 3303984867021922368A76F7CBD20266 + 5A962140C8E6C1336CC4071B38ABB957 + xor-digest = 0FF8DA8AE74C2F194FE35FEA66F69380 + BF1D368CC0282F6E570477EB426F1858 + 204DD9752E48E32C1F40A2ED3BE10FF6 + B5C80216884D0357AFA002E01B7B5FE8 + +Set 6, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 167DE44BB21980E74EB51C83EA51B81F + stream[0..63] = 4F864BF3C96D0363B1903F0739189138 + F6ED2BC0AF583FEEA0CEA66BA7E06E63 + FB28BF8B3CA0031D24ABB511C57DD17B + FC2861C32400072CB680DF2E58A5CECC + stream[65472..65535] = A27D9CFEEBB098C44E94F477A5AA9FB6 + 286339533CF62E2781B574B9CCC53619 + CA27303E83FF9D986EFDB5D0AECC93C2 + F249325A37779D894549C0408B6A47E1 + stream[65536..65599] = 36893EF2C9173CABEA2B5BB027938EA6 + 0004121DDD27E79DB469B6402B4C23AB + C08066B24EF0242234F9439019DADF4D + 000A8B68FD539F2B6C8087AAF89C76C6 + stream[131008..131071] = 8FD0EB93722FCD5093AD826167F0F158 + E2A7B86751E85D796D5269866FD317B9 + 523032CBB52F6978DC7E0933A2312E40 + 57E0C9B1366C98941867D2EB0CD8CAF9 + xor-digest = 63DCDFC74EE1C446705C01CF185C7F23 + E083DDD7A70E2685DC1E051F2AAC63EC + 7E64399369B7D1CE49A732F594B6A587 + 3B89E848F70A3AA9B04D219BAF14807F + +Set 6, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 1F86ED54BB2289F057BE258CF35AC128 + stream[0..63] = 82168AB0023B79AAF1E6B4D823855E14 + A7084378036A951B1CFEF35173875ED8 + 6CB66AB8410491A08582BE40080C3102 + 193BA567F9E95D096C3CC60927DD7901 + stream[65472..65535] = 2A30BFDE279B750D56B0B10A79BDA0DB + 21C246D133F4B91E4ECAF80DA7AAC425 + 646523F6BB762D688BFE2DB1852B77E7 + 733BC1005CF3D7CFAEC4BD966DCA6773 + stream[65536..65599] = 991EC57DE1BDFFE2C70A0196A8902C91 + D3CE6C63E4B8D81C83AABE7BF370D1B5 + 4D0B72B0C3C857621A7BBE2B72EBD81F + 50B25E08A9D492AFDDD37B983E9E2E4A + stream[131008..131071] = BC301B9FD7C554C592EFD092A435C2C6 + E74CBBF905CE424FE5872EEFE8DC62BF + F93C3917BD37D142CFCA623B84C2652E + 0E61BB5C5D5387AD95EBA7A5ADF16F81 + xor-digest = F8F5AA473428C00F7F71E4D1BF1976DC + 2856619D2E1CD79BDE2FA1FCE880E816 + 09B8D5AC28691FB90718E0981C3BB2BF + A7E5888E44A0FEDAE7D481AA3AA684AA + +Set 6, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 288FF65DC42B92F960C72E95FC63CA31 + stream[0..63] = 1CD8AEDDFE52E217E835D0B7E84E2922 + D04B1ADBCA53C4522B1AA604C42856A9 + 0AF83E2614BCE65C0AECABDD8975B557 + 00D6A26D52FFF0888DA38F1DE20B77B7 + stream[65472..65535] = BB599F93F4F244D717CA9818212B06D5 + 6D99AD4CA1F78725DBA89EA1D1F05B27 + 093A17D745396D8CFD0256CD50674046 + 13108E2200A8F1C49075B376A7460515 + stream[65536..65599] = 996C074A7C7C524F539037A8A9F3D193 + 3BC311B548BD567F8AE1B4325C51C5F3 + 4B0DE1B4A4651829108CA92AE23D57C7 + 0EAFA766097DB0539BE77E6500703746 + stream[131008..131071] = 43EF1ADFE8265C46FF7FBA43B78F899F + 22C3B9F069B786982145D601627CDC49 + 2D27BB8D70FF6DA908F2606A0C44690C + 8502F9CFB3BD6CBFC9205470E3ABA387 + xor-digest = B097BF56D79F1A343F61F7B66AC405AA + 6242493ECECBA06876276B36ABDDBFC3 + 76D8C370503A8B8FF6D121D2FFC4959C + 6A96721616782688FFCBC748C9A168A1 + + + +End of test vectors diff --git a/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt b/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt new file mode 100644 index 000000000..6460df61f --- /dev/null +++ b/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt @@ -0,0 +1,2337 @@ +******************************************************************************** +* ECRYPT Stream Cipher Project * +******************************************************************************** + +Primitive Name: HC-256 +====================== +Profile: S3___ +Key size: 128 bits +IV size: 128 bits + +Test vectors -- set 1 +===================== + +(stream is generated by encrypting 512 zero bytes) + +Set 1, vector# 0: + key = 80000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = F1B055D7BF34DE7E524D23B5556B743A + EAF06AE9076FD2F48389039C4B24C38D + DFC3AC63A148755FB3CF0CB8FB1EDEEA + 63CD484036FFAC3F5F99FC7A10335060 + stream[192..255] = 2541F0EDA5633B4F47C6B74CDCC612AE + CD27E46B2C8FC9036A09C6FFB5891168 + 7A8FAEDC225E34C45B6E081EF5279FE7 + 3271CED417549740EAEC6616C2B6A57F + stream[256..319] = 0C8C0567803E2537804BFA15742D3E08 + A29985688DF3D6B4C3044464C1D1F2CD + 4CBBC470C9A0FB05665CDED63C58E466 + 896F80ACC020F134CB622487D40E0AF8 + stream[448..511] = 1FD448C788A21BD30D4B6BC5D8AEF296 + 2772940557B9434E0FAF636D576B0737 + 1FF3AC12884BB431F396CF7C189D9AAE + D42797128CE645FE841A4CAABA429324 + xor-digest = A3F66A36C20A496A0D4D537B6106662A + DEB5AE1E35FD1486EAB6039F443E5D8A + C6A2D4A2C2E2A9F335E2E468AD8BA51E + 550E41533332E6929EC18CE35BBF741A + +Set 1, vector# 9: + key = 00400000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 9244D2B190FE8C4BD0E17247C4F1D282 + 3FECA8DBE546637E34BCA99236D09F79 + 5A8905A1E0FA94E6C51F7DC0C90FFAE1 + A8EBD4C99CC96FB3252DE0A0FB03F971 + stream[192..255] = BC0ADD787A5EA52E28B45192399DDDE5 + CEC4E283181408E554FC714586FB641E + B36F3727358BDD8223B5ADC9B9EF1044 + 0F7CD97FCF2ABA75AA9972B277CD6656 + stream[256..319] = C9F6315DA3CBAE23D32685C5549274E6 + 9C17FB2E46746C5D3260FF2E00FB234A + A460776CB0E7AC3AF0D297825C1796AC + 0B689DB219443BF4C0D4D19CD70A49E5 + stream[448..511] = FBFDF6D40BF2DA0EBB04D52C117E9EBD + 6FEF88D39B8EF8B31082EE9B19D50219 + 183DC962391FA4F602A2510BB476EF4A + A44439F61D589933A1F3F633C96E56FA + xor-digest = 49B435E6FA51A0AF8DC94CF1DE09F8D9 + AD76E08C061B54CCD62EF98ABE85969F + 3FC41DB934AF9DBC5F32748623639D3E + B15124F13DA8B008CA5016ED61917563 + +Set 1, vector# 18: + key = 00002000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 9D74BE686C2DE8B207E8D82E49236A3D + E86F5A7EE231B4239080FC9A55FA44ED + 7737FA7472B318A4F36FB788E863247F + 7067C20DCA632FF051789E9EB99CF409 + stream[192..255] = 4876774DBB886B72E54EE8160D8BA8DF + 6DB032B2A9BA0B79CF82426CEADE421F + EF5ABE9976E909DBADA0442FFC7BBA2B + 009F7240941F0C209853A514B0BE9062 + stream[256..319] = F2499CCE5D3268F4C5515C365D2F4411 + B0AA99ED01E7D5328BF0672584AC65CB + E47BCA14C3EB1F838ABDB7C611677BC3 + 7382E84D05848B9838A166A42E96B016 + stream[448..511] = C855EF5D1CC991D2DDC892AD8319E39B + 734E43E443F5910D03BB79CCEBE70569 + F92BBC63363943BEF88BFA5809B3759E + 6BA4ECA1FAAC572228458A229DD5BA06 + xor-digest = F125B88E0B5F143B836AFD7AC822E027 + FF44B736E32627D90FA05F3DB98576E1 + 9EC41AAF9D61ADE2BF00E38CA4EC2A54 + 49EE0655FEAE777D67EE127E8A5F8CD8 + +Set 1, vector# 27: + key = 00000010000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = CC447BF1B5D138025BEA2B269E625C4A + D4451F3851F04F118499040C6E564E38 + 5C5FE17FA7AFAE9FA559CA4835AC1F40 + 1C045AD439B400BB41984DFE7E4D4CC4 + stream[192..255] = EEC14B65E027BC2A96E566BB89218A89 + 31C4AE0BA5C444929EF852EF7E400AC5 + D8B3CFC62DEBBC2B20A7B32E350E3839 + 2953B7839AACC06B2018280770F84B65 + stream[256..319] = 8870B4F9A62B37A1929973D3975D7ED0 + 505AA43002B14B55A541EAE00148651A + 111D6E5A1581F85FFBC2304783EBF5AC + E924CD8111056B1069F13100DE15EB13 + stream[448..511] = 1513F3B7A2458674CBA2B566F3AD6169 + 2BA4EE30687A07AF2FD0D340D92384F5 + F5BFD9B8DF2F7098A209C280F6D5AEFF + BC07D167720DB47B4B649C8593E6F40C + xor-digest = FB5EE30BAE44FDFDF105796FB8A66F69 + 64D502230C191FF9AAF5A4447533D02F + 05A3772B99F9FA2A075DBB8BA59D8D5F + F819784D487C305280DF2F19EEA8BD47 + +Set 1, vector# 36: + key = 00000000080000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 831F1DAB278C6226785209C0AD34759B + 9F205B7BC6B987DD145B949336A8FA0E + 4550BC1737DAE7DD7D12E2C062BF9693 + F08C2FB808A1F0A5887A06B93D132BBC + stream[192..255] = 76631E9D4A673D09B9769251433D5EFF + 3114AA59E1A9B7E21B4123DE3E34FBF8 + 4ED6E80EC29B4F75B53A63902C373EB3 + D644B8823789743CA407FFEBA4A1AA75 + stream[256..319] = ABD84B2A5479CDBC5587FB9EEC5DC661 + 5A3CC6136314F67AD2C96803E8E4BE92 + E33DC35F0DBF3C401AA5D7A9F46E54CA + A7ECD68E561BC08E6A5B847A82777E4B + stream[448..511] = 9ED1D44510201727B2E92B55DBE06BA1 + 46762AB34937364B2157292CE68B9D78 + 3D3C3FFD1FDCA836E4C4FEC750B10668 + 600C26AC05B4DED64F8CC2EAA0D22052 + xor-digest = 843D7B97B3316595111DCBDE3DC13DA4 + C14402936D68035CDAF9A1C168120B34 + 0EBA1FC47E957C5F69F369B4C2ADC4AE + 37E743226D72A9F122EC8E00BCAAA126 + +Set 1, vector# 45: + key = 00000000000400000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = D2D629E84843638274ACB79FA257DD9C + D48A08B823DC9F175CD92C5236B9D230 + 5931FDEC5A8F531B1ADF30DE0527AD2D + 0D2B253D008913558E0FECCA7D7BEA4F + stream[192..255] = 6F9322E84D69CFD6A1E589283CD028D1 + E2A114B719FB2E18E732B97629313772 + CD2F2F8AF77EDB5B4360E4B679441346 + 03C59E88C042713C3E403E5D93F9BBC2 + stream[256..319] = EE7BED6C85B20E0A39C103D0B6949F4F + 5F6FE0DF2BCE315CCCEF6E537C488525 + BFC27FD249A6D36548C558153661861A + 78422A563166BBD0D72D6D7876FB4DB4 + stream[448..511] = D2CFFCD4185EB1D8E15B629225B9C278 + 6E7BFEACBFE29D7AF396B3D5917A8038 + 7263018C7E98F49A1D5FA4B64B8E2AA0 + 7192ADE0376388E8295AE5B54CC51389 + xor-digest = A26BEFF2FD72BE47175C1B6F3D749CEB + 0E3472FB0FD5E173DE66A5BB60357565 + 505E3AA44A67651DCA75DFB6F0AFCFE3 + F4C89F064FC42D7C2953694B0CD47832 + +Set 1, vector# 54: + key = 00000000000002000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = DD1649517BE76EFF747658F0ACF5D354 + 2C7FFD52F09FF7DDDFBC48487450607B + CB90ACC3406D0302E84450FC0BFEC660 + 9BD44C7FFF670D69C9B19FA50C62EBE3 + stream[192..255] = EEACF8ABD7D48E285A6658C255A6196B + 66B091773A9F81807A119DC24023D5C9 + 041AF75F2C078C5246BC5F50B622A678 + 64EB7A07DA6A8764437E20C7E1E0E579 + stream[256..319] = BF55E777AC644A0938D438FA374360ED + F842BECB027FA3A0F364B9150FFBEB47 + 09FE2D2056A6CD5A7076172152484BEF + A86EC7DDE657307580BC6F9ACEDA4C73 + stream[448..511] = AB4CF968EC00E7F08553A10270A7D439 + 68B0BC79C2DAE278AF1CB81FD516CCA6 + F5B8A47271FAAC3223F02DB4D0D5945F + 9C13A47906B03B80878CB0596D37CC47 + xor-digest = 76ADECA36B9401DDD5CBDEE821B70FD6 + 65EB9CDB1E3F25C0BE90DEC49C03A9CF + 4049CD34F9550B28E0187B0AD47D86D4 + 88DE4617EDB5F03C67FA2E7B9D20AA25 + +Set 1, vector# 63: + key = 00000000000000010000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = C0CEF6E3CA9F0D523587FF47973FE896 + 9FEB08773E3C694FBAC4804B37121B31 + 06B99ECC2A08603EBA72EB3DC650E8F3 + 462119F4685EF4CEA18D5765A6F22765 + stream[192..255] = 79E92E248BA61D72C610876D3078F1CC + CAD662F2423E7EECA813133136A64E54 + A1B6A151BECD2B815EAD959DE8E8DC62 + 8F388D366103296A058CF60F525D6467 + stream[256..319] = 03BD62A0892D939C1C28C4EB490F87B2 + 527536AD6790AAA6C3CC50013E2BB883 + 5710EAB7916FD89896B7983B326AE271 + AF9ECF975CDBBB968D076685BAA3343D + stream[448..511] = 98762E306A2B9D488FFB671D3975551E + A06A6CFC5DB719B888E3164387EC922F + 12BC31A8DCAB8AC0CD6E12212CDA3B13 + 4CF7F870221D6CDAC2B222AF4FD93DEE + xor-digest = 606FA49585621E34BCC3748C06B51FE5 + A8AF320BFB83A4D1D3AEC6373519B28F + 2048A975732BA8DEBDFC5F85B84E7C3A + EC0FCC9B1FA9EBB9D79D6B18BA2D70B7 + +Set 1, vector# 72: + key = 00000000000000000080000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 33A81D48866B04388451BC2730A2980B + 5F5BE248369911340E6C024A1F94D4FE + ACFB246F7C0B9E27A40772D68DB36DE1 + 7E87AEF19C8A68854A46B3F654E0AEC8 + stream[192..255] = F67C60413B25FF7CB8647D1E9C361696 + 3B23ECE23A9DBFEC644E855AEC5212F2 + D336E6F074EEC8FF5F8D4FC6398AEB9D + BCAF6C29FDFE6E69A03D906C527FB0B5 + stream[256..319] = 263D512137BAB758F646C71058D02B20 + 3920965D84E52A99B50FFE79305E491C + E0D61EF71F7A07937CEC8590B758F63E + B3EB5890E8678F170C2E95B827FD8DDE + stream[448..511] = 023AD00A87D3D9441D4E8CB603F5CDDD + AE8F3EBFEFB9C5435B72B9B8D03ACDF1 + E4A0FB796FF8401854998015905B878C + 99B3EDC7DD33A86AD4EA6AD208440C5D + xor-digest = 5DAC8E3446BB3B0DCFB3F0A3A3E788C6 + 07FA7436C63BF7AC9FAFCF4A231AFAC7 + 75A3A810EA0FD4E5E6A5B8FE5D165A80 + 798A9F58EE1AD27016E867D2E774507A + +Set 1, vector# 81: + key = 00000000000000000000400000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = B33EA681CA88C80EAD8F2D57C87EA42B + 742550FF8AD2B01BDF945BF160AF763B + 15D6B3BD92E6CF3E6A2B61A7D4BB94AC + E3DAB365E4EA50EBFD2654E60CE849BE + stream[192..255] = E97318BDF61934188A94BCFB4441809D + 36C37D1A43BDBB3EB06FFE143B6153FE + C8453A13387923F434CFC7AAF8CBA097 + 7D796DE95EEFED3B2126B611F477619F + stream[256..319] = 4183971367E71731111D2212520306E1 + 1CBEB05BE6FDB338414C826A8E359C7E + CC680F317C12C6EDE6B443E68B4767AB + 4190E95E1AE4E4FFE61707BE742775C1 + stream[448..511] = 56841724B7D7F95809456EDC1D3A532F + E1C6BA252017DA90EEC71FEE9A639A89 + 4CB7E1575494BC8B44FE4C5DAF90FF4C + A32E03D6399BCB3D9D25B62764A4977D + xor-digest = 3E80587D70A53AFFB96A62F6493B9BE0 + 1C25339CBFF7784F5100A7922EE3E6B9 + 9D17B026C0EE69C5383F63E0E5AEE9DB + 5814E2C526192AEFE17004AAA1996280 + +Set 1, vector# 90: + key = 00000000000000000000002000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 51A7510726D12FE9574095633A3710E6 + 3EB8196622BC808B8A18800E208648C9 + F7031F8171B71F37613753A5E49B37C1 + CBC7933A52CAD48601E91CA198EC19EB + stream[192..255] = 286EF1C4F74C993A7D783E86527CDFE5 + 213CE4DF7EC72544685291D8108C7621 + 50D488AEF761D819781814F4501553CC + B45EDDA85828C33C4D0608169AD20B2A + stream[256..319] = 89DF5C916612EF0ACC1035EB75752239 + ADE08E0D63B622EA52CC997DC8178C4C + 4E57951FC8C6659A225E88502742B888 + 1F300FC9F278AA3D9C1063A83CF33C44 + stream[448..511] = B2DE3AE2941AFBDB21D80ABB0EB852D3 + A076D98C696F886C302D96D6AD226CA3 + 7B3213B3E641632B728A0AC7131B74FE + F733D1B18666D36A02C148FC98AD2E89 + xor-digest = 01090125BA6C43AAA3910B650D046F37 + E04896E9D2BC276D969A10C1B26FAD48 + 8A2CA5E59044ADDF698588A561557669 + A4EF25E1BB85C0A9D63F69FBB2924F83 + +Set 1, vector# 99: + key = 00000000000000000000000010000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 545E2C75365948B40FFF042EB6919907 + 6E63EE636CB343C51AF6C17BA24E1BF5 + C045B0893B8CBDF6A4068F8574513676 + 80000B10BA11666A546D8DC75374F5BB + stream[192..255] = 9805DCB5596FADF01224553F3A8DCC5C + 909D1A5EC2C29BA0DB86A46ABF70BAF4 + 4A171739309A923428EA7BA8EFCA5CB0 + B0B8A5EFE9A4A39BE0EA6CEA782DD862 + stream[256..319] = 531EE320A584EE1E4E0701400F86DC29 + 69531C2BB1BC922CFA9E0919A05B84C2 + 46495A7C358015724B62A986220DFA17 + 6BF39FE4263A9D27D93F3737CC1D5C59 + stream[448..511] = 92CC0D63772783AF62E642A5849CE7AF + 4D21EC815D644F88887242F4F5F7E1DC + 55E241D72691ED50D59CB3E2FE68A856 + 7696F8B8E3099642D70EC3945B8BA656 + xor-digest = 855CFA62E449250845472BCE9453BA45 + F91601ABA6BB715B079D407E05D94CF5 + 93B5A1E2C12C04C78AB719339AFC11C5 + 213E17ED9DC2B0B9CCF751E0613D4F2C + +Set 1, vector#108: + key = 00000000000000000000000000080000 + IV = 00000000000000000000000000000000 + stream[0..63] = F9748DADA2741A7CA30EFA167ED09978 + 71619682AB68CB400A74BFD642180CC7 + F3499CE2CC86AB7727786DD01AB8D08E + 8774C5A3CFB4738FF1E3243DECF720FD + stream[192..255] = 5AA20B305F5D6363180CDCD4E16427E7 + 2E3DFD73D2C4E2498008F6E0FA9CE3BB + D751F6EB8DD5F48EB42B994688601E3D + 2CEB3DE19BF16C4BD7FD4B331FC93473 + stream[256..319] = 81E3D9BB421CB09A9139534C6E430668 + FCFCB87E48CFA085D4FA1AB316CD5AB6 + 35294E434852C1509C1023A85B26622C + 68BE19944CA3233A4D3272710A791E3D + stream[448..511] = A499D228204BC22C32047DF550E2CCC0 + 260ECB7BA32E8F5CBA2C1D9A09D1F38D + FB30815BA3C9A8D3243CFE7AC4A14B1A + D6AA67D3EC0A5CB617FAD57E41A2A0DF + xor-digest = 0324B7F1BD990F8DBF19C021CCDF741A + 1B4A9C3C3940CC59CD715F0B2CC31C08 + 82E5B93721AC98B00F7B45FCCF19FFA9 + 782B7D7FC048F0756A29B066B472B394 + +Set 1, vector#117: + key = 00000000000000000000000000000400 + IV = 00000000000000000000000000000000 + stream[0..63] = 7EA95775329E2D1163E30F429FECAEF4 + CA177BB4D3C4D1AEFA6B5A01904266F7 + 7D7B7243B9DB1490245EC05129CA2DBE + E3A98885DAD0B43B0E725DDA39B444EB + stream[192..255] = 78ED15A7B4A8151F384C740B844115CF + D4FA31F9BC16E22158B0F896E70C0F73 + F74AA5EF024F6B386ED71239CBD57996 + 4583C37104AD8C7E5C812C378AF00F98 + stream[256..319] = 292FF21E49659AF99AB21753BA2A2B28 + 25DDB156D4F7AFC1888FBE8376AE4C6B + 905D5916121E9F9D76C83FB146ADA735 + 2AAAB6E89CE9398C484D69D1A33F0C97 + stream[448..511] = A50FF5FC20C57F8297C9CE2599A3E6CE + 3193746E8C45FD9AECA0C5A0FB3BF70F + 5981B5BA8D2FA57677EF65B535FC3E65 + 405BECF0A508445E36A7B6DE2BB56106 + xor-digest = D9650FA5D128620134828E1C99D9678C + CFD5BDFADC46A5E79D47AC5967B8A1CF + 32F7DB65B949C88CCEE0D96D960A110E + FF1D09EF5549B88D5B53ED46D4C2F296 + +Set 1, vector#126: + key = 00000000000000000000000000000002 + IV = 00000000000000000000000000000000 + stream[0..63] = 25874CF64ABA4536844F815F486F9DEF + 927E325CFF2FAC48134A4D30824C5BF1 + EC75F8FEFC624AFCC717BF2C8EAAE374 + 0AF399C2653389DBE31F9FF5D451D362 + stream[192..255] = B151A1EDCCB8B4A3CA9BC98F19EFE637 + BE2D6A97A8F794091E7FFF06E7B4E574 + 46B81E8C787BB77E461592160C44B5AB + 49329142D01A1CD5CFC6681F93DF1E33 + stream[256..319] = 29B2B0C04E07D33EC3146E60AA305F0C + 2288913B55DDC18FC17EE836B39193DB + 87089DF2BAC4185A57E910331864E25B + 540BBC968099900F7BF18645A28A419B + stream[448..511] = 286FCC98B40EA26BFCBE5CDEE52B30F5 + 810CFB26E756C628B56B3B5ACDA49E07 + 192592CA2241C6C5193221EDA36CB0E7 + B5C3132F08087DF0673D3101FC559962 + xor-digest = DBF1D7E0AC062FE6BA9834F0AE41ABA2 + B28B41FDFEF914F070007B0A48EE9D9F + E69DB8395BECDBA7B545201318177A49 + 7D343A317B5A37A9DF98DD25C84DF948 + +Test vectors -- set 2 +===================== + +Set 2, vector# 0: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951 + 53F06534801F89F24E74248B720B4818 + CD9227ECEBCF4DBF8DBF6977E4AE14FA + E8504C7BC8A9F3EA6C0106F5327E6981 + stream[192..255] = 30DA9453A90909A5675D6B691CB0990F + C423CDD8222EB47245BBB67BCA2B9C10 + 8D1F016DF0CF8CEAF6829910916DBC1E + 113D11E91BEC3D85C47E3042EC865658 + stream[256..319] = CAFED71B892EDBE13388CEF6A3365797 + E0D88C0D3A5B91BE4CBAF5162F69558F + DBB45CA6F8C8D4C371D62736EC244584 + 60131F54854F3EC804AA9A38E6ADE281 + stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F + 2C3EA0F56AF46ED93DFAA4E16F5F0831 + 2D77BD0E9122043CD6A202CBA9351F6A + 0E8E6263F4017355136A0C551E6FD0F8 + xor-digest = 023D719F61C193E4CCD87755C87F9604 + C5A29DD7E31637B3DD70D43441D48CC7 + D474013C85EEAB1897C80ED0A0272543 + F951C72E3954616CB5D6B51FC24F4B0F + +Set 2, vector# 9: + key = 09090909090909090909090909090909 + IV = 00000000000000000000000000000000 + stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081 + 2145B56AEA46EB283A25A4C9E3D8BEB4 + 821B418F06F2B9DCDF1A85AB8C02CD14 + 62E1BBCAEC9AB0E99AA6AFF918BA627C + stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58 + 11FA9BB02CECF7440239FBB0497347EF + D8F1A8AA71AFC70ECCD64E81388E6E87 + 9521C2B47AD84F9CFD9E240D8D2F3001 + stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD + 3C8D6A2EFDAA9CC11BFCC61D94F6104A + 4091B3634FA57AB0AB9B209F22DA5529 + 75C3C322DEBE4AE68623BFE1B2BB7F0A + stream[448..511] = 35B290F85EBA78A978750690C4747E8F + 72621951483772E8B89876CC5D55F3AB + 02D9B8FB35C741279FF9B5B571B26329 + 4D011F813CB5B209CA1A22D532BF09B7 + xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34 + F6CD0A795B8347E1441CEBEE35540D41 + 64FC2B95D71FD47A2C4ADF732261EE52 + 8125BE374FA4A90132CC1063971A2862 + +Set 2, vector# 18: + key = 12121212121212121212121212121212 + IV = 00000000000000000000000000000000 + stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD + BD8853C329B3A881B489090853FE0F43 + 89DA105F0ADFA9CF51DA2521C40FD2B8 + FB0BF80B93E3F2B3D8A8EB1C615E0FA6 + stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D + 43A82A80DAEDBF29C048639BA38B690B + 7ED11323E3C0A8E77A16356705431EC9 + 9F2CB7F7E1ED3B83EAF2CAEC00B00755 + stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417 + 376F334E6AEF9C187012C8AD2B94BE7C + 00A876756EB232510FD0798E72EEC87F + 75EC1467C07B3A1EFB0D51A5FA65E382 + stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B + AAFD131432CFD7D2F675E03320395313 + AD4ED96E9052FE6B2D2A17428660A25E + EE642B712800BE3F7E44F21A1E6A03AC + xor-digest = EF4E84DBD66497B142EEAC56B830FF78 + 0465CEE20B9CFAF5727D4B3A588F4D00 + AAF718330CFF35508C44C1ADB8476625 + 2CC3AA6AAAE74F8BF1DDB6D4AADA425E + +Set 2, vector# 27: + key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + IV = 00000000000000000000000000000000 + stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676 + 263C1CB9AB941119B19D15EBA3462F56 + 2F69220595DE5E0E7C595FA40F1F06B2 + 6EC32252AF05310809DDDFAE2E24B170 + stream[192..255] = B29A740B51B4EA1080666337D5551484 + FFED6860A5125DC0573C8F90F23A98E0 + BA7B3E4C28C2CEFB1C33D2C36D1B7625 + 64B9A67240CF174347A4C8D868F00F6F + stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6 + 537C06AFB23354F054E25457B729B534 + CD10B2ABD45BE3E38DAF1B7A9103268F + 4FDB4C0FC9A80A003FCB907E8F249AE0 + stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39 + F62D54311207B617B727FCCE1B2E762A + 060810C4DEF672E7D76083E3E4BED0D1 + 0BAFD27CDFD2C937E660190D36B3FD7B + xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C + 18CC5E1E3F6A317ED7257887446EF734 + 65CA15F51AF5E077B7915062391D8497 + 8F437985DD08F5FA3A8D74B3227A6EEF + +Set 2, vector# 36: + key = 24242424242424242424242424242424 + IV = 00000000000000000000000000000000 + stream[0..63] = C845BA29D542FBED2D021C85188E119F + D34967B79D9F44635DD45D2E41DC5AFB + B237AD2FA0E4CF4202D83DF3073C578D + 2AA8A32D30FB45DE28F23CEB85E50FBF + stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297 + FD12081B4B23F0A32CE5B3196173C7CA + 7EDD03F9637E08CA501C4850C15B207D + 7AA724377396CED2357B572BBF9E69AA + stream[256..319] = E484AF567EF80BAE77461855294E9280 + EF57E7366605785034D639D6DE3EBB0D + E21886D0E1E0679BC2E2C9C2D9201484 + 4A452B6AD3F1AC8B7762FF3C0E405B3B + stream[448..511] = 595D9855200786BB575FF7977509F395 + 7879CA1F19619A99174BF013CB62F85B + FF2C3C4FE724E26DD0C10D7635A2491A + 9E7E868D9DAD9201465AA178184D06AC + xor-digest = 08737B82505F46F4FF282EF42F387AA8 + 0450058F5314389BB73733BC163D75D5 + D32FC6408F8DE5F6ED2050027D605FAC + A7119FC2DC1B6D3E84E8048DCC42FBD2 + +Set 2, vector# 45: + key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + IV = 00000000000000000000000000000000 + stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E + 6E6320101999BCE5550C2BBC9BC65D91 + FAA2D72FA4BF46B6EE916244048B1D09 + A115E3AB6C00BAC8EE382B58859E8157 + stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82 + 0C18B867C561E96DF4ADADC5A4375E44 + 5A34F9457E5F8C9A337A0C88DF0F723A + D4509F1449DF2C6AEC0EADF4C7A8139A + stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8 + 452A1A893EF034C51750388D294947EE + 3F505839C69C1708E8323C449C39A96B + FC9EC91B0E1CAA8112057EB0389FDFD2 + stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC + EDD92C4461EFBA5CF1664B9AF54857BE + C3D00319E5E8A89A8322831151EE1D52 + D8585AC79CB60B61ED2C852D04BB0FB1 + xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D + 2363BC12259B0FDB2BD8F052A572ECA8 + D1EF62AA9A48497805A413742B5AF5A2 + 6DC9FF624B49E5D6FE58BBE5251B4983 + +Set 2, vector# 54: + key = 36363636363636363636363636363636 + IV = 00000000000000000000000000000000 + stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340 + 42D4F07DA4D5EB05554CB7426D65C5EC + A93C2D321175B6F72FCBEBA6E38CB098 + B72534F7D534B1AADD97B77E8513B482 + stream[192..255] = B2466A173F436C8433F264CBF125B8E4 + C10BC81BD46B5C21FA161CB2AE07D27B + F66812A2C2FCB2B14C23E413CEF4E591 + AD52EF810A000B42E5C1B76EEBB17739 + stream[256..319] = ECBED2058DC50223614EB8635B834C3B + B176719C18CA5E3D087A93E5CDF81123 + C6FB819CCAFB5042AADFED5E3C33116A + FD92AA21031165A22F4751C423B8B945 + stream[448..511] = 758BD9435DE607867DA256064C304C8E + DDDF5B64173CF2C98B2842992F8C5FE1 + A37C3227B7F37D49A39F9FF929A883FD + 56DB8B1A174E1E55FCB21C9E1164C20B + xor-digest = 31761A49503946701D35306FBCBE10E2 + 02967E7EC14A328B4DB19FE79F03553F + 13A012B7297B2D02F18A216AD24A682B + 299518C3769123EE86A4937DAA9FC39B + +Set 2, vector# 63: + key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + IV = 00000000000000000000000000000000 + stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B + 26A4E7E34C0CA9CB9399F655E566383E + 246143F57776C8E08951E87F76091FE7 + 2356CC901F09A07895A890AECF047B3F + stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF + C862100A07E55FB449BCFA2D9BD48658 + 958B37B3EA3565FA66824102A14B5770 + 5E3914E0680E116ED58212CBF61028E3 + stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701 + 057710F24C01E680F58090B8E949AF01 + 8970A43A698A04C0C8639FAA665DA3AA + 562B2C5C3A03BCC38FE75DC1821ED718 + stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948 + 821FBB049DAD15B988A77C0247868A38 + 2056B66F47B0195FA30C9DB5A2334A9D + CD7C0D22E479FAE1BBCDFFE60F261C7F + xor-digest = 94D41CCAD940CED3C854DA0796DC62E5 + 6B566A980E34F353CFFD0F53AE9E34FF + A6A057645FE66D86BE30F93805D9E2B5 + D78C68EEBF61CE387277A51EB2EF835B + +Set 2, vector# 72: + key = 48484848484848484848484848484848 + IV = 00000000000000000000000000000000 + stream[0..63] = E45194379659D1D8904DB3698AF8B245 + 762910B7FBD019AD1AA20A6C433B4C80 + 308A9EA68697631646BF3A2107C4E7FE + 2235E8F3262A9DFD3F5CC23FEB0B2DAB + stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA + 4E947598C4757976F6F61DA5F0DAC8BC + DDF72F08BA2F446FA37F9A490F6A2B6D + 79227C93271D6B763DA7B2A907220A42 + stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74 + A43D83AB8ECBAC5206D108F869561D70 + F151A0037F8E28951B5026643F8B2D6D + 56A62E259F04A5EA304791A9468E66AF + stream[448..511] = F70794C084E6EDC07BA0347413B05FC9 + FC46994CA820CE4FC037ADBA50EAA9AD + 55064ACB7308CFCE3F35AD5C7C628362 + F4210FBC2D3264F734728626BABF5356 + xor-digest = 31815B36BA034BB1941DB1E45A941A59 + 7C3882F34BD3BF441CAE8A9790B05BCA + 72049FD10C09A14AC9DB867A82C38A5F + 524C72F783DFD16980DBCDEB486FAE96 + +Set 2, vector# 81: + key = 51515151515151515151515151515151 + IV = 00000000000000000000000000000000 + stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6 + FF53889A9979ABA8F23AA51DB1EDB8E9 + D08F696C1100799A7D004DEF1CA94110 + FCF0C054B0C131E6FAE0FE2F2DBF22B3 + stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC + 55A5F3F19C5A10E12EBE46DD84F10385 + 33837693588D584FDAF86E3A217C3CFF + 020278736F1A90CE07F0DCE4329005B9 + stream[256..319] = 135FAD68B5282FE59B28D2DF66463632 + 06CA92E84A73FA131EDDCE89A5C23B4D + 08FA57D455BDB32F8ED58DAF3EF288A2 + 7C72020E35DAE19B446E4C52DCDAC5B1 + stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D + 18F2111002891D3229102D72605B9BEE + F5DA36059B0DBBA7646927650305431B + FDA4A97570CD0C484BF1E974B157ED7F + xor-digest = 5125E77698C0DAA89A7E47DC5D038D40 + 7B732CE56CEB674CE653A1B6661B2740 + 0C092AFF83BEEE4FC4543B9D725C9387 + 2F89AA338222ED677BF59397200AB304 + +Set 2, vector# 90: + key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + IV = 00000000000000000000000000000000 + stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21 + 75E9AD91482965B651B495AEE819CC6E + C42AFE2C20EEACCEC4E90710D17210E0 + 4CC6832905985322C8007F872D3E58E1 + stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560 + D692A020F0A66F609374ABDCD1343722 + 05F19CA04EBDD3009844BC540C1B2B41 + 66D45E8A2E822B906DA34649E7FEEBB3 + stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF + CE2CFE99506677A956AEC86BD290B6AF + C5298A448D0DEFA99AA5CD26D318982F + E786D809C713D5A55B42CA6650191DDC + stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225 + EF6E3C21705EC9FB24873916A2C24668 + 963C03FE097DA8224A42A99E5DFFDC17 + 68CF518DE49CCAC8A70216C62C9CBA6D + xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5 + 5FF58B296071D5D39349A531E41F0BA9 + 893A1722B6102740BC5FE394A49363B9 + 6A626AB43FD6A288CD9B23F7255279F8 + +Set 2, vector# 99: + key = 63636363636363636363636363636363 + IV = 00000000000000000000000000000000 + stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333 + BCB02E3AD8797377AE1F1B4D6DDB86E6 + 2A59791CB553550E0492FAB42C7A2C42 + 3157C5092D2DD37D46589F17FBD86584 + stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91 + 4122EEE5736BCD12061C77DF5B0122B5 + 1784E946B4E93470170ACDD7E2779591 + 57BCC9B9F3E11E88BC2F740AA0C10C97 + stream[256..319] = FF22D8196AB3DF662210D12D0FE79255 + 6DCD39611C07F089979CF7D693A30CA3 + 5B795B7F6D64931916E717C8BFB92114 + DB75118BDB51D142CE8133415C6B3456 + stream[448..511] = 971F007EFE17662D95F47F4F28266516 + B22A1E50755EEF19149DE3A3121F5FEC + E0D9DFE7A055026CA44193542D7687EC + 695B97769BF02F92C1EF3D904A8010C6 + xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163 + C8D54A4CA36748C74721C7B6E1649A31 + 4B5B7A4BD43E7C3D2A22F0C8446C7892 + 90D54D421D37CB16400E59CC86215CC8 + +Set 2, vector#108: + key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + IV = 00000000000000000000000000000000 + stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6 + 54BC11ECF0010D2AEB9F899130F4AC2A + 38EBC15C8831D591E6675DC1CE7A471C + 4B869FE83CBF37AC70BAAE5D4AC607F9 + stream[192..255] = 518F298A6008532EEFECB3DCF72103BD + 5E3F84FEB6EA2311E8C19A2E93A9C3C3 + BB1DA7DBA78D5618D1C4FA5B0B202728 + 62645A361E55494D66C9359E41E5809B + stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A + 89BB20CCD92E7F13FDD816DD4E4963C2 + C5FC2570CBB8BB5C70848B73001F508F + 47AF179528200F51CDC6E4854EAA63C3 + stream[448..511] = 844B1D15FBFD1264169279ACD525611F + A39C7BB41F1E7A1C09090625F7926E51 + 23A4CD7FE1A3F37ADC67AC437BF0A5AE + FFFC6FB0ABF39D9908145004AA5B958D + xor-digest = EC67596C9DEF4012A2D543842829306A + 4285A3B8038818F265065DC848BD80FE + C27C2F66A57B27F7FA8AC912001EC954 + 05BC6E93D7E555C59060F5D2E294D103 + +Set 2, vector#117: + key = 75757575757575757575757575757575 + IV = 00000000000000000000000000000000 + stream[0..63] = 91D2772A18995DB3C0801DD3740F4466 + F9535E5BECB93DDCA0E94D19C0B57BDD + 0FFBA9DAF0B11D55C852927F8BA560EC + 4999E25848D08FCA7275E7E8571A5F1C + stream[192..255] = 72E64FF10CA9F07CC493715724DA7610 + 9E4358E8B0CAE451348B784A162DF036 + AB9796724D17FDBF356031D080A6631C + D1E8D217B041AD2EDF427972653206B2 + stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3 + 344956C29D10374E502C2EDD177ECE5E + 6625BAD9630DAD57976216CD69865058 + 130B132FEC1AB0C350DF4DACE4C7724A + stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90 + E402466550B518A177CD05985D238827 + BD92EE7EC22C274F19E682F85ABDAD95 + D0EBB3DB6C6134408353C8B0472C9A1D + xor-digest = 9A6C893F2108D13A29373DEDA65386C4 + AC356BDDD4A3178952F9126E322B7AE6 + 83C94F1A131CBEAFF26549D9F84CF04A + 1241FA374B055B0ADE7E49E8EC669E65 + +Set 2, vector#126: + key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + IV = 00000000000000000000000000000000 + stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3 + 059C5CC575D806B9029CCE3FA45A246E + 0EBD3AB2F2E324FE36ADC3B56AE2F7EF + C710AA964CB87381386C2A88B1308035 + stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E + 20BEB18D9C84187C347F43B17E0924F1 + 2348F825E106E57A00258CE4415294D9 + 4323A9812D8A71359CEC1001BAA0D567 + stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5 + 32D62E779FA0D2D08F8ABB6B0183A4DA + 4EE0329215F261D953150B9AB9FCBE2F + 568AAE361EAA8636ECC01A63F007977F + stream[448..511] = E7C44F44E06321A20E25F73E2069757C + 90499DB7E60025CF6D2D445E53A665F3 + 08EC96F6FE73C0AC90D7E4A712E18C2D + 3DED46DFBAFA24C4B0B329E52C525976 + xor-digest = 22035341489FA6EEB2A6488CA42F4043 + 57477C3F55569A1224EC39B1019E90C8 + 21D37D78ED4DCEAF6EA70724C3751760 + 38CF25DE4F84BABD80424D83A310881B + +Set 2, vector#135: + key = 87878787878787878787878787878787 + IV = 00000000000000000000000000000000 + stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191 + 3C69F2275EB97A1402EDF16C6FBE19BE + 79D65360445BCB63676E6553B609A065 + 0155C3B22DD1975AC0F3F65063A2E16E + stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB + 3373B816DA256CAAC37914B0C161E4E4 + 5F5ADBE444098A5B2A4CFD4251D79918 + 987BB834BB50F0834EF4985F356B92A2 + stream[256..319] = D89642D25DF97D149AE07EA18BA39497 + 8935978AC34C1DF9F444986D7505DB4C + 7E08DB3616B84CD52E7DD7FB108C36B8 + B50C2573172F4D3500B6D62A9D20B82A + stream[448..511] = A2C17FE7371604556F796429C6BE0688 + 8611638B310F3E9FAF484BA9EE29C16D + 2F842EAF33AFEC557B68D2F453569187 + A6F4CD204A0E7A733E81AB7CE9FCAE81 + xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B + 6E3A61977A7C6AC2F033B826AB9A9957 + 66671D2A1025CDF8E2824B2F58CB221D + 2A68679239D90152FF7D0D39B33FAB93 + +Set 2, vector#144: + key = 90909090909090909090909090909090 + IV = 00000000000000000000000000000000 + stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6 + 71A6D390BC7099A708D370DCD0E3D143 + A0334619EBD5C7DA9EF6301F29273F85 + 2DFA3C580ED65C6E952F88A0B7FE368E + stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B + 445792061AA0539DA69ED0B77B970C0B + 482156A5DEE4082A61364BF06E692399 + FB9F4411FEC515291F8949B20F57229E + stream[256..319] = 993E815F299D4841518119BFF88F6EFB + F3DB9BAE60238BDE2845DE4DBA6D79DB + C9E42BA5C3C004AE4546FD86C660FFC8 + FD6A8A349669FFE3D9E5BDF8E50A407D + stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2 + 1274F4A6D814B5440C74D53A3FF0735D + EF01B14AE4188E215CE7337C04871688 + 7159695A241BFB9D6B489FE9E23B2AD8 + xor-digest = 0BD5739ED28778023E6303FD88DAABC4 + 0FA0A211A1A5C5F230D9E67DDD9EA517 + FEBCDF0BDBC107291B6CF3ACD8B862B8 + 4BF15400493A54036E97FDEBB9A1DB2C + +Set 2, vector#153: + key = 99999999999999999999999999999999 + IV = 00000000000000000000000000000000 + stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC + BE99E7E515650511FF7016A0EF287ADE + 5A03839C4F83F05FAC3B0B24D4E3F602 + 3251F8D9CC4530A805F8A6A912EFAB1C + stream[192..255] = 792823ACE2C0DDB266A118068AE295CD + 716E424D3B98A9DB2501A3F5DF7DC70A + 3BD2C6E664D5E13317D6F57B8774C903 + D407D2BB6014E0F971141E89569C5868 + stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB + 304C81FA9DDE0C21592247C4098D9347 + 1DA30294DE8C100E5B17A199F744CAC2 + 4E33490FC7F223FD6B4923056117C6D9 + stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59 + 349AF2BB1DA2BA622B9824F729929098 + BD19DFC05D0D9454F604960C027752F9 + 7812E53DE6AC6CD2751AB331703646AF + xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2 + DC458E7E517637596FC8FB710E2E5636 + DB1F14848CB12793D54ABD0856B22F3A + ADFA8C33AD08B8CC5292DD76913CB105 + +Set 2, vector#162: + key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + IV = 00000000000000000000000000000000 + stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229 + 8A8806402755660C4A30CD216A500BB6 + AE975E08EC62D08425A8A62A71B00215 + DE35E5178902348698528CB82296F009 + stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C + E4F7E1B3E78C3A5DF07592F45B968BEF + F95B8B257DAF2B468284627AF4481FD2 + 67BE0B164DD86721DC8C1607A0607EF0 + stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3 + 9C056162B626F383F3E77B5C98C0FBE9 + 119A7C335C333E6490126AC2510CDFAA + 86441C72D1DD9ACBCD3FEFC0D0C794C7 + stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754 + 246C065AD23A8D709161FC74B34E23DB + B918EAFA4465125D3780BF0B5803AACA + 037AA0A14D977141B611A6CA2278B634 + xor-digest = FEFDA1A6E95920B93380CC24FAE214C5 + 6B009ADCB176D519CA4B8538EDFC95D1 + 6CA06B730B28A230F0085FE43CBEE2FA + 2EE5DCD74D66F5CBB59F256CC1ED885A + +Set 2, vector#171: + key = ABABABABABABABABABABABABABABABAB + IV = 00000000000000000000000000000000 + stream[0..63] = 22E1A884ED2C67CCB2977105649B6544 + 367858D1A730AA2FA96703FA406B337A + B2159A389BEF48D8A215D870B2968E16 + B11571F12BEC0A07FA7D3B9790987EC7 + stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74 + B27776E9250B8B063E52E169C7B76A15 + 0D699278AA4124427B5EB6AFC4AD5DBF + 600FEAAA98A88DFF297DACA5ACB4878F + stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484 + 976B640E60CCD6ABFB908583ABEC3E75 + 2878371EBB5374C9B37A63E0768AE10B + D857253D940AC408EF49EDD590E806AE + stream[448..511] = F012E429C44D5DC03B88123855B62C0E + 90E06759306017B5773752973850531B + C480316CBBAEDE6353AD5FB298349AA9 + 16AC0221A4CE1E4729BFB9C230AAF9FB + xor-digest = D73B872315F9052C67C4CFC5CD912DBD + 60DA32FD06D9C8E804968E688898200C + 1D979DFFCE52E1C3B3309B58D12BDBB3 + D3EBA2954D1587D720E004E12EB4A13B + +Set 2, vector#180: + key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + IV = 00000000000000000000000000000000 + stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88 + D2EF924014F7445ED922E9C021571909 + D7E6BFCAEE0724F2A9C522C4BDE4BBE9 + FE53FE592C0FEB80D2C7A51FB8BE9EF3 + stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484 + 0D22CDDFF39EB0E3D5FDF74C6E7B3394 + A0A4271D780DE6DEE9AC58B4903EEDD2 + 6DD14E14A4DFE506748D5DCA6DDF4C5A + stream[256..319] = E79D99119996FBB5163335E2F79F0502 + 7AEA5372136E7B3C5BE1F4A673A2DC74 + 60834B81BE6C4976C4A727C8E6046A64 + 4CAF42EEA6A068B7E532581E9037BE9F + stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614 + 9F3EE55A136EFA3B417DB63D2487DF82 + 794E161B3153DDB2E1E4F385E1A848C7 + 729FF5CB1CB58D5E73FAB1F2DCEEE5AD + xor-digest = 2F3C231B0228C274255F3BD314ECC7F3 + 1B9C49177009AFF2CD88F807092D77E3 + C74C1B9B8650F581EC7603F4D6E70955 + 1B00C3192414C04AB0AD8B0B9BCFE988 + +Set 2, vector#189: + key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + IV = 00000000000000000000000000000000 + stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410 + DED6D4E331633C5621B94E7EBD15E856 + 04AB202A553EFED55A548C7AFFCD2550 + 60315FD50A305D8BCAC9C077229D34AC + stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF + 3CFD130D5B6A9CE37BEBA429AD137A82 + 44D0586FEB16D086F533D1885A82F73C + F2AD2C645591F80ED09942F0A08D898C + stream[256..319] = C214B6AC700164FA66DE346A27A99463 + C5B6C0E43A9057384BE168E163058FCB + 6E7DEC871C6531EFC8B8D581EF92757E + 219294D39E0C9C8276440BE56C3D9941 + stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE + 4C8D2171695C9CF97E2936A8BB320670 + 015825547A508EB43D96F2EE1EE2CB34 + 4E120F001500F8ACC3E19E30455D09D0 + xor-digest = FE5928C74EA21F23E29171E5AAACA20C + DD8571E907763C96B99A8C11F9A1D2F5 + 78F68A6C440996995F7AB6E69B3CCE33 + CF8CE0C16F54355696D47DBF82EA8D56 + +Set 2, vector#198: + key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + IV = 00000000000000000000000000000000 + stream[0..63] = 75559677D7C762F6CFED942D800F2FAB + AB5F3892DC2C79922E96FD34FE511C11 + 251C8EB7C639E531CE08A8C99F62E7BC + F68FBAFF99D62348FF91CCFEC2710055 + stream[192..255] = 149806A4D862EEA81F0208D927339E5E + C98E9C2A6E0DB85CC0380DED7EC5B8AC + 4ADAE76AEB9C7B7264C3834316209615 + 25221D58C0174577110596FF89C8FC69 + stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B + 3CDD19BF89B31FF75A814F470BF97E0E + 1293B750B769F5BDD750DE5025D7534C + AD541A1F26C6AE9AC2FD3237C156AEBB + stream[448..511] = 0958243E88921B81F04AE63658E52D76 + CF2638495B3A6B970633A7C8F67B8CF9 + AC378082F72FC63BEA02881CC5B28D9D + C8C261C78B2872B5EBFC82336D6E1A28 + xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7 + 0028A08A00EF935C06A8B3632DAD5914 + 84E44E372A753F8E630741266C0F4218 + 4923608103042C70ED4ECC5112B9AF6B + +Set 2, vector#207: + key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + IV = 00000000000000000000000000000000 + stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28 + 98C701CBF5E88F1F3DCB6B873E5CAEEF + 23024ADA678E1A2CA9E25AA8B476CF4F + 9FCBC297FF03A9B94A5A736274EA776C + stream[192..255] = 73B9891D1770289A67D6338909FB6282 + 9A425B7947FC30DC52B11E398E85B1EB + 537E1C02898FEBFC15A9172C254CA55A + AA1B56EA856F47E37E2F252D92D94ED8 + stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4 + 38B63B9F436FE00CC075C585297B8F90 + E6062358D29641FF9C28EED4A23FC53A + 6B5C60C2AF1E8146DB27CCF5F43BA838 + stream[448..511] = 642541A9733946827D79BBD815C03C17 + 6357BD6E81E9A61FFFD4A0BF6863AC71 + 72AEFB92C1F235641BBE1457B724A6AA + AF9FAC687552A778B034C4A4F8E41ADE + xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668 + BD0BC5A97655978E79056B3D25DF3E79 + 5D5D8BE5D1AAE877F2E7D03225CB6609 + 6EFE11CBCB728039A243E326437CE73B + +Set 2, vector#216: + key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + IV = 00000000000000000000000000000000 + stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F + 1F7BDFBB81428FFEE9FBE14DF5F5F3D8 + A044EF53A868D989E16165A0F2B95E8D + 83439BB4805A125AD0CA7994AE11B852 + stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184 + EE7A7F4B822A1C955A69E238022AA313 + 276C2003E27AEF1B4F94B33A6428685B + F048B357EAB297B7DD98E612F054A317 + stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C + 978B976BE1B6CB0D15C0324D6B70D265 + 385B615B3EA97A55D94C47F53FF40861 + 4460857AC9568556AE54A52546B41B5A + stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6 + 5BE2BF56D2B78A401D5761E2F3AF8B18 + A2B1089864999D9B99E5BF6959F8F802 + 975FBF204D6159CF23F3706CAF0D9BA5 + xor-digest = 0957D6887501D4360C430614B67D99B5 + 32849E2F5C69CE8A9F3F707A2B5438BD + 0C1237B5617FB525CC9C043A10DBB265 + 3C3F0A353E89A19838B8F68542E09526 + +Set 2, vector#225: + key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + IV = 00000000000000000000000000000000 + stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A + 50CF101BF065F69F3E78BEF5D689B1D1 + D306FF41EB3E78BEB75C4200937CFE60 + E89E370680C519B2F64E23516ADF8062 + stream[192..255] = AA30580A210B87727BE17EC52AAAD037 + 3E0DD11FBFC89B37825CA4D6F9E8D433 + E3EA54C37D678B58CE834AFA310F6D4D + 06B4603F12DBF38595AC76511D0B13CF + stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC + 8FC9B09DAA6F418D3434BFBBFF6BFFFB + F93F8A963F2F51CC487BE868F010EC0B + EE17A480542A301E33B36F59BEE13D91 + stream[448..511] = 672048756C221C12DA6178BE711B3371 + 525A92BC9A219CABC5501B0DA4CC248B + 8742E8BCBD6F5A1CFE522F3DF3BED6B6 + 5D60D1AC737ADC582C2CB9751521828B + xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB + 3F418EBEB69509D69B2594E964759D15 + 104F674CD44681AFECC3B4939CA0A0C9 + DD7AA5726653ED3FBFC833DDB0C87B42 + +Set 2, vector#234: + key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + IV = 00000000000000000000000000000000 + stream[0..63] = 2479A8F2872A813D16D15F060D300237 + 25297B812F6F3B97D74D9716E4403A5A + 684D2BFD1E15275470FEDADF1578277E + 44C6C06B8A5FCE3D0CCC5E13BF49947C + stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3 + 132D4B0065A563288F848E05EB45E48B + D15C069C02F90B4FC10AEBF1AF4BF90E + 2CF7F48C8CD7A8091014131EBC21FBE8 + stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C + EC170B064429EB832924CDA9C47B5174 + 9BFEF80D96FAE36DDA65659FEA1CC06B + 4EA3A1601A3304AA4DDBEB62381FD4DB + stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145 + BFBCDBAE19F5281CD0E6AA37419778DA + 64DDF68726DD7F4D78BBBFF4576C2AAD + 93F477A2AB2C3CA8A381F30BB944C7B0 + xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070 + 9EC7E9B89DB8EEA11045ACC5FF003DC9 + CD3318BB6F9675EEF20E15490F525066 + AF8380C663B60EDBAE30663C94C39892 + +Set 2, vector#243: + key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + IV = 00000000000000000000000000000000 + stream[0..63] = CC3701E703946194401D1BA23AD99B5D + F3F856138E142D4B9C23DC9F252A277B + D62DAA33A71A0C61079AD5A20562291A + B6EC92C66D7BE6A17E27D4DDB48EFD31 + stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903 + D565423614409AD11E821B83F5B35D83 + F26F3EF9EC1766FEA9C21C09E0AE248F + 4BA01E48BCE09D06471593B3466703DD + stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF + 96CDC215EF1A62FAA29A5608C852FFA1 + 18B473C5A7319446F3ED2E8AB39A533D + 714325D1B14E838C9EC6E037DB0DD93C + stream[448..511] = 4FF3B43841B17A279002EFB07324625B + 7E937D480DC73F12836195110ECB4DB5 + CD31CA4F92F612A95E82815328DA7D5E + 4DCC5BB6791603EDA64C57B5A5AAA04C + xor-digest = 9202B874C48D4B1A9E857E645EE8F884 + D971CE97923AC024ABEFB944E34550CE + 31712BB832F9174F86FCD369E75CA9AD + 85095F43A4B7F33AB641BD6912D2C59C + +Set 2, vector#252: + key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + IV = 00000000000000000000000000000000 + stream[0..63] = F374DA745A5CF93A567027609E5D3B1D + 5C3C8A4D15203705D978AD42279F6548 + 51FF713F5120CC93D044EF717F5A75E4 + 98DBEF559E5F157A8C819E213E93B3F4 + stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9 + 175AEAA99D55485954B265B5CAB86509 + C810E664766A8E6C90D4BEE3A58B1815 + 9076959FFFA2F30EEB12343E9E7778C5 + stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC + 418DA96336991A27DADA74FDA987B867 + B125C53C0E4E2889FDFEFBFB48797A22 + 2836B2EA42793CE2BFFD568F6234B368 + stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36 + 4CD2D730DC8D7E183EC55A777C2445EB + BA7E9CD95C8F3A206B73C422AC2E2C08 + 15A8C6FED156FFF93B63DE512EF69725 + xor-digest = 467EDA43B849054EE747A532ED0D9AA4 + 6EA1BF2B6AF19F481D6E3D55EBAA96FC + 6629FE65B5EC4B5EB6A155A6D60FEA32 + F04F8230E26390F1C8FA53D47B68FEAE + +Test vectors -- set 3 +===================== + +Set 3, vector# 0: + key = 000102030405060708090A0B0C0D0E0F + IV = 00000000000000000000000000000000 + stream[0..63] = 0315CE93BE05F88212B413335CA65F33 + 6387BA612421C7BE8276299CC178EC31 + 2143C503A9F2644685882201137BBBD7 + 3A2385F0AD14B690281B54B8DC064150 + stream[192..255] = 8B663563AE31DCE7AC61BF4943466774 + E9EE784644AA761B9D8AA9B8E04D4C91 + 75650DDF130454DD60724864DF2FB6B4 + 31F947F8FCA83F6D3B113BC413D3CC10 + stream[256..319] = 35EE3D4294E5660A99A1A1C9254D27A4 + B42FEA8CBD5C5BD8B902E1B1BFEF17D6 + ADC9B6B924C7C53D44A5C58210989BE8 + 72E532300EA9115CD2AAC8024779B3FC + stream[448..511] = 402F841F64827A197FC56EE9C180F5D1 + 075107622178407B063F70C6C860C6EA + E3016D56F7CDC13A109283F5F4FC9420 + 6C62BC3D1012EA03EE08EBE8C2DC074A + xor-digest = 6815E00D7D3414FCB103EA82B38FD4F4 + 68A453E84A520B7119E9D3A4C938BF0B + AC26F7F73EDA7F3E2F20FBA551C15205 + EBBF2F6BFE6DBAF95061F0AB3988DD57 + +Set 3, vector# 9: + key = 090A0B0C0D0E0F101112131415161718 + IV = 00000000000000000000000000000000 + stream[0..63] = E695E5417AEC9FBFC0EB0909435E79C6 + 76AB8E2F28C556CC2C81CFC5F7A2A6F1 + 254EC0CD2CFAFC257907723557C1DF5A + D81D1E3D201410A12A5FA3A6160F266F + stream[192..255] = E3D590D9AF3869FFCBE2A4B8C77A09F6 + 211193F83B8A43714CCFC02D014376C5 + A44FF7C061471AE208F04DCAA89792FF + AE7096EAC47898C1011095DE9B55682F + stream[256..319] = 0F31D78C0B86D246FE105AA6D9B93CE0 + 257E75CC0D2A0BE96B9156555D8A407E + 01F47AFF719CC894EE111C32672B0404 + B5F26C1DB1D7D0F9E470900AE53B192E + stream[448..511] = 1A01733BB8EACDF2B2F4322FB54FB6CB + C92989248FF31BBAAA8304ECC4AF9A39 + CAB21BB66E0A144D8B77C537BD52DDD8 + C5B0909CC6423D4F243E5AFE6E22D07D + xor-digest = F8C3BF6905A19184D14039E4B7FCFACF + 2EFA004B35B55DD04F56199C6C9DE1B4 + 458C5EFAC45C6062BA1EB726426987ED + 88FA899849CF5F6CEF60119F6A68AF9B + +Set 3, vector# 18: + key = 12131415161718191A1B1C1D1E1F2021 + IV = 00000000000000000000000000000000 + stream[0..63] = 3C189DEDA71E56926CA2C3A2974C4FAA + B7EA3C1250E768CEA797ABD6477B59F0 + E5494635CB4700A95BBD54B0E93D12A6 + 423DF8F34BC6B3BE705ED6704BA33894 + stream[192..255] = F21E411ACF063846BF68F61F7673710D + CFBF8088E2A815F406E17C4BF4E839AA + D2EB9D137B0F7889E68F4B5C8160199A + 7C9C697EA6A1794E954ACB535A72B255 + stream[256..319] = BD7E1C4A54C911E84067AB00F8427810 + BDBF4029E78D424E65F477BEB457900D + 0EA49B639863BAEB1427A161B8C629D3 + 55097F5DFFB24BB97329A73B144DB7CA + stream[448..511] = A4D9A80D0055F2D8C55D2A49B39DCA69 + 9A5652C43258152B42BECDE07F21F8D0 + EAAC565DCDE549CA4A9A27D82F5AF4BB + 1EEB1B0A53A58E50C3E83CBCDCB980F5 + xor-digest = FF451365606D0117E15FC2721F40C9CC + 0FBF6442A771F8FC3B06186C35C6CA13 + B30F65FC84B9A38A6FBA2B6F16541B0A + 0D77BDB4F696894B2B73CCCB8D6FA3B7 + +Set 3, vector# 27: + key = 1B1C1D1E1F202122232425262728292A + IV = 00000000000000000000000000000000 + stream[0..63] = BE4A26D09D47D25416355FB7FF60AA06 + 3B3CDE5374780F2C66514A0CAA07406A + 88490A2E3D6294A799C9BAAAA1B10ACB + 88FF4F6F70EF1F4F67D591040244FEE8 + stream[192..255] = 54F1AB7235B6440D6A7FC7851E3FFDA8 + 6CAF44E3F57E1E9406908064FDDA3A3A + 3C7AA1CB6ECAAF376C5F290EA02844EA + 779A225131F24D2E7D34AD0342399FED + stream[256..319] = 81AC4F45FC40CE7E1FF890F5EFF2B583 + 36F71D1911C7E0227AD8E4DFF7369B41 + A8C266B3468A78773C4C40A3EEA6B724 + 97662462F48835FAC7B6C77CEFD39A65 + stream[448..511] = CACFA9A51224F533C600BEFF1EC03C7C + 7C22EDF93E8596128F8709F0CED4E291 + 997229AC5542FD2CC9B1167C3D2BB57D + 9B08B82C0FC41D93B7CE2211C5E2D534 + xor-digest = 0D949205B6024DAC1D215F2AEA7CB484 + 3FAA9A1719398AB8828A28BD2568369A + C78A224AAD95BAE6A6333C4C13D630B9 + 42AA52099F6EFD6871B1E45C8DC68AC7 + +Set 3, vector# 36: + key = 2425262728292A2B2C2D2E2F30313233 + IV = 00000000000000000000000000000000 + stream[0..63] = 65906EA9CC0080D2044671D22C7DE242 + F764184ABE8DADBCD550225BFD541D6A + 762C7A5268EA0ECE51D18269E71A4CCC + 054AF634616204C81AE7E515719775DF + stream[192..255] = 9ED75834EBBD9576E11DCE8C583ECEDD + 2B8780FE98B44E9F08BBE96922C77BEF + 08DCE0DFD7C77C42236885BE6EDC8343 + 24EAED350AA5A513009272818CBC4BE5 + stream[256..319] = EB1D998260B3AF4472DE59E1C9DD359A + B346B32DCE36C92C9B7BD808BAB76AB1 + EDCA2827557501BE0FE28F6498B33B9A + F4EA48786F3158E8047A32A03AE1CD90 + stream[448..511] = D06B1B9B8110FB9809F5887A35CB24BB + 80EDE203AE648AF9FA348B18D8A15B8E + E98E8AB98A7AC5BF71FDEAA1A6E978F6 + 7D5734AA7FA88E8DA44C861E2F54E585 + xor-digest = E77DF8C1D5F46F8896DD00187C840B0A + E4404581DD053C6F39323815729DCE90 + 0D85C2D8C97D0A3B57CF622F81077B80 + 92988EFFA36CA176F7393D1E38AAB206 + +Set 3, vector# 45: + key = 2D2E2F303132333435363738393A3B3C + IV = 00000000000000000000000000000000 + stream[0..63] = 3FBFE9A391DE0CE5AAEBF9DA3A15EB99 + D6CBAD0341CB78042C89F5D5B0B555C8 + A400DC47FD19F40493B348CB51430B44 + D05AFCA9D399709EFAB8ED2587F72E85 + stream[192..255] = 68969047EE54910C44F8B5718E993234 + D814C27C0B59EE09F0D35B58352AA6C6 + 594F605C25C16CDDC29A354A1C6F5948 + AE497C093E2D41C211E4C1417DFAAFC4 + stream[256..319] = 0DD68E08A25ACA4448DF4B562EEBB855 + 14E41F1F560C479542FE62C2DCBCF03C + 30AF180FB71E65A9A09C551551A33942 + 53558C2440084E6B4CB664A4EAFCAB66 + stream[448..511] = D93B80D67B6484030103CDD72536E695 + E7BAF8B1115109D5D5517BD1E06F4236 + A3551688F5C0D78B2CB080AC072B4C48 + 94A2AF54AD9D816E2068AC569BCD2AE2 + xor-digest = 7C071BF395B48A023A7B708A9651EC8F + 0C9A00DE8BD9D0764C7F1F394AA2B747 + 3EF87BF792D5B89AE0548EB9C1344DAB + DF2E4EC6064D50EE1622160D6DD7ADFE + +Set 3, vector# 54: + key = 363738393A3B3C3D3E3F404142434445 + IV = 00000000000000000000000000000000 + stream[0..63] = 64468807E7EFE78E11B0231D8D7AE80D + BFF3FAE444A60496C8F2DA202941686B + 95C48457C1F9DE1AD2FE581336AE36AB + CA574BCB9619CDDB96E4499409516635 + stream[192..255] = A7DBFEAD9B969D334705B6C53A0CDBC2 + 21E0BB92854B0B107CC39F8C6E4761C3 + EACC8D8C5741AA4243C5BE1A79971A0A + 5A23F2BEDE9F3628CB9099B8C7EA9324 + stream[256..319] = 1A44FB18740973F3124EA805C90C4B27 + 4EE788D43F4B894B01F63C13410EC204 + 2607241E87555B0E1A6FF33AF0DB010B + 8ADF607E6353FCF74F568E0BAF0F4455 + stream[448..511] = 11568B95495E520EB6BE106986A07C57 + 8FDF21463607619E5AAF117D84611E75 + F8979F59E60B43C0A37BC24429892742 + 0D206274DA45EBBA7660422DA45294CD + xor-digest = A70B9BFC683AF2716E17980A49C4F747 + AC25992BA7BCA5E5C2AE162497E4E8BB + 62C837F64EEBE4A55B5705F115CBA057 + C560B1AF0A733B5631E23442601A741F + +Set 3, vector# 63: + key = 3F404142434445464748494A4B4C4D4E + IV = 00000000000000000000000000000000 + stream[0..63] = 35865AF843244DD2F95CDF7C9BD54471 + 9C8432538842C28F93AA21F6E10F8B18 + 31C2AA7EC010A66E539CF65BE55120BF + 090233750995003C7AE414DA6D55F86C + stream[192..255] = 190F215FD14E44CD141E47A2322D324A + A63A7B512A77C20A02D3BFC1EF8273C8 + F65226CBD1BF32A104D1AFEFD6719E4B + DD6355B044EC8D0CE95023C61007E6BB + stream[256..319] = BD02130F7CFDBDBC2171BBDEAB501136 + B2364F5879E6E9CCA7E75AD81105D9E4 + 87E9175B62AFCAD79B23D392B2E9C418 + 437527118797602E629A70CC869AB7EC + stream[448..511] = 1F0DF396B5CA6EC9767B0674B2C7A9C9 + 133CF872DA39DE78F56D41C7F2FF6B50 + 716717E995D42C51D6A2ED66FA6CC7DA + 92E9B3B4D1F130E699C430CFC96969BB + xor-digest = 70291060FEA7D40B5C3FF731FAF7630F + D9BBED1A7FC25A05E6B3F632E6FD6B91 + 1F1010E1BEC69F16D44C5183E38BE8DA + 8949A4D8AA85F5149C203F8C92887875 + +Set 3, vector# 72: + key = 48494A4B4C4D4E4F5051525354555657 + IV = 00000000000000000000000000000000 + stream[0..63] = BFFC0703408DF6EB169656D09A5400DD + 9C4BAF06A3BC7220E45814104B6D9000 + 9585BF9B0CD988E94B8C5026D07AD7F5 + 7D81364775D54D808A5C18453B62A2A1 + stream[192..255] = 5FC95B73A4C91DB20B93319E420B4C5B + A9DE1873C81C835CB455970A90921594 + F9635EF4F411C9ACB4298F75B2CC84F9 + 7F52182F7F001A1EDF72A68FA1ADE313 + stream[256..319] = FB24E97B0CCFE15644BAAFF342C55FDF + 64434708407AA6D73576E842D5ADF4A2 + 6B32D329A2DC9F1451C4BF3E9599E9E6 + 4E5E65F73E09E4F1254BA0DDD8E6C52C + stream[448..511] = E2EB303CD0A67C99CDCEE86BEA581FF7 + 093C9228900B563C6D10B20BF99D3911 + D47C805D1447C8F233D3FDD27CF0DA42 + D42E0389E2CCE99A274AD9D20B9C6102 + xor-digest = F83FB58CAEC8B13BC25C152FCF24E10E + 392A197FDA05A6A20E14093EA0B34C5D + FAE102266465324F5AC07FFCECC8E618 + D0BB60761A26D5FD59D188097A2348F3 + +Set 3, vector# 81: + key = 5152535455565758595A5B5C5D5E5F60 + IV = 00000000000000000000000000000000 + stream[0..63] = 84076D83A841C8C6ADDE3B5D9FDD6529 + 4D0F92B549112F0A6DE05236F732E81B + 3C8E92229C411D2295129ECD18DD08DD + C98BA78D9BAFF6271D95E1F361EF699A + stream[192..255] = 7063A52FB2729433D8A7BF30F27E6EF6 + F17C2A422E60A737270787985508D062 + 4E678A597845CA9EF939F4B8966BD99F + B8633FEA673CE7BFD2ACFB5942D7EDD9 + stream[256..319] = 4FCE866E8C2359C53F0429F569D02DAE + E99A4062246B633D4C502DC897AD8025 + 38C95D49D3B1FA94F4E92441357B622A + 6264F50D5554BBE42191AB3D6073A8AF + stream[448..511] = 2F7C38BD00309FC81D28D84EE4355216 + D97A823CC46FAB9DCAF621E4128F9CB8 + 838BF02E0EF940EFE96860CC0B996044 + 42CACFD3306335241C1B4B65E790233E + xor-digest = 44038A33AF0013BB34CBCFB77F7E060B + 96F5134DFCDBF04EB8F7F29B15C3FDA0 + F766DC940FF548C23712625793851A94 + 294CC7201E1EDC6056C12A46524C6FD0 + +Set 3, vector# 90: + key = 5A5B5C5D5E5F60616263646566676869 + IV = 00000000000000000000000000000000 + stream[0..63] = E811CA3DD1DD0057AD3A1794D3F9CCB6 + 362049B1692D6ACFE1A6A0FCC99C7A04 + 3AB9932A146B4040AC9F8E2F0A227C7E + C60B1F35D60EA14483BAE1F8D1AC7FE1 + stream[192..255] = 865B05E224133AFC45043F05F8082FEA + 487BF63BCFB96DA3EE26960061446669 + B1C92C6BC5905BD1EB57D579CB62A220 + 2F35CEB603658237AF1908132A25971C + stream[256..319] = A84BE383FC852F1BF44130EAD15B3548 + 56737C7EA68A0700A22D357FBA70E031 + BDC0FE8EC36C41790A8B7706A00CA338 + 603E054A83881599D718B1911D1CE9D4 + stream[448..511] = 9286C3479F9A17B51D8749257F59E892 + CE7C3EB8638B29C17D779811F01EA405 + 257062A5F28BCDA1862FE653C7607350 + 9A87D12EDC5CAAFF9E8F9F76DA0BEDE2 + xor-digest = D629CA4708BEF7EED04BB5531DDF9C64 + BA4981C9A705D59C4B2391E94B79CFCD + 058406845D81E7EBC097330C01FCBCF8 + D78940893B4FA38554A32D861AE96D04 + +Set 3, vector# 99: + key = 636465666768696A6B6C6D6E6F707172 + IV = 00000000000000000000000000000000 + stream[0..63] = B89516368AFEEEC12434F76AD1E1ECA8 + FF6FEF7B46D05EDD6041C7B8C1E3A33D + 2818E38113592B615E980304D93435DF + BDD5676225173331C3667F30AA2A3D2C + stream[192..255] = 249528FA392B19B6811711F523D27578 + F1BDE75CA167DDEC08303906B64FAC0F + B2912A7A0EDBEDAF9FEDA420DEA330CA + 7302F5780827CB11B15A4DD333FD7099 + stream[256..319] = CECC1B5077BCB9E129B01D8D75089B41 + 64E76DBC9C8CF2E4D2F17A6248522A51 + FCFBFBC992F75D613307F4DD6472B6DF + C8A5B29F1068FC0F1C3F8964B0E09170 + stream[448..511] = 8B26C436E918B099E4D3A7D4D3395E49 + 056A8A29130667A32C6A2B0FD08A482F + 8F7538ED90374846FFD2E1C733AFFDA1 + 12148C9718F3F208344D5FC20128AE2C + xor-digest = EAA0ACA59CF63BC27082BD52D6757FD7 + 620A7AC5AA2FAEC52646978E2057C5FC + F60B36C09D87419C1D1A64133357DB05 + 6B96C854F38C36DD657524FD09729341 + +Set 3, vector#108: + key = 6C6D6E6F707172737475767778797A7B + IV = 00000000000000000000000000000000 + stream[0..63] = 741C607A6BD38F93B33244C8B7F05D78 + 46F6A05CEE5A87762480DE123D3BEE63 + 240928FFC75ECD9AD1785B1664DCB59B + A12F3B64C93BD4FC8C67C0934E5B0ABD + stream[192..255] = 3BDB31A701DD7F2E929803C3A47896F0 + 9E5F569A32AA829E505E34BB7232597D + B838F543A34CC288F9518BE16A228D42 + BED0CA3CE0C6E7FF9AEE63625C699B9A + stream[256..319] = 1CB7FE159EC1A57043BD142236DC0A18 + 0CEF37316A6E96354AE319142282F19C + 1550EB645DA8F7BEE2ABAE4EAAC0BA29 + 893E722A6F8E0A9B34368DF56C5845B4 + stream[448..511] = B6DF810D69EAFB7F2360F6ECB50C5861 + 7D32B3F495B3E4424045E88CFA0871A2 + 9314121CC78B98B456ADF53E540346B1 + 214AE2ADB65C552273F1FA498FA74101 + xor-digest = D35A8AE5783348824175BD34F2E16FBB + 975E7695DC6C4FF1ED763D404B0D4D30 + 07AAF01E988BC85DB2FDD017691D3BB9 + 811355C3C7A6156197AF57B794DCE85D + +Set 3, vector#117: + key = 75767778797A7B7C7D7E7F8081828384 + IV = 00000000000000000000000000000000 + stream[0..63] = EA9DA2D5BD4B6E070479ABF8CA2D1B3A + 6B968A025D010944FEB51AB2E507F86B + 111F8A351A3F32CE1FBC4A75AC34F722 + 1B5190F2390073084F8153E00BB98D0E + stream[192..255] = 0AE0DC3D0E2D3F5F93E446BEBECC4F60 + 862D190829A209966E132DD029ED6998 + DEF4F613F3D53D0A36CFBA2CFE345DCF + 013B6CFFEC0116FFC1659A57FB42E0BE + stream[256..319] = 5A7FF46C335912389D8B88437CEFD27B + 76706405F45F87C91390273D9B70CC5D + 89FDFA85E20EC82B98A79BFF5FBF6AB1 + 4F61F2C1289CD7B8357126C8E13271AD + stream[448..511] = 9398E699F5AD8FF31A50C8EFB9DF0D0C + FD612B951A203C1BF85C62AB5AF1C412 + 42BFD0A55F21820C6F917EC90A8FCAB2 + E774A93713A99C7900B80A2BF496D0AF + xor-digest = 05D9732FF20A61E19428873830DA7282 + 819234F22FE7DFD8871C21CF10C08EF0 + 7C0413898DB144861B0CCB62992DF40B + 29A0A4688C91275F0A198AF39899E362 + +Set 3, vector#126: + key = 7E7F808182838485868788898A8B8C8D + IV = 00000000000000000000000000000000 + stream[0..63] = 8C4F8495C7231AAEB704E7AB9E79E748 + 6CB5BC85D3622B8A2E2CB778BBFDACD4 + CEF73CC485D8E08406F5986A28706CD0 + 56D085201DEDB875573B57629B8541C6 + stream[192..255] = CC6374A744E9205CA39BCD678074B844 + 16346A7E54F9B87905BADD2FACE7B9F4 + B0A366AA3F632A7A67AD8AAC4827C9BB + A1E801A8786BC4FAC2ADE6A6AD6A45F4 + stream[256..319] = 4F52AAB001BE94A60761CDE0334F8A84 + C617195B084E441070E343CEC3189CF6 + D6D955F9AD649A3891BDFFACA0A6E6E7 + 7291396670BA07469D267EB80E48353A + stream[448..511] = 673AF85AD5A9A3F26CBABCE9BEBBAE21 + E0B6DCCC3256227FC0EAEDF343CC7E9A + 8896023DF073E88EEEF135BE34CF67A5 + 5FB51D3A1754B15A7C4E2CCCB4C8D51C + xor-digest = 2BD4B8BF9B7E79B0EB53318396B03575 + 0AC918A6A05BBA499D81C9EFD32A0FCA + 34A83FC801CD6475A774091F33AE7689 + B9FE28645F545E9A9531F528085926F1 + +Set 3, vector#135: + key = 8788898A8B8C8D8E8F90919293949596 + IV = 00000000000000000000000000000000 + stream[0..63] = BDF2E95B80FDF304C3C4A8081391EDC9 + 7F9553F93C27788F03797EDEBB8F59EC + 2FB2FCCA7727CA1CAEBF5C8DA8719492 + F1369D96B2FEFA23D89400CF7CA667EC + stream[192..255] = 6AB7500D876A4924DE59800345AD69FB + BA1690733713BF372E0108D9FB65B0E4 + 50BB89899AB84198381623094F823FF4 + 8BF9A09F0FCA23684E78654F3D231173 + stream[256..319] = 34ED638D249BB1AB8B16D350309AE32B + 9FB62CAB0EC7AB9D5F3C12C9A6502497 + 6323EBBBC4CF308FFA68A3D4D8D3959E + AFD3BE46E36072FD15A5DC3FCDECA6D1 + stream[448..511] = A8BA33AF6CF545424E607A7FC4CBA593 + CB05B38C836B21D85B6FB1894926A459 + 8D71AB424A5A582A491747FED94125D1 + 08D6C693EC9E4BDE2F418810A921B54F + xor-digest = 84F29F11524741D39779025D792AB735 + 07963EAA0FA8EE220ECD3592E1320567 + BFE76EFC3356860192DDC5F06B94E552 + 43D659D49FB94C30AB69AB5E9C370A5B + +Set 3, vector#144: + key = 909192939495969798999A9B9C9D9E9F + IV = 00000000000000000000000000000000 + stream[0..63] = 1C03A0D6CB75670CD7D978B2E371857E + 27E597B15B905D5F4F4384FEC227073B + 5A56D8C0C4AF767F267DDEFF86AA036C + 41EB6170603AEB3E3C1EF3E176CED812 + stream[192..255] = 6447D1E067550DEC9E8AE89DB02B85B4 + 3DD7E511C8B98438BAA50CFAF7CDBB68 + 757DA1D03A29B9EC6BD633E17BEBC8EB + 2D8D453F583E4D183AF30C9F47C8DD56 + stream[256..319] = B324756101C28D9FC4D1F065F1D000F4 + 1155514EDB30A7FE36C26B18FD93D6D2 + 0470A41B6F8D2E8BE140568BF72223F0 + 981CEB9D100B21C8B751BA6B2816B2D0 + stream[448..511] = 304AADCAE0CE80E91E3558974A944663 + D1E2253977CD7B0D1BFAA138DD81A501 + D7EADD8FC834931A44642BA9873AC1B2 + 47A454EE71F7AD8671BC15E088D01532 + xor-digest = 5980D43A91C09B20B0F3323F1750CB47 + 118550920627B6C512AC5CC53AA6AD25 + 68EE1EFE702FEDE7CADBFA25B32696FA + 12A18CCDE35A1B679F709F28920DF92C + +Set 3, vector#153: + key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8 + IV = 00000000000000000000000000000000 + stream[0..63] = C2083A758037E850A6FE642EFDE59AED + F51F3002BEE2E69DBDB538BE2D93EE8B + 27A1CC89672DC14C44DADE531A88A769 + 5DC730A2CDF3096DE7F4BD08A1ABA918 + stream[192..255] = F4D19950E6365AE6BE8011A24B9D803A + D9A8547D452D8B0B8C51676E207DF323 + 808B5A094A2FDEA5DBC86BFCA576E98E + D0E049834CBE0B3AFAD6892B542EC7AF + stream[256..319] = 8F2A026EB2165F39E27DB86607878926 + 4EC8F42A09E8C80B317FD4F1E32AF4C3 + 73B7F5160C635ECABE495B01A3488E27 + 94D226E2D86C4654810C08B2FC42610D + stream[448..511] = A1D17725577B7A4FD3D1A280BA2B5C0C + 386FCFA09E110F00C85ECA05CC142644 + 4D8EB87CCDC2B23D1CDBBFFF822B5555 + 11055B93ADC9168B7353CAE10551AF14 + xor-digest = 7B4E8A6123216818A218FBD50D8540B0 + A0B62DC114F25DD476680F85DEEA9306 + 4CBC4526C7A8832D4BC534684A403FE7 + B80E7F20D967ECE044085B554C158AFA + +Set 3, vector#162: + key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1 + IV = 00000000000000000000000000000000 + stream[0..63] = 6FB232154275843C74BB886D09CBE0EC + CCC539DD6DEC1EC6F31578B80DD3BAD8 + 5C992CB1A0B4EA40B3EE0C5174E36A74 + E1CDCAB13830453984E4365A6C599F72 + stream[192..255] = 2682C05E19F6D8FC4DDB15B2F8385B52 + C5A4A70FF5A0063CD696AADBF8505122 + 6F696746D4F8C314543BC3869B1E7F9B + 1C0D004655FB6585723CD1EA7A700A60 + stream[256..319] = D6BA4C5A33B8C2DE342DE48E26AE7B14 + 8E91552D0E05AC9458ED0010E6FF53AE + EDE70E910165B5986876799E60B7E6BF + 3109B9BAF7EE3670497FA7CAFCB14733 + stream[448..511] = 70C4E8AB8E8BA681A2A06F319CBC952E + E3E78DA589369FEEF8A6BC6D976BECFE + E6C7143337758929FCA7E0945892411B + 047C2CC2F2AA284E95733DD94D46B89B + xor-digest = E2D3DD6AC908FF3BAE4791A50F717B63 + FB3F1F380CC738E2B1626FD026C9BEBC + 33957AF4ED6E8B9864EEEAE262FC6168 + 9A34FA14A35BD915B6945F35BC3D5573 + +Set 3, vector#171: + key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA + IV = 00000000000000000000000000000000 + stream[0..63] = D25BF02A1BB050E0D15246C2EFB3EB89 + 390BB913916D347586DCDF71D6792CC6 + BF72F6F6A9B779BD8833C468684B4480 + 52E153D11A0CE183CB337450C4482F6B + stream[192..255] = 07980A2C57E9094C5334016A782C830E + B59420086EF9D36542A97220A5EEFE42 + 026B39B1F00A78992ECA17FCDDCEEA2F + 88A15F934A1C65EFB770C2FB9712FFF2 + stream[256..319] = 8C0AF45C68CB7CA8CFF1AB18F2F9659D + E49DB5C4E3609B50C06F94FC01C059B5 + 40E302FA8604F030701FE3C833617E0B + 094D0BBF10580F7C1C7047E86FBF93E2 + stream[448..511] = 4D4BEFAB68D63085A05C729F54468567 + 2C2A9452DF6B4B651A29FBC29513E3C9 + 635DFD75EAC87A5B1362E99033304EF5 + DF42420DFD49C1830D66F4F90928F1AE + xor-digest = 9A7DD8AA5D9E9DA4F34AFBDE9D909CE5 + DEBC05D2F930FF08AEEE4096B2E1E453 + 8587B88E535A217E986F31965C5965DE + 3BF4A7F99B3B9D938D2C1AF7DFEFA14A + +Set 3, vector#180: + key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3 + IV = 00000000000000000000000000000000 + stream[0..63] = 5FB2BFB5B9CC4F84D7641B4555DA4A7F + C07C0053E7AD2CF2187F7F34ED4068AC + 6D5B43A5FA41437C05C65550786D60F9 + A737F44BE450A1F416C1B1A49890C609 + stream[192..255] = 8EDCA89958225E39CF796EE587877A55 + F9B7A7381241597CA6280F7617A11922 + 9268F95BB326585AB59F08BFCE8B5638 + B3A0D32A761C796060DFEBB5BCE859D5 + stream[256..319] = 09601C099BAC574564E4CC6FD659776E + 4726FB22E0025C37873042866B913C03 + 285EA24E37847F9AF6C838B82FE651D4 + EC5FBD40A256E6C765757B6A3CD08C92 + stream[448..511] = CA5AC4ED4FBEF0D754F033B5267B9FDF + 3CA52B131E118174F70CD4F833A5ABBB + 198DBCDF18BABB0B0CC37ECFC8D93AA1 + 5949FBB21974169B46D545F0ED03C71D + xor-digest = 5DAFDEBC75291BA8F55B4A370756B28F + 554FEADDB7888F2834BA1EF221E917F5 + F631D5BD789701282DCF16FA450D250B + 52C627741369DA654E237B8D7F4A8BA0 + +Set 3, vector#189: + key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC + IV = 00000000000000000000000000000000 + stream[0..63] = E9EAE6C4903004A2AFCD05FE2E3E7F95 + FF8BD2888C4AEBB81CDBBCB7488C54E5 + B50467FA82B0CA7EA923C608074E1B45 + 6452821FC36789C8061E99E8A0C0B579 + stream[192..255] = 1EC898A6958F23C186261F833BB3EF0B + 3C185AE8138311B6AB42098E9C6C7FE1 + 0306DADE1DBF2B1C3215DEBD88AF1CBD + 2D805B8006FA0DCF136E225AE3D91AA3 + stream[256..319] = 55566604D1C85FFE1D29810B6C49F019 + 69ACB59765A3FBA2B0B9880064606E47 + 18BC5F08C32EFC250FEE91FB88077A2E + 0840615CCF627C64FBB500B7B800B9CD + stream[448..511] = 707821EFE4119A32CFD99F7ED7CEC018 + C8EE90493FD9268A83E5482DAF9A646E + 8765D8199A56A12ECA50775099179D70 + B72A3CEC8F0EFF1AFD074F04548874E3 + xor-digest = A51E3C9C948B68A1543FDD1F158DD419 + 195AE7662739446D9FD543681A866A6C + F09756FF4E0C59BDEFFBF98D53F193A1 + 77D7BF19320063B8AEEC8A544D5D72C7 + +Set 3, vector#198: + key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5 + IV = 00000000000000000000000000000000 + stream[0..63] = EAA9729F0222A16C750540C605974B55 + 4FA622F67C71FBA40236A71AC19706F7 + 9E3792F4B444A39C9C1C902FDBD81898 + 096338F6A8EB7C934B9558D48AC53301 + stream[192..255] = 3B5E53787C050061000E3622876AA126 + 00971A76253833C53B9DABA976169395 + 3944B5050AB17E492E185737D67581B8 + B1C766D50C5B0C2B0D8C78A781E77D89 + stream[256..319] = 175C28764FEAF8396B3CD34C829D0D0B + E9CE0D75E79017A96C4E7B158B171BE9 + 4C906FD4BD4946E6DEEC3C78B34C0754 + 9E85AFCD958AF345E0B432F33C86AA76 + stream[448..511] = 37BDD665CD9D5A8A8190AC3EEF981379 + AD5311E15F853A8A89840879165147A2 + 807AFABB6236CEA9319DB32344987889 + 5744A506CA76CE69D9E474840529D667 + xor-digest = 4CAAE8F441F6EF3DB6971E274181F8F0 + 4D7BC603E040833E77921A393EA13F0F + ADFF07AEC94555224F6204874027106A + 6D7DDF0546F300D3E84AC87699ED40D2 + +Set 3, vector#207: + key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE + IV = 00000000000000000000000000000000 + stream[0..63] = 83AC8C40850F4FCA5452871C954AA61F + 31A9BD276D39EEC03EC5977A71FDAC38 + 368D110C57C1A19F2A7461BBFA88E372 + F78103F9FFAC1361AC2D2AD84C6AA3E8 + stream[192..255] = 48E95C2FCFC79C91BACD0C41F626F05E + F80E076E359299EB5272A2F688F96F6B + 3147C5A19A99D562A11E953CB2A90911 + 205A7760B5C8CD959EE6C183A8C1420D + stream[256..319] = 974A4DE50EB45F6144DAFFA6B4A68E39 + 48838434497B8F9700FC42005F3C2FB5 + A79984CC2E770C5400EA21AA4EC05751 + 80A288499879E50462225BE03D677875 + stream[448..511] = 09823B2D55E26C49E42FC0820D7BA081 + 5A7EA9380637A2AE2C0D29253EEDB884 + 9BF4F54D64677F08A1763EFFD904B62D + B3843B0ADE885C00640D16A99E28DCC0 + xor-digest = E73D8783F926558E0C1E1B0D3FD86CFA + 974CD70EBAACC0CEA2D977E9AFCCD384 + 935584D2FFEDEA813E6234112CAA1401 + 71E99BCFE61A7D0E430D4D3F75AA3E28 + +Set 3, vector#216: + key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7 + IV = 00000000000000000000000000000000 + stream[0..63] = 5DE3EC7E6D724976985B426D722D93E6 + 1F40F5F17EA14B298AC898CBD69F2BBA + 5705E1D0CEF7B7122362FCC0D5106D54 + 25D51F51E29C938C592D9E862DEE9E33 + stream[192..255] = E079C49AC8F160A9D529F30151AAA7A3 + 1D137E03DF4C23F8734AAC3B20BF8520 + 90E3C2529761EB4D67AEF1CC46399947 + 1240DEE8343D6355B5D7377A7934B019 + stream[256..319] = DF574E03ADD1DCBD0712D2748C93CD72 + D8488396AE3D3275E5A53CAF3EC112E9 + 50A79494F25B9EC111FE9A7A68A5AEA9 + 63A4F87B37F822B79D954436368D8E20 + stream[448..511] = CCEF4C93BCEB2494EB4C70F5E301E980 + C494AF8C117F291DD09E3960D2C5A7F1 + 9928C08F2F51C419E734DE9AADD25C81 + 3579A7F0B8B367A49B97DED5793E4DCB + xor-digest = 868706BC1A5F3D0BDF96E10324EC36FE + 01596216B0B8BBFF69C5BDAF69D0F38E + FE89FFC32D34D142F413A5BEA7AB38ED + 22436C62F86C540101DC0267FAF67904 + +Set 3, vector#225: + key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0 + IV = 00000000000000000000000000000000 + stream[0..63] = 45A0736DB4A28A3A6DD181FEF3485F2C + 918C65663597C49F4FB23CA550C77CAF + 7B331B5D183844278E0D959EA024CC21 + CE1A84923E6E782472BA1645BEDFC60D + stream[192..255] = E9EE0DFD717F72FD8899D23E87E77DD9 + F9DA66B4645AAD8D8C3B489B0A637449 + 80020326469B4C6403012B6E315CD35A + 4344934D720467F30B61C8AEE5C3C342 + stream[256..319] = 94A2BA2B744CB83A29004AE21470212F + 67C2FD18F227FC017131D7F4DD0AB412 + 48C59BADAE2E408584DF35C603192E37 + 344C52664DD68B9231661F304F483F41 + stream[448..511] = 6A29174A1099BF8759D2F5F9BA60816A + B290252AEE08339BE0021033DED03C46 + 9C8E28AAFAFDC67A7F2219C8942B004E + 47263842BEBB47EC6B0666ACCC884591 + xor-digest = 7A7411EE5D174907B1138575FCC7479F + AF3437BBF098CCB5D8D25F49E6788374 + CBC9CC5812982CBEAF59111813430BEF + 56D9DEEDB6C935804013759CFAAC40E4 + +Set 3, vector#234: + key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9 + IV = 00000000000000000000000000000000 + stream[0..63] = C430C2A9FC44DE1563B1679C1A2DFA98 + 91D01A302C5165EC13B26F6EE4F25437 + 264AE9E18C98BE112BF560C72024827B + 85665C491C47BB396B5AEC66CFCCA371 + stream[192..255] = 60F3A13B9EBF8784CC81C132E004A179 + BEA0606D4C2C830077A50004FB0487E6 + E179D81FD9784DC3783ABF86523FE4A4 + 68930272980E3B46F865E4729DD34773 + stream[256..319] = 44BC861136F6856B1C74C1CC13753B82 + A75E34EB40C518400B507D99B42E488C + 8A1F2F590E029EF48DAF2674FDB053AE + 5C0967923102EB964602256F70A9CC9D + stream[448..511] = 0EE3ADBC4CCC63A8B67C7812CD294183 + A2E9D4EF0D65F854FE66CF9D76A34F91 + 867B27336F8EEC2E2CD30CCB98AD5769 + 77B07C73C833B51753BB9B0DF08C4834 + xor-digest = 7F848C96AE9310B5282712493AD7E13E + 2B4581545E625A4DCD98576C75835058 + 6C621244B6CD439F8E62625ECD9460D3 + A18BC2F5DCD9FA7E8CF7880CCFD1A44C + +Set 3, vector#243: + key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102 + IV = 00000000000000000000000000000000 + stream[0..63] = B9B3501C75EE296AE858573B63C4888F + 72B18683CBCD6B95602D51E4388D6DD3 + 7129169A5209202E2C6EDEB5026B6511 + 55E4747DD706DDF248A8705D50D38A29 + stream[192..255] = 12F90D1028010D8296DD0D6ECC4F2354 + 89856C315555279BD0A4E3161178AAAE + BD849EC0A90903CCFE9DC7CC821C1CAA + D63A45A1D0C0247F1FB1423877FE9A32 + stream[256..319] = 9F0608162C6315D206B5EFB0E40291AD + E882445B9F34154F6E21B9FA23356DD4 + 79DFFB16482F6A4F28A8A0629E8B1D78 + EAA473CB126FB3727B826B4B3D6175E6 + stream[448..511] = F26FAB00C37C03AE33209E19F865B135 + 115A5E254A6B5C1A4896987EAC35C2F4 + 327822E165AC6BF99F535055ED74833B + C1FFEB32588D8995CEF0708E2D3CF832 + xor-digest = 87243F1D4D08D7EE39213D1A4B9E2458 + 368339A11E364345B4367F84154B36DA + 03A3728A7EBD4237897F9D1A19CCFE92 + B9D67D3A4A755E6EA8382041D4827A17 + +Set 3, vector#252: + key = FCFDFEFF000102030405060708090A0B + IV = 00000000000000000000000000000000 + stream[0..63] = 05A90DAF1A6B6B60CD3B999A11FEEE39 + 6D38983ECDA326EC9229D2A1EC722B0C + 3C0539DDBF6A4CF62B9BAFEA6C60A29D + 4AB63BBBC88987E9A74AE2F71B1E8DE2 + stream[192..255] = 0AE6673D9F99C5EC9A4532B2B9786CB9 + E948A206CB992335FE868BB2271DCA5F + 9AB75995A7E7D46F8EA6693765C93D90 + 9D41C24EF4856252986DDFCBE65D2D11 + stream[256..319] = D8B07A866003059BAEE90378AD5EFFD5 + 2732755E79402B50BA0F26A038B3D9C8 + 1481C19080CB39FE840F8E7313D0C034 + 9FEA4AA4801225630AAED3E522D6F920 + stream[448..511] = DED21140E5A3C0C4615D7153DF9381F7 + 269616817A273BFD984AA5E7CD9D9CA1 + 9C28E51F4C03C262F5BB4175C799236F + DA69AB27590857C0F270CE4BBFE02D5E + xor-digest = 2D47DA3161389F5F54FAB37F391C21CD + 63A748112A1AB415670524B6CB93DA0B + 6B54C541ED59F3A54DE238C3FADB3236 + 3871F6DB1A507B33C1B8F280B0C04B1A + +Test vectors -- set 4 +===================== + +Set 4, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 00000000000000000000000000000000 + stream[0..63] = 114265E078311C062B518148B4530F73 + DC9B95DCC41C214F8C9486473DC46847 + 71819020010586A750426A0E633BC787 + 6E228E2353AC0A68533C85A742387800 + stream[65472..65535] = 196F53D41603BF286D1D11F012E564E9 + 3C7FEEEC9539A015D49475DD8CC73C84 + 2F85521B4DD9789A813A59D444AEC702 + 164F669C59B43B5115202D08662D4EC2 + stream[65536..65599] = 8A7B672621B0B77E8BA8EB9A71DB4558 + A78364244F182519F89D25D3012CF8C4 + E429DD543C8DC56C6DB8FA5E351BF615 + 106B51F9FD00F54018A94DAA91D76715 + stream[131008..131071] = 33EC15BB2C553646CAED9ABD83F37ADF + AD3B3313A074B69FEAD405BAF897C3A3 + E12BFB2F4CC3136ACFDA284DA1E780DA + B3E4D34C053302989FE6A79A1EB0F5D2 + xor-digest = D899BF7CD2972EBB7333D4E57DC809A1 + B717373577B15544443915B36ED162E1 + 25452584F3E0C2B62164092219FBA924 + 31C1FF2A14C8E2E437427DACF80A200E + +Set 4, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 00000000000000000000000000000000 + stream[0..63] = 8EA023E23D94434EAA064A4BE52866DB + 57EFB7B200DAFF5AF2AA72D3E55EE5F4 + 5060FA89024F259CD2490C628452B1F0 + 91020DE10263BA86838B2E388F5AD040 + stream[65472..65535] = 5BE1EAE0077FCE5C2C21120EFD560A96 + 27C3DA9462BE42580065C9E51B7D36C1 + D9D717DADF4A3122A08303A8E27721E2 + 1DADC91138A2461713998AEE26F811D5 + stream[65536..65599] = 482694A9797978003DFDA5183F00FF97 + 9F38894BC92DC88418FF68156117A2B4 + EF10D76923A734ABCAD1A5B4224BBD08 + 836E3765321045C3BF6A352371F82CAE + stream[131008..131071] = 614BC8A38C5F9E8507595E8F5A03484E + C9DEC6CF52DECFAB008327527B822365 + A2038FF09411D7B952417C8C7375289A + 244D50703B73577EC272827A21BB917F + xor-digest = CA9E6EC13B679609EA778447EEA1157C + B366A08AC5A96A73D0B5E182DF24EBD9 + FC297219A0AF67591BFD68B1721B5970 + 8EBEB3655791107FD2A0F2F2E341FCC4 + +Set 4, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 00000000000000000000000000000000 + stream[0..63] = 5BD3D0625CEAA75ECFC9828179F7B73B + 288A208D60A2297F2C328DB0789BC869 + 4E50F50E8797F8C7A49E24F72A3AC359 + 796E6188C71A9B3DB88DAEB1BB2C77D3 + stream[65472..65535] = 726C7D7AD756CF567E0E8F812A282675 + 7E75D593C7FCBB45F842020AD59F2B53 + 888354CEF541411B92C3AF6D57ADE7E9 + 273805927DEEBE552B32D10754C9D2E5 + stream[65536..65599] = 5703464C0AED290E65815D8D04098B0E + 22D2FA825ACD4391B56CA64CB8201BE5 + 7B4FB9ED6BB7608BD820436146339559 + E7464BC13A8AE3167AFCDA58E3C017AE + stream[131008..131071] = FFC5787A10E340B07D08160D2C4F653E + 407857845A0D68D1EED8EAC0116CC376 + E33AF8A1120D8DCAD6C86B757AC50393 + 46AADEFF012BD0DAA294DD240D87A98C + xor-digest = B3BAA21AA82617D3BB9C2612E177CB71 + 51A51790D97FE33C3F33C01B32091758 + 5766643C125293E1F75D6BA3C46AB381 + 75A2A4934D4C115A6A1547932B077A58 + +Set 4, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 00000000000000000000000000000000 + stream[0..63] = AC5DEC8B95C89F4794B7289C69FABE29 + F4AA64476D057873D87BD524666F62F6 + B71B5131BFB897AE64F2D500437E1798 + A742E7B7D06B8089F3DB2453D008C554 + stream[65472..65535] = A2F58800E24BA8B754C64BAD9252BEC3 + ED1273598EEF4C6FE42FE2CADB81F220 + 26A90BC88B43F2F1FD2E054E8EEECF57 + A114D087D5228CB276FD5F4FA3ECF4FB + stream[65536..65599] = 5C67BC8E188170A57DB85ACD2F7121A3 + 7D83F1A708ADC54C14064A9559FE7E1E + 3F9E60B9670EA4394521B11D8283EE42 + 12874323628EAEF0B90FC4653106D68F + stream[131008..131071] = 8AA6F8A20F7D4A0B7EBAF6A7336B6D76 + 731E65DCCD179BD53F6B879E70B8776C + 6A8EA30BFF09BA3026B3827EDB9F9C2C + 0F96655D8B84EF725D0603F8CCE3C2F6 + xor-digest = 458DB66B656320F5F7E4FEB12E748C0A + 59F0CD8A7ACAECC25479C309628EC0B5 + 3B441B831B484FD3180C52F63EDA1858 + 7C232B195356996DC29DE6DF54E5BB37 + +Test vectors -- set 5 +===================== + +Set 5, vector# 0: + key = 00000000000000000000000000000000 + IV = 80000000000000000000000000000000 + stream[0..63] = 04740F92C2470701F289669A25BF9092 + EB4212FEACF66DAB6B1D520977945F8C + 6D350BF26A1CA35EB37FA53B0BA2CBF6 + 6AC07A8C75D494B4B8281CFBAD4937BF + stream[192..255] = 5E47F5F506AA34E7D296C6911FCD3D43 + 31A032269214ECEFDDB492C47A51C4B4 + DE9EF0A63A6EB32AF1DF1C5576A93F19 + 02B7BB89F10D8C7CDFF9C097D3D49148 + stream[256..319] = 015494CB3CC9BDE8A2981B25C06DD18B + 52FA7B94CBE24C152FC60762290329C9 + E58C4E5148585F417733737059E310D9 + 309D0CEF48D2F1589994657A081BA6D7 + stream[448..511] = 3B67C1B37D96E1076595660D61340EC8 + DDE8F492134270951D9D4B260C8E2254 + A7FE8C10DE837A617A8E261FBBF42259 + C636B3DEEA0F373FE7C2CA2B01EE3FC3 + xor-digest = A8CC89F06815EFF6A91CA276BEBA7F41 + 75F842F85BEAE99F4335A3B85FB28394 + 8B7EE3C659274C6B784035B94886BF9A + 5C1483941B20170EE3A374E39006C09B + +Set 5, vector# 9: + key = 00000000000000000000000000000000 + IV = 00400000000000000000000000000000 + stream[0..63] = C25BA6DE4C87FE5360BCDEF864F3F778 + 598A6A584325D5E6C44EEA4464D7580C + 9B8D42B5B3634F739D6A53D15FA41070 + D1DD4621BF87F53F42107618D9742FD4 + stream[192..255] = 4A3808B0619C9D94E19F3AEA0BEF3839 + 21D7E2BED05F1128A82D9DC010654ECF + 65199A645606CC44FDAE763694E6757F + 8FF864CBE4204D45102E465F16CAB8EC + stream[256..319] = 3097394E0CD0A9DAA28EA873566E42A8 + 710C28366C2B41B6BF6687D881094676 + 9970A5BA54D28D7BF772C4FED13A9F5C + 6E7AD3F6948667D6C2DF981955F73293 + stream[448..511] = E685BC2ACD3A67791416E78699C83D31 + 852EBCB1C1AF71B926D9161CB6D894BC + 8C5E85C7E30A0896369BAE50C1112D4C + CC583E44A8275F44B7ED140E9721C7F8 + xor-digest = D9B51AAF4A9B75508FCD02443EFE2267 + 1148C73264776B5513860BCE8547370B + 2BA66E82CCDB15F3DEB0F0728411B765 + 1A098C23202745C19B045C58AB196309 + +Set 5, vector# 18: + key = 00000000000000000000000000000000 + IV = 00002000000000000000000000000000 + stream[0..63] = EE43BB5B79EAFB54B823DE95B71F3BD2 + F2A7CBB6D28E9BED590C20A2C52F9B2C + 74EEB9A1A48474D5DA4964EEE0BB98E4 + 88030E213A4482BD1A8CAD4CF8A962CB + stream[192..255] = 150C4D68BF29DD27A2E6FFDFBD6984F4 + 3AB56AACC08AC0C0149008F0882292EC + A5359CCF4C257ADD4FC535E41D6F67CA + E5210068F77A5D5F32A23B17F79EB7A5 + stream[256..319] = FEA319287C29AB84585D4BF38DCFA71F + A36253AD7F4BF58398731713614D0047 + F85A465C6915E05232A5FE5AE7A559EC + 42733403ECF6B11E4D5E8F4A8288A3E3 + stream[448..511] = 79CE66DD3F77D40889906EAB1F671B2F + 98D9FBF8693C1EAFC89D19209408F3B2 + 7CD83CB3B9F33151DD4A8D79911255FD + 3CCBA14918744B0ACB93A5F96AC9AB38 + xor-digest = E1E3F49B342F873263F585EC34969176 + 2CC46C17FDEE0B32224BB77A8EC82A87 + 816DC612439E998476F50E876481EE6C + B32ADBCF6A5D50FA16355AF63AA30D66 + +Set 5, vector# 27: + key = 00000000000000000000000000000000 + IV = 00000010000000000000000000000000 + stream[0..63] = FB8F4925A4F922119A6F29F8DDC2338C + 0AEF333B55919AF0D0D9B1DB61BA2E5E + 4CFB394E15F6A78E01B5C4AB043225FD + 9C8F50AB1BFDB16F944C2660995AA4DE + stream[192..255] = 87767D451D81D5B40503913508C2448B + 7CC093982642089843D7D9C3DA05598F + 7AEFC5B70ECCE327B20658D6301F4D6B + E58FA5CE0525C9CE8E93FC0B387AE5C6 + stream[256..319] = D146E4312CC11F11916ED9FF8EA8ABCD + E0736DDD0A8AF3E067CDED397E429D30 + 8F2DBF848C5C1653EA969B608CE01275 + 53573C88DDD32937EF6F8B0864C581B4 + stream[448..511] = CE919096A83BF3702D8899787DA7BC23 + 43F1F10833F16E3EB467440B4921BA1D + 96845B6B4141E1CA85364E2D508456A0 + E399DD048E72685389FD7EF3F78B655F + xor-digest = 00333EC3A59AD0B8FCA054A08340BF91 + 906512917E72BED76BEFFE29FC011632 + 082CDCB1A656FB817F968E26063279CC + ABA796307912984BFC267325DB84F621 + +Set 5, vector# 36: + key = 00000000000000000000000000000000 + IV = 00000000080000000000000000000000 + stream[0..63] = 202723F8212AB20D9369C2E1EEF8553D + C468854873D04FDD32641E324DCB4EE0 + 883AC1D40D7C9C7783DF4132093724DA + 113B1CB12144E00509FD5D36957A4E1A + stream[192..255] = E6717FE0A77F9043607A1A7665716225 + C8D417FFE2CD7572083C7C552B79DB6F + ABEBBC2D4D36AB319407982187C248F4 + 83596AC071C0B0CED08686603B024E7B + stream[256..319] = 8C59D97F7A093EA2D0AB890923AE4DBD + D40C33508838A3966FBA360E776670C4 + DEED8BC8CA57592463781550BCFD1E28 + 818E7C33A3AEC43775ED0A984044E9D8 + stream[448..511] = 0A3DC66754E02423C6EC1C1DD26CE11E + FD70C386729C8290DF358C69087CA7DF + D11F5E0D37A313F74B09F29C552CAC0A + 5621556828B0145A6A1D43F563AFF672 + xor-digest = 6673BA5866E8E96FB48FAC88D307079E + 77AC03692B23070EB5BB9D04FA94B9C9 + 6C2F958E834DEB51C6ADCE432BFB9632 + 9B3151E0A89EB72019A4522233B8FFE2 + +Set 5, vector# 45: + key = 00000000000000000000000000000000 + IV = 00000000000400000000000000000000 + stream[0..63] = 95AE241C4E9B6690C319D1FD828BE454 + 52F18F061C1B1E13AA409829E194D70C + AD5BBACA2738B508A5398DF6C2552497 + 6D143DF0405F68037C285A0E19FEC9CC + stream[192..255] = C0E2D5C6B614E4A498F46D5399DCE7EB + 7DFAFAC62794F5C39864C521B8DB574C + 149E35D1F0EA36EA7F24EF8FD855FDCB + 9CCC79F1ABB13EC33E00A9E137809C05 + stream[256..319] = 285907400C1A86AA9942ABD7BEA8EEC8 + BB6AF2F9667D424C1DD56349C99FC65E + 8A00893AE529D7BA492089EB6B525964 + E9CAF15221A342C4F88697D818AC0F1A + stream[448..511] = 13D511737F3A092643E94E74F6C76241 + 0007158FEF40C63B33E10360FFB3B152 + 8BD8B33093D722BDCAC1FA99D16D1C27 + 6E59E428601F256542BD3E7A4A135152 + xor-digest = 1D1352487AB5081A28DF23B1B19D5ED1 + 192F08964E4C0F048AFA9CAA8BF17185 + D7B97AD6003E2FD2DCCAD492FF3FBE5A + 5CD7AAC627DFE7CC6D0972D423B67128 + +Set 5, vector# 54: + key = 00000000000000000000000000000000 + IV = 00000000000002000000000000000000 + stream[0..63] = ECA0F29C3F5C4D62ACBD601C3042673F + 6F8B17C946FE8FEEEB0089059765F067 + 5AF3E5DADF6DECDA20F72AF486E7E967 + 40B2DBF22B57FCCDFE571B2D8989C95B + stream[192..255] = D2BDF6ED912478A3C53713389C9DFA5A + 9272D030543295E8CF6F0929F1A56041 + EA22BD04E0DD810F43D9D28D94254F04 + F73DFF3B766DB55100EFC9697FA844C7 + stream[256..319] = C7CE1CD4D8C42FA36724A49107A78630 + A60E15673A42C57B609740EC8DE78EE0 + B48F2644DC0DD1E80FB8326DDBCC7191 + 5E6C8DEEFCCB1FBE1456532840A89DB6 + stream[448..511] = 337650A0B03D30C9697CE85449B0F995 + 668FB2B73E37E1A550E07632F9F5AA3B + 04D61AC41F8A830299FB8F70FAA0419A + 42C4589D71C965DDB3A9D000667616AA + xor-digest = 7A26C50BA37BD9F38281FD2DA3CC14F2 + E1FFEEC9D7776E87D99053B531EEF792 + 0C0BF834EA9A0065AF38422A40A31BEF + AFAA17AD565F685BD6E505C7E02FB895 + +Set 5, vector# 63: + key = 00000000000000000000000000000000 + IV = 00000000000000010000000000000000 + stream[0..63] = 567919917583CE03DBDA69907CBAE562 + 107FBBABB4DFC81A3A15438C94AC0C28 + 8CC35A91DED9A79ADF4EF2670A55699C + 000994EF33674B578F5D77928A43416F + stream[192..255] = 13D0EC5B7302C0D8AB329E7AADFC3FDE + 1D24A80B751948C4BCEF516D94DF7AB2 + 2B1D9E076BBFE367CBED341B2A5A3BA2 + D48735F83855460F9D9953279BFC2AA8 + stream[256..319] = 5EFFE922E2FE25410E8050A973C3FAE2 + EE372E9686B6E7B35294B52A579CDB43 + 9D5CA7F1EABFEB4303DFD7DFBCC812DB + 9D70CD0698D1ED051E1E32C855EB39EE + stream[448..511] = 91A01C0EF63716515DB8B71273CA4399 + 1654AAEF2AFD4DEF25E21A08D5385766 + D8C29514065FFF00B07DCB32D1A20830 + 3C3402963EF252A4CAF5CA31A50BE591 + xor-digest = 9232F83FB054098FBED8474939476CEA + 5E9FC269E7B248E56B14F56CB396BE74 + C2B2203D1802D9515EEE232FD612FE21 + 11C291A46A89D54B2E5437E643239636 + +Set 5, vector# 72: + key = 00000000000000000000000000000000 + IV = 00000000000000000080000000000000 + stream[0..63] = 507958BFA08EB41F4D18F519E36FC476 + 5BB8DC6CFCA36290CE9AB8B165D7AF72 + CBF49DCF8BA2D145D7935EDD2CD2242A + 7B7FCCB85B4C8625532D84B4BC602515 + stream[192..255] = B2B06A7C3977D4A1A39892E832A32A55 + 3EE6E52DB24DC453835893A55D0FF3A2 + 949B8B96688237E13DBBB2D0C9038AFE + 8B9D18CCAF62019ACB908499D292F280 + stream[256..319] = 1D28AADF7B262A1EEEC11D39F4325CAA + 6181F9FA1A6C65F3BEF4F1614B0DF599 + EC92E5B6B42A931352965CFFC025F68F + DB2D6D0181F259F12989E5FB23ADAE8E + stream[448..511] = F60E3DAD5004E31F6DC89292ECF517F1 + CD18AF7E79E775334F4644A09346AAF0 + F2B4F5C1DD03555A6D27C43AE53EA7BC + 7167F793190071C7AB7B5330A6C6CAD0 + xor-digest = 5A65D44021E67626E62FE87B8547210E + F736490C0D51485A8EF0E1CCBB512DC6 + 0FC18114A29AF923EE3E85655771D6C0 + 7CFE342A52190C540BE3409853F12065 + +Set 5, vector# 81: + key = 00000000000000000000000000000000 + IV = 00000000000000000000400000000000 + stream[0..63] = 2416B634134170CB4F67F431BC94612B + 5F2F72545DAED2356081C91A26554614 + 5FF2526D8D8FC7D02D8BCDD9AE03187A + 9E404C360E115CE949667987AC73624F + stream[192..255] = 4D456233EC7E761891A56BF9F9659533 + 22375C169D7F16DD81D8D69B12092F47 + 09703B85AA3184827935B60C1E5987A3 + C4C2EDFEAD4F777B53989C469B575EB4 + stream[256..319] = 5F9CDDCBE09CD759B346AAADA2436887 + 0D47BD8859CB9225B61AD9F99197FB14 + B5D625F5DBE0955DCBAA5B874A7C89C0 + 07BF926AEE571CCD7E20635ED4FF312C + stream[448..511] = 642391D8851A9BDBDCA37B9587D5D0A4 + 877EDEC31D6EB78AA3F1E068B0ECE877 + D83EA29906D0C0816EDF7EC5BB417A3E + F3DDAA2145CB37CEEAF8C07DDEE0AAD9 + xor-digest = DF93E4E01EA55D18AB8AB1A927A5B5AE + 9ACB871B7493DC283581262771852013 + EE54288580A03B3991126BE8BC20C5D2 + 230F00D8216CFB632271750F4FD2595A + +Set 5, vector# 90: + key = 00000000000000000000000000000000 + IV = 00000000000000000000002000000000 + stream[0..63] = 4981C83E26859DEDB32D84C7BE32830E + 784376A12FA6D0077D4CB47ECBA08A92 + C841D45D6CDAA3F1FB48C6FE747B0F67 + 1B32C2B35BE69497737FE4B98770DEE9 + stream[192..255] = 1FA51FFD0360615EFEB03042AE8E4210 + D3D38B4EF07536BAFE43C0585818F012 + 8F8B3F8CA8DADBDF049688253066C74B + 01849C5BD85DCE27C0138D24E8B8B198 + stream[256..319] = 2D8C58008EE94CFEA1EC545C26466D39 + D7BFD5B226E32F1270B5BD3677818B7E + CFD98BDEA26488248B10418C1F854159 + 8F42C6CC237885A1DEAC5C33F22C27CD + stream[448..511] = 94502058B5828AE4F4CDC0516E5B5143 + 1F07EE1ECAD7CA266C931327BE6BF1B7 + A34810220CE00497D7BB9600FC524999 + CDEB6DDE8919B03064EB56B3766DAFCB + xor-digest = 1DEDBE0B7B6099DCF285B3C30E91AA0F + 7859496E034A1EA1AAE3D3D13C2061C6 + 0878E595B63D849B7DB77BE7E0C08157 + 94232B645BE946E5D8278B14427172AD + +Set 5, vector# 99: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000010000000 + stream[0..63] = B84C72BF69B601FB1804CE333C5A2C19 + 25BC8A5877DF9E574295380611D03FD2 + 46D2EBB58CC6E918F4DB1B1A0E39642B + D6B39DC76764E18108497E4CC4394057 + stream[192..255] = AA84DF8195B3F7564D0715517476085D + 1B40511A72340DFEAE5134C7BB8F39CE + 03E6EE15217986C7E4788453EF054027 + 8CBF6336073092EF661C13C7EA8B4850 + stream[256..319] = A7F0C413EE143F55C6356519AE620A9F + 4CEF8432C51E2677EB5D700CE333F314 + ACA374D86A8FD4A67BDC31C1B0DA2AB1 + B20E6DB91E7F85DC13E348314A4FC782 + stream[448..511] = 3445E08F13D09A1AC09EEB65451F4504 + 0AFFDE94F6C2667BC4D8FCBECD6C6565 + F09FD05EC660DD38307F856AACC95549 + AEBCF31B3FBE84FFB3261D7FEF7A3379 + xor-digest = 360199B22EB28401FB4F621E37800801 + FE69C809D83BE29A50FD1A476B6AAF02 + 54B1F4B048CB6423182C390B8EDFF1FD + 9CE49C26727F0D68EB837C19F58F3F42 + +Set 5, vector#108: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000080000 + stream[0..63] = BC618F4A557E5B7CB75B3572FFC31CD8 + 4DB96FD22E281C198DD33B5E9E419099 + BE30E84ED61C0EDEC04B1E16E06B40E2 + 372E0EA1A48DC55BFBFBE3355B566AB9 + stream[192..255] = 33372015C7E5749D98A92CC55CC22206 + 90BEC9878D3CA0AC50765D0B4457CE50 + 9BCE196BF0388599E692B99EA8169474 + 546F10891A3FCE22DFF0AF9733C2A2EE + stream[256..319] = 382684F74B0F02F7B987D37F6BAD97F4 + 20B4811FFC744CBB9F00C2855A609FC7 + 7CD24D0137304B95217E25FF45AFA4CF + 28E4335D29DA392D26DBD341A44C082A + stream[448..511] = B0B2B619708435C5DB45FFADD2FE4449 + E603FA9785E1F521E364DEA0B127F72F + 6C8A956CAF2AC9ABCE9772ECC58D3E36 + 2E758BDE3678D4F4C9804CAF11129BE4 + xor-digest = 80FC64E2441F6CA9C0F4C207007FD0E2 + 5F1C0514D203A1B01A6EEFD1055CA355 + 0174FAAD47ED0956A736A9404164ED85 + CBEB31F80561AAFC4ED8EDC9829D83A9 + +Set 5, vector#117: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000400 + stream[0..63] = 69FEF0D5DD7CFA6590821B6C12E239E3 + 5DCDE7B218A66CF3C75ED278092A6228 + 143EC00BC16DC2FDB8CD9DDBD802AB56 + A4011F6A8CF432F2D34657AB84DEFA4C + stream[192..255] = 312EBF427B3D22A22EE1F85D89E12AE7 + 07160C9BBF4073E538171365290B499B + 8904B01801CC897FF09A520449A44D0D + 34622DB8477EF1E73DCF15417478FA03 + stream[256..319] = 83CF222FDBEB77FFC6E282C1212D8D1E + 014865E9C1251FC07E901A41A50A3AF9 + F8E130394F621B739578C7E238866431 + 10827799C75F08C47664B09B477F31A8 + stream[448..511] = 4130A8F8015F082EE8712B6D61178CAE + B1D3CF90AC2DB9F2D402F65E8395DE95 + DA0605E8540E553CFFBD029AD5BA8FB7 + 5950C2FB29097E13ED4A1B1818E0D07D + xor-digest = 21FA07F8AA2FBC12F5B2B14E034C2AB4 + 54D7D8DA66EB0308D9AB024DBFA414B3 + 38F36D188D33C71E888FFE1A6AC620CD + 55B33C1A146AB8FD275584589BD65606 + +Set 5, vector#126: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000002 + stream[0..63] = 0CF41A77C30118D0931FF3142132A627 + 7A778D3BCF7466EFE56238B166A57043 + 2DB3B222523330233F81836282A27B40 + F6823BD076D84DC3B831DD78828F0FD5 + stream[192..255] = 38A0C28325566FBAEF5AB3D50D54F407 + 91182DEF4FC945992AA0D62134451914 + F07F16E86E20DB119692966E6CD6165B + 79BE7CE6C45D1248F2E0432393BFA726 + stream[256..319] = DE91DACF57B176EF6E59E485DF02A20E + 3A4EE5FF44B1AA3D7F36265221CC71EB + FB9565AA4F269B7DBF3CB9631CCBAAA4 + BBBB6BFABB97E52954958D4E7A283F20 + stream[448..511] = 8FFDC8CCBF864721D6C98E1896FA052D + 15141D9C3DFEB48AE91B2436C5C3D088 + 931470CE951B66C38998F15CF23BED01 + F6D95D84150D482C0C289A8E5B2C7C10 + xor-digest = 03DA7ADC3E5931928D3FD89E1E0876AF + 9D4CE659175E671D6D80EEA78F241AB2 + 86CE3C26DAE267D91DB556AE0CAA60E0 + 2B481282E6470A7A161AC8E84C2311EB + +Test vectors -- set 6 +===================== + +Set 6, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 0D74DB42A91077DE45AC137AE148AF16 + stream[0..63] = 425A5E6F68EC055F38383ADC5CA9C048 + D6455C56A5ACED215E22665185E497EB + 3A2F5C0D45057169965EA37FE19F5D83 + C95C4BEE11E8FA89545A38DD9D18AD6D + stream[65472..65535] = EFFA27F50B0B4C4AB3C7855CD5DD9EFD + B61783161678C9728B9032C2CB09A0B2 + D2578C53BF3C3E67D382BC89D824D63B + 20E62F414E4AC36472A16F4992DF4496 + stream[65536..65599] = 0111EEC218892B446FDFDBA9D0C734DF + C209D35FA86C1BEAC0D266E5DC4B3243 + 68B4263BA7A3517805D1501B36450FFA + 1544812EBC0B9DDED93F5D45C4D83FFC + stream[131008..131071] = D966650E1A27DF3CB71B1E64CD3E7EEC + 2D3EEEA2953E2FC5571B4380EA3BAEB5 + 3F014B4EE071A426E4A518E1AF335BD3 + 76309236760E0DF6184B3E34BF861458 + xor-digest = B234A4CB646B0C2792023EABCD3E974F + 1E5BF1D5DD8E07E5C11BCC47BF1F1DCD + BFFA3605A37008813029BFC32D1EEC11 + FE775D9889560C847C79ABB5C7181E6D + +Set 6, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 167DE44BB21980E74EB51C83EA51B81F + stream[0..63] = 5C1C44F155CF8595D52D003B7CE6C584 + F04708B55E3A8B952379A4F03C6C5118 + E0848F52C846BEF459335EEF7033CF25 + AC643ED139A9383B9DE13A5652E2B754 + stream[65472..65535] = C4710CE8066A43B7E7FFBC8190CA79ED + 5E14AEC2C153F83966322553D5D4824E + 782AA1C91400027395D74B3A39DA1925 + C6A757E36B48A8F1FFF12321602379CA + stream[65536..65599] = DF29C91A08AB080662764B01223C818B + 27DCB638FB2535DA034D325DF996F57A + 7F4C67BA94C72EA6C88112E575D55906 + 3C900A87B205A8144FC1717D5ECEB77F + stream[131008..131071] = 63FD83511C8C39ED3968EEC5FD281279 + 70626BB91625CEFA381AC48E166778DF + 63709701FDD99F4A547D8CD6F7324B29 + A9E0C025EA1BA007246941D3566D15F9 + xor-digest = 959850E75A99AA747502E7BA9D19D870 + 5895593FCB7BFD7A7DD4FB218F17DC6A + BC8B96520FE83F287429BE3B87D35D78 + C6F100D8A9561A149297CBC44306E5A4 + +Set 6, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 1F86ED54BB2289F057BE258CF35AC128 + stream[0..63] = 696FF80A8A547A2E215C6E0572821F70 + 201A090460E7B36A48ED5CC976417DEC + EE32E7102AC764805E4A1BED3DF7D786 + 0B3BC625B121B5200629AB58799DC406 + stream[65472..65535] = 7BF69658F0EA9905897C1460D30333D8 + DA83E3F1377FB75D015D927365C7316B + 307CD91A7167B87FB13DBD4739F88A20 + F7878C2A483A4FFE1AB4A60840EF3EEE + stream[65536..65599] = A55326496CDE23F447CA6A4D1BE0182F + ABC30D61C7A9E655CD99273232CA6589 + FDDC8179038B720D5A12CB698FA50B28 + 9E6CF476ECE2DE213F44F9F23E8AB4FF + stream[131008..131071] = FB47C745519AC58C91CA9081B1DB0CA2 + 8662116EE04AC6C4171A4BD11572677E + DA507990B45C145DD21A56E1FD8F7AE7 + 1BC54AC550309631C12A80FBB27187C4 + xor-digest = 3B3E44A1154CA7C4B74A432D0427AA6B + 3B6D81FA45AB9D3A37CF075F57E62AFA + 15DCED3DB08B96F48A12B176ABF203D0 + 922DACF266985DB9D52A9D4AA00614E2 + +Set 6, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 288FF65DC42B92F960C72E95FC63CA31 + stream[0..63] = 0A12311E99506D44616A24E124676D15 + D06BB6A73EDDA4E9767952E1FF698BEC + 593FF8E2422D80C9C55DD660C6622CA9 + 86140571D0958C070E2A8929C24E5562 + stream[65472..65535] = 6BF87D409915D407FDAA06FED0EDA87B + 8CC4F20760B7669009795EC87DFA6BB2 + 9825706AA3ED93F4197B28587D042223 + 7D1F6761D7F8D8F8B3E0421AE9EBB9BF + stream[65536..65599] = 290EBBC73FA33ED00E0BD9CCAE6ABDB5 + EB5E86C533BF3E69D24AE720D0FE30AB + F92B57C1EBAEBE8DCD0DE7EBBA5E8CB6 + 67669D286E0B8F8A3A53C3192D2DCE67 + stream[131008..131071] = B6082022254F783C501C08370D8F5678 + CA2F08825D4F7D09BF0868CE44DB1F5F + AE8D30C6380C3A20B1EEBD4083E58BC7 + A4EAEAA9D54117253784E4917C3A7039 + xor-digest = 2181364DEDEDCA0C6F51A4634490FD9E + 3E89D0D30AE94F5E75730E4B9E82FF68 + 5D82723A59CA0879C6B80588AD312CDE + 18723B80828EA4914BEE062A68EFDCBA + + + +End of test vectors diff --git a/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt b/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt new file mode 100644 index 000000000..a4784edac --- /dev/null +++ b/crypto/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt @@ -0,0 +1,2783 @@ +******************************************************************************** +* ECRYPT Stream Cipher Project * +******************************************************************************** + +Primitive Name: HC-256 +====================== +Profile: S3___ +Key size: 128 bits +IV size: 256 bits + +Test vectors -- set 1 +===================== + +(stream is generated by encrypting 512 zero bytes) + +Set 1, vector# 0: + key = 80000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F1B055D7BF34DE7E524D23B5556B743A + EAF06AE9076FD2F48389039C4B24C38D + DFC3AC63A148755FB3CF0CB8FB1EDEEA + 63CD484036FFAC3F5F99FC7A10335060 + stream[192..255] = 2541F0EDA5633B4F47C6B74CDCC612AE + CD27E46B2C8FC9036A09C6FFB5891168 + 7A8FAEDC225E34C45B6E081EF5279FE7 + 3271CED417549740EAEC6616C2B6A57F + stream[256..319] = 0C8C0567803E2537804BFA15742D3E08 + A29985688DF3D6B4C3044464C1D1F2CD + 4CBBC470C9A0FB05665CDED63C58E466 + 896F80ACC020F134CB622487D40E0AF8 + stream[448..511] = 1FD448C788A21BD30D4B6BC5D8AEF296 + 2772940557B9434E0FAF636D576B0737 + 1FF3AC12884BB431F396CF7C189D9AAE + D42797128CE645FE841A4CAABA429324 + xor-digest = A3F66A36C20A496A0D4D537B6106662A + DEB5AE1E35FD1486EAB6039F443E5D8A + C6A2D4A2C2E2A9F335E2E468AD8BA51E + 550E41533332E6929EC18CE35BBF741A + +Set 1, vector# 9: + key = 00400000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 9244D2B190FE8C4BD0E17247C4F1D282 + 3FECA8DBE546637E34BCA99236D09F79 + 5A8905A1E0FA94E6C51F7DC0C90FFAE1 + A8EBD4C99CC96FB3252DE0A0FB03F971 + stream[192..255] = BC0ADD787A5EA52E28B45192399DDDE5 + CEC4E283181408E554FC714586FB641E + B36F3727358BDD8223B5ADC9B9EF1044 + 0F7CD97FCF2ABA75AA9972B277CD6656 + stream[256..319] = C9F6315DA3CBAE23D32685C5549274E6 + 9C17FB2E46746C5D3260FF2E00FB234A + A460776CB0E7AC3AF0D297825C1796AC + 0B689DB219443BF4C0D4D19CD70A49E5 + stream[448..511] = FBFDF6D40BF2DA0EBB04D52C117E9EBD + 6FEF88D39B8EF8B31082EE9B19D50219 + 183DC962391FA4F602A2510BB476EF4A + A44439F61D589933A1F3F633C96E56FA + xor-digest = 49B435E6FA51A0AF8DC94CF1DE09F8D9 + AD76E08C061B54CCD62EF98ABE85969F + 3FC41DB934AF9DBC5F32748623639D3E + B15124F13DA8B008CA5016ED61917563 + +Set 1, vector# 18: + key = 00002000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 9D74BE686C2DE8B207E8D82E49236A3D + E86F5A7EE231B4239080FC9A55FA44ED + 7737FA7472B318A4F36FB788E863247F + 7067C20DCA632FF051789E9EB99CF409 + stream[192..255] = 4876774DBB886B72E54EE8160D8BA8DF + 6DB032B2A9BA0B79CF82426CEADE421F + EF5ABE9976E909DBADA0442FFC7BBA2B + 009F7240941F0C209853A514B0BE9062 + stream[256..319] = F2499CCE5D3268F4C5515C365D2F4411 + B0AA99ED01E7D5328BF0672584AC65CB + E47BCA14C3EB1F838ABDB7C611677BC3 + 7382E84D05848B9838A166A42E96B016 + stream[448..511] = C855EF5D1CC991D2DDC892AD8319E39B + 734E43E443F5910D03BB79CCEBE70569 + F92BBC63363943BEF88BFA5809B3759E + 6BA4ECA1FAAC572228458A229DD5BA06 + xor-digest = F125B88E0B5F143B836AFD7AC822E027 + FF44B736E32627D90FA05F3DB98576E1 + 9EC41AAF9D61ADE2BF00E38CA4EC2A54 + 49EE0655FEAE777D67EE127E8A5F8CD8 + +Set 1, vector# 27: + key = 00000010000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CC447BF1B5D138025BEA2B269E625C4A + D4451F3851F04F118499040C6E564E38 + 5C5FE17FA7AFAE9FA559CA4835AC1F40 + 1C045AD439B400BB41984DFE7E4D4CC4 + stream[192..255] = EEC14B65E027BC2A96E566BB89218A89 + 31C4AE0BA5C444929EF852EF7E400AC5 + D8B3CFC62DEBBC2B20A7B32E350E3839 + 2953B7839AACC06B2018280770F84B65 + stream[256..319] = 8870B4F9A62B37A1929973D3975D7ED0 + 505AA43002B14B55A541EAE00148651A + 111D6E5A1581F85FFBC2304783EBF5AC + E924CD8111056B1069F13100DE15EB13 + stream[448..511] = 1513F3B7A2458674CBA2B566F3AD6169 + 2BA4EE30687A07AF2FD0D340D92384F5 + F5BFD9B8DF2F7098A209C280F6D5AEFF + BC07D167720DB47B4B649C8593E6F40C + xor-digest = FB5EE30BAE44FDFDF105796FB8A66F69 + 64D502230C191FF9AAF5A4447533D02F + 05A3772B99F9FA2A075DBB8BA59D8D5F + F819784D487C305280DF2F19EEA8BD47 + +Set 1, vector# 36: + key = 00000000080000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 831F1DAB278C6226785209C0AD34759B + 9F205B7BC6B987DD145B949336A8FA0E + 4550BC1737DAE7DD7D12E2C062BF9693 + F08C2FB808A1F0A5887A06B93D132BBC + stream[192..255] = 76631E9D4A673D09B9769251433D5EFF + 3114AA59E1A9B7E21B4123DE3E34FBF8 + 4ED6E80EC29B4F75B53A63902C373EB3 + D644B8823789743CA407FFEBA4A1AA75 + stream[256..319] = ABD84B2A5479CDBC5587FB9EEC5DC661 + 5A3CC6136314F67AD2C96803E8E4BE92 + E33DC35F0DBF3C401AA5D7A9F46E54CA + A7ECD68E561BC08E6A5B847A82777E4B + stream[448..511] = 9ED1D44510201727B2E92B55DBE06BA1 + 46762AB34937364B2157292CE68B9D78 + 3D3C3FFD1FDCA836E4C4FEC750B10668 + 600C26AC05B4DED64F8CC2EAA0D22052 + xor-digest = 843D7B97B3316595111DCBDE3DC13DA4 + C14402936D68035CDAF9A1C168120B34 + 0EBA1FC47E957C5F69F369B4C2ADC4AE + 37E743226D72A9F122EC8E00BCAAA126 + +Set 1, vector# 45: + key = 00000000000400000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = D2D629E84843638274ACB79FA257DD9C + D48A08B823DC9F175CD92C5236B9D230 + 5931FDEC5A8F531B1ADF30DE0527AD2D + 0D2B253D008913558E0FECCA7D7BEA4F + stream[192..255] = 6F9322E84D69CFD6A1E589283CD028D1 + E2A114B719FB2E18E732B97629313772 + CD2F2F8AF77EDB5B4360E4B679441346 + 03C59E88C042713C3E403E5D93F9BBC2 + stream[256..319] = EE7BED6C85B20E0A39C103D0B6949F4F + 5F6FE0DF2BCE315CCCEF6E537C488525 + BFC27FD249A6D36548C558153661861A + 78422A563166BBD0D72D6D7876FB4DB4 + stream[448..511] = D2CFFCD4185EB1D8E15B629225B9C278 + 6E7BFEACBFE29D7AF396B3D5917A8038 + 7263018C7E98F49A1D5FA4B64B8E2AA0 + 7192ADE0376388E8295AE5B54CC51389 + xor-digest = A26BEFF2FD72BE47175C1B6F3D749CEB + 0E3472FB0FD5E173DE66A5BB60357565 + 505E3AA44A67651DCA75DFB6F0AFCFE3 + F4C89F064FC42D7C2953694B0CD47832 + +Set 1, vector# 54: + key = 00000000000002000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DD1649517BE76EFF747658F0ACF5D354 + 2C7FFD52F09FF7DDDFBC48487450607B + CB90ACC3406D0302E84450FC0BFEC660 + 9BD44C7FFF670D69C9B19FA50C62EBE3 + stream[192..255] = EEACF8ABD7D48E285A6658C255A6196B + 66B091773A9F81807A119DC24023D5C9 + 041AF75F2C078C5246BC5F50B622A678 + 64EB7A07DA6A8764437E20C7E1E0E579 + stream[256..319] = BF55E777AC644A0938D438FA374360ED + F842BECB027FA3A0F364B9150FFBEB47 + 09FE2D2056A6CD5A7076172152484BEF + A86EC7DDE657307580BC6F9ACEDA4C73 + stream[448..511] = AB4CF968EC00E7F08553A10270A7D439 + 68B0BC79C2DAE278AF1CB81FD516CCA6 + F5B8A47271FAAC3223F02DB4D0D5945F + 9C13A47906B03B80878CB0596D37CC47 + xor-digest = 76ADECA36B9401DDD5CBDEE821B70FD6 + 65EB9CDB1E3F25C0BE90DEC49C03A9CF + 4049CD34F9550B28E0187B0AD47D86D4 + 88DE4617EDB5F03C67FA2E7B9D20AA25 + +Set 1, vector# 63: + key = 00000000000000010000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C0CEF6E3CA9F0D523587FF47973FE896 + 9FEB08773E3C694FBAC4804B37121B31 + 06B99ECC2A08603EBA72EB3DC650E8F3 + 462119F4685EF4CEA18D5765A6F22765 + stream[192..255] = 79E92E248BA61D72C610876D3078F1CC + CAD662F2423E7EECA813133136A64E54 + A1B6A151BECD2B815EAD959DE8E8DC62 + 8F388D366103296A058CF60F525D6467 + stream[256..319] = 03BD62A0892D939C1C28C4EB490F87B2 + 527536AD6790AAA6C3CC50013E2BB883 + 5710EAB7916FD89896B7983B326AE271 + AF9ECF975CDBBB968D076685BAA3343D + stream[448..511] = 98762E306A2B9D488FFB671D3975551E + A06A6CFC5DB719B888E3164387EC922F + 12BC31A8DCAB8AC0CD6E12212CDA3B13 + 4CF7F870221D6CDAC2B222AF4FD93DEE + xor-digest = 606FA49585621E34BCC3748C06B51FE5 + A8AF320BFB83A4D1D3AEC6373519B28F + 2048A975732BA8DEBDFC5F85B84E7C3A + EC0FCC9B1FA9EBB9D79D6B18BA2D70B7 + +Set 1, vector# 72: + key = 00000000000000000080000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 33A81D48866B04388451BC2730A2980B + 5F5BE248369911340E6C024A1F94D4FE + ACFB246F7C0B9E27A40772D68DB36DE1 + 7E87AEF19C8A68854A46B3F654E0AEC8 + stream[192..255] = F67C60413B25FF7CB8647D1E9C361696 + 3B23ECE23A9DBFEC644E855AEC5212F2 + D336E6F074EEC8FF5F8D4FC6398AEB9D + BCAF6C29FDFE6E69A03D906C527FB0B5 + stream[256..319] = 263D512137BAB758F646C71058D02B20 + 3920965D84E52A99B50FFE79305E491C + E0D61EF71F7A07937CEC8590B758F63E + B3EB5890E8678F170C2E95B827FD8DDE + stream[448..511] = 023AD00A87D3D9441D4E8CB603F5CDDD + AE8F3EBFEFB9C5435B72B9B8D03ACDF1 + E4A0FB796FF8401854998015905B878C + 99B3EDC7DD33A86AD4EA6AD208440C5D + xor-digest = 5DAC8E3446BB3B0DCFB3F0A3A3E788C6 + 07FA7436C63BF7AC9FAFCF4A231AFAC7 + 75A3A810EA0FD4E5E6A5B8FE5D165A80 + 798A9F58EE1AD27016E867D2E774507A + +Set 1, vector# 81: + key = 00000000000000000000400000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B33EA681CA88C80EAD8F2D57C87EA42B + 742550FF8AD2B01BDF945BF160AF763B + 15D6B3BD92E6CF3E6A2B61A7D4BB94AC + E3DAB365E4EA50EBFD2654E60CE849BE + stream[192..255] = E97318BDF61934188A94BCFB4441809D + 36C37D1A43BDBB3EB06FFE143B6153FE + C8453A13387923F434CFC7AAF8CBA097 + 7D796DE95EEFED3B2126B611F477619F + stream[256..319] = 4183971367E71731111D2212520306E1 + 1CBEB05BE6FDB338414C826A8E359C7E + CC680F317C12C6EDE6B443E68B4767AB + 4190E95E1AE4E4FFE61707BE742775C1 + stream[448..511] = 56841724B7D7F95809456EDC1D3A532F + E1C6BA252017DA90EEC71FEE9A639A89 + 4CB7E1575494BC8B44FE4C5DAF90FF4C + A32E03D6399BCB3D9D25B62764A4977D + xor-digest = 3E80587D70A53AFFB96A62F6493B9BE0 + 1C25339CBFF7784F5100A7922EE3E6B9 + 9D17B026C0EE69C5383F63E0E5AEE9DB + 5814E2C526192AEFE17004AAA1996280 + +Set 1, vector# 90: + key = 00000000000000000000002000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 51A7510726D12FE9574095633A3710E6 + 3EB8196622BC808B8A18800E208648C9 + F7031F8171B71F37613753A5E49B37C1 + CBC7933A52CAD48601E91CA198EC19EB + stream[192..255] = 286EF1C4F74C993A7D783E86527CDFE5 + 213CE4DF7EC72544685291D8108C7621 + 50D488AEF761D819781814F4501553CC + B45EDDA85828C33C4D0608169AD20B2A + stream[256..319] = 89DF5C916612EF0ACC1035EB75752239 + ADE08E0D63B622EA52CC997DC8178C4C + 4E57951FC8C6659A225E88502742B888 + 1F300FC9F278AA3D9C1063A83CF33C44 + stream[448..511] = B2DE3AE2941AFBDB21D80ABB0EB852D3 + A076D98C696F886C302D96D6AD226CA3 + 7B3213B3E641632B728A0AC7131B74FE + F733D1B18666D36A02C148FC98AD2E89 + xor-digest = 01090125BA6C43AAA3910B650D046F37 + E04896E9D2BC276D969A10C1B26FAD48 + 8A2CA5E59044ADDF698588A561557669 + A4EF25E1BB85C0A9D63F69FBB2924F83 + +Set 1, vector# 99: + key = 00000000000000000000000010000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 545E2C75365948B40FFF042EB6919907 + 6E63EE636CB343C51AF6C17BA24E1BF5 + C045B0893B8CBDF6A4068F8574513676 + 80000B10BA11666A546D8DC75374F5BB + stream[192..255] = 9805DCB5596FADF01224553F3A8DCC5C + 909D1A5EC2C29BA0DB86A46ABF70BAF4 + 4A171739309A923428EA7BA8EFCA5CB0 + B0B8A5EFE9A4A39BE0EA6CEA782DD862 + stream[256..319] = 531EE320A584EE1E4E0701400F86DC29 + 69531C2BB1BC922CFA9E0919A05B84C2 + 46495A7C358015724B62A986220DFA17 + 6BF39FE4263A9D27D93F3737CC1D5C59 + stream[448..511] = 92CC0D63772783AF62E642A5849CE7AF + 4D21EC815D644F88887242F4F5F7E1DC + 55E241D72691ED50D59CB3E2FE68A856 + 7696F8B8E3099642D70EC3945B8BA656 + xor-digest = 855CFA62E449250845472BCE9453BA45 + F91601ABA6BB715B079D407E05D94CF5 + 93B5A1E2C12C04C78AB719339AFC11C5 + 213E17ED9DC2B0B9CCF751E0613D4F2C + +Set 1, vector#108: + key = 00000000000000000000000000080000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F9748DADA2741A7CA30EFA167ED09978 + 71619682AB68CB400A74BFD642180CC7 + F3499CE2CC86AB7727786DD01AB8D08E + 8774C5A3CFB4738FF1E3243DECF720FD + stream[192..255] = 5AA20B305F5D6363180CDCD4E16427E7 + 2E3DFD73D2C4E2498008F6E0FA9CE3BB + D751F6EB8DD5F48EB42B994688601E3D + 2CEB3DE19BF16C4BD7FD4B331FC93473 + stream[256..319] = 81E3D9BB421CB09A9139534C6E430668 + FCFCB87E48CFA085D4FA1AB316CD5AB6 + 35294E434852C1509C1023A85B26622C + 68BE19944CA3233A4D3272710A791E3D + stream[448..511] = A499D228204BC22C32047DF550E2CCC0 + 260ECB7BA32E8F5CBA2C1D9A09D1F38D + FB30815BA3C9A8D3243CFE7AC4A14B1A + D6AA67D3EC0A5CB617FAD57E41A2A0DF + xor-digest = 0324B7F1BD990F8DBF19C021CCDF741A + 1B4A9C3C3940CC59CD715F0B2CC31C08 + 82E5B93721AC98B00F7B45FCCF19FFA9 + 782B7D7FC048F0756A29B066B472B394 + +Set 1, vector#117: + key = 00000000000000000000000000000400 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 7EA95775329E2D1163E30F429FECAEF4 + CA177BB4D3C4D1AEFA6B5A01904266F7 + 7D7B7243B9DB1490245EC05129CA2DBE + E3A98885DAD0B43B0E725DDA39B444EB + stream[192..255] = 78ED15A7B4A8151F384C740B844115CF + D4FA31F9BC16E22158B0F896E70C0F73 + F74AA5EF024F6B386ED71239CBD57996 + 4583C37104AD8C7E5C812C378AF00F98 + stream[256..319] = 292FF21E49659AF99AB21753BA2A2B28 + 25DDB156D4F7AFC1888FBE8376AE4C6B + 905D5916121E9F9D76C83FB146ADA735 + 2AAAB6E89CE9398C484D69D1A33F0C97 + stream[448..511] = A50FF5FC20C57F8297C9CE2599A3E6CE + 3193746E8C45FD9AECA0C5A0FB3BF70F + 5981B5BA8D2FA57677EF65B535FC3E65 + 405BECF0A508445E36A7B6DE2BB56106 + xor-digest = D9650FA5D128620134828E1C99D9678C + CFD5BDFADC46A5E79D47AC5967B8A1CF + 32F7DB65B949C88CCEE0D96D960A110E + FF1D09EF5549B88D5B53ED46D4C2F296 + +Set 1, vector#126: + key = 00000000000000000000000000000002 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 25874CF64ABA4536844F815F486F9DEF + 927E325CFF2FAC48134A4D30824C5BF1 + EC75F8FEFC624AFCC717BF2C8EAAE374 + 0AF399C2653389DBE31F9FF5D451D362 + stream[192..255] = B151A1EDCCB8B4A3CA9BC98F19EFE637 + BE2D6A97A8F794091E7FFF06E7B4E574 + 46B81E8C787BB77E461592160C44B5AB + 49329142D01A1CD5CFC6681F93DF1E33 + stream[256..319] = 29B2B0C04E07D33EC3146E60AA305F0C + 2288913B55DDC18FC17EE836B39193DB + 87089DF2BAC4185A57E910331864E25B + 540BBC968099900F7BF18645A28A419B + stream[448..511] = 286FCC98B40EA26BFCBE5CDEE52B30F5 + 810CFB26E756C628B56B3B5ACDA49E07 + 192592CA2241C6C5193221EDA36CB0E7 + B5C3132F08087DF0673D3101FC559962 + xor-digest = DBF1D7E0AC062FE6BA9834F0AE41ABA2 + B28B41FDFEF914F070007B0A48EE9D9F + E69DB8395BECDBA7B545201318177A49 + 7D343A317B5A37A9DF98DD25C84DF948 + +Test vectors -- set 2 +===================== + +Set 2, vector# 0: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951 + 53F06534801F89F24E74248B720B4818 + CD9227ECEBCF4DBF8DBF6977E4AE14FA + E8504C7BC8A9F3EA6C0106F5327E6981 + stream[192..255] = 30DA9453A90909A5675D6B691CB0990F + C423CDD8222EB47245BBB67BCA2B9C10 + 8D1F016DF0CF8CEAF6829910916DBC1E + 113D11E91BEC3D85C47E3042EC865658 + stream[256..319] = CAFED71B892EDBE13388CEF6A3365797 + E0D88C0D3A5B91BE4CBAF5162F69558F + DBB45CA6F8C8D4C371D62736EC244584 + 60131F54854F3EC804AA9A38E6ADE281 + stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F + 2C3EA0F56AF46ED93DFAA4E16F5F0831 + 2D77BD0E9122043CD6A202CBA9351F6A + 0E8E6263F4017355136A0C551E6FD0F8 + xor-digest = 023D719F61C193E4CCD87755C87F9604 + C5A29DD7E31637B3DD70D43441D48CC7 + D474013C85EEAB1897C80ED0A0272543 + F951C72E3954616CB5D6B51FC24F4B0F + +Set 2, vector# 9: + key = 09090909090909090909090909090909 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081 + 2145B56AEA46EB283A25A4C9E3D8BEB4 + 821B418F06F2B9DCDF1A85AB8C02CD14 + 62E1BBCAEC9AB0E99AA6AFF918BA627C + stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58 + 11FA9BB02CECF7440239FBB0497347EF + D8F1A8AA71AFC70ECCD64E81388E6E87 + 9521C2B47AD84F9CFD9E240D8D2F3001 + stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD + 3C8D6A2EFDAA9CC11BFCC61D94F6104A + 4091B3634FA57AB0AB9B209F22DA5529 + 75C3C322DEBE4AE68623BFE1B2BB7F0A + stream[448..511] = 35B290F85EBA78A978750690C4747E8F + 72621951483772E8B89876CC5D55F3AB + 02D9B8FB35C741279FF9B5B571B26329 + 4D011F813CB5B209CA1A22D532BF09B7 + xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34 + F6CD0A795B8347E1441CEBEE35540D41 + 64FC2B95D71FD47A2C4ADF732261EE52 + 8125BE374FA4A90132CC1063971A2862 + +Set 2, vector# 18: + key = 12121212121212121212121212121212 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD + BD8853C329B3A881B489090853FE0F43 + 89DA105F0ADFA9CF51DA2521C40FD2B8 + FB0BF80B93E3F2B3D8A8EB1C615E0FA6 + stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D + 43A82A80DAEDBF29C048639BA38B690B + 7ED11323E3C0A8E77A16356705431EC9 + 9F2CB7F7E1ED3B83EAF2CAEC00B00755 + stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417 + 376F334E6AEF9C187012C8AD2B94BE7C + 00A876756EB232510FD0798E72EEC87F + 75EC1467C07B3A1EFB0D51A5FA65E382 + stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B + AAFD131432CFD7D2F675E03320395313 + AD4ED96E9052FE6B2D2A17428660A25E + EE642B712800BE3F7E44F21A1E6A03AC + xor-digest = EF4E84DBD66497B142EEAC56B830FF78 + 0465CEE20B9CFAF5727D4B3A588F4D00 + AAF718330CFF35508C44C1ADB8476625 + 2CC3AA6AAAE74F8BF1DDB6D4AADA425E + +Set 2, vector# 27: + key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676 + 263C1CB9AB941119B19D15EBA3462F56 + 2F69220595DE5E0E7C595FA40F1F06B2 + 6EC32252AF05310809DDDFAE2E24B170 + stream[192..255] = B29A740B51B4EA1080666337D5551484 + FFED6860A5125DC0573C8F90F23A98E0 + BA7B3E4C28C2CEFB1C33D2C36D1B7625 + 64B9A67240CF174347A4C8D868F00F6F + stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6 + 537C06AFB23354F054E25457B729B534 + CD10B2ABD45BE3E38DAF1B7A9103268F + 4FDB4C0FC9A80A003FCB907E8F249AE0 + stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39 + F62D54311207B617B727FCCE1B2E762A + 060810C4DEF672E7D76083E3E4BED0D1 + 0BAFD27CDFD2C937E660190D36B3FD7B + xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C + 18CC5E1E3F6A317ED7257887446EF734 + 65CA15F51AF5E077B7915062391D8497 + 8F437985DD08F5FA3A8D74B3227A6EEF + +Set 2, vector# 36: + key = 24242424242424242424242424242424 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C845BA29D542FBED2D021C85188E119F + D34967B79D9F44635DD45D2E41DC5AFB + B237AD2FA0E4CF4202D83DF3073C578D + 2AA8A32D30FB45DE28F23CEB85E50FBF + stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297 + FD12081B4B23F0A32CE5B3196173C7CA + 7EDD03F9637E08CA501C4850C15B207D + 7AA724377396CED2357B572BBF9E69AA + stream[256..319] = E484AF567EF80BAE77461855294E9280 + EF57E7366605785034D639D6DE3EBB0D + E21886D0E1E0679BC2E2C9C2D9201484 + 4A452B6AD3F1AC8B7762FF3C0E405B3B + stream[448..511] = 595D9855200786BB575FF7977509F395 + 7879CA1F19619A99174BF013CB62F85B + FF2C3C4FE724E26DD0C10D7635A2491A + 9E7E868D9DAD9201465AA178184D06AC + xor-digest = 08737B82505F46F4FF282EF42F387AA8 + 0450058F5314389BB73733BC163D75D5 + D32FC6408F8DE5F6ED2050027D605FAC + A7119FC2DC1B6D3E84E8048DCC42FBD2 + +Set 2, vector# 45: + key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E + 6E6320101999BCE5550C2BBC9BC65D91 + FAA2D72FA4BF46B6EE916244048B1D09 + A115E3AB6C00BAC8EE382B58859E8157 + stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82 + 0C18B867C561E96DF4ADADC5A4375E44 + 5A34F9457E5F8C9A337A0C88DF0F723A + D4509F1449DF2C6AEC0EADF4C7A8139A + stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8 + 452A1A893EF034C51750388D294947EE + 3F505839C69C1708E8323C449C39A96B + FC9EC91B0E1CAA8112057EB0389FDFD2 + stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC + EDD92C4461EFBA5CF1664B9AF54857BE + C3D00319E5E8A89A8322831151EE1D52 + D8585AC79CB60B61ED2C852D04BB0FB1 + xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D + 2363BC12259B0FDB2BD8F052A572ECA8 + D1EF62AA9A48497805A413742B5AF5A2 + 6DC9FF624B49E5D6FE58BBE5251B4983 + +Set 2, vector# 54: + key = 36363636363636363636363636363636 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340 + 42D4F07DA4D5EB05554CB7426D65C5EC + A93C2D321175B6F72FCBEBA6E38CB098 + B72534F7D534B1AADD97B77E8513B482 + stream[192..255] = B2466A173F436C8433F264CBF125B8E4 + C10BC81BD46B5C21FA161CB2AE07D27B + F66812A2C2FCB2B14C23E413CEF4E591 + AD52EF810A000B42E5C1B76EEBB17739 + stream[256..319] = ECBED2058DC50223614EB8635B834C3B + B176719C18CA5E3D087A93E5CDF81123 + C6FB819CCAFB5042AADFED5E3C33116A + FD92AA21031165A22F4751C423B8B945 + stream[448..511] = 758BD9435DE607867DA256064C304C8E + DDDF5B64173CF2C98B2842992F8C5FE1 + A37C3227B7F37D49A39F9FF929A883FD + 56DB8B1A174E1E55FCB21C9E1164C20B + xor-digest = 31761A49503946701D35306FBCBE10E2 + 02967E7EC14A328B4DB19FE79F03553F + 13A012B7297B2D02F18A216AD24A682B + 299518C3769123EE86A4937DAA9FC39B + +Set 2, vector# 63: + key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B + 26A4E7E34C0CA9CB9399F655E566383E + 246143F57776C8E08951E87F76091FE7 + 2356CC901F09A07895A890AECF047B3F + stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF + C862100A07E55FB449BCFA2D9BD48658 + 958B37B3EA3565FA66824102A14B5770 + 5E3914E0680E116ED58212CBF61028E3 + stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701 + 057710F24C01E680F58090B8E949AF01 + 8970A43A698A04C0C8639FAA665DA3AA + 562B2C5C3A03BCC38FE75DC1821ED718 + stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948 + 821FBB049DAD15B988A77C0247868A38 + 2056B66F47B0195FA30C9DB5A2334A9D + CD7C0D22E479FAE1BBCDFFE60F261C7F + xor-digest = 94D41CCAD940CED3C854DA0796DC62E5 + 6B566A980E34F353CFFD0F53AE9E34FF + A6A057645FE66D86BE30F93805D9E2B5 + D78C68EEBF61CE387277A51EB2EF835B + +Set 2, vector# 72: + key = 48484848484848484848484848484848 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E45194379659D1D8904DB3698AF8B245 + 762910B7FBD019AD1AA20A6C433B4C80 + 308A9EA68697631646BF3A2107C4E7FE + 2235E8F3262A9DFD3F5CC23FEB0B2DAB + stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA + 4E947598C4757976F6F61DA5F0DAC8BC + DDF72F08BA2F446FA37F9A490F6A2B6D + 79227C93271D6B763DA7B2A907220A42 + stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74 + A43D83AB8ECBAC5206D108F869561D70 + F151A0037F8E28951B5026643F8B2D6D + 56A62E259F04A5EA304791A9468E66AF + stream[448..511] = F70794C084E6EDC07BA0347413B05FC9 + FC46994CA820CE4FC037ADBA50EAA9AD + 55064ACB7308CFCE3F35AD5C7C628362 + F4210FBC2D3264F734728626BABF5356 + xor-digest = 31815B36BA034BB1941DB1E45A941A59 + 7C3882F34BD3BF441CAE8A9790B05BCA + 72049FD10C09A14AC9DB867A82C38A5F + 524C72F783DFD16980DBCDEB486FAE96 + +Set 2, vector# 81: + key = 51515151515151515151515151515151 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6 + FF53889A9979ABA8F23AA51DB1EDB8E9 + D08F696C1100799A7D004DEF1CA94110 + FCF0C054B0C131E6FAE0FE2F2DBF22B3 + stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC + 55A5F3F19C5A10E12EBE46DD84F10385 + 33837693588D584FDAF86E3A217C3CFF + 020278736F1A90CE07F0DCE4329005B9 + stream[256..319] = 135FAD68B5282FE59B28D2DF66463632 + 06CA92E84A73FA131EDDCE89A5C23B4D + 08FA57D455BDB32F8ED58DAF3EF288A2 + 7C72020E35DAE19B446E4C52DCDAC5B1 + stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D + 18F2111002891D3229102D72605B9BEE + F5DA36059B0DBBA7646927650305431B + FDA4A97570CD0C484BF1E974B157ED7F + xor-digest = 5125E77698C0DAA89A7E47DC5D038D40 + 7B732CE56CEB674CE653A1B6661B2740 + 0C092AFF83BEEE4FC4543B9D725C9387 + 2F89AA338222ED677BF59397200AB304 + +Set 2, vector# 90: + key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21 + 75E9AD91482965B651B495AEE819CC6E + C42AFE2C20EEACCEC4E90710D17210E0 + 4CC6832905985322C8007F872D3E58E1 + stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560 + D692A020F0A66F609374ABDCD1343722 + 05F19CA04EBDD3009844BC540C1B2B41 + 66D45E8A2E822B906DA34649E7FEEBB3 + stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF + CE2CFE99506677A956AEC86BD290B6AF + C5298A448D0DEFA99AA5CD26D318982F + E786D809C713D5A55B42CA6650191DDC + stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225 + EF6E3C21705EC9FB24873916A2C24668 + 963C03FE097DA8224A42A99E5DFFDC17 + 68CF518DE49CCAC8A70216C62C9CBA6D + xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5 + 5FF58B296071D5D39349A531E41F0BA9 + 893A1722B6102740BC5FE394A49363B9 + 6A626AB43FD6A288CD9B23F7255279F8 + +Set 2, vector# 99: + key = 63636363636363636363636363636363 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333 + BCB02E3AD8797377AE1F1B4D6DDB86E6 + 2A59791CB553550E0492FAB42C7A2C42 + 3157C5092D2DD37D46589F17FBD86584 + stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91 + 4122EEE5736BCD12061C77DF5B0122B5 + 1784E946B4E93470170ACDD7E2779591 + 57BCC9B9F3E11E88BC2F740AA0C10C97 + stream[256..319] = FF22D8196AB3DF662210D12D0FE79255 + 6DCD39611C07F089979CF7D693A30CA3 + 5B795B7F6D64931916E717C8BFB92114 + DB75118BDB51D142CE8133415C6B3456 + stream[448..511] = 971F007EFE17662D95F47F4F28266516 + B22A1E50755EEF19149DE3A3121F5FEC + E0D9DFE7A055026CA44193542D7687EC + 695B97769BF02F92C1EF3D904A8010C6 + xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163 + C8D54A4CA36748C74721C7B6E1649A31 + 4B5B7A4BD43E7C3D2A22F0C8446C7892 + 90D54D421D37CB16400E59CC86215CC8 + +Set 2, vector#108: + key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6 + 54BC11ECF0010D2AEB9F899130F4AC2A + 38EBC15C8831D591E6675DC1CE7A471C + 4B869FE83CBF37AC70BAAE5D4AC607F9 + stream[192..255] = 518F298A6008532EEFECB3DCF72103BD + 5E3F84FEB6EA2311E8C19A2E93A9C3C3 + BB1DA7DBA78D5618D1C4FA5B0B202728 + 62645A361E55494D66C9359E41E5809B + stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A + 89BB20CCD92E7F13FDD816DD4E4963C2 + C5FC2570CBB8BB5C70848B73001F508F + 47AF179528200F51CDC6E4854EAA63C3 + stream[448..511] = 844B1D15FBFD1264169279ACD525611F + A39C7BB41F1E7A1C09090625F7926E51 + 23A4CD7FE1A3F37ADC67AC437BF0A5AE + FFFC6FB0ABF39D9908145004AA5B958D + xor-digest = EC67596C9DEF4012A2D543842829306A + 4285A3B8038818F265065DC848BD80FE + C27C2F66A57B27F7FA8AC912001EC954 + 05BC6E93D7E555C59060F5D2E294D103 + +Set 2, vector#117: + key = 75757575757575757575757575757575 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 91D2772A18995DB3C0801DD3740F4466 + F9535E5BECB93DDCA0E94D19C0B57BDD + 0FFBA9DAF0B11D55C852927F8BA560EC + 4999E25848D08FCA7275E7E8571A5F1C + stream[192..255] = 72E64FF10CA9F07CC493715724DA7610 + 9E4358E8B0CAE451348B784A162DF036 + AB9796724D17FDBF356031D080A6631C + D1E8D217B041AD2EDF427972653206B2 + stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3 + 344956C29D10374E502C2EDD177ECE5E + 6625BAD9630DAD57976216CD69865058 + 130B132FEC1AB0C350DF4DACE4C7724A + stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90 + E402466550B518A177CD05985D238827 + BD92EE7EC22C274F19E682F85ABDAD95 + D0EBB3DB6C6134408353C8B0472C9A1D + xor-digest = 9A6C893F2108D13A29373DEDA65386C4 + AC356BDDD4A3178952F9126E322B7AE6 + 83C94F1A131CBEAFF26549D9F84CF04A + 1241FA374B055B0ADE7E49E8EC669E65 + +Set 2, vector#126: + key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3 + 059C5CC575D806B9029CCE3FA45A246E + 0EBD3AB2F2E324FE36ADC3B56AE2F7EF + C710AA964CB87381386C2A88B1308035 + stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E + 20BEB18D9C84187C347F43B17E0924F1 + 2348F825E106E57A00258CE4415294D9 + 4323A9812D8A71359CEC1001BAA0D567 + stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5 + 32D62E779FA0D2D08F8ABB6B0183A4DA + 4EE0329215F261D953150B9AB9FCBE2F + 568AAE361EAA8636ECC01A63F007977F + stream[448..511] = E7C44F44E06321A20E25F73E2069757C + 90499DB7E60025CF6D2D445E53A665F3 + 08EC96F6FE73C0AC90D7E4A712E18C2D + 3DED46DFBAFA24C4B0B329E52C525976 + xor-digest = 22035341489FA6EEB2A6488CA42F4043 + 57477C3F55569A1224EC39B1019E90C8 + 21D37D78ED4DCEAF6EA70724C3751760 + 38CF25DE4F84BABD80424D83A310881B + +Set 2, vector#135: + key = 87878787878787878787878787878787 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191 + 3C69F2275EB97A1402EDF16C6FBE19BE + 79D65360445BCB63676E6553B609A065 + 0155C3B22DD1975AC0F3F65063A2E16E + stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB + 3373B816DA256CAAC37914B0C161E4E4 + 5F5ADBE444098A5B2A4CFD4251D79918 + 987BB834BB50F0834EF4985F356B92A2 + stream[256..319] = D89642D25DF97D149AE07EA18BA39497 + 8935978AC34C1DF9F444986D7505DB4C + 7E08DB3616B84CD52E7DD7FB108C36B8 + B50C2573172F4D3500B6D62A9D20B82A + stream[448..511] = A2C17FE7371604556F796429C6BE0688 + 8611638B310F3E9FAF484BA9EE29C16D + 2F842EAF33AFEC557B68D2F453569187 + A6F4CD204A0E7A733E81AB7CE9FCAE81 + xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B + 6E3A61977A7C6AC2F033B826AB9A9957 + 66671D2A1025CDF8E2824B2F58CB221D + 2A68679239D90152FF7D0D39B33FAB93 + +Set 2, vector#144: + key = 90909090909090909090909090909090 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6 + 71A6D390BC7099A708D370DCD0E3D143 + A0334619EBD5C7DA9EF6301F29273F85 + 2DFA3C580ED65C6E952F88A0B7FE368E + stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B + 445792061AA0539DA69ED0B77B970C0B + 482156A5DEE4082A61364BF06E692399 + FB9F4411FEC515291F8949B20F57229E + stream[256..319] = 993E815F299D4841518119BFF88F6EFB + F3DB9BAE60238BDE2845DE4DBA6D79DB + C9E42BA5C3C004AE4546FD86C660FFC8 + FD6A8A349669FFE3D9E5BDF8E50A407D + stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2 + 1274F4A6D814B5440C74D53A3FF0735D + EF01B14AE4188E215CE7337C04871688 + 7159695A241BFB9D6B489FE9E23B2AD8 + xor-digest = 0BD5739ED28778023E6303FD88DAABC4 + 0FA0A211A1A5C5F230D9E67DDD9EA517 + FEBCDF0BDBC107291B6CF3ACD8B862B8 + 4BF15400493A54036E97FDEBB9A1DB2C + +Set 2, vector#153: + key = 99999999999999999999999999999999 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC + BE99E7E515650511FF7016A0EF287ADE + 5A03839C4F83F05FAC3B0B24D4E3F602 + 3251F8D9CC4530A805F8A6A912EFAB1C + stream[192..255] = 792823ACE2C0DDB266A118068AE295CD + 716E424D3B98A9DB2501A3F5DF7DC70A + 3BD2C6E664D5E13317D6F57B8774C903 + D407D2BB6014E0F971141E89569C5868 + stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB + 304C81FA9DDE0C21592247C4098D9347 + 1DA30294DE8C100E5B17A199F744CAC2 + 4E33490FC7F223FD6B4923056117C6D9 + stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59 + 349AF2BB1DA2BA622B9824F729929098 + BD19DFC05D0D9454F604960C027752F9 + 7812E53DE6AC6CD2751AB331703646AF + xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2 + DC458E7E517637596FC8FB710E2E5636 + DB1F14848CB12793D54ABD0856B22F3A + ADFA8C33AD08B8CC5292DD76913CB105 + +Set 2, vector#162: + key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229 + 8A8806402755660C4A30CD216A500BB6 + AE975E08EC62D08425A8A62A71B00215 + DE35E5178902348698528CB82296F009 + stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C + E4F7E1B3E78C3A5DF07592F45B968BEF + F95B8B257DAF2B468284627AF4481FD2 + 67BE0B164DD86721DC8C1607A0607EF0 + stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3 + 9C056162B626F383F3E77B5C98C0FBE9 + 119A7C335C333E6490126AC2510CDFAA + 86441C72D1DD9ACBCD3FEFC0D0C794C7 + stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754 + 246C065AD23A8D709161FC74B34E23DB + B918EAFA4465125D3780BF0B5803AACA + 037AA0A14D977141B611A6CA2278B634 + xor-digest = FEFDA1A6E95920B93380CC24FAE214C5 + 6B009ADCB176D519CA4B8538EDFC95D1 + 6CA06B730B28A230F0085FE43CBEE2FA + 2EE5DCD74D66F5CBB59F256CC1ED885A + +Set 2, vector#171: + key = ABABABABABABABABABABABABABABABAB + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 22E1A884ED2C67CCB2977105649B6544 + 367858D1A730AA2FA96703FA406B337A + B2159A389BEF48D8A215D870B2968E16 + B11571F12BEC0A07FA7D3B9790987EC7 + stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74 + B27776E9250B8B063E52E169C7B76A15 + 0D699278AA4124427B5EB6AFC4AD5DBF + 600FEAAA98A88DFF297DACA5ACB4878F + stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484 + 976B640E60CCD6ABFB908583ABEC3E75 + 2878371EBB5374C9B37A63E0768AE10B + D857253D940AC408EF49EDD590E806AE + stream[448..511] = F012E429C44D5DC03B88123855B62C0E + 90E06759306017B5773752973850531B + C480316CBBAEDE6353AD5FB298349AA9 + 16AC0221A4CE1E4729BFB9C230AAF9FB + xor-digest = D73B872315F9052C67C4CFC5CD912DBD + 60DA32FD06D9C8E804968E688898200C + 1D979DFFCE52E1C3B3309B58D12BDBB3 + D3EBA2954D1587D720E004E12EB4A13B + +Set 2, vector#180: + key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88 + D2EF924014F7445ED922E9C021571909 + D7E6BFCAEE0724F2A9C522C4BDE4BBE9 + FE53FE592C0FEB80D2C7A51FB8BE9EF3 + stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484 + 0D22CDDFF39EB0E3D5FDF74C6E7B3394 + A0A4271D780DE6DEE9AC58B4903EEDD2 + 6DD14E14A4DFE506748D5DCA6DDF4C5A + stream[256..319] = E79D99119996FBB5163335E2F79F0502 + 7AEA5372136E7B3C5BE1F4A673A2DC74 + 60834B81BE6C4976C4A727C8E6046A64 + 4CAF42EEA6A068B7E532581E9037BE9F + stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614 + 9F3EE55A136EFA3B417DB63D2487DF82 + 794E161B3153DDB2E1E4F385E1A848C7 + 729FF5CB1CB58D5E73FAB1F2DCEEE5AD + xor-digest = 2F3C231B0228C274255F3BD314ECC7F3 + 1B9C49177009AFF2CD88F807092D77E3 + C74C1B9B8650F581EC7603F4D6E70955 + 1B00C3192414C04AB0AD8B0B9BCFE988 + +Set 2, vector#189: + key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410 + DED6D4E331633C5621B94E7EBD15E856 + 04AB202A553EFED55A548C7AFFCD2550 + 60315FD50A305D8BCAC9C077229D34AC + stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF + 3CFD130D5B6A9CE37BEBA429AD137A82 + 44D0586FEB16D086F533D1885A82F73C + F2AD2C645591F80ED09942F0A08D898C + stream[256..319] = C214B6AC700164FA66DE346A27A99463 + C5B6C0E43A9057384BE168E163058FCB + 6E7DEC871C6531EFC8B8D581EF92757E + 219294D39E0C9C8276440BE56C3D9941 + stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE + 4C8D2171695C9CF97E2936A8BB320670 + 015825547A508EB43D96F2EE1EE2CB34 + 4E120F001500F8ACC3E19E30455D09D0 + xor-digest = FE5928C74EA21F23E29171E5AAACA20C + DD8571E907763C96B99A8C11F9A1D2F5 + 78F68A6C440996995F7AB6E69B3CCE33 + CF8CE0C16F54355696D47DBF82EA8D56 + +Set 2, vector#198: + key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 75559677D7C762F6CFED942D800F2FAB + AB5F3892DC2C79922E96FD34FE511C11 + 251C8EB7C639E531CE08A8C99F62E7BC + F68FBAFF99D62348FF91CCFEC2710055 + stream[192..255] = 149806A4D862EEA81F0208D927339E5E + C98E9C2A6E0DB85CC0380DED7EC5B8AC + 4ADAE76AEB9C7B7264C3834316209615 + 25221D58C0174577110596FF89C8FC69 + stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B + 3CDD19BF89B31FF75A814F470BF97E0E + 1293B750B769F5BDD750DE5025D7534C + AD541A1F26C6AE9AC2FD3237C156AEBB + stream[448..511] = 0958243E88921B81F04AE63658E52D76 + CF2638495B3A6B970633A7C8F67B8CF9 + AC378082F72FC63BEA02881CC5B28D9D + C8C261C78B2872B5EBFC82336D6E1A28 + xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7 + 0028A08A00EF935C06A8B3632DAD5914 + 84E44E372A753F8E630741266C0F4218 + 4923608103042C70ED4ECC5112B9AF6B + +Set 2, vector#207: + key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28 + 98C701CBF5E88F1F3DCB6B873E5CAEEF + 23024ADA678E1A2CA9E25AA8B476CF4F + 9FCBC297FF03A9B94A5A736274EA776C + stream[192..255] = 73B9891D1770289A67D6338909FB6282 + 9A425B7947FC30DC52B11E398E85B1EB + 537E1C02898FEBFC15A9172C254CA55A + AA1B56EA856F47E37E2F252D92D94ED8 + stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4 + 38B63B9F436FE00CC075C585297B8F90 + E6062358D29641FF9C28EED4A23FC53A + 6B5C60C2AF1E8146DB27CCF5F43BA838 + stream[448..511] = 642541A9733946827D79BBD815C03C17 + 6357BD6E81E9A61FFFD4A0BF6863AC71 + 72AEFB92C1F235641BBE1457B724A6AA + AF9FAC687552A778B034C4A4F8E41ADE + xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668 + BD0BC5A97655978E79056B3D25DF3E79 + 5D5D8BE5D1AAE877F2E7D03225CB6609 + 6EFE11CBCB728039A243E326437CE73B + +Set 2, vector#216: + key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F + 1F7BDFBB81428FFEE9FBE14DF5F5F3D8 + A044EF53A868D989E16165A0F2B95E8D + 83439BB4805A125AD0CA7994AE11B852 + stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184 + EE7A7F4B822A1C955A69E238022AA313 + 276C2003E27AEF1B4F94B33A6428685B + F048B357EAB297B7DD98E612F054A317 + stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C + 978B976BE1B6CB0D15C0324D6B70D265 + 385B615B3EA97A55D94C47F53FF40861 + 4460857AC9568556AE54A52546B41B5A + stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6 + 5BE2BF56D2B78A401D5761E2F3AF8B18 + A2B1089864999D9B99E5BF6959F8F802 + 975FBF204D6159CF23F3706CAF0D9BA5 + xor-digest = 0957D6887501D4360C430614B67D99B5 + 32849E2F5C69CE8A9F3F707A2B5438BD + 0C1237B5617FB525CC9C043A10DBB265 + 3C3F0A353E89A19838B8F68542E09526 + +Set 2, vector#225: + key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A + 50CF101BF065F69F3E78BEF5D689B1D1 + D306FF41EB3E78BEB75C4200937CFE60 + E89E370680C519B2F64E23516ADF8062 + stream[192..255] = AA30580A210B87727BE17EC52AAAD037 + 3E0DD11FBFC89B37825CA4D6F9E8D433 + E3EA54C37D678B58CE834AFA310F6D4D + 06B4603F12DBF38595AC76511D0B13CF + stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC + 8FC9B09DAA6F418D3434BFBBFF6BFFFB + F93F8A963F2F51CC487BE868F010EC0B + EE17A480542A301E33B36F59BEE13D91 + stream[448..511] = 672048756C221C12DA6178BE711B3371 + 525A92BC9A219CABC5501B0DA4CC248B + 8742E8BCBD6F5A1CFE522F3DF3BED6B6 + 5D60D1AC737ADC582C2CB9751521828B + xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB + 3F418EBEB69509D69B2594E964759D15 + 104F674CD44681AFECC3B4939CA0A0C9 + DD7AA5726653ED3FBFC833DDB0C87B42 + +Set 2, vector#234: + key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 2479A8F2872A813D16D15F060D300237 + 25297B812F6F3B97D74D9716E4403A5A + 684D2BFD1E15275470FEDADF1578277E + 44C6C06B8A5FCE3D0CCC5E13BF49947C + stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3 + 132D4B0065A563288F848E05EB45E48B + D15C069C02F90B4FC10AEBF1AF4BF90E + 2CF7F48C8CD7A8091014131EBC21FBE8 + stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C + EC170B064429EB832924CDA9C47B5174 + 9BFEF80D96FAE36DDA65659FEA1CC06B + 4EA3A1601A3304AA4DDBEB62381FD4DB + stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145 + BFBCDBAE19F5281CD0E6AA37419778DA + 64DDF68726DD7F4D78BBBFF4576C2AAD + 93F477A2AB2C3CA8A381F30BB944C7B0 + xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070 + 9EC7E9B89DB8EEA11045ACC5FF003DC9 + CD3318BB6F9675EEF20E15490F525066 + AF8380C663B60EDBAE30663C94C39892 + +Set 2, vector#243: + key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CC3701E703946194401D1BA23AD99B5D + F3F856138E142D4B9C23DC9F252A277B + D62DAA33A71A0C61079AD5A20562291A + B6EC92C66D7BE6A17E27D4DDB48EFD31 + stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903 + D565423614409AD11E821B83F5B35D83 + F26F3EF9EC1766FEA9C21C09E0AE248F + 4BA01E48BCE09D06471593B3466703DD + stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF + 96CDC215EF1A62FAA29A5608C852FFA1 + 18B473C5A7319446F3ED2E8AB39A533D + 714325D1B14E838C9EC6E037DB0DD93C + stream[448..511] = 4FF3B43841B17A279002EFB07324625B + 7E937D480DC73F12836195110ECB4DB5 + CD31CA4F92F612A95E82815328DA7D5E + 4DCC5BB6791603EDA64C57B5A5AAA04C + xor-digest = 9202B874C48D4B1A9E857E645EE8F884 + D971CE97923AC024ABEFB944E34550CE + 31712BB832F9174F86FCD369E75CA9AD + 85095F43A4B7F33AB641BD6912D2C59C + +Set 2, vector#252: + key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F374DA745A5CF93A567027609E5D3B1D + 5C3C8A4D15203705D978AD42279F6548 + 51FF713F5120CC93D044EF717F5A75E4 + 98DBEF559E5F157A8C819E213E93B3F4 + stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9 + 175AEAA99D55485954B265B5CAB86509 + C810E664766A8E6C90D4BEE3A58B1815 + 9076959FFFA2F30EEB12343E9E7778C5 + stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC + 418DA96336991A27DADA74FDA987B867 + B125C53C0E4E2889FDFEFBFB48797A22 + 2836B2EA42793CE2BFFD568F6234B368 + stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36 + 4CD2D730DC8D7E183EC55A777C2445EB + BA7E9CD95C8F3A206B73C422AC2E2C08 + 15A8C6FED156FFF93B63DE512EF69725 + xor-digest = 467EDA43B849054EE747A532ED0D9AA4 + 6EA1BF2B6AF19F481D6E3D55EBAA96FC + 6629FE65B5EC4B5EB6A155A6D60FEA32 + F04F8230E26390F1C8FA53D47B68FEAE + +Test vectors -- set 3 +===================== + +Set 3, vector# 0: + key = 000102030405060708090A0B0C0D0E0F + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0315CE93BE05F88212B413335CA65F33 + 6387BA612421C7BE8276299CC178EC31 + 2143C503A9F2644685882201137BBBD7 + 3A2385F0AD14B690281B54B8DC064150 + stream[192..255] = 8B663563AE31DCE7AC61BF4943466774 + E9EE784644AA761B9D8AA9B8E04D4C91 + 75650DDF130454DD60724864DF2FB6B4 + 31F947F8FCA83F6D3B113BC413D3CC10 + stream[256..319] = 35EE3D4294E5660A99A1A1C9254D27A4 + B42FEA8CBD5C5BD8B902E1B1BFEF17D6 + ADC9B6B924C7C53D44A5C58210989BE8 + 72E532300EA9115CD2AAC8024779B3FC + stream[448..511] = 402F841F64827A197FC56EE9C180F5D1 + 075107622178407B063F70C6C860C6EA + E3016D56F7CDC13A109283F5F4FC9420 + 6C62BC3D1012EA03EE08EBE8C2DC074A + xor-digest = 6815E00D7D3414FCB103EA82B38FD4F4 + 68A453E84A520B7119E9D3A4C938BF0B + AC26F7F73EDA7F3E2F20FBA551C15205 + EBBF2F6BFE6DBAF95061F0AB3988DD57 + +Set 3, vector# 9: + key = 090A0B0C0D0E0F101112131415161718 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E695E5417AEC9FBFC0EB0909435E79C6 + 76AB8E2F28C556CC2C81CFC5F7A2A6F1 + 254EC0CD2CFAFC257907723557C1DF5A + D81D1E3D201410A12A5FA3A6160F266F + stream[192..255] = E3D590D9AF3869FFCBE2A4B8C77A09F6 + 211193F83B8A43714CCFC02D014376C5 + A44FF7C061471AE208F04DCAA89792FF + AE7096EAC47898C1011095DE9B55682F + stream[256..319] = 0F31D78C0B86D246FE105AA6D9B93CE0 + 257E75CC0D2A0BE96B9156555D8A407E + 01F47AFF719CC894EE111C32672B0404 + B5F26C1DB1D7D0F9E470900AE53B192E + stream[448..511] = 1A01733BB8EACDF2B2F4322FB54FB6CB + C92989248FF31BBAAA8304ECC4AF9A39 + CAB21BB66E0A144D8B77C537BD52DDD8 + C5B0909CC6423D4F243E5AFE6E22D07D + xor-digest = F8C3BF6905A19184D14039E4B7FCFACF + 2EFA004B35B55DD04F56199C6C9DE1B4 + 458C5EFAC45C6062BA1EB726426987ED + 88FA899849CF5F6CEF60119F6A68AF9B + +Set 3, vector# 18: + key = 12131415161718191A1B1C1D1E1F2021 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3C189DEDA71E56926CA2C3A2974C4FAA + B7EA3C1250E768CEA797ABD6477B59F0 + E5494635CB4700A95BBD54B0E93D12A6 + 423DF8F34BC6B3BE705ED6704BA33894 + stream[192..255] = F21E411ACF063846BF68F61F7673710D + CFBF8088E2A815F406E17C4BF4E839AA + D2EB9D137B0F7889E68F4B5C8160199A + 7C9C697EA6A1794E954ACB535A72B255 + stream[256..319] = BD7E1C4A54C911E84067AB00F8427810 + BDBF4029E78D424E65F477BEB457900D + 0EA49B639863BAEB1427A161B8C629D3 + 55097F5DFFB24BB97329A73B144DB7CA + stream[448..511] = A4D9A80D0055F2D8C55D2A49B39DCA69 + 9A5652C43258152B42BECDE07F21F8D0 + EAAC565DCDE549CA4A9A27D82F5AF4BB + 1EEB1B0A53A58E50C3E83CBCDCB980F5 + xor-digest = FF451365606D0117E15FC2721F40C9CC + 0FBF6442A771F8FC3B06186C35C6CA13 + B30F65FC84B9A38A6FBA2B6F16541B0A + 0D77BDB4F696894B2B73CCCB8D6FA3B7 + +Set 3, vector# 27: + key = 1B1C1D1E1F202122232425262728292A + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BE4A26D09D47D25416355FB7FF60AA06 + 3B3CDE5374780F2C66514A0CAA07406A + 88490A2E3D6294A799C9BAAAA1B10ACB + 88FF4F6F70EF1F4F67D591040244FEE8 + stream[192..255] = 54F1AB7235B6440D6A7FC7851E3FFDA8 + 6CAF44E3F57E1E9406908064FDDA3A3A + 3C7AA1CB6ECAAF376C5F290EA02844EA + 779A225131F24D2E7D34AD0342399FED + stream[256..319] = 81AC4F45FC40CE7E1FF890F5EFF2B583 + 36F71D1911C7E0227AD8E4DFF7369B41 + A8C266B3468A78773C4C40A3EEA6B724 + 97662462F48835FAC7B6C77CEFD39A65 + stream[448..511] = CACFA9A51224F533C600BEFF1EC03C7C + 7C22EDF93E8596128F8709F0CED4E291 + 997229AC5542FD2CC9B1167C3D2BB57D + 9B08B82C0FC41D93B7CE2211C5E2D534 + xor-digest = 0D949205B6024DAC1D215F2AEA7CB484 + 3FAA9A1719398AB8828A28BD2568369A + C78A224AAD95BAE6A6333C4C13D630B9 + 42AA52099F6EFD6871B1E45C8DC68AC7 + +Set 3, vector# 36: + key = 2425262728292A2B2C2D2E2F30313233 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 65906EA9CC0080D2044671D22C7DE242 + F764184ABE8DADBCD550225BFD541D6A + 762C7A5268EA0ECE51D18269E71A4CCC + 054AF634616204C81AE7E515719775DF + stream[192..255] = 9ED75834EBBD9576E11DCE8C583ECEDD + 2B8780FE98B44E9F08BBE96922C77BEF + 08DCE0DFD7C77C42236885BE6EDC8343 + 24EAED350AA5A513009272818CBC4BE5 + stream[256..319] = EB1D998260B3AF4472DE59E1C9DD359A + B346B32DCE36C92C9B7BD808BAB76AB1 + EDCA2827557501BE0FE28F6498B33B9A + F4EA48786F3158E8047A32A03AE1CD90 + stream[448..511] = D06B1B9B8110FB9809F5887A35CB24BB + 80EDE203AE648AF9FA348B18D8A15B8E + E98E8AB98A7AC5BF71FDEAA1A6E978F6 + 7D5734AA7FA88E8DA44C861E2F54E585 + xor-digest = E77DF8C1D5F46F8896DD00187C840B0A + E4404581DD053C6F39323815729DCE90 + 0D85C2D8C97D0A3B57CF622F81077B80 + 92988EFFA36CA176F7393D1E38AAB206 + +Set 3, vector# 45: + key = 2D2E2F303132333435363738393A3B3C + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3FBFE9A391DE0CE5AAEBF9DA3A15EB99 + D6CBAD0341CB78042C89F5D5B0B555C8 + A400DC47FD19F40493B348CB51430B44 + D05AFCA9D399709EFAB8ED2587F72E85 + stream[192..255] = 68969047EE54910C44F8B5718E993234 + D814C27C0B59EE09F0D35B58352AA6C6 + 594F605C25C16CDDC29A354A1C6F5948 + AE497C093E2D41C211E4C1417DFAAFC4 + stream[256..319] = 0DD68E08A25ACA4448DF4B562EEBB855 + 14E41F1F560C479542FE62C2DCBCF03C + 30AF180FB71E65A9A09C551551A33942 + 53558C2440084E6B4CB664A4EAFCAB66 + stream[448..511] = D93B80D67B6484030103CDD72536E695 + E7BAF8B1115109D5D5517BD1E06F4236 + A3551688F5C0D78B2CB080AC072B4C48 + 94A2AF54AD9D816E2068AC569BCD2AE2 + xor-digest = 7C071BF395B48A023A7B708A9651EC8F + 0C9A00DE8BD9D0764C7F1F394AA2B747 + 3EF87BF792D5B89AE0548EB9C1344DAB + DF2E4EC6064D50EE1622160D6DD7ADFE + +Set 3, vector# 54: + key = 363738393A3B3C3D3E3F404142434445 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 64468807E7EFE78E11B0231D8D7AE80D + BFF3FAE444A60496C8F2DA202941686B + 95C48457C1F9DE1AD2FE581336AE36AB + CA574BCB9619CDDB96E4499409516635 + stream[192..255] = A7DBFEAD9B969D334705B6C53A0CDBC2 + 21E0BB92854B0B107CC39F8C6E4761C3 + EACC8D8C5741AA4243C5BE1A79971A0A + 5A23F2BEDE9F3628CB9099B8C7EA9324 + stream[256..319] = 1A44FB18740973F3124EA805C90C4B27 + 4EE788D43F4B894B01F63C13410EC204 + 2607241E87555B0E1A6FF33AF0DB010B + 8ADF607E6353FCF74F568E0BAF0F4455 + stream[448..511] = 11568B95495E520EB6BE106986A07C57 + 8FDF21463607619E5AAF117D84611E75 + F8979F59E60B43C0A37BC24429892742 + 0D206274DA45EBBA7660422DA45294CD + xor-digest = A70B9BFC683AF2716E17980A49C4F747 + AC25992BA7BCA5E5C2AE162497E4E8BB + 62C837F64EEBE4A55B5705F115CBA057 + C560B1AF0A733B5631E23442601A741F + +Set 3, vector# 63: + key = 3F404142434445464748494A4B4C4D4E + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 35865AF843244DD2F95CDF7C9BD54471 + 9C8432538842C28F93AA21F6E10F8B18 + 31C2AA7EC010A66E539CF65BE55120BF + 090233750995003C7AE414DA6D55F86C + stream[192..255] = 190F215FD14E44CD141E47A2322D324A + A63A7B512A77C20A02D3BFC1EF8273C8 + F65226CBD1BF32A104D1AFEFD6719E4B + DD6355B044EC8D0CE95023C61007E6BB + stream[256..319] = BD02130F7CFDBDBC2171BBDEAB501136 + B2364F5879E6E9CCA7E75AD81105D9E4 + 87E9175B62AFCAD79B23D392B2E9C418 + 437527118797602E629A70CC869AB7EC + stream[448..511] = 1F0DF396B5CA6EC9767B0674B2C7A9C9 + 133CF872DA39DE78F56D41C7F2FF6B50 + 716717E995D42C51D6A2ED66FA6CC7DA + 92E9B3B4D1F130E699C430CFC96969BB + xor-digest = 70291060FEA7D40B5C3FF731FAF7630F + D9BBED1A7FC25A05E6B3F632E6FD6B91 + 1F1010E1BEC69F16D44C5183E38BE8DA + 8949A4D8AA85F5149C203F8C92887875 + +Set 3, vector# 72: + key = 48494A4B4C4D4E4F5051525354555657 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BFFC0703408DF6EB169656D09A5400DD + 9C4BAF06A3BC7220E45814104B6D9000 + 9585BF9B0CD988E94B8C5026D07AD7F5 + 7D81364775D54D808A5C18453B62A2A1 + stream[192..255] = 5FC95B73A4C91DB20B93319E420B4C5B + A9DE1873C81C835CB455970A90921594 + F9635EF4F411C9ACB4298F75B2CC84F9 + 7F52182F7F001A1EDF72A68FA1ADE313 + stream[256..319] = FB24E97B0CCFE15644BAAFF342C55FDF + 64434708407AA6D73576E842D5ADF4A2 + 6B32D329A2DC9F1451C4BF3E9599E9E6 + 4E5E65F73E09E4F1254BA0DDD8E6C52C + stream[448..511] = E2EB303CD0A67C99CDCEE86BEA581FF7 + 093C9228900B563C6D10B20BF99D3911 + D47C805D1447C8F233D3FDD27CF0DA42 + D42E0389E2CCE99A274AD9D20B9C6102 + xor-digest = F83FB58CAEC8B13BC25C152FCF24E10E + 392A197FDA05A6A20E14093EA0B34C5D + FAE102266465324F5AC07FFCECC8E618 + D0BB60761A26D5FD59D188097A2348F3 + +Set 3, vector# 81: + key = 5152535455565758595A5B5C5D5E5F60 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 84076D83A841C8C6ADDE3B5D9FDD6529 + 4D0F92B549112F0A6DE05236F732E81B + 3C8E92229C411D2295129ECD18DD08DD + C98BA78D9BAFF6271D95E1F361EF699A + stream[192..255] = 7063A52FB2729433D8A7BF30F27E6EF6 + F17C2A422E60A737270787985508D062 + 4E678A597845CA9EF939F4B8966BD99F + B8633FEA673CE7BFD2ACFB5942D7EDD9 + stream[256..319] = 4FCE866E8C2359C53F0429F569D02DAE + E99A4062246B633D4C502DC897AD8025 + 38C95D49D3B1FA94F4E92441357B622A + 6264F50D5554BBE42191AB3D6073A8AF + stream[448..511] = 2F7C38BD00309FC81D28D84EE4355216 + D97A823CC46FAB9DCAF621E4128F9CB8 + 838BF02E0EF940EFE96860CC0B996044 + 42CACFD3306335241C1B4B65E790233E + xor-digest = 44038A33AF0013BB34CBCFB77F7E060B + 96F5134DFCDBF04EB8F7F29B15C3FDA0 + F766DC940FF548C23712625793851A94 + 294CC7201E1EDC6056C12A46524C6FD0 + +Set 3, vector# 90: + key = 5A5B5C5D5E5F60616263646566676869 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E811CA3DD1DD0057AD3A1794D3F9CCB6 + 362049B1692D6ACFE1A6A0FCC99C7A04 + 3AB9932A146B4040AC9F8E2F0A227C7E + C60B1F35D60EA14483BAE1F8D1AC7FE1 + stream[192..255] = 865B05E224133AFC45043F05F8082FEA + 487BF63BCFB96DA3EE26960061446669 + B1C92C6BC5905BD1EB57D579CB62A220 + 2F35CEB603658237AF1908132A25971C + stream[256..319] = A84BE383FC852F1BF44130EAD15B3548 + 56737C7EA68A0700A22D357FBA70E031 + BDC0FE8EC36C41790A8B7706A00CA338 + 603E054A83881599D718B1911D1CE9D4 + stream[448..511] = 9286C3479F9A17B51D8749257F59E892 + CE7C3EB8638B29C17D779811F01EA405 + 257062A5F28BCDA1862FE653C7607350 + 9A87D12EDC5CAAFF9E8F9F76DA0BEDE2 + xor-digest = D629CA4708BEF7EED04BB5531DDF9C64 + BA4981C9A705D59C4B2391E94B79CFCD + 058406845D81E7EBC097330C01FCBCF8 + D78940893B4FA38554A32D861AE96D04 + +Set 3, vector# 99: + key = 636465666768696A6B6C6D6E6F707172 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B89516368AFEEEC12434F76AD1E1ECA8 + FF6FEF7B46D05EDD6041C7B8C1E3A33D + 2818E38113592B615E980304D93435DF + BDD5676225173331C3667F30AA2A3D2C + stream[192..255] = 249528FA392B19B6811711F523D27578 + F1BDE75CA167DDEC08303906B64FAC0F + B2912A7A0EDBEDAF9FEDA420DEA330CA + 7302F5780827CB11B15A4DD333FD7099 + stream[256..319] = CECC1B5077BCB9E129B01D8D75089B41 + 64E76DBC9C8CF2E4D2F17A6248522A51 + FCFBFBC992F75D613307F4DD6472B6DF + C8A5B29F1068FC0F1C3F8964B0E09170 + stream[448..511] = 8B26C436E918B099E4D3A7D4D3395E49 + 056A8A29130667A32C6A2B0FD08A482F + 8F7538ED90374846FFD2E1C733AFFDA1 + 12148C9718F3F208344D5FC20128AE2C + xor-digest = EAA0ACA59CF63BC27082BD52D6757FD7 + 620A7AC5AA2FAEC52646978E2057C5FC + F60B36C09D87419C1D1A64133357DB05 + 6B96C854F38C36DD657524FD09729341 + +Set 3, vector#108: + key = 6C6D6E6F707172737475767778797A7B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 741C607A6BD38F93B33244C8B7F05D78 + 46F6A05CEE5A87762480DE123D3BEE63 + 240928FFC75ECD9AD1785B1664DCB59B + A12F3B64C93BD4FC8C67C0934E5B0ABD + stream[192..255] = 3BDB31A701DD7F2E929803C3A47896F0 + 9E5F569A32AA829E505E34BB7232597D + B838F543A34CC288F9518BE16A228D42 + BED0CA3CE0C6E7FF9AEE63625C699B9A + stream[256..319] = 1CB7FE159EC1A57043BD142236DC0A18 + 0CEF37316A6E96354AE319142282F19C + 1550EB645DA8F7BEE2ABAE4EAAC0BA29 + 893E722A6F8E0A9B34368DF56C5845B4 + stream[448..511] = B6DF810D69EAFB7F2360F6ECB50C5861 + 7D32B3F495B3E4424045E88CFA0871A2 + 9314121CC78B98B456ADF53E540346B1 + 214AE2ADB65C552273F1FA498FA74101 + xor-digest = D35A8AE5783348824175BD34F2E16FBB + 975E7695DC6C4FF1ED763D404B0D4D30 + 07AAF01E988BC85DB2FDD017691D3BB9 + 811355C3C7A6156197AF57B794DCE85D + +Set 3, vector#117: + key = 75767778797A7B7C7D7E7F8081828384 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = EA9DA2D5BD4B6E070479ABF8CA2D1B3A + 6B968A025D010944FEB51AB2E507F86B + 111F8A351A3F32CE1FBC4A75AC34F722 + 1B5190F2390073084F8153E00BB98D0E + stream[192..255] = 0AE0DC3D0E2D3F5F93E446BEBECC4F60 + 862D190829A209966E132DD029ED6998 + DEF4F613F3D53D0A36CFBA2CFE345DCF + 013B6CFFEC0116FFC1659A57FB42E0BE + stream[256..319] = 5A7FF46C335912389D8B88437CEFD27B + 76706405F45F87C91390273D9B70CC5D + 89FDFA85E20EC82B98A79BFF5FBF6AB1 + 4F61F2C1289CD7B8357126C8E13271AD + stream[448..511] = 9398E699F5AD8FF31A50C8EFB9DF0D0C + FD612B951A203C1BF85C62AB5AF1C412 + 42BFD0A55F21820C6F917EC90A8FCAB2 + E774A93713A99C7900B80A2BF496D0AF + xor-digest = 05D9732FF20A61E19428873830DA7282 + 819234F22FE7DFD8871C21CF10C08EF0 + 7C0413898DB144861B0CCB62992DF40B + 29A0A4688C91275F0A198AF39899E362 + +Set 3, vector#126: + key = 7E7F808182838485868788898A8B8C8D + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 8C4F8495C7231AAEB704E7AB9E79E748 + 6CB5BC85D3622B8A2E2CB778BBFDACD4 + CEF73CC485D8E08406F5986A28706CD0 + 56D085201DEDB875573B57629B8541C6 + stream[192..255] = CC6374A744E9205CA39BCD678074B844 + 16346A7E54F9B87905BADD2FACE7B9F4 + B0A366AA3F632A7A67AD8AAC4827C9BB + A1E801A8786BC4FAC2ADE6A6AD6A45F4 + stream[256..319] = 4F52AAB001BE94A60761CDE0334F8A84 + C617195B084E441070E343CEC3189CF6 + D6D955F9AD649A3891BDFFACA0A6E6E7 + 7291396670BA07469D267EB80E48353A + stream[448..511] = 673AF85AD5A9A3F26CBABCE9BEBBAE21 + E0B6DCCC3256227FC0EAEDF343CC7E9A + 8896023DF073E88EEEF135BE34CF67A5 + 5FB51D3A1754B15A7C4E2CCCB4C8D51C + xor-digest = 2BD4B8BF9B7E79B0EB53318396B03575 + 0AC918A6A05BBA499D81C9EFD32A0FCA + 34A83FC801CD6475A774091F33AE7689 + B9FE28645F545E9A9531F528085926F1 + +Set 3, vector#135: + key = 8788898A8B8C8D8E8F90919293949596 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BDF2E95B80FDF304C3C4A8081391EDC9 + 7F9553F93C27788F03797EDEBB8F59EC + 2FB2FCCA7727CA1CAEBF5C8DA8719492 + F1369D96B2FEFA23D89400CF7CA667EC + stream[192..255] = 6AB7500D876A4924DE59800345AD69FB + BA1690733713BF372E0108D9FB65B0E4 + 50BB89899AB84198381623094F823FF4 + 8BF9A09F0FCA23684E78654F3D231173 + stream[256..319] = 34ED638D249BB1AB8B16D350309AE32B + 9FB62CAB0EC7AB9D5F3C12C9A6502497 + 6323EBBBC4CF308FFA68A3D4D8D3959E + AFD3BE46E36072FD15A5DC3FCDECA6D1 + stream[448..511] = A8BA33AF6CF545424E607A7FC4CBA593 + CB05B38C836B21D85B6FB1894926A459 + 8D71AB424A5A582A491747FED94125D1 + 08D6C693EC9E4BDE2F418810A921B54F + xor-digest = 84F29F11524741D39779025D792AB735 + 07963EAA0FA8EE220ECD3592E1320567 + BFE76EFC3356860192DDC5F06B94E552 + 43D659D49FB94C30AB69AB5E9C370A5B + +Set 3, vector#144: + key = 909192939495969798999A9B9C9D9E9F + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 1C03A0D6CB75670CD7D978B2E371857E + 27E597B15B905D5F4F4384FEC227073B + 5A56D8C0C4AF767F267DDEFF86AA036C + 41EB6170603AEB3E3C1EF3E176CED812 + stream[192..255] = 6447D1E067550DEC9E8AE89DB02B85B4 + 3DD7E511C8B98438BAA50CFAF7CDBB68 + 757DA1D03A29B9EC6BD633E17BEBC8EB + 2D8D453F583E4D183AF30C9F47C8DD56 + stream[256..319] = B324756101C28D9FC4D1F065F1D000F4 + 1155514EDB30A7FE36C26B18FD93D6D2 + 0470A41B6F8D2E8BE140568BF72223F0 + 981CEB9D100B21C8B751BA6B2816B2D0 + stream[448..511] = 304AADCAE0CE80E91E3558974A944663 + D1E2253977CD7B0D1BFAA138DD81A501 + D7EADD8FC834931A44642BA9873AC1B2 + 47A454EE71F7AD8671BC15E088D01532 + xor-digest = 5980D43A91C09B20B0F3323F1750CB47 + 118550920627B6C512AC5CC53AA6AD25 + 68EE1EFE702FEDE7CADBFA25B32696FA + 12A18CCDE35A1B679F709F28920DF92C + +Set 3, vector#153: + key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C2083A758037E850A6FE642EFDE59AED + F51F3002BEE2E69DBDB538BE2D93EE8B + 27A1CC89672DC14C44DADE531A88A769 + 5DC730A2CDF3096DE7F4BD08A1ABA918 + stream[192..255] = F4D19950E6365AE6BE8011A24B9D803A + D9A8547D452D8B0B8C51676E207DF323 + 808B5A094A2FDEA5DBC86BFCA576E98E + D0E049834CBE0B3AFAD6892B542EC7AF + stream[256..319] = 8F2A026EB2165F39E27DB86607878926 + 4EC8F42A09E8C80B317FD4F1E32AF4C3 + 73B7F5160C635ECABE495B01A3488E27 + 94D226E2D86C4654810C08B2FC42610D + stream[448..511] = A1D17725577B7A4FD3D1A280BA2B5C0C + 386FCFA09E110F00C85ECA05CC142644 + 4D8EB87CCDC2B23D1CDBBFFF822B5555 + 11055B93ADC9168B7353CAE10551AF14 + xor-digest = 7B4E8A6123216818A218FBD50D8540B0 + A0B62DC114F25DD476680F85DEEA9306 + 4CBC4526C7A8832D4BC534684A403FE7 + B80E7F20D967ECE044085B554C158AFA + +Set 3, vector#162: + key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 6FB232154275843C74BB886D09CBE0EC + CCC539DD6DEC1EC6F31578B80DD3BAD8 + 5C992CB1A0B4EA40B3EE0C5174E36A74 + E1CDCAB13830453984E4365A6C599F72 + stream[192..255] = 2682C05E19F6D8FC4DDB15B2F8385B52 + C5A4A70FF5A0063CD696AADBF8505122 + 6F696746D4F8C314543BC3869B1E7F9B + 1C0D004655FB6585723CD1EA7A700A60 + stream[256..319] = D6BA4C5A33B8C2DE342DE48E26AE7B14 + 8E91552D0E05AC9458ED0010E6FF53AE + EDE70E910165B5986876799E60B7E6BF + 3109B9BAF7EE3670497FA7CAFCB14733 + stream[448..511] = 70C4E8AB8E8BA681A2A06F319CBC952E + E3E78DA589369FEEF8A6BC6D976BECFE + E6C7143337758929FCA7E0945892411B + 047C2CC2F2AA284E95733DD94D46B89B + xor-digest = E2D3DD6AC908FF3BAE4791A50F717B63 + FB3F1F380CC738E2B1626FD026C9BEBC + 33957AF4ED6E8B9864EEEAE262FC6168 + 9A34FA14A35BD915B6945F35BC3D5573 + +Set 3, vector#171: + key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = D25BF02A1BB050E0D15246C2EFB3EB89 + 390BB913916D347586DCDF71D6792CC6 + BF72F6F6A9B779BD8833C468684B4480 + 52E153D11A0CE183CB337450C4482F6B + stream[192..255] = 07980A2C57E9094C5334016A782C830E + B59420086EF9D36542A97220A5EEFE42 + 026B39B1F00A78992ECA17FCDDCEEA2F + 88A15F934A1C65EFB770C2FB9712FFF2 + stream[256..319] = 8C0AF45C68CB7CA8CFF1AB18F2F9659D + E49DB5C4E3609B50C06F94FC01C059B5 + 40E302FA8604F030701FE3C833617E0B + 094D0BBF10580F7C1C7047E86FBF93E2 + stream[448..511] = 4D4BEFAB68D63085A05C729F54468567 + 2C2A9452DF6B4B651A29FBC29513E3C9 + 635DFD75EAC87A5B1362E99033304EF5 + DF42420DFD49C1830D66F4F90928F1AE + xor-digest = 9A7DD8AA5D9E9DA4F34AFBDE9D909CE5 + DEBC05D2F930FF08AEEE4096B2E1E453 + 8587B88E535A217E986F31965C5965DE + 3BF4A7F99B3B9D938D2C1AF7DFEFA14A + +Set 3, vector#180: + key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 5FB2BFB5B9CC4F84D7641B4555DA4A7F + C07C0053E7AD2CF2187F7F34ED4068AC + 6D5B43A5FA41437C05C65550786D60F9 + A737F44BE450A1F416C1B1A49890C609 + stream[192..255] = 8EDCA89958225E39CF796EE587877A55 + F9B7A7381241597CA6280F7617A11922 + 9268F95BB326585AB59F08BFCE8B5638 + B3A0D32A761C796060DFEBB5BCE859D5 + stream[256..319] = 09601C099BAC574564E4CC6FD659776E + 4726FB22E0025C37873042866B913C03 + 285EA24E37847F9AF6C838B82FE651D4 + EC5FBD40A256E6C765757B6A3CD08C92 + stream[448..511] = CA5AC4ED4FBEF0D754F033B5267B9FDF + 3CA52B131E118174F70CD4F833A5ABBB + 198DBCDF18BABB0B0CC37ECFC8D93AA1 + 5949FBB21974169B46D545F0ED03C71D + xor-digest = 5DAFDEBC75291BA8F55B4A370756B28F + 554FEADDB7888F2834BA1EF221E917F5 + F631D5BD789701282DCF16FA450D250B + 52C627741369DA654E237B8D7F4A8BA0 + +Set 3, vector#189: + key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E9EAE6C4903004A2AFCD05FE2E3E7F95 + FF8BD2888C4AEBB81CDBBCB7488C54E5 + B50467FA82B0CA7EA923C608074E1B45 + 6452821FC36789C8061E99E8A0C0B579 + stream[192..255] = 1EC898A6958F23C186261F833BB3EF0B + 3C185AE8138311B6AB42098E9C6C7FE1 + 0306DADE1DBF2B1C3215DEBD88AF1CBD + 2D805B8006FA0DCF136E225AE3D91AA3 + stream[256..319] = 55566604D1C85FFE1D29810B6C49F019 + 69ACB59765A3FBA2B0B9880064606E47 + 18BC5F08C32EFC250FEE91FB88077A2E + 0840615CCF627C64FBB500B7B800B9CD + stream[448..511] = 707821EFE4119A32CFD99F7ED7CEC018 + C8EE90493FD9268A83E5482DAF9A646E + 8765D8199A56A12ECA50775099179D70 + B72A3CEC8F0EFF1AFD074F04548874E3 + xor-digest = A51E3C9C948B68A1543FDD1F158DD419 + 195AE7662739446D9FD543681A866A6C + F09756FF4E0C59BDEFFBF98D53F193A1 + 77D7BF19320063B8AEEC8A544D5D72C7 + +Set 3, vector#198: + key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = EAA9729F0222A16C750540C605974B55 + 4FA622F67C71FBA40236A71AC19706F7 + 9E3792F4B444A39C9C1C902FDBD81898 + 096338F6A8EB7C934B9558D48AC53301 + stream[192..255] = 3B5E53787C050061000E3622876AA126 + 00971A76253833C53B9DABA976169395 + 3944B5050AB17E492E185737D67581B8 + B1C766D50C5B0C2B0D8C78A781E77D89 + stream[256..319] = 175C28764FEAF8396B3CD34C829D0D0B + E9CE0D75E79017A96C4E7B158B171BE9 + 4C906FD4BD4946E6DEEC3C78B34C0754 + 9E85AFCD958AF345E0B432F33C86AA76 + stream[448..511] = 37BDD665CD9D5A8A8190AC3EEF981379 + AD5311E15F853A8A89840879165147A2 + 807AFABB6236CEA9319DB32344987889 + 5744A506CA76CE69D9E474840529D667 + xor-digest = 4CAAE8F441F6EF3DB6971E274181F8F0 + 4D7BC603E040833E77921A393EA13F0F + ADFF07AEC94555224F6204874027106A + 6D7DDF0546F300D3E84AC87699ED40D2 + +Set 3, vector#207: + key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 83AC8C40850F4FCA5452871C954AA61F + 31A9BD276D39EEC03EC5977A71FDAC38 + 368D110C57C1A19F2A7461BBFA88E372 + F78103F9FFAC1361AC2D2AD84C6AA3E8 + stream[192..255] = 48E95C2FCFC79C91BACD0C41F626F05E + F80E076E359299EB5272A2F688F96F6B + 3147C5A19A99D562A11E953CB2A90911 + 205A7760B5C8CD959EE6C183A8C1420D + stream[256..319] = 974A4DE50EB45F6144DAFFA6B4A68E39 + 48838434497B8F9700FC42005F3C2FB5 + A79984CC2E770C5400EA21AA4EC05751 + 80A288499879E50462225BE03D677875 + stream[448..511] = 09823B2D55E26C49E42FC0820D7BA081 + 5A7EA9380637A2AE2C0D29253EEDB884 + 9BF4F54D64677F08A1763EFFD904B62D + B3843B0ADE885C00640D16A99E28DCC0 + xor-digest = E73D8783F926558E0C1E1B0D3FD86CFA + 974CD70EBAACC0CEA2D977E9AFCCD384 + 935584D2FFEDEA813E6234112CAA1401 + 71E99BCFE61A7D0E430D4D3F75AA3E28 + +Set 3, vector#216: + key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 5DE3EC7E6D724976985B426D722D93E6 + 1F40F5F17EA14B298AC898CBD69F2BBA + 5705E1D0CEF7B7122362FCC0D5106D54 + 25D51F51E29C938C592D9E862DEE9E33 + stream[192..255] = E079C49AC8F160A9D529F30151AAA7A3 + 1D137E03DF4C23F8734AAC3B20BF8520 + 90E3C2529761EB4D67AEF1CC46399947 + 1240DEE8343D6355B5D7377A7934B019 + stream[256..319] = DF574E03ADD1DCBD0712D2748C93CD72 + D8488396AE3D3275E5A53CAF3EC112E9 + 50A79494F25B9EC111FE9A7A68A5AEA9 + 63A4F87B37F822B79D954436368D8E20 + stream[448..511] = CCEF4C93BCEB2494EB4C70F5E301E980 + C494AF8C117F291DD09E3960D2C5A7F1 + 9928C08F2F51C419E734DE9AADD25C81 + 3579A7F0B8B367A49B97DED5793E4DCB + xor-digest = 868706BC1A5F3D0BDF96E10324EC36FE + 01596216B0B8BBFF69C5BDAF69D0F38E + FE89FFC32D34D142F413A5BEA7AB38ED + 22436C62F86C540101DC0267FAF67904 + +Set 3, vector#225: + key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 45A0736DB4A28A3A6DD181FEF3485F2C + 918C65663597C49F4FB23CA550C77CAF + 7B331B5D183844278E0D959EA024CC21 + CE1A84923E6E782472BA1645BEDFC60D + stream[192..255] = E9EE0DFD717F72FD8899D23E87E77DD9 + F9DA66B4645AAD8D8C3B489B0A637449 + 80020326469B4C6403012B6E315CD35A + 4344934D720467F30B61C8AEE5C3C342 + stream[256..319] = 94A2BA2B744CB83A29004AE21470212F + 67C2FD18F227FC017131D7F4DD0AB412 + 48C59BADAE2E408584DF35C603192E37 + 344C52664DD68B9231661F304F483F41 + stream[448..511] = 6A29174A1099BF8759D2F5F9BA60816A + B290252AEE08339BE0021033DED03C46 + 9C8E28AAFAFDC67A7F2219C8942B004E + 47263842BEBB47EC6B0666ACCC884591 + xor-digest = 7A7411EE5D174907B1138575FCC7479F + AF3437BBF098CCB5D8D25F49E6788374 + CBC9CC5812982CBEAF59111813430BEF + 56D9DEEDB6C935804013759CFAAC40E4 + +Set 3, vector#234: + key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C430C2A9FC44DE1563B1679C1A2DFA98 + 91D01A302C5165EC13B26F6EE4F25437 + 264AE9E18C98BE112BF560C72024827B + 85665C491C47BB396B5AEC66CFCCA371 + stream[192..255] = 60F3A13B9EBF8784CC81C132E004A179 + BEA0606D4C2C830077A50004FB0487E6 + E179D81FD9784DC3783ABF86523FE4A4 + 68930272980E3B46F865E4729DD34773 + stream[256..319] = 44BC861136F6856B1C74C1CC13753B82 + A75E34EB40C518400B507D99B42E488C + 8A1F2F590E029EF48DAF2674FDB053AE + 5C0967923102EB964602256F70A9CC9D + stream[448..511] = 0EE3ADBC4CCC63A8B67C7812CD294183 + A2E9D4EF0D65F854FE66CF9D76A34F91 + 867B27336F8EEC2E2CD30CCB98AD5769 + 77B07C73C833B51753BB9B0DF08C4834 + xor-digest = 7F848C96AE9310B5282712493AD7E13E + 2B4581545E625A4DCD98576C75835058 + 6C621244B6CD439F8E62625ECD9460D3 + A18BC2F5DCD9FA7E8CF7880CCFD1A44C + +Set 3, vector#243: + key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B9B3501C75EE296AE858573B63C4888F + 72B18683CBCD6B95602D51E4388D6DD3 + 7129169A5209202E2C6EDEB5026B6511 + 55E4747DD706DDF248A8705D50D38A29 + stream[192..255] = 12F90D1028010D8296DD0D6ECC4F2354 + 89856C315555279BD0A4E3161178AAAE + BD849EC0A90903CCFE9DC7CC821C1CAA + D63A45A1D0C0247F1FB1423877FE9A32 + stream[256..319] = 9F0608162C6315D206B5EFB0E40291AD + E882445B9F34154F6E21B9FA23356DD4 + 79DFFB16482F6A4F28A8A0629E8B1D78 + EAA473CB126FB3727B826B4B3D6175E6 + stream[448..511] = F26FAB00C37C03AE33209E19F865B135 + 115A5E254A6B5C1A4896987EAC35C2F4 + 327822E165AC6BF99F535055ED74833B + C1FFEB32588D8995CEF0708E2D3CF832 + xor-digest = 87243F1D4D08D7EE39213D1A4B9E2458 + 368339A11E364345B4367F84154B36DA + 03A3728A7EBD4237897F9D1A19CCFE92 + B9D67D3A4A755E6EA8382041D4827A17 + +Set 3, vector#252: + key = FCFDFEFF000102030405060708090A0B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 05A90DAF1A6B6B60CD3B999A11FEEE39 + 6D38983ECDA326EC9229D2A1EC722B0C + 3C0539DDBF6A4CF62B9BAFEA6C60A29D + 4AB63BBBC88987E9A74AE2F71B1E8DE2 + stream[192..255] = 0AE6673D9F99C5EC9A4532B2B9786CB9 + E948A206CB992335FE868BB2271DCA5F + 9AB75995A7E7D46F8EA6693765C93D90 + 9D41C24EF4856252986DDFCBE65D2D11 + stream[256..319] = D8B07A866003059BAEE90378AD5EFFD5 + 2732755E79402B50BA0F26A038B3D9C8 + 1481C19080CB39FE840F8E7313D0C034 + 9FEA4AA4801225630AAED3E522D6F920 + stream[448..511] = DED21140E5A3C0C4615D7153DF9381F7 + 269616817A273BFD984AA5E7CD9D9CA1 + 9C28E51F4C03C262F5BB4175C799236F + DA69AB27590857C0F270CE4BBFE02D5E + xor-digest = 2D47DA3161389F5F54FAB37F391C21CD + 63A748112A1AB415670524B6CB93DA0B + 6B54C541ED59F3A54DE238C3FADB3236 + 3871F6DB1A507B33C1B8F280B0C04B1A + +Test vectors -- set 4 +===================== + +Set 4, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 114265E078311C062B518148B4530F73 + DC9B95DCC41C214F8C9486473DC46847 + 71819020010586A750426A0E633BC787 + 6E228E2353AC0A68533C85A742387800 + stream[65472..65535] = 196F53D41603BF286D1D11F012E564E9 + 3C7FEEEC9539A015D49475DD8CC73C84 + 2F85521B4DD9789A813A59D444AEC702 + 164F669C59B43B5115202D08662D4EC2 + stream[65536..65599] = 8A7B672621B0B77E8BA8EB9A71DB4558 + A78364244F182519F89D25D3012CF8C4 + E429DD543C8DC56C6DB8FA5E351BF615 + 106B51F9FD00F54018A94DAA91D76715 + stream[131008..131071] = 33EC15BB2C553646CAED9ABD83F37ADF + AD3B3313A074B69FEAD405BAF897C3A3 + E12BFB2F4CC3136ACFDA284DA1E780DA + B3E4D34C053302989FE6A79A1EB0F5D2 + xor-digest = D899BF7CD2972EBB7333D4E57DC809A1 + B717373577B15544443915B36ED162E1 + 25452584F3E0C2B62164092219FBA924 + 31C1FF2A14C8E2E437427DACF80A200E + +Set 4, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 8EA023E23D94434EAA064A4BE52866DB + 57EFB7B200DAFF5AF2AA72D3E55EE5F4 + 5060FA89024F259CD2490C628452B1F0 + 91020DE10263BA86838B2E388F5AD040 + stream[65472..65535] = 5BE1EAE0077FCE5C2C21120EFD560A96 + 27C3DA9462BE42580065C9E51B7D36C1 + D9D717DADF4A3122A08303A8E27721E2 + 1DADC91138A2461713998AEE26F811D5 + stream[65536..65599] = 482694A9797978003DFDA5183F00FF97 + 9F38894BC92DC88418FF68156117A2B4 + EF10D76923A734ABCAD1A5B4224BBD08 + 836E3765321045C3BF6A352371F82CAE + stream[131008..131071] = 614BC8A38C5F9E8507595E8F5A03484E + C9DEC6CF52DECFAB008327527B822365 + A2038FF09411D7B952417C8C7375289A + 244D50703B73577EC272827A21BB917F + xor-digest = CA9E6EC13B679609EA778447EEA1157C + B366A08AC5A96A73D0B5E182DF24EBD9 + FC297219A0AF67591BFD68B1721B5970 + 8EBEB3655791107FD2A0F2F2E341FCC4 + +Set 4, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 5BD3D0625CEAA75ECFC9828179F7B73B + 288A208D60A2297F2C328DB0789BC869 + 4E50F50E8797F8C7A49E24F72A3AC359 + 796E6188C71A9B3DB88DAEB1BB2C77D3 + stream[65472..65535] = 726C7D7AD756CF567E0E8F812A282675 + 7E75D593C7FCBB45F842020AD59F2B53 + 888354CEF541411B92C3AF6D57ADE7E9 + 273805927DEEBE552B32D10754C9D2E5 + stream[65536..65599] = 5703464C0AED290E65815D8D04098B0E + 22D2FA825ACD4391B56CA64CB8201BE5 + 7B4FB9ED6BB7608BD820436146339559 + E7464BC13A8AE3167AFCDA58E3C017AE + stream[131008..131071] = FFC5787A10E340B07D08160D2C4F653E + 407857845A0D68D1EED8EAC0116CC376 + E33AF8A1120D8DCAD6C86B757AC50393 + 46AADEFF012BD0DAA294DD240D87A98C + xor-digest = B3BAA21AA82617D3BB9C2612E177CB71 + 51A51790D97FE33C3F33C01B32091758 + 5766643C125293E1F75D6BA3C46AB381 + 75A2A4934D4C115A6A1547932B077A58 + +Set 4, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = AC5DEC8B95C89F4794B7289C69FABE29 + F4AA64476D057873D87BD524666F62F6 + B71B5131BFB897AE64F2D500437E1798 + A742E7B7D06B8089F3DB2453D008C554 + stream[65472..65535] = A2F58800E24BA8B754C64BAD9252BEC3 + ED1273598EEF4C6FE42FE2CADB81F220 + 26A90BC88B43F2F1FD2E054E8EEECF57 + A114D087D5228CB276FD5F4FA3ECF4FB + stream[65536..65599] = 5C67BC8E188170A57DB85ACD2F7121A3 + 7D83F1A708ADC54C14064A9559FE7E1E + 3F9E60B9670EA4394521B11D8283EE42 + 12874323628EAEF0B90FC4653106D68F + stream[131008..131071] = 8AA6F8A20F7D4A0B7EBAF6A7336B6D76 + 731E65DCCD179BD53F6B879E70B8776C + 6A8EA30BFF09BA3026B3827EDB9F9C2C + 0F96655D8B84EF725D0603F8CCE3C2F6 + xor-digest = 458DB66B656320F5F7E4FEB12E748C0A + 59F0CD8A7ACAECC25479C309628EC0B5 + 3B441B831B484FD3180C52F63EDA1858 + 7C232B195356996DC29DE6DF54E5BB37 + +Test vectors -- set 5 +===================== + +Set 5, vector# 0: + key = 00000000000000000000000000000000 + IV = 80000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 635990D909A80CE2A75E521ABF588B6E + 85320D2C722D1C93B42AFBE6358D6E2B + F2BE933BC961FB50F9A2B55389A08CD7 + A0131F89CF0E61D0C7071DEA6D8DD4C2 + stream[192..255] = 0F92D4DCC222BFC7020CA6BC3D044F69 + 12D9A93668C65401C570A01D6BF6B3BC + A6F00F6FF46AAE3C09C6158EF05A520D + F8D55FF27CDB7AEB5D03C1FFCE7B95ED + stream[256..319] = 664CCED71B27680F9458952173BE0043 + D3C27F35F9CEE7AE9D783ABA671C4FC6 + 8F2815DC904316BEB39020F646041276 + 5BE5500A60DE2209961755C1BF96E1E2 + stream[448..511] = 8F02C1FB389DD1C5F0CB730ADA528D37 + DD778C4782C7B5DF1961F97CC82B63E2 + 9CF4BE512EE27B50781E297D1633D700 + 1298F13FD8AF9D1EA83F831A70EE50EA + xor-digest = 3F9A4D249220E1AC8E559399FCA23DD1 + 1A250DCDA841502F5FEF0F5D4EFE7E46 + D9B1E5E4312903E290D695C2B681949F + 480D45F78FD69597570338049464FECA + +Set 5, vector# 9: + key = 00000000000000000000000000000000 + IV = 00400000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 8E932D78DCDE35F1E5B8B2E863859A64 + 7AEE8B0867F6F221B09C37B7A78B4043 + D055164B1FF1608EC17F3F148FEBBFF5 + A9FCE4158B33D2CAA4AC5FE5551C788A + stream[192..255] = 7034BE31CED03DEFAB3F69A24E622BDD + 9B202ADAF05D0324EE933064ED6D965B + 937FBC8405F0D7236AC28C320CE66C06 + C5B93EC581FDD59ED40102C651495EBD + stream[256..319] = 37C4EB0E72191FF0F70C8A70F475061E + A0BEDD8A9AF1901FC6BB5482B5A29469 + 06E8C40249E02784896D5D42387127DA + CDF1657A66E0D43E6F69632519D1D3A1 + stream[448..511] = 8CBE98126AE27A51146FE05F40CEA89A + 39781F515D621DD48B6D6234F9AFAFF3 + 6FB862084F5249BCC0018E8FBC090121 + E227FF494BC180FF68EA2B134E7B00D6 + xor-digest = 24556A29026E3CAE101E7112B2FE5BCD + 3D925460B66A9EADDC271E39C317DC27 + 51DC9254491F76F9163AF09AA5372F34 + 1B76D54C09DEC9419F839E5C50F1957C + +Set 5, vector# 18: + key = 00000000000000000000000000000000 + IV = 00002000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = AC05D72564EDC8EB439A95579D04BF65 + 592AB1024152B9B14D71B18FEB5374A4 + C07AA2F58EB2E45F737580241CFB9C0B + 842F8CC9230B540FC50A590DEBDC29D8 + stream[192..255] = 48AB7E018380336AD0CFF37379D9E370 + 5B0C938600C6713FF4CF5C142F640FF9 + 72CF147E7C38389DF426FBF560E7DEF8 + 41B4B1CFE6A4E2DB4A85505C931FFFBF + stream[256..319] = E9C6536F67F4B3053B353170CC5B77B3 + 06A47B759A5FEE5BE45842C01E11519E + 5746B056C86D8A6712446949DFFE6935 + 8E4512E7BBD6E6F544CACA98BDC723E9 + stream[448..511] = 731EF8977E1307CB5FE80BD4F89025A5 + AFEE3E54F7CCEE6556A211097498827F + 6219704F96652420BB9EE830DB3DD940 + 96987BAEC5A43526FCBCD85C9BFDB209 + xor-digest = A37E582543E75640DD988C7FB5579D43 + 9C41669EBCCA5580184743BD54D24CBE + E32F2B1433CDBE51E8208C78FD739CC5 + 4E2A37E16A7AE4F2193ABC4F04C35D23 + +Set 5, vector# 27: + key = 00000000000000000000000000000000 + IV = 00000010000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0B295517E5A2E100C262736DAE920F2D + 26C40787AFEA87FC34C27D6E0BF98A62 + 53B695751F9095C8766184EA44042F2D + 6DE099A80C75DB1F33F53EFE578A8F0B + stream[192..255] = B54C4F2EDF17A1EC22F536586A5BD691 + 2008DA6642C84AFC8ACD35A7DAE73F79 + C835D83F4C0C3B1E510D1BB42013A872 + 8E4899A8CE134625698CAB31852AA7D2 + stream[256..319] = BBE2221921E73DC79E795AC0AF9B890F + FE88A14DA29DE45FA38F4C3E94E6BE9D + 98238BFB181FE664B4147CDDC125FD06 + D11A65F1975A0D781024DE1EF026DFE7 + stream[448..511] = 83E61FCEEB1367635632B45BC73B8B39 + 165015E7A6B8D9851390D4CA9DCCB935 + F09BDF52883FF37BC77DE94842E39BBE + 0BE530FC9D3B4564E11B7EBAC8083818 + xor-digest = 55242D44DFDB1A747071F1C825DB5620 + EDE1AF37B6D73A22264B14F7D35E4412 + 4A6242C5AD34B54E98738D6CC90FE355 + BB9402DD017B6678FCC0EF27CF5D67C2 + +Set 5, vector# 36: + key = 00000000000000000000000000000000 + IV = 00000000080000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B89065FE0B458C64FD6EDC6A893C8C81 + 83578E7D37BE97E6FF82E45110A25960 + 49A817CDE859B67B56CB80768D6DD275 + 6EC368FBABC35C8B51C62AC92F913281 + stream[192..255] = 0E0AB045409ADA1A9540504550404B8B + 2C38384E577F2DCAD5316CE7E806A0F1 + 21D2A3298F71F301340F3C0A9CDD4815 + 936F16B4EC229E63451980646D45E3AB + stream[256..319] = 1DC37BCE039878BA2E5938E4563D2523 + 7350E41C8EF9262A9EF7D7FED7E22F45 + DC3E98EC981D2BCCC1185857C627EE20 + C86DFEF500756B241320798764C3C09A + stream[448..511] = 9A0082CDB35BB3CB1C74CE337D944D3B + 2C833B4F786A92DEA4445A2E5E101384 + AEA834F5E01C1B37EF8291D039875A3E + 21D613FC71212DE686AE52295B773E42 + xor-digest = F94584BB343C6BD6BE3AA1EF799989CD + 93F6DDB6A9AC7E2EDFC92460F0905E6E + AA3E81F6E173C7F9FCE8FB5D7B261A58 + 3FF006AD017A09FBA3B3D084285169A6 + +Set 5, vector# 45: + key = 00000000000000000000000000000000 + IV = 00000000000400000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 486343B348F2A1726617D6E93989B000 + B41FC9707E2A99C7FE5CE9423DC3004B + 67EB02F45B368F87FF2C4CC0C59D1728 + 9F713E714E049CFD8E5D593255092A7B + stream[192..255] = A1A3127E632EF47679F52224E6D5A16A + 6E0598271F36F4DAA98B115535E77C71 + 84170D2DB4B8C5D804790A666D105108 + 81213A0684DD4AF03DE7707702F4F73A + stream[256..319] = C917B1577463E05F34350C4C7F6CBB5B + D63B2D74EAF1500832132CA1A1F289C4 + 3D93BFDC5E9D91897D2F7E05740F3C95 + 0AD872A93DAF3850A452410FBD706A92 + stream[448..511] = 11646E84240BB95D1B14694785E7E119 + 848855E462DD14176442B8595CF602C2 + D1F4A2E09B8D7DE28382D1DA4DB3B1E5 + 910DAE6ACC02E79FEB07A8E55747046B + xor-digest = 65E9982A725056B8FBC275052EA48C00 + 69A1BA0939831C4014E81AAF14F66FB0 + E01FC0C70A49C4533ACBF304A5309F4B + 60D6B310BC66C6684BD5B9C83F994E95 + +Set 5, vector# 54: + key = 00000000000000000000000000000000 + IV = 00000000000002000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = ACAB34102EDDB67B8A5D8B135BAC15CB + 1CD52AE386364C709C2B9D6BD322D7B8 + 477577B4958D448A3BEBA473D861E592 + CA15371AEA0F500361CBDD865488A7A5 + stream[192..255] = F25DAF77D7D734E5486A1AAE01794FB3 + C17099E01489A5B4213EFAE6D745B798 + 77939C7A178D1FF09EB2C42A8A3CE51D + 59D501B36BF9E4960BF3FC8D50F5A847 + stream[256..319] = 1C9C6F63998627AE1AA7E8F0B2D73A99 + 707256CDB12E3AB239EFA72AEC516FBD + 6DECC9375EAAC634707A139E59B32B51 + 5D25ED6951FF4228A11DC87E8DE61385 + stream[448..511] = 6A997977A25F4E9E0D9AFD8C20B56EE1 + C702C301528E332BF8F5E7DBEEE5CC28 + C9E12E1A8BD7A2118A0F31F800B574A8 + 2FC44FE19B20F1D3396432DBB02DACC1 + xor-digest = 0B2BA364EE76F0549A10200D129196B8 + E2B69667999FADFAD55CA479AE679C56 + 54A453C43898443B9DF2835AE806C2A5 + EF30CB8AC25DBA756A705F66759029FA + +Set 5, vector# 63: + key = 00000000000000000000000000000000 + IV = 00000000000000010000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4DD010482D0DB2D09D76872D25F73B26 + 749FFE70B9674587FC4CEDBA5966D217 + 489244D0177F676188A1762C430DD8F1 + 5ED9F7BB67F2E8A79F7633DB7B45CFF3 + stream[192..255] = 3587F0A7B9F410D45357626BE10B4EAB + FF8798FECA5F91F3AD2543B301B5C301 + F84404071C7BC77AC31E423E1AB1E2AC + 2CFAA37DBC2A1316D16A5C7BFED1A77B + stream[256..319] = BFC632891511228ADBA0211EF390A7F8 + 08A12AC6BDD7C2E29DF27025EBA1A6EE + 00B9718FF2BC003904C1C28878894AE0 + E5CE5E9F55CAA522EBEF5747C755CB73 + stream[448..511] = 513D9FFA86D8AFC20E4870DE0E9B330D + 76F02E44A6C4D7C5270B89C6BAC9426B + 5A12666244C0CC5A641118B93F72668A + B7C53CD7FAB0940F1B37A85015DC91BE + xor-digest = CACA8BD50E28720128B57B37D45DFB02 + 206D53785FCE81205AEA085466142DB4 + A17F841156916294F3B7CA93CD99CB12 + 93FF593B5105D2822CA9BC3BAF178935 + +Set 5, vector# 72: + key = 00000000000000000000000000000000 + IV = 00000000000000000080000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4DB6CB1D5BA89BA45BA8E3DFCEFC444B + 7D97C73F53EBC50BC46047CD76499CF1 + FAB51AA6C8B24118AC4EC8E49192B41A + 2812AA1A4325418AA6C69F6143F0A6B9 + stream[192..255] = 33FB647044F3918513212D3538C31662 + 1DD9F3A10C0589CB718564CED7ECC391 + D9701C7A23AD48E05A79BE9E32F60819 + 3E57FA8D8EDDF9F43F38BF8BBCBAF52D + stream[256..319] = 79F3525A6EE300764DE481C20A40135E + 94362F56DBF4C5AFD214F9D4039A0899 + F74A7D7C27494B39D1B0145B9F691B5F + F436F2AE8B335EC62CCB0FF506E0240D + stream[448..511] = FFE0E6B8D741377FF1A02764FEE3D681 + 6CD020C6DDA5097989137E9BCFFFD35E + 0E6379AD2ED3D9D298C6B98DEA82DE6C + 2B66529C860DD4ED56265CA09B16A8A3 + xor-digest = BEC66A4FEB220D732F04AE0B98FCDE2C + 0B70613BAD57D7590E007E84AC546B09 + AF1D5BEB509CFE5523254B5FC8CC2672 + 215C67477AFF14D0788DB166C5B4B12B + +Set 5, vector# 81: + key = 00000000000000000000000000000000 + IV = 00000000000000000000400000000000 + 00000000000000000000000000000000 + stream[0..63] = ED4C49EAEBE78999C0DBC4674757D435 + B056A45036DC51B390A6C87B3CE8BCE8 + 2C7DD348C7775D2402EBE359E7895FEB + B9F44DB5D0F7B40AC207A3CA750EF25A + stream[192..255] = 32F897ACB5CE63D1A64781524B1CB4FF + 9E595EEF93A3206A0D1B4E6F4ED7501D + 2DDFCA31B4FC1A33F589167B070FC003 + F67C528B6AB99ED308EC3CEF82B4E2F0 + stream[256..319] = 57CE29261DAB385309C97955261874B7 + 676349DEDF7582B7654D1A8DAA570EA5 + 9745D2167F2AE1ED538F1D0ECE53AA38 + 379F9AE542EBE229D561E34ACB28FA14 + stream[448..511] = 667E22A8BE7BB84CA1B1C0848E5F22D7 + E98E54A79D5A960C33D07357199AF1AD + 53F3F803EA698127C22F75F31C40656F + 8C28818775B3D88460CFD29798187537 + xor-digest = C68E7F4A7CDB68892794933392C1BA84 + 5B6B7CF52B8421137EE0220BA67C91E9 + 81B47F9BFC39FDFF9DD48F3617F2D523 + 0680B87D18A821A09525FDB79DE6FED2 + +Set 5, vector# 90: + key = 00000000000000000000000000000000 + IV = 00000000000000000000002000000000 + 00000000000000000000000000000000 + stream[0..63] = 80FC6D794178A189EC423AF926622982 + 60C44DC5DD5AC91F779D02958366CFE2 + C5551DE2A5D635353757AFDDE68DF592 + A034D87C871D7D871264BB0F89E99536 + stream[192..255] = 0BEF31DBC3F3DBCC5B3D28BE296384D5 + D33DD0AD9A80D4AB8F58274B4397A658 + 94F67376AD8DCEC19BC2C74A835D9F70 + 1F4C60DC256DBA4E83B21D36B66F5DC8 + stream[256..319] = 625DDFD8D922D848380D45D6D7E730BB + 049666B3900E4305218BB7089D059FD5 + 825F9EAA3AC047A006F1353C37AFD11E + 0143DD68CBE9543B959E26ECB4C649A1 + stream[448..511] = 636E6EB97E3127EB703D5170D2C8FAF8 + 63E8C333F5EFEFCF9063E3D770FF9E0F + 2B37396CEC935239797FE430DA4CFFB2 + 9B19D833687318DF01750DD2F3D942B5 + xor-digest = 0865679CB53BC2845A0B71AB820F61AA + 9B99E100AC7F0358D5B610C09EC52C7F + 8C7C5D973CB85B18F8990F3BDBFBDCBD + 13071BB3AB3F329E75A44E80320BF86E + +Set 5, vector# 99: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000010000000 + 00000000000000000000000000000000 + stream[0..63] = FC2DEE44B15BD914C17DADE6645A0250 + 2F40B39C0C6AA26C0250D328112AC67A + 0C55D48700EFE67EFBCED927B62427C1 + 41DB8089774E2DE23C5FDDFD66D39BC3 + stream[192..255] = B6A4D34FC81937580BFC32E04C8E2B20 + 309AF3E2152B98BD748A344D4537788D + 35B16DD2C01444CAAAB8684916705C88 + FE75C53D75713FFFFA2693E91395F919 + stream[256..319] = 9E619BB0045C58C2D303F79E659CF5E2 + 011D619E0CB10CFDD53AEE6812DD780E + 36407CFE9BFC1C73C27CBBD491BB6A7E + 8918023EFD6E2227C0C840F1DFA5924A + stream[448..511] = 2A320747019AE86A59D5422B634448E0 + B43C41457428AC7A4E5D0C9D7327B44B + BBB6F64CC2423299C009E5B24DDF10C9 + F87F2A525ACF803C50837EF6C2FF3D34 + xor-digest = 3737C19DCC04C7C72EC9280D53C17E64 + E9F4B1E47980711DC64FE6D3E7DD05E0 + DEFF339F38868B1F7CFFAD4298127949 + 11EAD4D34047B22B07C397A37F6BD2A0 + +Set 5, vector#108: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000080000 + 00000000000000000000000000000000 + stream[0..63] = 84F71EA20D46B3802A787C1322DE6A79 + 34587F447AE7FE277362497E4FDB69CE + 129EC4D8D80ABD0C15026EED3DFE2B6F + C48C5DF09CBE035E348A22F8A2AB7DAA + stream[192..255] = 6444791C6DE062EB9A494AEB910A458A + DE3D834BD6F87F26A9D6F99FD970C820 + ED9FE0DF88A924F97945B0EB10E5D464 + 559AA278DAF6A942651E06C66D33F7A0 + stream[256..319] = 1878644E35B3BC562F82647D45C84317 + 769BACDB95DCEACA456727616BC90FF5 + E78FEE1EFB86A714CFCDE79AA9E66FAC + D600B0FC5C471569BBEB5692E7D9616D + stream[448..511] = 54BD56C4F0F3A0CB89A678F2912E5B21 + C2B225030E82A90470EB6040F50A818D + C91F65BFFCEA3F9041BF110A762DE3D4 + B41A8D1E18CAC776063B2DC93BC2D02E + xor-digest = 52E18382B88883C5648E067675468200 + 2AA9AC5C18A856E89175C449A6033501 + 87FA4C17A4D36269340F0877385A35AC + 4B7FEF6E1463D34BCDF3597618FAF352 + +Set 5, vector#117: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000400 + 00000000000000000000000000000000 + stream[0..63] = 3F40E9A3C872ED15A6AA296F716E095B + F39153C7C6F4ECE6F550AD35582083A1 + CA0DC3CD817AE3946E43AA9C8700420F + F0DFC21B34F4E5E40B3EA14299EF468D + stream[192..255] = 853C4A895DCBE411B9B2E340B0AB55AC + 8EEEC42885768110ED7E1CCADC10121D + 8DE12AFD0DCA4507A8A7A2650FF68C6B + 5DB1DD670C8C68365E846934D16A46CC + stream[256..319] = 565AEFAC0325093EF87FDC51413BD5E8 + 56AB6C90FCE7D3C6EEB7E58F22AF63D6 + 73BCF3840D611A5E1102E9A4108CB902 + 5A1D837510A971536231CA247965379B + stream[448..511] = 887287B62116FE2A28957ECC71DE5BA9 + CBBC16DBFA4EC141EB617F9314FCD238 + 91C4237FA35871C0C795E2F3A4197DB4 + F81BA4A29759BEB5FA2277CBB9169734 + xor-digest = 78E564BE9E7102E2CB009D7A540395C6 + 188C8499B7E96C0AD709C3BA2C341741 + 6EED55AB00AE5719F25CFA06F1488E83 + 798F18BFD755B9061AFB4EA5D864FC24 + +Set 5, vector#126: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000002 + 00000000000000000000000000000000 + stream[0..63] = F4C281D9C88A7FD6B2CBA9EB0366C594 + 59327932DBEF8118A7A680D0F0AA41A3 + 735FE0874F047D2B071B5B9E755A7B6A + 9426353B923A5913C647A88B642B2C00 + stream[192..255] = C7DAC2AE7631D11EB21EF15FDCD3EEDE + 7DC98A7060613A643EE8A944EEB6C7D1 + EDE08538E1BA6092ACDE0C648D29AF5C + 309CFCBC4F40A713FA58D93C954961AE + stream[256..319] = D1647D6453798B7E15A49199134384B5 + C9BDEBF7F859F6460C2666F297410070 + E68307CA78790EF01D160D94B69729D6 + 90A4FE477A27AFF8B254875C98116485 + stream[448..511] = C6D3DCBD0E9D4746B142C819867E0A14 + 8B81FEE3D1007E907F8E9D597EAD63F7 + A87E6F224C67CF8162C4E92FC1BE44EA + FE3715B3C1C432CC660CCF1536A20F46 + xor-digest = 59FDF05B6D16079B7E18F6A8CE0C58FF + AD7C985C01A12C07D1ECEA740A92F761 + FDAC3F96357498B5F5FBA91DE6502A86 + 1332A1B3E85C5E72444A2168C25D6FEB + +Set 5, vector#135: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 01000000000000000000000000000000 + stream[0..63] = 494BAFEFE4FBF2C406F55FFB436105BA + 09211B71DA446A0F5436E6DBF42F8E1C + C805E797C9987C14997083E9004473E1 + B2B3729DE9B483361CD38CC78C982533 + stream[192..255] = 3C04C6633F7D8B714E8549AEA1851035 + A520EB6422F42B2C840C74CF51A13FA2 + 9C1875212E8DC07774D6911415F1C305 + 9826A05DA9F09942273CDB592F7E3A6E + stream[256..319] = 1FF6BEFD79A7E5BA0DF64948BA0ECE7D + ABFB3883BF8A95D3E76DEA30550F5C3A + 2B67FE2AB78DF091E758E498418EF514 + 089283275588A41AD20D53E6394635A5 + stream[448..511] = A4D10D3B6AFDF415D49FB6ADA1245812 + 1DA1365ECEBDB6C2508F1EB92E91E8EF + 90892E6FCC9E70AB9A2EC4D49A11C197 + 68E6B4C154A4D65C55AFD38B2BE3F4DE + xor-digest = 91D4EA4C6ECE28536C415A6AF46DC432 + 3B6DC2DC98C3A3FE2BFE53C8FF556C16 + 0197D655357512A808415BF757AB3A84 + 6BE7865622D32B7DE3867B3B096408DB + +Set 5, vector#144: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00008000000000000000000000000000 + stream[0..63] = 521913EA655235FA0E713B0DA3ECB98F + 7AB817E70827D29E75E3BF2729EC2AAB + 8747B8FE0FC9489B6E0EFF45EF985980 + CC0189D9D0F2EF34E809D992E7695D9E + stream[192..255] = D265AAD80EC96DFF08859F93B236136A + BE146981E919C0554D64FBB7D03DC9AC + 9021F2A1B39866567D8BA1DBE2C3CD21 + E5C4C94085F7083F4C640E918C4004F1 + stream[256..319] = 7DCD3CF623332365E6CF2D92FD147BE4 + 1E532F51F939C921DD4492E026993E56 + 843ECBF0925CC52D56084E7F2B538653 + 2020DEE6FE7E85D4A89AEEBD5F3EAAAB + stream[448..511] = 00E20611C7ADFC3BD9E59B9E6D7ADB03 + F87FAAB01D7771B89299BDC59E1E2EAD + FC9FDE416B62FEF07AB7A816AF261E77 + FCF79DBEB09323D44B5956CD93AAA990 + xor-digest = 0578B3E20EBF98D89E2DE82A6EA8E34B + 424E526CF419713F0AA662B852E58BB6 + 7ED570D75534E1F23F85F160690A464F + 122CCBFA5CD1DCC0969F2E57D65D64F8 + +Set 5, vector#153: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000040000000000000000000000000 + stream[0..63] = 2617095641B825094DE44205319CA853 + 418588D5B6BFC05A2713CF898DC42B3D + 6ABDDF4C287235438A48BDDA49E5ECF7 + EFA235A23BF667289612893708704F08 + stream[192..255] = 04F668517ADC1AF6E31DE6B7007ABAC3 + 59A2DD6DD61755C6CA7053E05FBBA2AC + D9AF682EFC71391EDA4A5872B53D7CFB + BD35ACB719169283EFD9FF9E172269C4 + stream[256..319] = BCBA3F15D83B9AD41317AB9EF7DFDF0F + FF05CDB058AB08D7BBD720723E969CAD + 79F16D26DF0222CFF4249B839EB9F9F1 + 422EDAFB8EC285F27E347B7B4C9B2C23 + stream[448..511] = F15F17F38917DFCA9141314047595C17 + 047F91E4859D849E9A6339F640E3633B + 6A1B62D089B24062BA5987C3FAAB6633 + 99698CDE6FE7A461F127AF67B2C5CFBA + xor-digest = 68B2369B45F059964A1FD3822DAF61B7 + 82A9FBA7EB563F83DEC4D058CA5D8931 + EC74AF4043FEA803B696791C8E0A675B + DD8982AEA862BB76847E1DE12F2A5E86 + +Set 5, vector#162: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000200000000000000000000000 + stream[0..63] = B090CC267B29A95ADFAF6BE3E147D647 + 21ECACBF6B7D0C4061D17FB7DE0A6662 + 6D6F9FC167FB3FFF237C240AA03FAD55 + 13B6DA848F22796DB501A8FB89F2B85D + stream[192..255] = 1CB95ED9AADFA0E1FFE5704BE69CBA3C + 9593746AE87F36A786E5EBE18A1D3B25 + F4785EEF4DB439472035BF053687C5F1 + 0B60EF55A76DD1994FBB482BBD250755 + stream[256..319] = 826BE3D679C872536D55C3F0E49C2624 + D41726A4525A50CF91EB71E7CEC5AC47 + F3834358E2296CF0D04B8D8CE8A701B6 + 6AFBBB8776DB2B75F1CFA01231B365FA + stream[448..511] = 244DB28A98619907AFFDCCAF303A3795 + 3B6D21EE6D22780C4D3C939C084E4181 + 1FFCD8F2DA2E6A2243BD0B5428FB86C1 + F0EA2E8C8B6950ED961F4FA8CDFDCD17 + xor-digest = AAAFCEB42F2EF40C4B5462307085434E + E4399F87B4AE5CA828A952A851F47913 + A51430A8BB9B3CD0A4B2F12E297F51E8 + FE0B1A6FE0F21177EAD9284087D3706A + +Set 5, vector#171: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000001000000000000000000000 + stream[0..63] = 0F4309F63F237DBB51567573126F09E8 + E49990F26E541EF888B9F2922FE9D280 + C8FF4874C0D4FA3F41034B82E2E026C4 + 594A79C2B689BC502C41244DC1AD472D + stream[192..255] = 95DCF9685E429DEC2833E1B5E78823BB + ACD9332D668C4B342B89A290E1CA6127 + B0E5125E44445A1156A70B27966C3E0B + 4E0BCBDD9F4561998A5CBCFAA05C7459 + stream[256..319] = 0886E9887182156005548CA1A08B57C0 + E9FA76C2A694E1CEE22E9B715E99B115 + 9AE064DE644FD580E8356164A45EA1C4 + 3DD85E16158B5130AA103267C8118105 + stream[448..511] = F8AF6F9992781BB09808B7AF404F6546 + 6FA697C2A1BC9BF64F8D6B6D8CA0B856 + 6B64E6BF0500F6D80113D9457855FDCE + 1791C7436F5FF41ADA87562C175942D6 + xor-digest = 8D32FFAA409C8CCDA6892C388D5D654B + 4AD50ED00BA649737BA8F350811A2AE5 + 5C89463C7D63F1F1F16C4007826C2CF0 + E4BD9453A60D88BE86F60BADC3E71E98 + +Set 5, vector#180: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000008000000000000000000 + stream[0..63] = EBABC8B756971D46C1A5E86CC7AEB329 + 4DEDACFC795F2AE02CCAF68B933DEF4A + 19E96BA64DF14EB6FE67CA48861B49BC + 16052E33C8B47556DFBD96037B7DE5F2 + stream[192..255] = 0438A8CF718F4C52E33DA087FFEC01E0 + 459D26757D5DF55D5D7BC9BA88F57EC0 + 4B84D854374F95317CBDDEE928A2CCAB + E4BA1BBBF47776B29890DF00D864FBD2 + stream[256..319] = BC4A80F9CACFE63D2E54044ACFF39F97 + 2C69015058AD3F81CBBA28FB0987FFCF + 9CD1F6AE4F0602BAE2B828D3FA162936 + 23CF3AC2950BD651F7E467DF8B454BD6 + stream[448..511] = EDC95FB80C9FED4A73D6EE9B2CD74BB7 + E6DEB9E7868D40FC49BD1C52838457F0 + 88DCB29C2107066D55A80908EFD1392A + B4F2F13C0A79F67E58C91A89A5C88991 + xor-digest = BECD7FD2014BB9A25701E69F9788FC84 + 1AA9DA56CDE1CD93DF45D28F29D32E22 + F488B0C2D9FE95B267CBFD35EDB2F6E3 + 05DFA5A2CF09D7E2D13348BC0C9405E2 + +Set 5, vector#189: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000040000000000000000 + stream[0..63] = F28A15A90386237127A5682EB09E0E58 + 30709455034A7189AC9710DBB50D5012 + 9EB4E0E9036D4504054B281F3FE9F45F + C80116B8FFC0B42F9A636A399B7A8BD1 + stream[192..255] = 1219EF9BDC250E88BD0A62DDCF9AA1DB + B62E19FBA748DFE1035C6A5B3B94954E + 1370487A455916F7DAB451F79C5E1298 + F549CE005A1321E6B136B59BAD9EBCD5 + stream[256..319] = EBBE81DAE5637C4C7EE6FF9251D5407E + DF7E8EAE384D1E588CAD39AD9F763004 + 9A8E028120B5065B658EF3E2B357E52F + F18891819EEE3EE021BD1AF08A4B1F53 + stream[448..511] = 50086FCFCF5EFFEDC4A52B0212B7321A + 8664F2976493868F13D7CFDFB7583E99 + EBA70778A83CB88850D45B300F7F6A80 + E721860560B2FA642B2E77C7F7AB0662 + xor-digest = 336516670616300FD5FB014C1076B53F + 6637AD0EFB453615924396785CA4D284 + B03F526FC2179FF3BFB0A1A2ACFFD87E + EDC4C8360DFFC132CE6A502EB173A0D4 + +Set 5, vector#198: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000200000000000000 + stream[0..63] = 93261A7231FD030CEAA974BBF8F3A721 + 33334C5F3B25D5831B203C353A566D80 + DA578081A047E28DDF8E4BD5B68BE4A7 + FDE4BB3A4875BA84553AE120ED77C9CF + stream[192..255] = DEC4B603E6A6F911B68E5C1265FA2004 + 71B296A647D20C13E42202C1A3AAE880 + 305F969BB88002C8FC00CC5DBE40AA06 + 4AF85646AA8C7F7191FE26FAA2918A95 + stream[256..319] = 849431145F27957D53CD355501363E4C + 5F191DA666B77364E5866CAA16A9DEF0 + DDB9BC266EF41DB0C2A7642B9E8DD27D + 60DEA6E69052D4BDE9FC83B2578C72E7 + stream[448..511] = 5556EF9874E3150FC539C9BD3BAFD308 + 8FB347D5E38DB318A72AE0C6B6FB4163 + 082545A9AD8872AC383A78230729D083 + 31BFC3F2C80DA20617435FFDF2529A7D + xor-digest = BA9CA5F3C27246F931824A9A425F2390 + E183188FEDE5BE3591053ADCC933E1F3 + DDF5627A94F80F8922F53E951490E96B + F51491ED2D6DA26F3BF69CC41B8C0C98 + +Set 5, vector#207: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000001000000000000 + stream[0..63] = C449AF4CD437641A3B40D0E0E7B5696D + CE973B3B217E02DC20B2F5573FDDF78F + E6E55D75CFAB8EE04C8962376D22A843 + A80BB79C8B8D8B500C4B6DA27748C398 + stream[192..255] = D5C92B62B0818165096551DF2B007F66 + 2DF953742EF0BBE97982FF9D3EE83E1B + 87EC9D710CF1700262B1CAA9C68A897A + 8AB4A162DB0443A43962EECFE5B4C0DF + stream[256..319] = 3B8CC7E847669AC6858B7BB716206386 + 40D8C2DD259EE4970A5F254077101271 + DF745AD7F57712065E2D03B9D7220591 + 5C8C033A4F9146EE561B4179DB465989 + stream[448..511] = BA4ECB7D74CEE56CF1D5AB636BBD6421 + C30A51DABDCED17C8D50F5293424AFCE + 33AF71095CAAD3913A8A3A12286A8E91 + 89DAFCC1E2E744FBF4B526E910B5F2CF + xor-digest = FAD57A608E04CD71B176BBFADED7B229 + D855A8025E963B55FB83EC7311427779 + 490F25D34C6385FE1C036FF0807E136F + 40C10588678E2414163AF1819EF7D3C9 + +Set 5, vector#216: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000008000000000 + stream[0..63] = 989F302DF6BF8C63F9EB69D2625115B1 + 2CCDA42A2D33BC6F21BD55E0594DBAAD + 9A294DDFD6710E36000C27FEA7E03440 + C8A6E728716D0DF14E825B798A6C420C + stream[192..255] = 3F3140320AA02367512E7C1789F5C03D + 83CC634354237E78E16B1A64DBDFA6EF + 0697B28BDFFAEC311C6E2089BCF64203 + A2EC7BF3CA922080380241A47A673634 + stream[256..319] = 6049048A5307D55D6DB387A6149C7B23 + 0AE33195D53E0026103EB44489BB86C6 + BAEC7A0D920CAE25B1E7B9F07C07C4AF + 6485FF281C7B7FE1D61E660AE55C20EA + stream[448..511] = A6DCBEC85525FA19FA6066470B4CD83F + 17D42DB3353B327BF3DD6E7D047CD752 + 71E79CCBD46E757F3654C2506C2B593A + BC93B8985C491017A8E616D69E8974FD + xor-digest = 55BE97FD8317A47742F8F3BB762160AA + 7FDFBA371864823D93EF6C029D457AC1 + 2D679CB424DA9EAF8E4FE28271C66F06 + 1E91D8F2EF41733AC1084F54330C9786 + +Set 5, vector#225: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000040000000 + stream[0..63] = B8989CF76BB1AE894699604320C14706 + E20C8BD86C016B5E2EF705AEC54C6023 + 2A9AA961C10914A8D910D517059A93F9 + 78C537767A057E0E11DBB5C9BBC4EFA9 + stream[192..255] = 83FC232D21D0DB82747D9EDFEDFB58E2 + BB37362FA2B4E1AA0C9A58AE521EFC86 + C512831CC6D2E85FBD96FD3B60D1D153 + E83DDC6C5755899CF96FDF69E3732E4E + stream[256..319] = 201DDE5D82B754341A3452BF7DDDBF6F + 167B2A087900EF40E4268A80217D7310 + F1E9E25C707A1EC05219E3CCFEC0F6F5 + 28CD98534F6C579A1ACD3171D131D87B + stream[448..511] = C2F68B5F03B0045FEE0FC92DA08F8545 + 762F73E553D2F539C64B88D4FAC9B011 + DE0504D66007A115E428F627A667FA2E + 296F222734FA0F905548058897DEA990 + xor-digest = 7DFA65F57FD58891C5576B3CC7002513 + C1A983E9D31317B681604DA09F176AAC + 4FD78CE84EB9427BE8D6A63058582F16 + 148D55B3C2544CF4DB9306699CA74D80 + +Set 5, vector#234: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000200000 + stream[0..63] = 307B13F3D3EEEA4C8FAF34416689F354 + AD26336D6B33DFC5AA004420D2DEAA69 + F69E531EB6D672AD62B2A6A136046373 + F70272E84E14CABA9AEA3102863A0B10 + stream[192..255] = 8E4DA19FEDAD4C842917ECD5E7256097 + C2F524324D8A974D4185D8B11B611C72 + 6C39DDB5E58180971DA181D36A289CBC + 1937E8F020645EC8D0363A58C6147F38 + stream[256..319] = 012A99871D6C4CB7328C1374F37D0BE3 + DCC2232F6484A22C8F330D77316A1756 + 71DF7CB32773F25D772BFE9DED5981B2 + 0C3F0DDB2879AF61E7549F03AE26D233 + stream[448..511] = 47C6CA462D35580BC0C78C6427FB96F3 + BB762662F5B52FB3938CCCEAC35884C1 + 54F5BBF513970FC08F51C91059A757B9 + A8B6F1EFE467FAADA8D4DF68C6AC1942 + xor-digest = 6409F8C255BAE6167686F5F9C7EB2349 + 0FC7BA4DCBC80006B57A5F56CA9F907F + 849C2A0FB0D74CAAFC0E2D4367E2912E + BA6487D8A48DA60E48277A20E326266A + +Set 5, vector#243: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000001000 + stream[0..63] = 543BAEFA799FA0CF5295B92EF3FDC07D + 69B87C1B5FF0A9F25B32F8FCC473D04D + 54B6E467D6183F25E3664A330889889F + A530E354B6E53EBC78354100637A62C3 + stream[192..255] = E15997D1E7C0FA38333DEE2EE2477A4F + AD32F0810E8D3D65EAFB110C2B8D0948 + 59DC45C4AA38B8050A87C23782E1A26C + C193985BB0C3E754A528BEAAE1508D76 + stream[256..319] = A94F1BD38219097B70EC0700A64B0ADC + 7BA8883B5C2C3BBABD0497E80D53121A + 2DC5A5C6A77913330EF5469871BABF86 + 0A09F1474D893ADC28B473EE508F473F + stream[448..511] = A43AC01FC186AB42241ED3729E7EEA39 + F0823D124E8CB696E2F4B047A6B71164 + 5B803623CD0371C4975217B3CBD7D9B2 + FD89D3B6BD23FD11FEC0B03B9CC22AC0 + xor-digest = 792A5EDB6E7FDBE99B7EC2119665C2F2 + 34038F561BB1923F3BF493AE35CE2006 + 55B8EE47490B53EBB481AB7C6B82FACB + 233AD86D74385FA108C94666CD34C164 + +Set 5, vector#252: + key = 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000008 + stream[0..63] = CB4377099B2D7CD6A982A1B1A53E05F2 + E097164EDCB381468C21D8F0615A654A + 45A4D09B7C0218A19496EA71CEEEAE5A + 886307DB0026C96049B60E5154F99AA4 + stream[192..255] = 25FCE0B7E28D5D0D1654D912DBB21AE0 + 288CCC71396CA5AA36AC44AB08EC72A1 + 01E5B189535C1987B79DE4C4E32DB7FA + 48ACBC8F854868FC287E03D54752230C + stream[256..319] = D3B02A39A4E467C44C109E1E25593278 + 2E9B3CCB02D6F107C9263A24E113FAEF + 847A9064E1AD1EC8881EFEB239CAD6C4 + E90ACEC36A7E87E002F35D477CD63F2B + stream[448..511] = 7D4282D7E11439C04ACFF087708DA22D + 236F1A08A6343704DA4D24EA3582253A + 35419183A915B571DDE80C1DEE2B8A13 + 76EE973234FFF6A0DD91D31037F51C72 + xor-digest = D52720D8DF114235D99E5292E14DE96F + 9D8478E016CD40EBA25C4B9D8E11713E + FE9AC151E1F39377FCC07D06E9BF6931 + 6EFD7E27F87E9F76DCBF7831CC3FA98B + +Test vectors -- set 6 +===================== + +Set 6, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + IV = 0D74DB42A91077DE45AC137AE148AF16 + 7DE44BB21980E74EB51C83EA51B81F86 + stream[0..63] = 914AEBA9E4BE90FD07AA58B6E2536B59 + 0DD63BA810A2B96BAD5DAC1818722BEC + 61725C75B9E6194F57D3D2BBFE795E73 + 90405CA97249262093234239E35ED9E4 + stream[65472..65535] = 346C1A7D71DBB8FB69EA78F07D60A9A7 + 20D0ED544149AF102C12678D4AE0C5DF + E3521B7344F91977799085008EA00432 + 772C0B4ABEC1DB2C47608F9A29CC76EA + stream[65536..65599] = 6F3B93E808687BE8E37A635E15B13052 + 60ED65488A59125D84726219AEE62087 + 47C6672C585759BA60BFD7F55AB975D4 + B61596A506F8763F715F27A36082DB51 + stream[131008..131071] = C64CAD1578C28BF19F11B14F3D33C681 + A85D28A4B2D547652A7179C31127C306 + DC04BE79BC1DA0279C69F9418311E57C + 0F13D9E993008796EA10607A63BDC772 + xor-digest = A67B88BA16F74643B49BB149E6E214F4 + 624BDC9559CEE75DDCDA01CD343FEB4F + A8F6D62492037A0939B7F745FED8C3F4 + 93102B006D3AF8167E38D1A216B0AE0C + +Set 6, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + IV = 167DE44BB21980E74EB51C83EA51B81F + 86ED54BB2289F057BE258CF35AC1288F + stream[0..63] = 0B739B0FB68C82FE4120545C8930AB02 + F7C1F08E6C5A1EF913F58148283C873C + 346703A489B00BACD14E9CF30D8EA149 + 14937EEA9074DE932F4847E69D793D3F + stream[65472..65535] = ABA9A96B26DC34C1684B1B9E565D7292 + 0B3467672185FC0C000710265DAD5A9F + FDC7D5D42E412170046AB05591C19998 + F8AA47E5C634E5719B74936526EF6960 + stream[65536..65599] = 286FA01C6BA9498FA55E3AB7B7481D21 + 05D82DBD03CCD59760690DC89EFF5B3F + 9D3FE06CD3E8D9C2C77EA2581AA5790A + 6D1457D534A1090799EA0B1B3BAB059D + stream[131008..131071] = 8FEA40A11790CFB0BA2F199B01F68FB9 + 33874E294F7A08F319B87D0990317915 + C12CE3C47A19001FDAEF72DFD5AE2174 + 72FA2DC47D492393792C407716CD965E + xor-digest = 7362D014CAB8247E7F5A7476238D5C0E + 931B2F9D79D03E773994BBDB93B4447A + 81770D6D1EFABAFFB756ACA945D929C7 + 5CFE214A53F2FE7EF78D76B2FDDC2267 + +Set 6, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + IV = 1F86ED54BB2289F057BE258CF35AC128 + 8FF65DC42B92F960C72E95FC63CA3198 + stream[0..63] = E6A0C18EE34238191E39B2DD0F0066DD + D7C0033F82C388043CF13C72CCFB9DBB + 553D782AAFC983F419649CC9B29510C6 + 03302235278AC3F1CE5405829F7E63B5 + stream[65472..65535] = 16B4B4A51FDD9B41DCB8A1CBDFBE8D5E + 5E2F60F7ACFE5761826E68F7C4DDACC6 + 7E0AD9A0B431F089FFE1E5780A66945D + 9E3C32136992ED78B8D8F9E7C38DA359 + stream[65536..65599] = A450FCA398BC87C0079DA4D71E1BF0D5 + 490FDAC094BF45C7F0FE0BF28017DD19 + BD3894BC0E54DEC98F57BBBE71EE25D4 + D96A2E1A003CADC37775CA370DA2898E + stream[131008..131071] = 17D7D66A32B7A47676FE3BCB180CBF52 + C4585015CD9D994C56E6DFA854D9DA76 + 9AB45C8CFE938901BAEE5CFCE73D8604 + A0773736C3336C40355472B6F9208FAB + xor-digest = 9727B576E6090D39333BCC2B993D0F16 + CD0508D7273BE022E907C99E93A17FA7 + 23AB9CDDA9A4D310C8E5A9BAD26767AA + 8FF3C514AD1852DC6749F10FE663C9EF + +Set 6, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + IV = 288FF65DC42B92F960C72E95FC63CA31 + 98FF66CD349B0269D0379E056CD33AA1 + stream[0..63] = 857EB9871D1CB2623103A4D04443CEF6 + 5AED61EAF8264866A7B3276F6B5DA8B8 + D2E7C63E3213CEA9BD3333E4687C6962 + 5D2B980D0E28EA54492148AA16EE6FF4 + stream[65472..65535] = D498F0830A147DF5D15C6DEDC76E0687 + 20D8A1A57F27DF19895CAFDC92846955 + CA942F39F64524E5F70B4B1D3F7B76C9 + 55877A81311CFBE09AA0E9EABF0403A5 + stream[65536..65599] = C850035DB7C0750E015EA60DC1EFD84A + 79C830EFD07675C0664039C90EBA1442 + 5C523DCC60A47E60716F7F302BFD4BF0 + 2A2DBB2CE29DCA01A1AC7B1EE9815727 + stream[131008..131071] = 6D580F0D0C722DA5F901321F57C3F438 + 109F2D2F46ED5572298B40F28C204252 + 6429F5436DC67F15C0427C8EE7FBF49A + 8B5674674E1840E0E664E73C429B36F5 + xor-digest = 65367188C7BD2B0064CCED9E64FB7531 + EFE91EE531F4203B9C367A79B015B4B1 + F79349D68DD316899F5B39A867765747 + 49461826B9511C99C0BB569F7455601C + + + +End of test vectors diff --git a/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt b/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt new file mode 100644 index 000000000..46a86d7dd --- /dev/null +++ b/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt @@ -0,0 +1,2783 @@ +******************************************************************************** +* ECRYPT Stream Cipher Project * +******************************************************************************** + +Primitive Name: HC-256 +====================== +Profile: S3___ +Key size: 256 bits +IV size: 128 bits + +Test vectors -- set 1 +===================== + +(stream is generated by encrypting 512 zero bytes) + +Set 1, vector# 0: + key = 80000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 240146C5EA6C72A8DFC93E54E8811C32 + A85E0BF7291BDDC0DBEAE086D051D5B0 + 5CC9DD5C311ED2F7E8484CC477C68BC8 + C5D3F3450553F5327253768E958C0C55 + stream[192..255] = 26C5976C37B009E57BE86064A99E8F59 + F9536410FAA9BF625D8DD2ABC9AABF09 + DF6B5EFC76CC6200F9E321E327AB0703 + 2C78B351C5F7EEEFF2C6E374521CFF6E + stream[256..319] = 2F72E0E6E710D807D5120AD686DAADC3 + A5C1544557A4BA6B1D61F90FECD55328 + 3C8F91B801DC435C5FFB1F8B33A23644 + 8E21217C367108893D13AD41EA8F20F5 + stream[448..511] = 68320BFC459C78596162EF5FEE2CF46C + 79EAFC681AE91F875672350C59D33D6F + 9E0CEEFE42EA9A0485E3E41C241CDE84 + 9849DEC99219729D91270358B2F83F38 + xor-digest = 19E8083DE3499286788AE3A6DFE90AC7 + B77084682ED86D8039A67663CDC9ACCE + D297F22C10FF7E4FAD773337B008A32B + A7176F733045DE44782F04C1DDF28776 + +Set 1, vector# 9: + key = 00400000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 4B1E2D728E06D7356F151D10DE9CBFB3 + C66A1E5B5ECD926E33F56B14CEDBFCC5 + 40CD6D1089DD8E5CF008E4AAA3C4C89D + 11B136FB5656B5D4818D1BD1E562BB38 + stream[192..255] = D5E6B5482535DB7F9352933242C164D7 + 6528DF7AA013A4FC2F2B8C2D7DC0202F + 85774C16FAF22D5071A875B6A671D4B1 + A8C396AA5D2F14AFF9C4CD6C1DB89175 + stream[256..319] = 3D0FCC3C90DE0328FD0C752458996FF2 + DF822E496CA42A7D7EBF3D958676A41D + 83A16EF3150B8C4C8F1763560B314287 + 54B4A2EA5C4F74783BF8809F3A624664 + stream[448..511] = 2D68526D25483C2A1F0B6F7101507804 + C9619E267F1FFF28C934D19201351465 + 31D13592BC9F1739A0B090718052E4A0 + CAE9E0FA4555F2FAD27EC8AA2F14CC60 + xor-digest = D3C3131E402BCBA54DCE0AD35C5FD241 + 3ED7056BF67B5163CBE6C9EAA9D27535 + 7D2BFB7B2843DFE92709F047675CE06F + 5201611BCB8FF15C76D0E328D46345E4 + +Set 1, vector# 18: + key = 00002000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 4A0CCA5AD387D49DF33FE8BE69FAD669 + 270E3E6CF724F53FC3E509A2CEF1D174 + A67C2EF4B9D2C9B8A8177BBFBAA2C45F + BDD25CBECBDB59A402FE3C4835854CAF + stream[192..255] = CA0F19D9996E6D3518D28D8169968ED2 + B03D118D4BC1C5E1847BA6EFE6A32D6A + 32BAF71A4C27B0BBC9B9BA03FE044D7A + C9785A69E3B0E5B3B26AABE3AB093965 + stream[256..319] = 6FD1A9F1EA228C39625FC0CBB2D4BF8F + 2C0EF1F37D4FAC56D8024D1B4F2AF33B + 8AB0D452F5155ADD5F0FEEED8104AD55 + 9946D2E274ADE44170F5113630200B57 + stream[448..511] = 5DA1476A1CBADD0797DD7EB9C0E563B9 + EEA2C55860C42C2C0A6B38B9344BA0C2 + 345C7143D9A7E5BCDF9FA2606098DEA2 + 142632258F844AA1A77CC9950D5ABD7F + xor-digest = 0CCEB42D4045C09C45CD6C27B88606BA + ECF7F6B30F50004AB2ACDAF89849519F + 61482EC4AAA2CF58C4206A228FA23AFE + DD3BD50BC9C04744940A238966C2926B + +Set 1, vector# 27: + key = 00000010000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 77CB199A639DE60664225AD1DB954B5F + 70DC01305D2D4073BE772B0863175EBB + 64FAB80EF324DBC85A9EF827EBAC7A5F + CB088619C246CECE6F92B89A2122B6AB + stream[192..255] = 84C1E9B365F1CD23AFD5711BDF2B6F26 + F988A6CE29450108FD6814802355217D + F6F329FCB3F5997401019BAE0AE43760 + ED6B658FCB4280F5A070728411EDA4CC + stream[256..319] = D0AD4A851E7A60DC789762A554A8FA76 + 77FA610F4D868CFF1AB6025B2ECDECE8 + C554B4C0BDF543F58A1DD7CC68FD7AA6 + 7EFCFD59D55372E85131D6284E7949AF + stream[448..511] = CF7F791090D04350930AA1E1A53B70E2 + 691A231595E83F8BAB9613BDBAD868AB + 197D5E06B3397CC3D81F56B87BC7521E + B0BE346552DABEBA863D5C81D7245C8B + xor-digest = 2C77C0ED1F5AE20A97388ACA5300918D + 6246B04429F298E64A75828EDBD01900 + FC70CC103C31E0BB67B06D04128686AC + 5C5FA63FE714FC4DF18C551BDF81862F + +Set 1, vector# 36: + key = 00000000080000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 54A5A2E883714170B471C0651D74A9F7 + D51287C89FB345DE0AF7003C3871425E + FC885F033D79BAC9716B1ED5C637BD9B + 0F16FD8D613BFFAB634F0EC2497D7B3C + stream[192..255] = C7FBA70B19B749BBD0C84C7D31A5AA44 + 155623116C44CD53D2E640034211E730 + 277402F62D1FF1578236A2646AFE6108 + 2C958D9D01C065D7335EF9C29415AD42 + stream[256..319] = 2385E2A7070FEC7399BB3CEEA43C8D0F + 54D3607FC1C21BF173642287C1FC2C96 + D37695A7B1310E5E918EBE37113348B1 + 707BB39E401A10FF14EF020CB7C44261 + stream[448..511] = 5A87EF81C2CFA70D86B147E9587467B5 + 22FCDB4EAF0353E11F73F3BCC1EA6C09 + E962A87A0842B9225E164DB0CD1A3BA3 + DA8C02E6746CD3AE0BC4754ADBE7EF6D + xor-digest = A65BBEA2E397048E4714A8AB3C19EE6E + 91B9EB8048F35FA7AB9E003E9359BE0E + C3EDA827AF485C23A941F7D656C76CA2 + 5D12044923E43E61E7DDEBE7D9C87E3F + +Set 1, vector# 45: + key = 00000000000400000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = FF81E156907CC2C01EE23F79F936809E + 3F88AC15CC01BDDDA378CC1BD2317444 + 200E4E2C63E15FF07B0B40721970E7CA + 68F748A95A965EEC606318447BB31C2F + stream[192..255] = 4C4C42A330AD444388FCA4009CC0B196 + 84AEC3EE65138A747FE86526A263969D + 87CCDDCC4C9A0EBDE2D088CCCEBE76F0 + 52BAC07636937B1567637ADB498F7F8F + stream[256..319] = F550BCDF67C8E9C17B800487DF83A4BC + 73B809C4F3279D4CFE857780412F0F7B + B838A9F0322BBA84D7AC51E469C5012E + D774E52E3507C7D069F5169F0403C577 + stream[448..511] = 9D92715109A301AD47BF2376D65E2519 + 78E12098B0DEA5B779079A0FAAC4DB42 + 5BA9EB00301A5F964336F7EE9C0D9667 + C4F0DBAE14BED3E49A6A746FCB186C65 + xor-digest = AD2264EC651E311BAC5FB36434773F5B + 4A4777B2B7F811A755269FDA8339DC97 + 7A8C6A5F66E8737DD16A88DAB8545110 + EAE275892A767BCAC0757C396A690F67 + +Set 1, vector# 54: + key = 00000000000002000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 3DC3C1A1A40E721F8A3A66960DB2C0F0 + 6D8B7C07FE90D67C26F86200D6A1A1D9 + ADE4D53A35F7A016A506D9C62D344D49 + 5C6DEAAE053247103B8F202B85A5036D + stream[192..255] = 9B83E56BB5E10B5C6C05C4B450B64FA5 + 9C52AA63E207592999CBB48355517F05 + C93EA878BFAECE58CBCB948E81BEFD89 + AE0C5C13359C6CF5A673B4EDE28FAF0B + stream[256..319] = 388163F9F26536BE1221A46834CC77FE + 03D021C570A9DA36CD528E887ECEB2A4 + 7146A8A930D6AC04694A0B9AE50FF55A + 41AD3B3D3E53F982563B5B458C078C0E + stream[448..511] = 3B0FF94C0C9FA0EB8B8CC1C691D04180 + 5AB6436BAFCE8C16A1351883C88E945F + 8F912FF79CFCEFF7374936E830C9440D + C676A5F00BB50EDB34F810AFFD9CA8B3 + xor-digest = 879534CEDD8CDBDDDE2E2216D55529AC + 1189B1C34A76ECEC179B8A240E890F8C + 640738DC37C14E4B950B9D8C507685B1 + 28CF4782EC424A3712F54F6265A41E7B + +Set 1, vector# 63: + key = 00000000000000010000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 12F0A17DEA167676992DFF2E7D812878 + 629579519578EAFD885F212C7E04F035 + AF03732C3DA8CFB7B73054662F0593E7 + E40133706F04B1329BC3155DACD296AC + stream[192..255] = 41BB89D0BE44055E23813783C3EC4487 + 2D102D6EE94475AAFFC7FEB8DE6849A2 + 6B50DE77EB9B0B96EC9EA0216D13D64B + 1264A83D6B571A92948A5E35446B0503 + stream[256..319] = 15E9C9168AF4AEF7F2EF1E832F40110B + A8C08DE71D4F0AAA3A5C2FC59BF41005 + ECA654EB7F316B757FEAD5B0F4BF41F2 + C6D035A88B5477632F34D7F904B2939A + stream[448..511] = 8A2D446044F7930B696DBA896BA6CE69 + 8F8B01E4282BCCDC4740BB6AB6ECF7B8 + 9CA1CFCB5745B6577D0F440AAB7985BE + BEC5DBEBD8B028B15DEA138F09018297 + xor-digest = 89CFE7E84993C6B608EAAECBAECD7847 + 472703F3CD97F9315BA9CA13204B616C + AAC0F37EBD1C58186620710FD6AE5EFC + B7CBADA19AF8C0F7E1FB24913C2300FB + +Set 1, vector# 72: + key = 00000000000000000080000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 7BC411ECF4AC2EF2C9B8C5B7CCFD791A + E8250119E08C1B7F7A82F576FF66FC9A + 9D9BDB7570EAF276A60A3BC7E7BCBB86 + 7A791A48F9E742D7D7480FBA67DCDA6E + stream[192..255] = F85A8E3219AE1E5F20A4FFC6814458C9 + 5A4ECFE7FE739E151A45247A136E3BB6 + 9C11987BB5D13B1B9A3077C8F4ADC9AA + A555FC9725339E02390B9C9F75E1F38C + stream[256..319] = 8A2E88E0A773EA00C11138710BF12ED2 + 7797AE7863B1EC84801D11B5B3914786 + F1D547382DAA9D5215CD4CBC783C700A + 9B09FCCFED28899D2F2EC148CEFA39B2 + stream[448..511] = 95E3BA3237F370A4E0850F2CA0FCEC89 + E9D832CA6DC6A062BE7ADA8D8AEFD55D + 2BC7A3F46BF81DEA5DD9155E8D8FE918 + B5DFB1926460AB69663856EEBCD4C338 + xor-digest = ECE252DA29D20602D138E13C004D8B66 + 8B09FD764B7D84FB83B8F4D924504D60 + 277BAFC521A8AB0464E4EFC6BBB9E4B9 + A206C38154AE3A57B84D2D39CF45616E + +Set 1, vector# 81: + key = 00000000000000000000400000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 139C2843F0BCBDD32C685F4EE2C7AF4D + E6BC79789B77B1CA6CD94A01645EA243 + 5B491F27C27D4EEB96FEA0ACE65C0D8B + BAA642B5A07245BCD0930588FFC92A50 + stream[192..255] = 5C76EB0D5323A7AAAA228F7718BB6736 + 5B344559C24BEDEB2CA66414B5E81795 + 428D55868611AF9AC7EA0E7424984037 + 3251BF5206C361AA3631DEDA52DDD519 + stream[256..319] = EAB18EFED266D4788015DBDD20A75058 + FA4DE35C1DC774ABABC476BCB0AA2CB1 + 214E5463F4E20E7B999ED475D77DBA9D + 70FFCA0C7971CAEC3B285EE8F9F37C02 + stream[448..511] = 081083D9AC30C9DB4E53597D64249D7B + CCD847495A928CF4CE876237D92ED5E9 + E3D723EFC663CA0DDF34DABB941F42C1 + B48EFD59DDCAE71A1B82358A3328644A + xor-digest = C08714035439EFBE455BAE68EEDDA0D2 + A6968F18827B214A097221C3A77F80AA + E1DD9F3C72FA66C16EE278A76C19107B + 37CC32346DBDD29FB30059A8FC732DED + +Set 1, vector# 90: + key = 00000000000000000000002000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = AD897A3C509B66728342A817D745460F + 6A258386FECF71DB95ADC716B8BC0462 + 22C4EE887334718534E719F36454E440 + F9EC44A2DC38345CEEA9425BF5F10123 + stream[192..255] = B32235522391A0BE105A993923760C6F + BBDA849213C628776BCC5364F28EE5BA + D498F186C3C57A8DBE5355C2A38DDB82 + 54B321636EAD186788DF1BFC5B6F85F6 + stream[256..319] = 499CC51B20538B14A05E490B6D5D10D9 + 11079F58E3603A84AE6689293E3AEC56 + 7545823F0B085469CAFFF01D2AFC5076 + C155F8B4B7DB4C49A9A993964928D11E + stream[448..511] = 65983D36E97AEF89C3A75616F7C098B7 + 5CFD9C531AFF8184010E2CFD45163312 + FFBCF5AC70139CF12D97325CCEFD0B01 + FBE571FFBD7DC21B54D4B277A2205E56 + xor-digest = 90CD243B35747378B85B99474EE0BB3F + CE7574CC19BEC5220255523276CDECE4 + 5A16EF44C414ADF1D1CBE264872419CC + EAF664CC74D36072E9B975FF40074006 + +Set 1, vector# 99: + key = 00000000000000000000000010000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 26F731F36F626943D4CBBD605CB67FBF + E9301F24AA4E93EDB2D0DBB3FB17E8C8 + 623054B3003BB12E1C8607FB53315AF0 + A139CDC381753A14342AB90AFDF43E67 + stream[192..255] = C3B755D009DE9965D36B4111308B25EF + 39A137E373BA0E90E5AE2748115F29FC + 562A6F6894BFEA59587F991DD105DE1F + 67F62A73A72A4802ACE727335467F503 + stream[256..319] = BA815578D19B3B384BA7AA7B972B1FC1 + 7244FA75A4CFDC8C30ABBFDF6861F356 + 6A9B68A6F60A61E6DC8E046FE75373E4 + B45EAC193127CBA3AC4F22345BFDCCFE + stream[448..511] = 99C68AC554291FCDC03F300D69CE68D8 + C4D4DFF5FB2D4C3079992D40FFCC9683 + DE471E6F2A406DCE03AF8EA17B7AE905 + 12F1368B8EFDA838274812C4F134E2E6 + xor-digest = 01AB73AE53306196763ACB9ACFF9A624 + B83A7B339DB517AEB408292627EEBC43 + FCA6397320F50E96ECC3595B13BFED85 + 1309458EFE35FA1167C2CCCC6A4CA83D + +Set 1, vector#108: + key = 00000000000000000000000000080000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 031A1BAA02280255F0413D76F945138B + C0835BFE7CA64B16AD090454F098B8CF + 34B1EE138E03C3CCD9FF918A58D06AD9 + 2D7F3FB57D2E161A863A0C25391CCABF + stream[192..255] = 6810368C2B2A091C6FB3EBB76E960AC3 + BFD678F028EB6FC0F5B36C2D386A21A8 + FE46A5AE09DB0BD75359A8482EB6F5DF + ADE199B796520807D60D9D93995EAFE7 + stream[256..319] = 0F2CDD428FF6DF2A4621A8423E09939B + 014BEBC0ADBB8CE71B5E587DA408ED43 + 04A12BD535257322122EEA2840A9447E + CB1B6D3550ED14EE31424F5404B2B5B0 + stream[448..511] = C63FCB06883F3AC65612EDF28C875477 + 1D383D42A553EAFA37ECCE26061EC5AD + C6FE3BF23E06CFDB14EC1DD996A7D4E3 + FCF7A0B9ACC69F37ADF428B434994595 + xor-digest = 463386D0F7A1306E87F3221C4ECC0597 + 9474F620AF3563686ED5DEE291155225 + 56B9372496638BA1631982D6B3F58CAE + 27810BB7AA93351B838D54EE761A8C94 + +Set 1, vector#117: + key = 00000000000000000000000000000400 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = AA4E7E8171A8E0AEDA6049999E0A06C2 + FFA43B9ADC5E9DCE4ECD8FC1D27BE792 + 6FBE2ABB69A6B69D8C213A793C77096F + D4DF7BBDBCDF007C914B7C817837D99C + stream[192..255] = FC90E3C82B8E7228C1ADC2F555068372 + 4307902A0750149CE0B2EFD2CCFE9875 + DABE60E1B85CA117D05E4BD4F45B42E4 + 55A9F42C60910C9BFF8DF8FAB53C81E1 + stream[256..319] = 9BD976B88E9E5E23D0D40779644BB3F4 + CE5C6B16FA6D955C32369DFD19D632BC + 7730683D562320E39F75D8D8BD074968 + 9ECAF0DCDCD99FF4C3939092E9576144 + stream[448..511] = 51BE9CC1362669C0F79D2D88A42DBED6 + C3315002380AEB647C8F9C4036590527 + 1D8915B985B8BE9CC1C5C7652139E609 + 651EAC8A14DF661D9869982AE5735E9F + xor-digest = 0B0C84D430687F488F8E45DECECD6D7F + 1947E32AC49BDD2139F5413E08A88F31 + F9AF6599498431F155AA10B7EC09F095 + 8A5AFDAD486D2E6D50AF77FE98E33738 + +Set 1, vector#126: + key = 00000000000000000000000000000002 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 52F49050156E957C605656B2DF88EE1A + 5E3ADA99F9793B65456C4C6C322B8B5A + 28DCC91EE0E711BC33E0C13354542227 + 613665CFA3A825B943444401EFB06ACB + stream[192..255] = D0907F5D5939D7B544476E299605972F + FE422C64BC6343F9C81093AD0E3ACC72 + F4B67314892E36764736C0715E4D3438 + 36BDB105214F5F8925F321F5FD865EE2 + stream[256..319] = 96EEDA75474D65615795185B1BEE8D44 + A687420304B260E4C70FE7F542967325 + 1826EAE010981F6262EE6CB639996467 + 5F6B23825748128617721752283C16DB + stream[448..511] = D926085A441E507207850AFF3008D59D + F7C9D3B69687D18CCFF2C2E09D4E4EA7 + FF0B72C04A86B80923DAE187FFB99170 + DBD4902AF77EEC42866A83B519F092FF + xor-digest = 1E068ACCA6062CF26ECEC79F149BE139 + 24AF8BF44377EAD1550B1560E4A1006A + A6986C61581FF9E47D58F2E52434911D + 5AFCF914DBBAE183D02DDA3210768984 + +Set 1, vector#135: + key = 00000000000000000000000000000000 + 01000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = EF5BBD7A620E8052F05DC269309AA7CF + 8AFD4AB2B941D905AEEFC721562E00D7 + 04CA70113C8A90FA12A0C9B9CD1B9F9E + 6176602CC08B66410A8BB0F5E9837C27 + stream[192..255] = AB843B43856FC77C1EC09C0DD2248617 + 820344BD2CA0B025C39B0EBD5A750A6C + 7BDCE863C068E0D3A937A5B2C5B6ADFC + 609F6DF7778D88238B89288B2768DE99 + stream[256..319] = 5E6AFBE41F47F35CA9298C973E613174 + 529D9BEFA6D0713A5BFFD96B70D39044 + 413E24FE57B01C426E8988EC365FEFEC + 1422CDFB956B12C6A799F5FDD4EE43D5 + stream[448..511] = AA960C189C0A20870901D4E2F1901D0F + A28AF3D974E14FB70736C191D4C9CA26 + 48EEBA776339F80D57A8B783419E61B7 + 52541CB296B4CD31C55DE3D34CEF0D31 + xor-digest = F163BB7ABD3914204ABAF08B844ECF05 + A36B7B37B8345115EFAA2AB2E7763E6A + E044A83597C023FB41EFAEFBB63E4195 + B60AEA6399DEBC94C75BE883B3623733 + +Set 1, vector#144: + key = 00000000000000000000000000000000 + 00008000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 9198011FAAD874AD77CD0C98DD99C7BA + 01B75CF9DE1E26321EC6AD293C73C675 + 69A349157FD47672C5326276BA40F4C5 + 0CF8D98134D0BC13879E9EC267110FDE + stream[192..255] = A9B3BEEA161ED996C44F6D3B93431C6F + 54DCD5DB88E62CA10D1067B9CB5D21DC + D7E04C48D88DF54E1370D1C24C871BD3 + BDF9B956315996F95867D1E2494370CD + stream[256..319] = D09ECB5DF5B0526372B57CDF5DCA6AE0 + F005D2E2F27D50398E3D1D7FF2100BAA + D6F2C03E431345A4F41CEF3E8D3F14CD + C76A423720A936D27322559289F13D92 + stream[448..511] = 5E8FE7964B052B6D27216E37C49CC913 + 450FAE159C087E34CF67E8B0B8F516D6 + 3C0B544CA29F9BCB2B48D3894D69DE3E + 1460783E82EB67990FFB7F92DA48E449 + xor-digest = 5515E37A3F274746847F551ECB7DB4BC + 2BC32237050BEE9AF2AD1BD8577034D3 + 4A23AB8A2FFD00C7B8CB7D5CA0AB2421 + E7CECB2801A1B73A44FF3E798ACA8443 + +Set 1, vector#153: + key = 00000000000000000000000000000000 + 00000040000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 02858548ED24761DC0AEC6752076D095 + 7E78EF1FCFFD8E756C747586A3B59C22 + F42A9FCA9F103C3054E0B4F6EEC82101 + 971F2A6F9611F7541152FA3BD7774474 + stream[192..255] = C32ADE80873D1190E9807C25D73EC5B7 + C208AC693D98A664FF4D11205650F7FA + A36B153BC1A3F0EE0F4319F2100F7F27 + 31856BFAE36110C12EF0361259641D74 + stream[256..319] = B8F74AD5930D1F2CEA6B9F7E4E775DF0 + AA97744677E5C96B9E55AD77BFAC5E8E + E9BA7A19607D9EC52DEEBECD185DAE13 + E304743019D831849F111602EE6EC34B + stream[448..511] = 513303A57165287E793DB91F49C9A8ED + 522389F03634930512744884BCA45F4C + ACB60FD077BF2C050D4002162FB811EC + 4AA855793CFF2E30665188471FFE0847 + xor-digest = 7EABCDBDA34E51E3A61D2F3340884BBB + 600E1D30216B7117081B3E5D04FD4523 + 706D4F34C5FD604134DC89F570D6119D + DBB7C5FB7CA90E38AC157832C3C956BD + +Set 1, vector#162: + key = 00000000000000000000000000000000 + 00000000200000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 689E48A85A40BD161BEC710F9B2457FD + 276F1156EBC10BB851A8517AFDBD692D + E4827BAAFF218AF886439ED976147EBB + BB1074BD599A80F6324C87BAC987B8C5 + stream[192..255] = D9BA3E74CBAA58CA97DA3D3B1051BDF3 + 29F6CD837B72022D2EAB5D20B02F53DC + 4755C764C50756A7101998C187E4F0F8 + F17A0C6797976C4FF1BA17B3D03C2218 + stream[256..319] = F6F9B6F0F6E1D756C0242B48BC55EDE3 + 3038BABF72FCDD5122C61804996F5ED0 + 86A78B33C517CCED9C34580AA54AC03E + BD0F9698A234787DFE97FCD3D9B7CEBE + stream[448..511] = C31091C4C5AD605BA90963B1D469E501 + 412FEECDE3EA8EE834F188793A98F830 + 81F8C941F11676E007074B40EB15DDB5 + 67D93E954422376F2E3039F4E4115D70 + xor-digest = DF047B3EE7F2AAACE9D5A2B0F6A1EA0B + 97E815E9B9BDD3B7862ECB414E9C08E9 + BA0109B1D6866C9D7D6D3DC9FAE5F51A + 48DE7B9077DA489B7982BA69228483A2 + +Set 1, vector#171: + key = 00000000000000000000000000000000 + 00000000001000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 1F8F707DDF0121AE4DF26A6ABDC195A7 + CB9CC8479588D2D436C52483DA54744A + 2880E3DC622180D36B64CC053CC245D8 + 0700EC62ABCA6944BF89C7DE1A532A3C + stream[192..255] = CB2D934DD1414C60550CEA6FFA776312 + 3C9336F99F16F8B5B8E60D5D0CE54A35 + E752A4887A03EEC95050E50B58F5C8C2 + FD814DE76D3F66B907C77C9B646EFD13 + stream[256..319] = 10306DD8B3EA307496D7BEB7A679D53C + 3650ADC53991D0565856F51DA82CEB45 + AFB460D6F90877557E17F534C3375FD9 + F96D13AB77FA3996998F5DC6F5D3C9A3 + stream[448..511] = 42F4D1F669741750B24A44F82990E6AD + 065E7B07B2194C96E7578F7A754E52A5 + 86C820FFDDBA671A7B08D65B51D8736F + D0DA8E81CC69BB8A56565C43845C0AF4 + xor-digest = C0535BC269BB39AC2ADCC50C62F87B6F + 2C9351DAD49813529A27BAEC163A1D8B + 778670F0FF1610A4688F86851050C9B7 + 275B087A0B5CE01B602F8D1D25C29392 + +Set 1, vector#180: + key = 00000000000000000000000000000000 + 00000000000008000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 899C1C50A80E374AE884F10BBD17D036 + 1632D89938FDB7E4BCFBE1050D5E948C + CF4631EDFEFD2F140FC3FBFCC096CD68 + 1F6C1B0CE9E395FDEC56295AE331D8D0 + stream[192..255] = 2F60CFD4D07E58DBC5127A98D2B1DDD6 + 1F216F61F70AF12427108906AFEDA4AB + B439A99765EB84E43D06EB7B3D984A3B + 53D8C054745A6E3B61F8444C84C7F30D + stream[256..319] = 1A92F3B4F6C4684201FA4AF201259AC2 + 53637B41B734062C298E6F932DBDAC5E + 999FEC21B63539B5FAFC312D0CCE6137 + 04AB3CE65E241A1C34D12ECCC840973C + stream[448..511] = 83A75C2E2C6D40FAEA049322DC1B2251 + 306A8906A37DD30182C328D50E7B7AAF + 89671DD776C9C730EEE0DACEAC7D7038 + 4A93426090F31EB851976B8B2ECA1FBA + xor-digest = 6D85E7DA2069F1308D20A56DB17F3629 + 09E80EA6A045DBE61FB037C3C8B9D448 + 526A37A431A8BE49CE4F10B8CF6A33B8 + 82E6ACD6309BA1B716810715666C6CDA + +Set 1, vector#189: + key = 00000000000000000000000000000000 + 00000000000000040000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = F9E151BE5EA0F532E56958F173B8F104 + DC9E73D8FA289CC2F84C4BB10E8EA769 + 57FBC8F539365B9E9518F8787D6CF927 + 55F0C2B2845318337F36B80E22C59FD6 + stream[192..255] = 27FAFEBD2EBCD2B67AB18BCFB7F8DC96 + F54C8A765B0E4B3DDC3013B599DEF791 + 287FF3C0F48F339DA04B667E54696485 + D48751A001B548727338AD6FB82EAE42 + stream[256..319] = 09DC2AFADEECB86278C64DDCA51EEF97 + C10B9852DB5F33A19C99C0D4F36D2959 + DE247E4DB356E67F2951E0309F18D6D7 + 27D2A1BADCC44DC320E2AA80E1834198 + stream[448..511] = 4103D8455B6DAE658915FACFF2F3F1F2 + 856E2343143671565936301E9D1F635F + EA732C9A096C3E955D33770E244ACEA4 + 094E390239489F4D4F0A1F3C26A1589D + xor-digest = 8DF4EC7886C386E5A0D7201A3E731E95 + 5D1E281321C2B592E31681CC95D173A7 + C92E6112197C6A605F494F6E9C4AE73A + 21B966CBAB1628794F0E44202742EACE + +Set 1, vector#198: + key = 00000000000000000000000000000000 + 00000000000000000200000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 8B9B0CC804CB353F49564926E3FD846F + A4758692FB110A428FAA3132F4C606CC + A41CA937FDE463D9FEC51F419D60AE60 + 1E8EDB30AB09E0B08D0143D885161B16 + stream[192..255] = DC6DFDC4E36FC1D4BD87F731F761BCC3 + 9837A790DBB766040B4508778C5CFC82 + 8EF9EC4D76BE3AE0967DBC844A2D252C + B942E97A2C6A185ECF4E1200BF9BC826 + stream[256..319] = A9DE78C2204B712A9803594B872F29E9 + 5E8962D7D719702FB3279F053D311292 + 26A14FB06058AEEB6D283EE0A272C6F2 + D392B102E294A7CDF24928D5281D024E + stream[448..511] = EB822D7BDDA456BB6E109ECD330D4FB5 + 1259D7042935BD5DFC787E903758C27C + E9E9B191957E721A7013D36E5A29C09A + 3433205956A55460D1498124B2800423 + xor-digest = 10128D9A5EEA1D93E65462702DB15A8A + 23D0FDFCC5B0871639D704DEB9F580C1 + C88213CA166F3BBB89D0926CAE7E64C1 + 0A24041A42B9D50CB0537A0585EE574D + +Set 1, vector#207: + key = 00000000000000000000000000000000 + 00000000000000000001000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = DD4CCBD0B5068DF0193F50C11D2576E1 + A70040D6C2CDB98061498891D1791E63 + C4B5103A52146CE27D8F721E147EA612 + 7E5BAE1FCD3DCD9053D5FF5EBA328BBF + stream[192..255] = 541F008D78EC1ADC5D1B930CC99D4A3D + 61BD60AAB9DDC8AF8594FCA129410232 + 92BC44EE064E44E88A07ACD1B742666A + D147F14102D23578E3B7DC00905586D1 + stream[256..319] = 6834D2FB6BF3B46C0552AD83275CE6EB + 9482C2DFE40C6B1FD6F743CAC8F40A91 + 5BA9A90FBE7CC0153D53C444D3F7A23D + CDC3134E237F63E5A07C99C10B8EE87A + stream[448..511] = 9F75BC84091695FDAA2579AF9D34B2A7 + 2B82D39A1E7FCFC4D18D6898A9CD3296 + 0D50AF1B720E1347A0848782BE6AECC4 + 684CCA05B893951A65EB7CB37F5FE240 + xor-digest = 12F358C7C4C697199F9AF17040115522 + 062514A5DC3584BC515AAA4474A1D85B + 47A6A2D8C39E8234A5D11860BC1036E3 + 957920C03E9A47E61AAFB058A9850559 + +Set 1, vector#216: + key = 00000000000000000000000000000000 + 00000000000000000000008000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = C5958694DB1D54B95101A9F48660CB26 + 8EDADED85C6239098248E0867117607C + D5278E5B5D9CDA7BE8A6BBDCE61215B6 + 2A93FFF627B28B271CF2275E54EA1CD0 + stream[192..255] = D9B69B25B5729759F3180FF17421092B + 0740B2E1307FA9141915CB8C30C0C322 + A1E4710674EE715DF3AC89F447442A7F + 845E154393273BA47F2322BC661D1755 + stream[256..319] = 49412E5F3C9B5B52FF790CBE82D6F037 + 217A13B7744740A887F7C1FBE3714DEA + 2A4EA4A5F444B2EC3C0B160A251CB44F + 8DCA914FBB80F72BC8D009F1C7E001EA + stream[448..511] = E1C2BE8C64D6BFE081EDD30681763928 + 85939DD7EBC13E16D83C8E7FF65EDBC5 + 90FA3904068784806E20F0A61CC73839 + E3BACD410F59D3848F5A628EE030FC4E + xor-digest = 54092B3D64197BD598F9050B44D2E785 + 029F29F46822B72ECA40182E8ABDABA8 + 751054FC50250DF5AF5AC75F4C51D1D5 + D2BE298770C353A7C5D608D1149F1452 + +Set 1, vector#225: + key = 00000000000000000000000000000000 + 00000000000000000000000040000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 633A6CAC516B7A84CFF8F5702CD9BC81 + BCE328741675EBA0FD1368190AB6BEEA + 7C8B0256CEDF9E5CC6F9249511AB87AD + ED95BF8E11182B8BEB75FFA279C3F706 + stream[192..255] = C3F700538A4EEA17773E74D10CE4493E + FB0417B380ED4229F651D6A9BE0AC617 + AF66C576B7D06F2210EF226462004D90 + E753D805AB198B73B0CCD752C7E57A2A + stream[256..319] = 30A11289A9E0C854B980BE044F07E945 + 06D772861896D0F75D739647FFB939C8 + 13FE4BE5C8DF84F64827306D0DD82415 + E104F787F30CD097EED7DB9340A0F47E + stream[448..511] = C2134984733448DD577DC48B5EE5D761 + 0A54AB6C32E3BB782849D8E7E8B522B8 + 0D6444342ADD9709D7434F9B4C18C6E0 + 15AE97DF8F3D29FA6D85DA387157E223 + xor-digest = 8613454AD0B424AB6EFCEA96C0802B6F + 47F1E98C52BC68DA25E653431CE31078 + 1658BC45DCC2EB43C4ACF8395727133D + 12A127D4CBAABAF24BA44930A58A87B6 + +Set 1, vector#234: + key = 00000000000000000000000000000000 + 00000000000000000000000000200000 + IV = 00000000000000000000000000000000 + stream[0..63] = 6A0F095C0E23FD6F8DCAEDAE5314141A + 0F1CE1C1BD6A16E81FEFF72F0753A5AF + C1C54DFC0DD6ED99F1D416BE3C5EF341 + 454C18D49729E80EE99F37734817658C + stream[192..255] = 05A4DF5BE8A35DC623D107728F28C789 + 3DE0E75268B3E1F94C07AE50CA0891D6 + 2B1E764CB41062391B33929273CE6B6D + 1C9CEFB35C37AB2FA8EC18749B5292B0 + stream[256..319] = 41C8AF9ADA46F7BE8EA72BB3B8661B78 + 2BE5649F18F216B75A0071A6617200B8 + 463B08F986D706AD140E27C8F4E040BD + 6BFB4872D758363281C62AE8C4B64E33 + stream[448..511] = 58CDA35476767EF58748A504B0E4A38B + 64162AD422A0DEC0434D879898558C77 + 1A8243DC43B15FF996B4C8CAD3C47C6F + 26F00C71ADFB538D9A983B7B624D6E62 + xor-digest = 240A699AF4DDBB56A4C502A9175C0E3A + BBD654D0717A1F6F6847381B978AE8C8 + 0EB7CA07A481DFF8606A31BD6B489AE7 + 89763068D641BAEADCBDA9ECAC465ABC + +Set 1, vector#243: + key = 00000000000000000000000000000000 + 00000000000000000000000000001000 + IV = 00000000000000000000000000000000 + stream[0..63] = B3C91DA5911D7D7A4BC16A66988AFD3C + 8462A9E9BD0D95C9B9884DD14801E464 + C27048FEB5F70B28013099F0A31255A4 + 9EACE528A13CB5DD067E520D183133BC + stream[192..255] = 756EDB0542FE1F11B159C7081D9CD742 + 2F0E5862D39E2CF1517B2F6F39AE5245 + D659A5B93EB8FA8C8FB751B378BB0DEB + 481B874663624C8DC15E6A1A64376340 + stream[256..319] = 436613C9293D5DCB204B46899CF23E65 + 698BCC3003FE064FD1263EEBC59DDBAC + 536566855510FA802128F0A968A2E359 + FB68EAFD6AA89D394B32BF6069E92EFC + stream[448..511] = 033FF40203ACAEDFBF561A674EE74D97 + A535A448AFF94C8C167200E5CA626388 + DB1BD6EBD4A1D83CF352E97CD8F02671 + 18E57B71D33930EC2752D2F262A55F9D + xor-digest = 2CEEE4705688B20B3AF71F285DB9361B + 0EC945296B97F3A050C31C54E9A07CA6 + 498B92917617571928E2663CBBAE21AD + 8DD880A037A024E46B6581974838AE1A + +Set 1, vector#252: + key = 00000000000000000000000000000000 + 00000000000000000000000000000008 + IV = 00000000000000000000000000000000 + stream[0..63] = A6AFA8AA02C3AE7F29E61202B4A5C25B + 6F74BCC176702C9C1D610FF722527A6E + 721ED90B871AEEC71EB62B24A8F24357 + 07765F7724BA03173F51C9B66C9F4BDE + stream[192..255] = 002B8929A54C1370067A36DB9057807D + DB747C2A4CE19BC085DDC517AADE3B97 + BB1B35F2BAA6A18E8154CD80DA6F9F4B + 0DBFD3EA5F69D5ED3B5770C6221A8D66 + stream[256..319] = AADBBFDFC6FCC6072747BB528EBEEF34 + 6DA76885CF1616ECFB89D3A134769902 + 904AA12744DD404F268B0B4B34700928 + E3C4B3665B9CFBAD9C528EA06F89CCDA + stream[448..511] = DD5453BD0D99E7D2CFC558EA969A4E35 + 743AFA96D570026106C5CF40037B1325 + 40C909C1278DAC8369B1AC257FD8D868 + 3648B4F22F7C66282BAC49D8D23626EB + xor-digest = B3F2AD900155FD5D39768B4F4B7F8E5A + 1C557936F2B5F06966DCB884AFF7F01C + 7AFC073C20EAF85363DFF41357E626B3 + B19607224467413D185A05E7BFBC5F0D + +Test vectors -- set 2 +===================== + +Set 2, vector# 0: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951 + 53F06534801F89F24E74248B720B4818 + CD9227ECEBCF4DBF8DBF6977E4AE14FA + E8504C7BC8A9F3EA6C0106F5327E6981 + stream[192..255] = 30DA9453A90909A5675D6B691CB0990F + C423CDD8222EB47245BBB67BCA2B9C10 + 8D1F016DF0CF8CEAF6829910916DBC1E + 113D11E91BEC3D85C47E3042EC865658 + stream[256..319] = CAFED71B892EDBE13388CEF6A3365797 + E0D88C0D3A5B91BE4CBAF5162F69558F + DBB45CA6F8C8D4C371D62736EC244584 + 60131F54854F3EC804AA9A38E6ADE281 + stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F + 2C3EA0F56AF46ED93DFAA4E16F5F0831 + 2D77BD0E9122043CD6A202CBA9351F6A + 0E8E6263F4017355136A0C551E6FD0F8 + xor-digest = 023D719F61C193E4CCD87755C87F9604 + C5A29DD7E31637B3DD70D43441D48CC7 + D474013C85EEAB1897C80ED0A0272543 + F951C72E3954616CB5D6B51FC24F4B0F + +Set 2, vector# 9: + key = 09090909090909090909090909090909 + 09090909090909090909090909090909 + IV = 00000000000000000000000000000000 + stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081 + 2145B56AEA46EB283A25A4C9E3D8BEB4 + 821B418F06F2B9DCDF1A85AB8C02CD14 + 62E1BBCAEC9AB0E99AA6AFF918BA627C + stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58 + 11FA9BB02CECF7440239FBB0497347EF + D8F1A8AA71AFC70ECCD64E81388E6E87 + 9521C2B47AD84F9CFD9E240D8D2F3001 + stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD + 3C8D6A2EFDAA9CC11BFCC61D94F6104A + 4091B3634FA57AB0AB9B209F22DA5529 + 75C3C322DEBE4AE68623BFE1B2BB7F0A + stream[448..511] = 35B290F85EBA78A978750690C4747E8F + 72621951483772E8B89876CC5D55F3AB + 02D9B8FB35C741279FF9B5B571B26329 + 4D011F813CB5B209CA1A22D532BF09B7 + xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34 + F6CD0A795B8347E1441CEBEE35540D41 + 64FC2B95D71FD47A2C4ADF732261EE52 + 8125BE374FA4A90132CC1063971A2862 + +Set 2, vector# 18: + key = 12121212121212121212121212121212 + 12121212121212121212121212121212 + IV = 00000000000000000000000000000000 + stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD + BD8853C329B3A881B489090853FE0F43 + 89DA105F0ADFA9CF51DA2521C40FD2B8 + FB0BF80B93E3F2B3D8A8EB1C615E0FA6 + stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D + 43A82A80DAEDBF29C048639BA38B690B + 7ED11323E3C0A8E77A16356705431EC9 + 9F2CB7F7E1ED3B83EAF2CAEC00B00755 + stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417 + 376F334E6AEF9C187012C8AD2B94BE7C + 00A876756EB232510FD0798E72EEC87F + 75EC1467C07B3A1EFB0D51A5FA65E382 + stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B + AAFD131432CFD7D2F675E03320395313 + AD4ED96E9052FE6B2D2A17428660A25E + EE642B712800BE3F7E44F21A1E6A03AC + xor-digest = EF4E84DBD66497B142EEAC56B830FF78 + 0465CEE20B9CFAF5727D4B3A588F4D00 + AAF718330CFF35508C44C1ADB8476625 + 2CC3AA6AAAE74F8BF1DDB6D4AADA425E + +Set 2, vector# 27: + key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + IV = 00000000000000000000000000000000 + stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676 + 263C1CB9AB941119B19D15EBA3462F56 + 2F69220595DE5E0E7C595FA40F1F06B2 + 6EC32252AF05310809DDDFAE2E24B170 + stream[192..255] = B29A740B51B4EA1080666337D5551484 + FFED6860A5125DC0573C8F90F23A98E0 + BA7B3E4C28C2CEFB1C33D2C36D1B7625 + 64B9A67240CF174347A4C8D868F00F6F + stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6 + 537C06AFB23354F054E25457B729B534 + CD10B2ABD45BE3E38DAF1B7A9103268F + 4FDB4C0FC9A80A003FCB907E8F249AE0 + stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39 + F62D54311207B617B727FCCE1B2E762A + 060810C4DEF672E7D76083E3E4BED0D1 + 0BAFD27CDFD2C937E660190D36B3FD7B + xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C + 18CC5E1E3F6A317ED7257887446EF734 + 65CA15F51AF5E077B7915062391D8497 + 8F437985DD08F5FA3A8D74B3227A6EEF + +Set 2, vector# 36: + key = 24242424242424242424242424242424 + 24242424242424242424242424242424 + IV = 00000000000000000000000000000000 + stream[0..63] = C845BA29D542FBED2D021C85188E119F + D34967B79D9F44635DD45D2E41DC5AFB + B237AD2FA0E4CF4202D83DF3073C578D + 2AA8A32D30FB45DE28F23CEB85E50FBF + stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297 + FD12081B4B23F0A32CE5B3196173C7CA + 7EDD03F9637E08CA501C4850C15B207D + 7AA724377396CED2357B572BBF9E69AA + stream[256..319] = E484AF567EF80BAE77461855294E9280 + EF57E7366605785034D639D6DE3EBB0D + E21886D0E1E0679BC2E2C9C2D9201484 + 4A452B6AD3F1AC8B7762FF3C0E405B3B + stream[448..511] = 595D9855200786BB575FF7977509F395 + 7879CA1F19619A99174BF013CB62F85B + FF2C3C4FE724E26DD0C10D7635A2491A + 9E7E868D9DAD9201465AA178184D06AC + xor-digest = 08737B82505F46F4FF282EF42F387AA8 + 0450058F5314389BB73733BC163D75D5 + D32FC6408F8DE5F6ED2050027D605FAC + A7119FC2DC1B6D3E84E8048DCC42FBD2 + +Set 2, vector# 45: + key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + IV = 00000000000000000000000000000000 + stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E + 6E6320101999BCE5550C2BBC9BC65D91 + FAA2D72FA4BF46B6EE916244048B1D09 + A115E3AB6C00BAC8EE382B58859E8157 + stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82 + 0C18B867C561E96DF4ADADC5A4375E44 + 5A34F9457E5F8C9A337A0C88DF0F723A + D4509F1449DF2C6AEC0EADF4C7A8139A + stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8 + 452A1A893EF034C51750388D294947EE + 3F505839C69C1708E8323C449C39A96B + FC9EC91B0E1CAA8112057EB0389FDFD2 + stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC + EDD92C4461EFBA5CF1664B9AF54857BE + C3D00319E5E8A89A8322831151EE1D52 + D8585AC79CB60B61ED2C852D04BB0FB1 + xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D + 2363BC12259B0FDB2BD8F052A572ECA8 + D1EF62AA9A48497805A413742B5AF5A2 + 6DC9FF624B49E5D6FE58BBE5251B4983 + +Set 2, vector# 54: + key = 36363636363636363636363636363636 + 36363636363636363636363636363636 + IV = 00000000000000000000000000000000 + stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340 + 42D4F07DA4D5EB05554CB7426D65C5EC + A93C2D321175B6F72FCBEBA6E38CB098 + B72534F7D534B1AADD97B77E8513B482 + stream[192..255] = B2466A173F436C8433F264CBF125B8E4 + C10BC81BD46B5C21FA161CB2AE07D27B + F66812A2C2FCB2B14C23E413CEF4E591 + AD52EF810A000B42E5C1B76EEBB17739 + stream[256..319] = ECBED2058DC50223614EB8635B834C3B + B176719C18CA5E3D087A93E5CDF81123 + C6FB819CCAFB5042AADFED5E3C33116A + FD92AA21031165A22F4751C423B8B945 + stream[448..511] = 758BD9435DE607867DA256064C304C8E + DDDF5B64173CF2C98B2842992F8C5FE1 + A37C3227B7F37D49A39F9FF929A883FD + 56DB8B1A174E1E55FCB21C9E1164C20B + xor-digest = 31761A49503946701D35306FBCBE10E2 + 02967E7EC14A328B4DB19FE79F03553F + 13A012B7297B2D02F18A216AD24A682B + 299518C3769123EE86A4937DAA9FC39B + +Set 2, vector# 63: + key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + IV = 00000000000000000000000000000000 + stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B + 26A4E7E34C0CA9CB9399F655E566383E + 246143F57776C8E08951E87F76091FE7 + 2356CC901F09A07895A890AECF047B3F + stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF + C862100A07E55FB449BCFA2D9BD48658 + 958B37B3EA3565FA66824102A14B5770 + 5E3914E0680E116ED58212CBF61028E3 + stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701 + 057710F24C01E680F58090B8E949AF01 + 8970A43A698A04C0C8639FAA665DA3AA + 562B2C5C3A03BCC38FE75DC1821ED718 + stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948 + 821FBB049DAD15B988A77C0247868A38 + 2056B66F47B0195FA30C9DB5A2334A9D + CD7C0D22E479FAE1BBCDFFE60F261C7F + xor-digest = 94D41CCAD940CED3C854DA0796DC62E5 + 6B566A980E34F353CFFD0F53AE9E34FF + A6A057645FE66D86BE30F93805D9E2B5 + D78C68EEBF61CE387277A51EB2EF835B + +Set 2, vector# 72: + key = 48484848484848484848484848484848 + 48484848484848484848484848484848 + IV = 00000000000000000000000000000000 + stream[0..63] = E45194379659D1D8904DB3698AF8B245 + 762910B7FBD019AD1AA20A6C433B4C80 + 308A9EA68697631646BF3A2107C4E7FE + 2235E8F3262A9DFD3F5CC23FEB0B2DAB + stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA + 4E947598C4757976F6F61DA5F0DAC8BC + DDF72F08BA2F446FA37F9A490F6A2B6D + 79227C93271D6B763DA7B2A907220A42 + stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74 + A43D83AB8ECBAC5206D108F869561D70 + F151A0037F8E28951B5026643F8B2D6D + 56A62E259F04A5EA304791A9468E66AF + stream[448..511] = F70794C084E6EDC07BA0347413B05FC9 + FC46994CA820CE4FC037ADBA50EAA9AD + 55064ACB7308CFCE3F35AD5C7C628362 + F4210FBC2D3264F734728626BABF5356 + xor-digest = 31815B36BA034BB1941DB1E45A941A59 + 7C3882F34BD3BF441CAE8A9790B05BCA + 72049FD10C09A14AC9DB867A82C38A5F + 524C72F783DFD16980DBCDEB486FAE96 + +Set 2, vector# 81: + key = 51515151515151515151515151515151 + 51515151515151515151515151515151 + IV = 00000000000000000000000000000000 + stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6 + FF53889A9979ABA8F23AA51DB1EDB8E9 + D08F696C1100799A7D004DEF1CA94110 + FCF0C054B0C131E6FAE0FE2F2DBF22B3 + stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC + 55A5F3F19C5A10E12EBE46DD84F10385 + 33837693588D584FDAF86E3A217C3CFF + 020278736F1A90CE07F0DCE4329005B9 + stream[256..319] = 135FAD68B5282FE59B28D2DF66463632 + 06CA92E84A73FA131EDDCE89A5C23B4D + 08FA57D455BDB32F8ED58DAF3EF288A2 + 7C72020E35DAE19B446E4C52DCDAC5B1 + stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D + 18F2111002891D3229102D72605B9BEE + F5DA36059B0DBBA7646927650305431B + FDA4A97570CD0C484BF1E974B157ED7F + xor-digest = 5125E77698C0DAA89A7E47DC5D038D40 + 7B732CE56CEB674CE653A1B6661B2740 + 0C092AFF83BEEE4FC4543B9D725C9387 + 2F89AA338222ED677BF59397200AB304 + +Set 2, vector# 90: + key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + IV = 00000000000000000000000000000000 + stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21 + 75E9AD91482965B651B495AEE819CC6E + C42AFE2C20EEACCEC4E90710D17210E0 + 4CC6832905985322C8007F872D3E58E1 + stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560 + D692A020F0A66F609374ABDCD1343722 + 05F19CA04EBDD3009844BC540C1B2B41 + 66D45E8A2E822B906DA34649E7FEEBB3 + stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF + CE2CFE99506677A956AEC86BD290B6AF + C5298A448D0DEFA99AA5CD26D318982F + E786D809C713D5A55B42CA6650191DDC + stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225 + EF6E3C21705EC9FB24873916A2C24668 + 963C03FE097DA8224A42A99E5DFFDC17 + 68CF518DE49CCAC8A70216C62C9CBA6D + xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5 + 5FF58B296071D5D39349A531E41F0BA9 + 893A1722B6102740BC5FE394A49363B9 + 6A626AB43FD6A288CD9B23F7255279F8 + +Set 2, vector# 99: + key = 63636363636363636363636363636363 + 63636363636363636363636363636363 + IV = 00000000000000000000000000000000 + stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333 + BCB02E3AD8797377AE1F1B4D6DDB86E6 + 2A59791CB553550E0492FAB42C7A2C42 + 3157C5092D2DD37D46589F17FBD86584 + stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91 + 4122EEE5736BCD12061C77DF5B0122B5 + 1784E946B4E93470170ACDD7E2779591 + 57BCC9B9F3E11E88BC2F740AA0C10C97 + stream[256..319] = FF22D8196AB3DF662210D12D0FE79255 + 6DCD39611C07F089979CF7D693A30CA3 + 5B795B7F6D64931916E717C8BFB92114 + DB75118BDB51D142CE8133415C6B3456 + stream[448..511] = 971F007EFE17662D95F47F4F28266516 + B22A1E50755EEF19149DE3A3121F5FEC + E0D9DFE7A055026CA44193542D7687EC + 695B97769BF02F92C1EF3D904A8010C6 + xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163 + C8D54A4CA36748C74721C7B6E1649A31 + 4B5B7A4BD43E7C3D2A22F0C8446C7892 + 90D54D421D37CB16400E59CC86215CC8 + +Set 2, vector#108: + key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + IV = 00000000000000000000000000000000 + stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6 + 54BC11ECF0010D2AEB9F899130F4AC2A + 38EBC15C8831D591E6675DC1CE7A471C + 4B869FE83CBF37AC70BAAE5D4AC607F9 + stream[192..255] = 518F298A6008532EEFECB3DCF72103BD + 5E3F84FEB6EA2311E8C19A2E93A9C3C3 + BB1DA7DBA78D5618D1C4FA5B0B202728 + 62645A361E55494D66C9359E41E5809B + stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A + 89BB20CCD92E7F13FDD816DD4E4963C2 + C5FC2570CBB8BB5C70848B73001F508F + 47AF179528200F51CDC6E4854EAA63C3 + stream[448..511] = 844B1D15FBFD1264169279ACD525611F + A39C7BB41F1E7A1C09090625F7926E51 + 23A4CD7FE1A3F37ADC67AC437BF0A5AE + FFFC6FB0ABF39D9908145004AA5B958D + xor-digest = EC67596C9DEF4012A2D543842829306A + 4285A3B8038818F265065DC848BD80FE + C27C2F66A57B27F7FA8AC912001EC954 + 05BC6E93D7E555C59060F5D2E294D103 + +Set 2, vector#117: + key = 75757575757575757575757575757575 + 75757575757575757575757575757575 + IV = 00000000000000000000000000000000 + stream[0..63] = 91D2772A18995DB3C0801DD3740F4466 + F9535E5BECB93DDCA0E94D19C0B57BDD + 0FFBA9DAF0B11D55C852927F8BA560EC + 4999E25848D08FCA7275E7E8571A5F1C + stream[192..255] = 72E64FF10CA9F07CC493715724DA7610 + 9E4358E8B0CAE451348B784A162DF036 + AB9796724D17FDBF356031D080A6631C + D1E8D217B041AD2EDF427972653206B2 + stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3 + 344956C29D10374E502C2EDD177ECE5E + 6625BAD9630DAD57976216CD69865058 + 130B132FEC1AB0C350DF4DACE4C7724A + stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90 + E402466550B518A177CD05985D238827 + BD92EE7EC22C274F19E682F85ABDAD95 + D0EBB3DB6C6134408353C8B0472C9A1D + xor-digest = 9A6C893F2108D13A29373DEDA65386C4 + AC356BDDD4A3178952F9126E322B7AE6 + 83C94F1A131CBEAFF26549D9F84CF04A + 1241FA374B055B0ADE7E49E8EC669E65 + +Set 2, vector#126: + key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + IV = 00000000000000000000000000000000 + stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3 + 059C5CC575D806B9029CCE3FA45A246E + 0EBD3AB2F2E324FE36ADC3B56AE2F7EF + C710AA964CB87381386C2A88B1308035 + stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E + 20BEB18D9C84187C347F43B17E0924F1 + 2348F825E106E57A00258CE4415294D9 + 4323A9812D8A71359CEC1001BAA0D567 + stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5 + 32D62E779FA0D2D08F8ABB6B0183A4DA + 4EE0329215F261D953150B9AB9FCBE2F + 568AAE361EAA8636ECC01A63F007977F + stream[448..511] = E7C44F44E06321A20E25F73E2069757C + 90499DB7E60025CF6D2D445E53A665F3 + 08EC96F6FE73C0AC90D7E4A712E18C2D + 3DED46DFBAFA24C4B0B329E52C525976 + xor-digest = 22035341489FA6EEB2A6488CA42F4043 + 57477C3F55569A1224EC39B1019E90C8 + 21D37D78ED4DCEAF6EA70724C3751760 + 38CF25DE4F84BABD80424D83A310881B + +Set 2, vector#135: + key = 87878787878787878787878787878787 + 87878787878787878787878787878787 + IV = 00000000000000000000000000000000 + stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191 + 3C69F2275EB97A1402EDF16C6FBE19BE + 79D65360445BCB63676E6553B609A065 + 0155C3B22DD1975AC0F3F65063A2E16E + stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB + 3373B816DA256CAAC37914B0C161E4E4 + 5F5ADBE444098A5B2A4CFD4251D79918 + 987BB834BB50F0834EF4985F356B92A2 + stream[256..319] = D89642D25DF97D149AE07EA18BA39497 + 8935978AC34C1DF9F444986D7505DB4C + 7E08DB3616B84CD52E7DD7FB108C36B8 + B50C2573172F4D3500B6D62A9D20B82A + stream[448..511] = A2C17FE7371604556F796429C6BE0688 + 8611638B310F3E9FAF484BA9EE29C16D + 2F842EAF33AFEC557B68D2F453569187 + A6F4CD204A0E7A733E81AB7CE9FCAE81 + xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B + 6E3A61977A7C6AC2F033B826AB9A9957 + 66671D2A1025CDF8E2824B2F58CB221D + 2A68679239D90152FF7D0D39B33FAB93 + +Set 2, vector#144: + key = 90909090909090909090909090909090 + 90909090909090909090909090909090 + IV = 00000000000000000000000000000000 + stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6 + 71A6D390BC7099A708D370DCD0E3D143 + A0334619EBD5C7DA9EF6301F29273F85 + 2DFA3C580ED65C6E952F88A0B7FE368E + stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B + 445792061AA0539DA69ED0B77B970C0B + 482156A5DEE4082A61364BF06E692399 + FB9F4411FEC515291F8949B20F57229E + stream[256..319] = 993E815F299D4841518119BFF88F6EFB + F3DB9BAE60238BDE2845DE4DBA6D79DB + C9E42BA5C3C004AE4546FD86C660FFC8 + FD6A8A349669FFE3D9E5BDF8E50A407D + stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2 + 1274F4A6D814B5440C74D53A3FF0735D + EF01B14AE4188E215CE7337C04871688 + 7159695A241BFB9D6B489FE9E23B2AD8 + xor-digest = 0BD5739ED28778023E6303FD88DAABC4 + 0FA0A211A1A5C5F230D9E67DDD9EA517 + FEBCDF0BDBC107291B6CF3ACD8B862B8 + 4BF15400493A54036E97FDEBB9A1DB2C + +Set 2, vector#153: + key = 99999999999999999999999999999999 + 99999999999999999999999999999999 + IV = 00000000000000000000000000000000 + stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC + BE99E7E515650511FF7016A0EF287ADE + 5A03839C4F83F05FAC3B0B24D4E3F602 + 3251F8D9CC4530A805F8A6A912EFAB1C + stream[192..255] = 792823ACE2C0DDB266A118068AE295CD + 716E424D3B98A9DB2501A3F5DF7DC70A + 3BD2C6E664D5E13317D6F57B8774C903 + D407D2BB6014E0F971141E89569C5868 + stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB + 304C81FA9DDE0C21592247C4098D9347 + 1DA30294DE8C100E5B17A199F744CAC2 + 4E33490FC7F223FD6B4923056117C6D9 + stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59 + 349AF2BB1DA2BA622B9824F729929098 + BD19DFC05D0D9454F604960C027752F9 + 7812E53DE6AC6CD2751AB331703646AF + xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2 + DC458E7E517637596FC8FB710E2E5636 + DB1F14848CB12793D54ABD0856B22F3A + ADFA8C33AD08B8CC5292DD76913CB105 + +Set 2, vector#162: + key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + IV = 00000000000000000000000000000000 + stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229 + 8A8806402755660C4A30CD216A500BB6 + AE975E08EC62D08425A8A62A71B00215 + DE35E5178902348698528CB82296F009 + stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C + E4F7E1B3E78C3A5DF07592F45B968BEF + F95B8B257DAF2B468284627AF4481FD2 + 67BE0B164DD86721DC8C1607A0607EF0 + stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3 + 9C056162B626F383F3E77B5C98C0FBE9 + 119A7C335C333E6490126AC2510CDFAA + 86441C72D1DD9ACBCD3FEFC0D0C794C7 + stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754 + 246C065AD23A8D709161FC74B34E23DB + B918EAFA4465125D3780BF0B5803AACA + 037AA0A14D977141B611A6CA2278B634 + xor-digest = FEFDA1A6E95920B93380CC24FAE214C5 + 6B009ADCB176D519CA4B8538EDFC95D1 + 6CA06B730B28A230F0085FE43CBEE2FA + 2EE5DCD74D66F5CBB59F256CC1ED885A + +Set 2, vector#171: + key = ABABABABABABABABABABABABABABABAB + ABABABABABABABABABABABABABABABAB + IV = 00000000000000000000000000000000 + stream[0..63] = 22E1A884ED2C67CCB2977105649B6544 + 367858D1A730AA2FA96703FA406B337A + B2159A389BEF48D8A215D870B2968E16 + B11571F12BEC0A07FA7D3B9790987EC7 + stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74 + B27776E9250B8B063E52E169C7B76A15 + 0D699278AA4124427B5EB6AFC4AD5DBF + 600FEAAA98A88DFF297DACA5ACB4878F + stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484 + 976B640E60CCD6ABFB908583ABEC3E75 + 2878371EBB5374C9B37A63E0768AE10B + D857253D940AC408EF49EDD590E806AE + stream[448..511] = F012E429C44D5DC03B88123855B62C0E + 90E06759306017B5773752973850531B + C480316CBBAEDE6353AD5FB298349AA9 + 16AC0221A4CE1E4729BFB9C230AAF9FB + xor-digest = D73B872315F9052C67C4CFC5CD912DBD + 60DA32FD06D9C8E804968E688898200C + 1D979DFFCE52E1C3B3309B58D12BDBB3 + D3EBA2954D1587D720E004E12EB4A13B + +Set 2, vector#180: + key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + IV = 00000000000000000000000000000000 + stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88 + D2EF924014F7445ED922E9C021571909 + D7E6BFCAEE0724F2A9C522C4BDE4BBE9 + FE53FE592C0FEB80D2C7A51FB8BE9EF3 + stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484 + 0D22CDDFF39EB0E3D5FDF74C6E7B3394 + A0A4271D780DE6DEE9AC58B4903EEDD2 + 6DD14E14A4DFE506748D5DCA6DDF4C5A + stream[256..319] = E79D99119996FBB5163335E2F79F0502 + 7AEA5372136E7B3C5BE1F4A673A2DC74 + 60834B81BE6C4976C4A727C8E6046A64 + 4CAF42EEA6A068B7E532581E9037BE9F + stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614 + 9F3EE55A136EFA3B417DB63D2487DF82 + 794E161B3153DDB2E1E4F385E1A848C7 + 729FF5CB1CB58D5E73FAB1F2DCEEE5AD + xor-digest = 2F3C231B0228C274255F3BD314ECC7F3 + 1B9C49177009AFF2CD88F807092D77E3 + C74C1B9B8650F581EC7603F4D6E70955 + 1B00C3192414C04AB0AD8B0B9BCFE988 + +Set 2, vector#189: + key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + IV = 00000000000000000000000000000000 + stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410 + DED6D4E331633C5621B94E7EBD15E856 + 04AB202A553EFED55A548C7AFFCD2550 + 60315FD50A305D8BCAC9C077229D34AC + stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF + 3CFD130D5B6A9CE37BEBA429AD137A82 + 44D0586FEB16D086F533D1885A82F73C + F2AD2C645591F80ED09942F0A08D898C + stream[256..319] = C214B6AC700164FA66DE346A27A99463 + C5B6C0E43A9057384BE168E163058FCB + 6E7DEC871C6531EFC8B8D581EF92757E + 219294D39E0C9C8276440BE56C3D9941 + stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE + 4C8D2171695C9CF97E2936A8BB320670 + 015825547A508EB43D96F2EE1EE2CB34 + 4E120F001500F8ACC3E19E30455D09D0 + xor-digest = FE5928C74EA21F23E29171E5AAACA20C + DD8571E907763C96B99A8C11F9A1D2F5 + 78F68A6C440996995F7AB6E69B3CCE33 + CF8CE0C16F54355696D47DBF82EA8D56 + +Set 2, vector#198: + key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + IV = 00000000000000000000000000000000 + stream[0..63] = 75559677D7C762F6CFED942D800F2FAB + AB5F3892DC2C79922E96FD34FE511C11 + 251C8EB7C639E531CE08A8C99F62E7BC + F68FBAFF99D62348FF91CCFEC2710055 + stream[192..255] = 149806A4D862EEA81F0208D927339E5E + C98E9C2A6E0DB85CC0380DED7EC5B8AC + 4ADAE76AEB9C7B7264C3834316209615 + 25221D58C0174577110596FF89C8FC69 + stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B + 3CDD19BF89B31FF75A814F470BF97E0E + 1293B750B769F5BDD750DE5025D7534C + AD541A1F26C6AE9AC2FD3237C156AEBB + stream[448..511] = 0958243E88921B81F04AE63658E52D76 + CF2638495B3A6B970633A7C8F67B8CF9 + AC378082F72FC63BEA02881CC5B28D9D + C8C261C78B2872B5EBFC82336D6E1A28 + xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7 + 0028A08A00EF935C06A8B3632DAD5914 + 84E44E372A753F8E630741266C0F4218 + 4923608103042C70ED4ECC5112B9AF6B + +Set 2, vector#207: + key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + IV = 00000000000000000000000000000000 + stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28 + 98C701CBF5E88F1F3DCB6B873E5CAEEF + 23024ADA678E1A2CA9E25AA8B476CF4F + 9FCBC297FF03A9B94A5A736274EA776C + stream[192..255] = 73B9891D1770289A67D6338909FB6282 + 9A425B7947FC30DC52B11E398E85B1EB + 537E1C02898FEBFC15A9172C254CA55A + AA1B56EA856F47E37E2F252D92D94ED8 + stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4 + 38B63B9F436FE00CC075C585297B8F90 + E6062358D29641FF9C28EED4A23FC53A + 6B5C60C2AF1E8146DB27CCF5F43BA838 + stream[448..511] = 642541A9733946827D79BBD815C03C17 + 6357BD6E81E9A61FFFD4A0BF6863AC71 + 72AEFB92C1F235641BBE1457B724A6AA + AF9FAC687552A778B034C4A4F8E41ADE + xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668 + BD0BC5A97655978E79056B3D25DF3E79 + 5D5D8BE5D1AAE877F2E7D03225CB6609 + 6EFE11CBCB728039A243E326437CE73B + +Set 2, vector#216: + key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + IV = 00000000000000000000000000000000 + stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F + 1F7BDFBB81428FFEE9FBE14DF5F5F3D8 + A044EF53A868D989E16165A0F2B95E8D + 83439BB4805A125AD0CA7994AE11B852 + stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184 + EE7A7F4B822A1C955A69E238022AA313 + 276C2003E27AEF1B4F94B33A6428685B + F048B357EAB297B7DD98E612F054A317 + stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C + 978B976BE1B6CB0D15C0324D6B70D265 + 385B615B3EA97A55D94C47F53FF40861 + 4460857AC9568556AE54A52546B41B5A + stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6 + 5BE2BF56D2B78A401D5761E2F3AF8B18 + A2B1089864999D9B99E5BF6959F8F802 + 975FBF204D6159CF23F3706CAF0D9BA5 + xor-digest = 0957D6887501D4360C430614B67D99B5 + 32849E2F5C69CE8A9F3F707A2B5438BD + 0C1237B5617FB525CC9C043A10DBB265 + 3C3F0A353E89A19838B8F68542E09526 + +Set 2, vector#225: + key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + IV = 00000000000000000000000000000000 + stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A + 50CF101BF065F69F3E78BEF5D689B1D1 + D306FF41EB3E78BEB75C4200937CFE60 + E89E370680C519B2F64E23516ADF8062 + stream[192..255] = AA30580A210B87727BE17EC52AAAD037 + 3E0DD11FBFC89B37825CA4D6F9E8D433 + E3EA54C37D678B58CE834AFA310F6D4D + 06B4603F12DBF38595AC76511D0B13CF + stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC + 8FC9B09DAA6F418D3434BFBBFF6BFFFB + F93F8A963F2F51CC487BE868F010EC0B + EE17A480542A301E33B36F59BEE13D91 + stream[448..511] = 672048756C221C12DA6178BE711B3371 + 525A92BC9A219CABC5501B0DA4CC248B + 8742E8BCBD6F5A1CFE522F3DF3BED6B6 + 5D60D1AC737ADC582C2CB9751521828B + xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB + 3F418EBEB69509D69B2594E964759D15 + 104F674CD44681AFECC3B4939CA0A0C9 + DD7AA5726653ED3FBFC833DDB0C87B42 + +Set 2, vector#234: + key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + IV = 00000000000000000000000000000000 + stream[0..63] = 2479A8F2872A813D16D15F060D300237 + 25297B812F6F3B97D74D9716E4403A5A + 684D2BFD1E15275470FEDADF1578277E + 44C6C06B8A5FCE3D0CCC5E13BF49947C + stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3 + 132D4B0065A563288F848E05EB45E48B + D15C069C02F90B4FC10AEBF1AF4BF90E + 2CF7F48C8CD7A8091014131EBC21FBE8 + stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C + EC170B064429EB832924CDA9C47B5174 + 9BFEF80D96FAE36DDA65659FEA1CC06B + 4EA3A1601A3304AA4DDBEB62381FD4DB + stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145 + BFBCDBAE19F5281CD0E6AA37419778DA + 64DDF68726DD7F4D78BBBFF4576C2AAD + 93F477A2AB2C3CA8A381F30BB944C7B0 + xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070 + 9EC7E9B89DB8EEA11045ACC5FF003DC9 + CD3318BB6F9675EEF20E15490F525066 + AF8380C663B60EDBAE30663C94C39892 + +Set 2, vector#243: + key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + IV = 00000000000000000000000000000000 + stream[0..63] = CC3701E703946194401D1BA23AD99B5D + F3F856138E142D4B9C23DC9F252A277B + D62DAA33A71A0C61079AD5A20562291A + B6EC92C66D7BE6A17E27D4DDB48EFD31 + stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903 + D565423614409AD11E821B83F5B35D83 + F26F3EF9EC1766FEA9C21C09E0AE248F + 4BA01E48BCE09D06471593B3466703DD + stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF + 96CDC215EF1A62FAA29A5608C852FFA1 + 18B473C5A7319446F3ED2E8AB39A533D + 714325D1B14E838C9EC6E037DB0DD93C + stream[448..511] = 4FF3B43841B17A279002EFB07324625B + 7E937D480DC73F12836195110ECB4DB5 + CD31CA4F92F612A95E82815328DA7D5E + 4DCC5BB6791603EDA64C57B5A5AAA04C + xor-digest = 9202B874C48D4B1A9E857E645EE8F884 + D971CE97923AC024ABEFB944E34550CE + 31712BB832F9174F86FCD369E75CA9AD + 85095F43A4B7F33AB641BD6912D2C59C + +Set 2, vector#252: + key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + IV = 00000000000000000000000000000000 + stream[0..63] = F374DA745A5CF93A567027609E5D3B1D + 5C3C8A4D15203705D978AD42279F6548 + 51FF713F5120CC93D044EF717F5A75E4 + 98DBEF559E5F157A8C819E213E93B3F4 + stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9 + 175AEAA99D55485954B265B5CAB86509 + C810E664766A8E6C90D4BEE3A58B1815 + 9076959FFFA2F30EEB12343E9E7778C5 + stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC + 418DA96336991A27DADA74FDA987B867 + B125C53C0E4E2889FDFEFBFB48797A22 + 2836B2EA42793CE2BFFD568F6234B368 + stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36 + 4CD2D730DC8D7E183EC55A777C2445EB + BA7E9CD95C8F3A206B73C422AC2E2C08 + 15A8C6FED156FFF93B63DE512EF69725 + xor-digest = 467EDA43B849054EE747A532ED0D9AA4 + 6EA1BF2B6AF19F481D6E3D55EBAA96FC + 6629FE65B5EC4B5EB6A155A6D60FEA32 + F04F8230E26390F1C8FA53D47B68FEAE + +Test vectors -- set 3 +===================== + +Set 3, vector# 0: + key = 000102030405060708090A0B0C0D0E0F + 101112131415161718191A1B1C1D1E1F + IV = 00000000000000000000000000000000 + stream[0..63] = 7CB997D6E1B46DD7C0A9629B441C3771 + 14D6C18F230291FA7EF0B039AEDCC9AA + A4AE05BA13F3931E3F8373AA320A8BCF + 28E825B2084D0FA486BE52C92C3C6F14 + stream[192..255] = FD4DC85E176D76062323B2F5B31E219B + 786596F3DC0A2AFD31AB48C5F911605D + 556399114B0779F43221FE5BDA899627 + BA6498C210D5AEC5FEC8733357571F77 + stream[256..319] = F00E84A92BEA966DC8359FA63B12E8E4 + F5611F6C8CDD04CE9D605D770B2EAE49 + D6976272057CF275EB5B4CC434EA9B0B + 8CD9FEA22D7E919097CBB36C5D239BE6 + stream[448..511] = 110560BCF38CC42478036CC228E9DBD7 + 4C44863DAFC81B528AEA2893FDBAC7BB + 2F68CCDF566E1602623EC9AE283EA69C + C032E90E409F368E28401AE6905BD4F8 + xor-digest = 9CCCCDF3F7D712D6E3931068138F9A9F + 8640478BEDFC3C7CD0802954234DD07F + 99F4B072D9847DEC2E16FAD0ACCB3609 + 16243175C84A317191A98AFF5EFCEED2 + +Set 3, vector# 9: + key = 090A0B0C0D0E0F101112131415161718 + 191A1B1C1D1E1F202122232425262728 + IV = 00000000000000000000000000000000 + stream[0..63] = 0889D6D9E155FC208941B945F2B15362 + 3CE5C79122C1085FC172836FA9B06C0B + 50910CACF399EFC9CD9CC484786AAC8B + 377972E9A90D7EDD40A59FE1B942710A + stream[192..255] = A540BDE9860D8687A45D8CF22E00299A + 36BE590AC92E70BA03B8A5F2898C2D1A + B9B1E5C87C4B10C9B6E08EB868AE3B10 + 3BB95C30831B903A3A9620ED16B96210 + stream[256..319] = 90E2A684D3960A4B1DA5DF19BF569288 + 5A23892F2003AF2319FED9C8D37B8702 + 7E61290E013FDF93683829DB99C177F0 + 222EDD6A0FE3D5F7F903D3CC15C6C6DF + stream[448..511] = AFE7454BF77E3CE1050ABFC2E25F9B15 + 011F33B93660EA4AB5E7BFC513F2D787 + 27F8008ABC1E14B06C36F7750AE88C1D + 7AA2F6EB9F2E925CD6CBDEC5FBA3EEA8 + xor-digest = F1A8C58EA8459686DC5BFA2A81E80653 + EF6141903898D1A3C7298358A79D674B + A971C106CAB035722F246D3E67D34543 + 3E71DD374DAF73036EE55E6C0ECE5FA3 + +Set 3, vector# 18: + key = 12131415161718191A1B1C1D1E1F2021 + 22232425262728292A2B2C2D2E2F3031 + IV = 00000000000000000000000000000000 + stream[0..63] = EB11D29C989FB09961A673D8412360B4 + F4E6DF0169A3CE207656A7C72D6FB8D0 + 95CB3A7A6CECDC2E167CD35F62A00110 + EF09FD32B61A8B405A3F55A1313F0DFC + stream[192..255] = 8ED27EA005A3E298560C829380D4F1E9 + F0C7FD5285F04AE6FD66C94CC07C8C51 + EE8163B7414A52B0594C5F7F80104D95 + 0858C9A52F3C156ADAA025C00B180429 + stream[256..319] = 12DA63247282599F2C50B172CDB4F31B + 20952134800FB8BCE743BBA90E6485BA + 057A9C5E0989A8FDCEF1C88DD54E920F + 7028EB284306FE6A87B0FE063DAB9557 + stream[448..511] = CD447E9F58BAFB77F6E02AB5A692120D + EC4F7BD597DE5C54523A7944DBA6A3C8 + D00000D3E70F7D9292B7135A7F054812 + 4B98680DEF6631D2D10E0E7B08F188BB + xor-digest = 6EF765CB84937D5E829A1A1664EBD23C + B474FEA3C5AB137F2D9B35BBE0816EDD + B26EC14D74EFD0F9768C521A6FAAF122 + B5E34A36344FF0F0DB3CC2F2780D05E8 + +Set 3, vector# 27: + key = 1B1C1D1E1F202122232425262728292A + 2B2C2D2E2F303132333435363738393A + IV = 00000000000000000000000000000000 + stream[0..63] = A71D4189D1338531D3C03D00A480C8B8 + 49C779B7E113FD8D59516164C161EAE3 + AEBF74542FFFDC2FF8C2666FD5AAE413 + 19072673F958F498F8FB9743BE46863B + stream[192..255] = B0B3803396AFF1646369B6FAE62EDBCE + 5254E7C8FEE88F9EEE5D8A7B6D44ADC8 + B89895198E3C147FAE0C9B8325EB3501 + 6EADF77C5D7F402CF3168448D2A59E23 + stream[256..319] = C1CCE6956C8257947C004528F568E3CA + BE9ABF891E2FC2B52D9A1E6EC97A22B1 + FFD1C77E50A17CB47014C9EDA1853AFC + 11526F6268102780ACB3E0F120398AD0 + stream[448..511] = 765857312C8994EF6BC7259673F02E38 + B7E0A764FB70534190033FB1BA86D5BA + 3BC6851DB596970A2F60831EA1A31CAA + 96085680CBCFADD9C5F0330CB72AB5E2 + xor-digest = 30EF19DE0E750BBF6AB3FC924742CDCF + 62B2FE5F25983BB9777C727679CAA39B + 1280AB468051463E7EB287AEEFA5AD0B + 9C9DFCA45A3124D5F41F4B0AF5849E62 + +Set 3, vector# 36: + key = 2425262728292A2B2C2D2E2F30313233 + 3435363738393A3B3C3D3E3F40414243 + IV = 00000000000000000000000000000000 + stream[0..63] = 2B9B987B7CADACD2FA50A53A9F9F44CF + 4ED11B3E25FE57F1372C6D570B470AFF + 5FCF3BEB89D0692D873EFEBD26EAF3E1 + 1B6892913F0CB27F3CA9BA20AF7A98F8 + stream[192..255] = 0148F54B1D24F3D69A2086D6938898F5 + 25BDB1B1F78C5F92BA21FCE803A52591 + FCEC9A1AFB0FB3B081CDB1D79D254845 + 40EB9D624B5E113A4F143716722687ED + stream[256..319] = 271FF1107AA8968E0ADDA5371F40224A + D8E134AF80D5ACDC9803B1B3A9819BF4 + 8ECC3A68B303E1275FA97222F7E984EF + 9C73899433230FD746DA6101DE37ADA2 + stream[448..511] = A66D3BB64C35C71BBAA3F5410F388253 + 2B32897B1CC1AD610F3AA195CDC1EB82 + 0262E817374384BFBE200339B284ADF4 + BFF6960B6A41AFA9D7C9B67B19C14C37 + xor-digest = 3CF10A4A8BA3E0DA3C0B63F1B913B57F + BE47580DF7D90B13459A9BC98B93B014 + 1185E910EDC0A5B37206542B17CAB8CE + F050A4ED3D7097B6A0738095E4BF7A77 + +Set 3, vector# 45: + key = 2D2E2F303132333435363738393A3B3C + 3D3E3F404142434445464748494A4B4C + IV = 00000000000000000000000000000000 + stream[0..63] = F32665A4C73608E133D85712D2CC9A76 + 6D2B83311B3F44564A56A97ACC9B6492 + B282A2E62A435A7B7799073E010C78C9 + 4B7B5BD1B25994D1CE31B51CBB13BE90 + stream[192..255] = C9F24592930A0A9148486D77C1FFAAA4 + 4E4EECB088D6AD38D73B195E576BEE56 + E2CDA968FEB85D19BF89391813501B02 + EAB39A2E78B8CC7456EE60EAC3454051 + stream[256..319] = D8E1D09F074708379189BBFEB1E24053 + E0BB5980FFD0371265320C3047F0ED36 + A65CA8D0DDF20DC25B552E1882811C77 + 6613DBB4297DC6C89E31529DFCD17C82 + stream[448..511] = 8012813E7879B3E99C40821A97469BF3 + 9D2EF3B888E3118275F47F8C78A5F7CA + 19A98B1817D2D7734E69C5ED43773D68 + FA100E2C37F40FF8E018DBA52C5C239C + xor-digest = 8AFB9CD876AF4F9693FF4FF511D89957 + C8BB31D9DE3F21B726667681F805FFF0 + 4B50850696D6C2E5C271D199CF49F1E6 + D366C7824273E99360BD5A294E415F0F + +Set 3, vector# 54: + key = 363738393A3B3C3D3E3F404142434445 + 464748494A4B4C4D4E4F505152535455 + IV = 00000000000000000000000000000000 + stream[0..63] = C72B0F98EE5C2D44260E929C70DBF174 + 02C03543483178C8BC129D67FE2746E2 + E881F8439E2A11EBB3716ADB16207BBB + 91454A71C444445CE64003F0BB1F481D + stream[192..255] = 5590F4278E78AD19293525095C2F76E3 + B35A3858CB5912B62304180225BDC985 + ED955521436DEC441B9C742B3C5F4CBE + 94B99689048AF93E48472980D058807F + stream[256..319] = FBAB34E9F432546EC8C52750DA4D2278 + 4C1323D4E3F4E9B63E65A7E3C8B2637B + AA5D0A3B897113F68C63CCB78B5AB40D + 0A0DC3EF1EB09DF5C4770B343B6B5155 + stream[448..511] = 78B0144CDF2692F0D0F164ECC8621F5D + A00C401007B82AAE7753712FD6185E9D + 7ADC8CFEA6D5BBC2F3EDB8BF2C77718B + 6A424BAFD30C30934FC645FF05704BB1 + xor-digest = 835B5361A9C1F88223DE7BCA09030CD4 + 67065AAE99198645029CC0AB9B9BD579 + 14332392ED7A433A64D95B44CE228860 + 7E029235580276BCAE88F37418FB641C + +Set 3, vector# 63: + key = 3F404142434445464748494A4B4C4D4E + 4F505152535455565758595A5B5C5D5E + IV = 00000000000000000000000000000000 + stream[0..63] = 804025A410EFFBA58647A9F4B443BFC6 + 1CDDC30CA04DA8DAB3EC6A098A830D68 + 2683B59B76C60C09938E67CB41385315 + E2504B024DB808923B0909EFC25F0927 + stream[192..255] = 7A4661190129E3F349DA7B44DAAFC388 + 5E4BEEAC9308844DDA45E8E06637246A + 0E6C8C7D94C5F710CB78CC6E0CA82870 + 8CA77B6266B41E3ED6BAA2940F1977A5 + stream[256..319] = A3EBC22126B6069C674DB604F8C22B54 + DA68FB4390617E86C4FF089344BD0DB3 + 887B3438E8EF8207FD89B2A485C0B383 + 22AEB69750AD054F843DCA7995BB58A9 + stream[448..511] = BAC68211F125B57B8CE5E42E644997F5 + 2FD4B8A7D5CBF89ED2F6B5F4D4C7FA5D + 0CC34212160C6BA536BB7604C184367F + 2E088528F3B3A0A1B20F9249711162B1 + xor-digest = F628E74D1EB94591694631F1B2F12234 + 38B056789D5C2ABD8CF34D9FA7B8C304 + 5A8C2298B7BEBB90C7CC86895693118B + 2A43B7E8AC7E534DA7965EA720F19180 + +Set 3, vector# 72: + key = 48494A4B4C4D4E4F5051525354555657 + 58595A5B5C5D5E5F6061626364656667 + IV = 00000000000000000000000000000000 + stream[0..63] = 40409D9AD4CFCEAEB8FF613D32B59180 + F5DFBBF44C1B7209AD1AD5AE94DBBF3A + 83EAB34D2617ABCC396880BD5F5D220F + F434DD575E66CA74BA32862293113C5D + stream[192..255] = 42D9EDDAF89B93DAB4AA790BC9C45BAC + 5E94575E175C2EB1CC08BB39019E25C0 + 9B0F4F435ACE371BD9235C61C56A362C + B1A64EE58F4938D59073C5A8A1BA679A + stream[256..319] = E40477D1B6C901AFCC4A2C429845C7B9 + 0DF890C317A5B9D6368672C58E0BD5B2 + 7E42DA77BDC2BF47F9AD195F7C192B53 + 24FEF88E6B3DD1669A068E3FCB58B203 + stream[448..511] = 7616AA094DFFD4BCF94E03C9CCF95C31 + 8F247AEBDE281334F8E6F46271070BC0 + 1AC838D8FCFE18865DD30949C68052C8 + 6E93815B4EA9480B2D0B6A5D9888E597 + xor-digest = 1FE60024F188CC243F7D8221D990ECE3 + 29E89847C9BD60AF23061E9C27C4908F + B00D8813E680F00665658CEB077BEFAB + 5DEB41D3547DD645DEDBB3BF5D7B651E + +Set 3, vector# 81: + key = 5152535455565758595A5B5C5D5E5F60 + 6162636465666768696A6B6C6D6E6F70 + IV = 00000000000000000000000000000000 + stream[0..63] = 1B8DA47812BF2353C17C89AAA8695E9F + F553BBA44087D262FA0C710B69765F12 + FFE190625F58DA899B56FA7AB5E0E674 + 4CA2B073517B9577712D7155E16A874C + stream[192..255] = CD2BB4A6C3D7211773421014611B677C + C0A8107544ABF4F914F825891E52DDDD + 76EFDBEE614573FF9674EBC154A3283B + 439ED8197E1EE0705955A8B6C8AFF8BD + stream[256..319] = A626C40CD2C48AAB016C29020096DE28 + F03842E785BCE9D9E385D0B13B63F82D + 789588FFAB07B8CC0FFC62AA86D37CAE + 5CF8FD43B575F9F4D6E07465B700D47B + stream[448..511] = 16A3C84858207E141022D228079D6067 + 2784EBB56E3B84F7DF07EFC69060E27C + D1311E51F5893AE6BFF80D34464DC60F + 61985F8F88164CCA69EFAE568BEB546F + xor-digest = A24EEDA74185884C5B287663C3F5F031 + 2743CCAC657C702A29E0C20BDDE304AE + A54A9292B447039D50479B6CE475115B + 8791854540E15D642859D10561AEF26A + +Set 3, vector# 90: + key = 5A5B5C5D5E5F60616263646566676869 + 6A6B6C6D6E6F70717273747576777879 + IV = 00000000000000000000000000000000 + stream[0..63] = 3F7261A3A4691A73441762D113EB7817 + 4C515A96C5C93C514EE559E7F78A633A + 01F0891910D44A7EBB18768E3B912488 + 6069CB5304E79ACA89F62EFEC4EAC11A + stream[192..255] = 5F11904F72123CE29D1D883AE5CD2A89 + 2AB26C9167A24A57D6F64BDE3A8E1A93 + 7C5347C585226DB44B6252AEBF3CCAAF + 2D5E60C56FBBA6068B35AA6A61C84A44 + stream[256..319] = CD6C5B784854E0121933E77C700D9C1D + 7452999F859798499A339F78FCF84615 + A3190A2F558CC529E636922A1B75A3A1 + AF280FB3F486303093DC1564EA0B6D3F + stream[448..511] = 61B8163A84540727204F0B18D9CAED3F + B5FA87089FF4E721D2EC34D21C59B93F + 95297725780DF04A5FE405FEBAE80AB9 + B8307B9A74774E76063F9218CE243002 + xor-digest = 944EF8435F32FF2A67CDA5FBDFE02C81 + 0997D9C8192633A193D6122A051B801C + 15555BDF410917B9E5DB86F4DE8B9874 + 3E9F92F903543AD14087F4E13A915DE0 + +Set 3, vector# 99: + key = 636465666768696A6B6C6D6E6F707172 + 737475767778797A7B7C7D7E7F808182 + IV = 00000000000000000000000000000000 + stream[0..63] = 71BA7454CF7F6CC93C89EB22B9D608EA + 0FACBB4358DD007421DAC1E65EE99161 + C542DF02611AF497B2D53748D0129C0F + 5B9704C8A6017507EEFB26B6287662CB + stream[192..255] = 92D5D35B2E02D204E68C1AD6C018DBA6 + 7A1C90F563AEFC3D031FD3F7D4F5E2F4 + C47D326A9C49A0B2ADF03D9E7E429AA3 + ABF253E623BFB9EB040B5F5CF1FF68DF + stream[256..319] = D6C22BEA96DF94CE9D5D34E6231CE4F9 + A2D2F6097540F9A9160DE139E2E80D0E + 5AFE08131FE10F0DD7367E43D314D7F2 + 2321B5F89DC64F286576BA599A58F48C + stream[448..511] = 43DC3ACAE02DBF68AB5B65A81630474C + 639FC4DD36FBED518B6471F7C3E70FDE + 23CF1E128B51538DE0D5A47F20A554F2 + 09668FE28B0C4884888FAC438960CE7F + xor-digest = 7B0EF650F3847E3EB15EA1CB64EE7189 + AA5B04F527661C00F4603E48CBE59F7F + 48498D80F6C5ED956ABBF97E6910EFB8 + 341C7BC2E81E66A4B9474BE420DFA5A6 + +Set 3, vector#108: + key = 6C6D6E6F707172737475767778797A7B + 7C7D7E7F808182838485868788898A8B + IV = 00000000000000000000000000000000 + stream[0..63] = 3C4CBA573D803324D099BE1F436F944F + EE506CE77EBC01FAF0060B76FA5D2005 + 05CE94AA15F3C4B1E0194264CF13878E + FD36288EA4C2ECBEEB76828EB460AED7 + stream[192..255] = FFA464FA648309E295314DEF7169DC60 + F63C90AEE9F27B534E11D25AEC454823 + DF6BD39C1F9CB46276C630C129536506 + 187251D638D3867E96A84BD570F78461 + stream[256..319] = 6BE88BD0D2257CF7EBF7100B442F68C1 + ACB94B6F8991C1461D318BB80E59A6EB + 8009DFF46B8E339A0CD4FB285ED1E433 + 5FDBD65537D9CF1FBB0F9F10E17952D0 + stream[448..511] = 909997D084DE4F6C910D57DB89E1EB56 + AB3F9974E3DB5935D59917CACCAA31CC + E009324E52334BDD6CA971AF49982122 + B195229DF0BFE2C508E981D303061B2A + xor-digest = 8B2B49D564662BFB29A9F4E1A3DC7664 + 774D41168EA27505A2A518DD94C2A507 + 0D28E1E69DA2F084DAB024E8EE2D022D + BC73071B8559BE2FCBC2AE3605696482 + +Set 3, vector#117: + key = 75767778797A7B7C7D7E7F8081828384 + 85868788898A8B8C8D8E8F9091929394 + IV = 00000000000000000000000000000000 + stream[0..63] = 6EE8B7E51036B951205064348C222881 + 624E9FF59DFED40AC6CDEA0945A39E72 + AD05FA929F7AB69BE8234567734F8F96 + D74DE6038A463BD8FB86224F5CEA0D45 + stream[192..255] = DD9CD1757A95E616E99590E76620E9DF + 0BF811F73B70C5CE982FC9CECEFFC6BA + F7DCA30517A9BDF44515262ACF297AA2 + 2CAC3F216C12A9D0D6912578DC672D18 + stream[256..319] = 0B7DE245062DCC9B1D8A945CD9A04938 + EB9BB258B4B7BCC263487B3599B1C6BE + 7FDE752D65345F00DF90896DF53244A5 + AB111134B36A99E2D2200B4D2003A520 + stream[448..511] = 2566E8427BBAC7F0A35C6E4BCDD326C9 + D7164A9E1F767038A09A75B5076E05AD + C51F008E9E3184FA4DC6E4764B381944 + BCB96B57FCE2339A01501BDEED46F8E3 + xor-digest = CC16803D36710AFDB1DEBC653DA7DD12 + F45B02349B87C3006DDCAC1635956846 + E4D7D6064D19012724BBF836A7DB7A3E + 3C12E6288F546EF316406D9C5E844BAC + +Set 3, vector#126: + key = 7E7F808182838485868788898A8B8C8D + 8E8F909192939495969798999A9B9C9D + IV = 00000000000000000000000000000000 + stream[0..63] = 4F4169DF51C9865A20D7E79DEFF7B121 + BD61F4C79AFEDD0598F55E9D9A3615AD + 19292095DDD83904B3683722A3337BF3 + 4E98F63EB19927155E176F2E8D5560B3 + stream[192..255] = CF82F8F2A46A898915B3E371BE941811 + 682A8A0A20837AF471B5CAA4B4FB01E7 + F2B0CA9ED3BA70BE305587F1ED995946 + 223032F94BB2ED7D418C95F202887E6B + stream[256..319] = 219C121E08F7458BD657AC4131221C78 + 43DB5817B17344922C54A002F3F67574 + BEE5F7FFC7EFC5615444B51FDDEE8B71 + 981FBFF658D2504BB53C13D0342258E4 + stream[448..511] = 55C2A93F43F260EABBC1A173AAF80A95 + A7EA74CCEF6E29C52957AB2247126336 + CEA5BD0D08F873AAF733B3A11885F04C + 58542B4C8ED3E1BB7F7918C4E92926FB + xor-digest = F69FE6EFBB4A6E65B517445069859EAC + A9C19FCB9C1771E75266E5B4C39019DB + E959AD97F2B8D7F1688FD0AC04AA7C2E + 602F28A63DEAA49A7BE1422B47CFBE00 + +Set 3, vector#135: + key = 8788898A8B8C8D8E8F90919293949596 + 9798999A9B9C9D9E9FA0A1A2A3A4A5A6 + IV = 00000000000000000000000000000000 + stream[0..63] = 3305344A71266B450B2CDEB049A048D2 + 6171B39A88C25CFC0821E4F4EFE378B0 + 702DA31652B5E1BAD9FF4C19C20BF329 + 639D5942DD2209DB1D1474B6A7B41B76 + stream[192..255] = BBD9714BF2C343B11DD7943DD8CDA8B4 + C6A913F1DBE21A0582B3FCFDE91B61A9 + 8863AAC17D07D8F98AE8E71BA5636251 + 49FAB3EA775D3C7735BFC732C3C42571 + stream[256..319] = 473F161607321838FEB9359B0006068F + 9D88B1A073DA14E60AAF1501F3A27350 + 53E3FCC794893257CC3C1D4E1E3CF609 + 975E865CA46C892823C838822AF0CD2B + stream[448..511] = 89F37A53F18778084307D0BB71E5712D + 32F0F3B7C2201D01D892F6BF6068E4B5 + 394995CE6BFACF08587ADA39CC647DAB + 9B12F5505055F372FDC4607F0355DBAF + xor-digest = C9E7E4A4D6782C02AAC4F47AF1D142AF + FAE569B755E880C6B8A5773EFC0E63D2 + 3D7A113738CDB1A0544175861401149C + 753D723CC1EF515A9323DDE4B4A765C8 + +Set 3, vector#144: + key = 909192939495969798999A9B9C9D9E9F + A0A1A2A3A4A5A6A7A8A9AAABACADAEAF + IV = 00000000000000000000000000000000 + stream[0..63] = B7954C45CF301CCAED3F1E7E77DCE45F + 2D41B3B1C1F28F0308B8AB4293B64A60 + AA7936DDF062613DC1C454033D2A40A5 + E99BD975A26185A7F419E7B337028FAC + stream[192..255] = 27AF957AC6C514514C24664AA0C9C23D + B1EE30950177389876FE4FF2E1739912 + A09E20A2098751049C8925334960A324 + 5ABB50F3D333587B67F153DB145B5F6C + stream[256..319] = D94FAF9FCB753E992B898178373A36D6 + 23C6BE2420AC2EA848130073F086164C + 9B4E69B024991FFA8FAE94E3C2FB16F9 + D747320A748DE9FAE4FE9E6A7E7D5659 + stream[448..511] = F664AFD3EDC0FAE88016C8A028E98D34 + A27843372C6BF8F51C7B49B94A11274A + 6A161D776E6C1FF05358F28426C3579E + 053B4137F8C4CAE07B994B80DA06DA27 + xor-digest = 521594487B583F5F71DA10E2316187F2 + 2A4885A69D522F82F7FD0D5F93F69B2A + 060EB60965AC010BC489B401F02C26E4 + FE3F82B83C964B4DB4E0E6BC2CE4B865 + +Set 3, vector#153: + key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8 + A9AAABACADAEAFB0B1B2B3B4B5B6B7B8 + IV = 00000000000000000000000000000000 + stream[0..63] = A5E320FF65811FF5E8934F3AC73B3733 + 77D3AC52446F64646946BFB8F6DEFE3A + 04E859DCCD9F421D2DF541F588B9C204 + A9846C7AA1C017D637D7C5E244602105 + stream[192..255] = BB16A9BDCA0D4BCA589A34F9278AE55D + 6A7711EC87563C9F394638041CBB0E40 + 4CD2149218D501D3B62421CBF81C6576 + FA659C2878839FCD6C8DD1BA38F46E6B + stream[256..319] = 58B4004C53EE64CD45BC4A1F11F700AF + 0EA5ED86C4BBC145C8F588B7F708427C + D2292D76329E4DB1F289DADA687B7784 + DABCCD29B8C464CE021856FD06554F76 + stream[448..511] = 1113D37AB2964AAE6586AEE1B060F0C1 + 02EB3AF048A59CB709792C9080183CFD + 2A1A47277F413F1219B5AAD7C8BC8079 + 246BD1D6F98C11997E4ED0F68E165D9C + xor-digest = 512F4852425DBF91234DA31986732CC3 + 1F9649A1965E22E18CF38979EE6D92B0 + 83333422A92F841C25F827782FD7BDB2 + 8F4B40AD5EE53C37192651A86F03A17E + +Set 3, vector#162: + key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1 + B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1 + IV = 00000000000000000000000000000000 + stream[0..63] = 96328CAA099502092359F397972568F8 + EE2FF1C4305EA06FFD8CC125CB10BE85 + 65EA30B621437AD4CF9CE731185720F2 + 0CFE17DD45E6361A8212EECB346D391F + stream[192..255] = 74F26B7A37D673DA0B78B38938C5C1EA + 2AC666612468F63B540EE7B17548F8BF + 60A9845BECCD7222620FDF7BE904FE24 + 7D2B7EA749C9590133CD6A218F6EF624 + stream[256..319] = 8F8AA7A4C64C3AEC5E85581C53E3FA64 + 22CEB927E370C7B0F98F038E7ACF4D05 + B54430D91B0A2CDC001BFDDDCD0081AF + 35B67E5BEE6B8E113F36E3B23CE29F57 + stream[448..511] = 53E20B4B90B2DDAB40DC30643AA5F539 + 70ADB65DD0B64CECF3D3B4C0567DC818 + 0362FE9CDF920526C59725AE861940A8 + A32C35382571F2FF20E7FBC504E1DF9D + xor-digest = 8C7C45F50A151D551E9EC81EDFDD5B2F + E676E14253FF38EBEA12395040643211 + 3254B0B7298AF77F8F9F4203B971EBC9 + B9850152A96C97BD4FA7BE8592670903 + +Set 3, vector#171: + key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA + BBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CA + IV = 00000000000000000000000000000000 + stream[0..63] = E8DBC8E5D18C5BB2B152A6AE9487AF35 + E2044F30EE8189659043923E579C70CD + 4A5590968600AAB0F021F7AF283D61B4 + 13C739DCFC22632E1F6CD553D4F21976 + stream[192..255] = 8675941731B385016430C9A157007EBB + E9BD8BBBEC44081C1F5E73C7E783AE90 + 1A7F56A20E5DECD1E94E1C92A07CD2B9 + 91619BC3358AB812D58E0B98EA288D03 + stream[256..319] = 8D09462E5B1154175513CE7FAE1AAE89 + EA2AFDFDF1B39D69FDF60B1954BF81E1 + 62F29468E07C251E2D174E9CE924A5F4 + 8A470D1808C68ECE534CC08204C5A2E6 + stream[448..511] = 60C5FD4C1831F0EFD70EFF86A5D38D96 + 2C402453561D0021A51F07D40A7D3B8A + DF455CE484E89437DFADC52A52741B80 + ED0EFA9AE4FC39659F8300AE9292B9CE + xor-digest = 12E57044A8E7F02EBF6912BB73836FFB + C4A2F47AE1B824AC97C1237B1B14DEFF + 12B5B87DF14A8B5B6C85C0481BD69DDB + FD76FA307F4C1F7D21E60C0BCFECD3E5 + +Set 3, vector#180: + key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3 + C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3 + IV = 00000000000000000000000000000000 + stream[0..63] = 540980C2A3794C04B93696B90E48999D + ED8E1D3F4720918C80C95B9AC0E911F4 + 6593C4A920AB291D98891374EF286286 + 2386B5FE17654278EC413AAFF1C384DC + stream[192..255] = F3E036D7620669F851A1B58BCE57B079 + F5D75829EDA4E68C36F086CBF2E5DD78 + F7F30C1AD9E4CB3C01B7F2FBF53A8AFE + 957786B2D3E9CCFE7D6FB24397803BC0 + stream[256..319] = 1AADB95F07E6268BD82ECF3453DB5014 + 9745CCEEA9F1887B5F257594ABBFFF43 + C3187BD9A9FFBCCACEBD7A21FF90D18B + 57FCBAA64B8FECB56D5A7FE05BF03E3E + stream[448..511] = 4170D41CAC2A7AA5A3C9228BF386B9C5 + 57795DB5D1AE547A31C553F55DE02E6E + B69D76A984F4F1D84F29D5CB98190C01 + 441DEEFABDBFE405F22FFDE734D9497A + xor-digest = CE103B99AA95B51D2D6CC54A15833E34 + A11778F5E05BB7AB61505D473228069F + CB40015BCFDD3E1D0D5E1F832791C8DD + 3184273D1B4C67D800EF5FF004660440 + +Set 3, vector#189: + key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC + CDCECFD0D1D2D3D4D5D6D7D8D9DADBDC + IV = 00000000000000000000000000000000 + stream[0..63] = CA30678AC97B4591E287FF8B5E28A838 + 611D654A4EC592328039E3A1DFE90FAB + BA5A37133E821E0960520EEC850B6962 + B0378E77770681ACC0929D16DD260925 + stream[192..255] = 79FD1893EBF30CC2CA9C5AE92B0C063D + 894EAE4BD50BF462420081D1CAC57A5B + AA92E73D3B3CEA147E1F7127AE1F6FA8 + E9B302A068F26157C904E0AA7B7A072F + stream[256..319] = 6880FCE56677345CF1CFB2D38F890C15 + FE33D377922AE43348F5590B84426EC9 + 0DC2A3863136790EBB7BD9493D2F0808 + CA9287CF95AAF366A11D6E7A556FDB02 + stream[448..511] = F385299A7038DA8A90058C510727F3E4 + 524A2D95D217A1C199552753F253D45D + 81DA40431910DD54B619A15C5C302411 + 613D28D53493AD836251F0047FB911DC + xor-digest = F3D10E261AC596959B4AACBCF335D043 + FFF65E2651F046D300C19510E1677F1D + 45F287DFB8C17055A012C234B6EB04C5 + 76ED2EDE12DFFE6EBA4A39A64DDC573A + +Set 3, vector#198: + key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5 + D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5 + IV = 00000000000000000000000000000000 + stream[0..63] = D5EC301FD496586D54D9B21FA23DECB2 + B25DCC0784BF77DE84898AF96023647B + F1618234A239F63FBF3478FD6EB79299 + 66BA9B670C64118444C95D31405873C9 + stream[192..255] = D455D37F435FD0FDD6E1EDF8BAC28D2E + DAF587F938C49A5F58C32CE8D5B8A4EB + 884B016E54277300D461FA21512E7695 + D2D7489A4560FC7A72A510219DF1C5C4 + stream[256..319] = A7B93D8B7787B6C8F80EDCE72D4D644F + 0C6400C3AD0443FDD19C3F3675083F4C + E5ED87032B1813DDFF758854C8D889A4 + 6FDC61C210058DB72D838A0913D80611 + stream[448..511] = 94232F4284F46DD2E7933F9635C26C48 + 6CB935031095777F59BDAECC4FDB4109 + 9037C38C91620586DE93B66EC7376502 + 6853B7390CA516B694583447DD863310 + xor-digest = 8596C088FA66361FD90A2132CE33FD52 + 34910610DB006D223B0574F21BF1CD4E + C282C67B24AF6DB0DB70BAFF65D5D8D2 + 1C3955D466EA2B49C5E8EB7E07475919 + +Set 3, vector#207: + key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE + DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE + IV = 00000000000000000000000000000000 + stream[0..63] = DBA2DF9ACC53C3EDBB566C28F689D7AA + EF631CB44EA91610A94685FBD862C9D9 + BFCF512BCECF36E035E2E577F6BF6EF9 + E4B0E7623E0DB23B10055677C7B9F857 + stream[192..255] = 8C78C9714577E497E3CDFE3ADE19F03F + D2DAA3211C1E9E5D9F21FD1ED696354A + B7552BFC7FC675FAFE7A739F6E60A839 + 547F8F15BA5EC6F75BB05606BBF209CC + stream[256..319] = B23F187B1BFB5A728BDBD78B75C3265B + B04C6B350A4DA4EB021D6191263F052B + CAE73E5776002FF05DEC3D341AA20D2C + FA523E6B92329A979BE06CF4F848A1B5 + stream[448..511] = 7E2ADEA91939388D36B3F97DC87C2A86 + BDE7BB4884C40D8A202964ECC7440987 + 1C64B03EAD0F46A3A1CD2CB935DCCD67 + 0B43292D5B852B7A1B3D1F853EF22EC7 + xor-digest = 1AC1E42C2DF9858537D0A1BE3B2AC094 + 54136E53AE56B006395969C7F999B2E2 + DE1DAE62740FF339DFC8769F67AEF352 + C4726B4AD4BAAEE56AB8C55FACE34860 + +Set 3, vector#216: + key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7 + E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7 + IV = 00000000000000000000000000000000 + stream[0..63] = BB00F8ECA9A10D2B137257E86B455DBD + F9A6A861F19533E38C3C9F54195AB803 + 171D35043FC9C4204AFC9A8E72EDA4CD + 60220B2EDDEBD5482D7833979C15B685 + stream[192..255] = 6CCE94C2BEBFD223AFB7AF1110F0F6C4 + 01AFC533BABD84F8C4A54E8A239A194B + B56E0CAFDCC59B9B5103471DCEB9F706 + 7801D79530B7CF40F2DEC73A169C7481 + stream[256..319] = 5144745E042B76A6B62E78C92FFC1C0E + E59979CE4B2E4B2CAFFDFCC5E75510A9 + 201E8A97A6A1729E35CA81D8645FC118 + 177DA5FACA0293B972AC0957C43BB1FD + stream[448..511] = DCF9B6116FA5EB9CFDBFC8C97EFD89B5 + 268C0D529141FC3C8262B8BE38E94973 + A21919D498FCC3896B0FB4CEB24D9E2A + F728003C36838638888FFF1D0D526B37 + xor-digest = 99EF8A7D0B8D08E976EFBAE56F7CAA91 + B1FFC7428EA56B7A697AA3B621AA8DBD + 52681C7A9A415049AFB6B7D8AABAD024 + 0F9C3112092816F4C69D36B1300ED3E6 + +Set 3, vector#225: + key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0 + F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF00 + IV = 00000000000000000000000000000000 + stream[0..63] = E3DAA6E498609DDC5A31BC0B6ACC880B + 695097D2CE2D1FD162C7802DC0D00BE3 + C0126CF947CEDBA7833421D70A914BD6 + C33B0A77BE8BA10879D664F054C29302 + stream[192..255] = 0015EFCCDC554D042531FD570C6B26D9 + 059F4F4DA675BCD12C038E4A8D16737B + AAB0D7992340F4EE4324959E96930934 + 21234D41F56A995C928F82944B46BB19 + stream[256..319] = 8CE7098F4C64DF2E8A170DA3D02CD99E + 0169B99A261D1072FA116ED39244EDBE + 73EB9F1CDCF8CCDAA9E94C0DA9C6EDC5 + 426751AB8300836435BC6F727F793281 + stream[448..511] = ADF85AF30894BD0207DB4BF72D9DBAC9 + 144EF6B24E515D96475897EADE40A92C + 79B818499B8CC328859561D79D727423 + BA81055F3387608E56173AA27D286924 + xor-digest = F47ABED85910334919B5868D4531FC15 + 24D61CB16C23920750C73E2B08A4B5C8 + C621482F6D9F01EB59763C5F89AC1514 + F6CA4C40216D6385F304E9514B014C02 + +Set 3, vector#234: + key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9 + FAFBFCFDFEFF00010203040506070809 + IV = 00000000000000000000000000000000 + stream[0..63] = 4728A29A2F2BD276FDE176CF4A38BE65 + B84BDD41F065DAFEA8302334CEF92A5A + 306EF904DADFE92E3E975EF9EEC9B3C8 + 4AFC167545A0CFCCB6B1CA688967D8EE + stream[192..255] = 734153A78089B6E6EC0F520D39BC3FAA + E1DBAD30CBDA32395E51E500CE4E118E + 23BC8CFDB08D443F1932EDEC52CDF3E2 + 1D021DB791A56A7C16FDA02912FE744C + stream[256..319] = C511914A4BD9B29488B7FB1E62DBF905 + 01C0D85C5A238448065C188F0A4134CF + 6A1FE1DAE57DB8BDF89FBF7FA66F3E32 + 14CC9658DB292E4562A1761B9EA77570 + stream[448..511] = 946944DF8E41BD585723CA1C03909E01 + 783617D9D1129220ADAE7E5487AF4B54 + FF6593B37BB77AB0025C28727AE5933E + E3873824E46F2209D26936FC5566B21C + xor-digest = 34E04FBDE6E3DF6EE14BD179226D51B0 + 1513510665589CB794C0C08391FA5929 + 37B390E86BB4A72D427F58A1EFE10F6F + D8A14A6F38ADE34331C8AC6AECA5DAB3 + +Set 3, vector#243: + key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102 + 030405060708090A0B0C0D0E0F101112 + IV = 00000000000000000000000000000000 + stream[0..63] = 2AC7F22D838F68107877E90869F98797 + 493171C8A5EC2E51D536A1578659DC16 + BB2F644C290B0F006BFE3FA0FE0CE917 + D32E94643848867B230270F54D0037B5 + stream[192..255] = D21F7FE6E368989CC75E8D9080579385 + E31680302BA8B9B2F56984FD49B01F4A + DD36AE4A28EBE23B5567BF5A539E2621 + 1AA8588507916CCB572611C352E73E42 + stream[256..319] = 25823586A7212D44811C75023193864D + 85DFA17EB7D5A34BD1CDD3260B5D53A5 + 56EE2E2A06F84E95CC7323379FB924E9 + 9E1A3F724F8C480A1F40B2C4A6FCD433 + stream[448..511] = C1DA25F3B4FBF8B2917103E6274FAE81 + A5BF4086A161A7786BBD5A33662E48AD + 6EB9A944CCA57C51AE266BAF756EA506 + AE077AF0AD8B577A5A02F5563FEBA2DF + xor-digest = 6176BC64072356BDF719676CD2ACF288 + CE2DC1272ED9C4685A5CBB7327669724 + DC8BB64BEBA04564A7879F7B9AD5A936 + C4BC1AA4007A0F85A5B5B945B418BC61 + +Set 3, vector#252: + key = FCFDFEFF000102030405060708090A0B + 0C0D0E0F101112131415161718191A1B + IV = 00000000000000000000000000000000 + stream[0..63] = 0854D9B674256934E204484C6D59668E + 1C94891FEAF6E08A92038E41EBA38292 + D19FDBF852400123237BD7DA620767D3 + 43C2FAAEB08A394EFD1E7C1A3776B1A7 + stream[192..255] = 4BBDDBE675E0F9D7DE0BC1B0E0C64FE4 + 52F95ADE61D5CF2EB805894B3CC3285E + 6C6AAB72DAFF826D945B05FC4D4A6BF9 + 37B352262AC12B7E6F92D5FBC4ABDA05 + stream[256..319] = 7BD11CF4273EA16E01154EF9615B88D9 + C52535D2F0C7FD394D94AA7EE542B448 + 9A046F2625011EE75F874641D1C5A709 + B7FD1DDDCCB2A6F1A47B65361A9B0D6F + stream[448..511] = 0AB902B571D11B5F2F24CDC7616143F8 + 45E7DF2050B263D7A841DA170E17C00B + 4A20221D7ACCDCB0E131108D94D903FD + 7E2F7988445A7DB54F653186D69F3CCC + xor-digest = 1266CF54E8BFFC95F1CD3C532BD8EAE3 + BF000577A811DA58A41AAD9164CCDEFC + 401C1B6BD2BDD9E992707718A9802B55 + 33D7A8F490DF116FBCD8C85E9B580487 + +Test vectors -- set 4 +===================== + +Set 4, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + 3083D6297CCF2275C81B6EC11467BA0D + IV = 00000000000000000000000000000000 + stream[0..63] = 1C43EFA7A2CA90F5E8F9A4F09D4C9077 + D5ABD79341FD75BB2DF9F13CA0B1CD6E + 065FA86938D971D8FAC8A3C34D08CA2D + 1BA08BE56D633951BD0338A227321CAF + stream[65472..65535] = 428908B703282E38E1BFDE62C6B0D8A1 + BD2AB1F5117C85703E9B656FDEAD2660 + 4B7B8EAAE16423A3BFE542AB13748DC8 + 35D81F981CD344015E0DF47BD180541A + stream[65536..65599] = 9D6D72F46C846D9BBF3AEEB463B9EF42 + F84915D664A20FB78AD94B61FEB7D63E + 5411A81D1E8F32BE3044E109C68B9EB5 + EC0BF180EF18BF3191D933F86045036B + stream[131008..131071] = E462CD92492726928381769FF205DC17 + AE7D31E1B82810F3CCB541B58C5F58D1 + 38DB708C5F5BF07A0432868A1AA40A07 + 601FCD1A07DE3071E8CE082833F0B02D + xor-digest = CDCA2F92BF75499E49B586BDA7D9306C + 12F111D1A9F183A83B5A07549D5F976E + 815F96BD716CCAC7178282CA8BEFF4F5 + 85DAFA9BDDDF8E6420DFDBA2573F0494 + +Set 4, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + 3588DB2E81D4277ACD2073C6196CBF12 + IV = 00000000000000000000000000000000 + stream[0..63] = 4F7D4E56036A57A303A9C7D978290216 + 297AC26C187E4F07678EC0069C34F93E + 072D734DBA239D81E566D1E6DCD09B5C + A132714291631C227E391EC0385A3A64 + stream[65472..65535] = C508DDD76C070F712FABA944BCB0F5CE + EB645825C520197867623ED5263E22B5 + 6270F0A878AC7FE03145DD2BF528E1AD + 784086FEFAA0D82F0F3571CEEDD3341B + stream[65536..65599] = B10CF49FE9266BBCA007C8DB526E760E + 79AA4D6A3B29FE82B8698C732FBB81AD + 1A27B2AEB06D05F3CF17E875BC0BBAC5 + 67762275EE650D03F62B29529F3C3E23 + stream[131008..131071] = 42B4F20EBAFB2C792006BD163064EC7C + F363DD996CDF839CCE61E739C3817B4E + 36D311A4C94C7918E82F5158D3A75844 + A5603742E33D7FC3AF018660E6B1185C + xor-digest = FB3EDA7C75E0AACEDD95B625F7EEDA62 + 3DDC94983A9B084645253C0BC72FBF9A + 67072228194F96C1E81004CB438D6381 + A5C7E9E7D134FB8B67DEF27462AD3335 + +Set 4, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + 3A8DE03386D92C7FD22578CB1E71C417 + IV = 00000000000000000000000000000000 + stream[0..63] = 23DE914D641DC0DCB4F818C687803858 + A6673E284F8323787756DAC9352BE031 + 28BC6149A59785F6AADF92FC68761E8A + 862AEDF29E851BF5422A83EE5EABFEE3 + stream[65472..65535] = D12E0C470A955DDAA7E851F43DA35B08 + 15D442DBBEDEECE3ADE18FABF08B4443 + 77ACFE9F138F8725CEA27B0F0ECCB4E2 + E5D6E476F88CAB4743E8E43CE2D48F4B + stream[65536..65599] = 26635796620003DE67406BF741B93D68 + 318F9A23FE823B2374E8BD8008EDD7BE + 2F750707A3835BBA7DAC45E06537DF8E + 53DFCDB928EA34CC08D2841FE3E492C3 + stream[131008..131071] = D3DFCE281FDC69F7800E765CB0B33D78 + 8BBDC17DFD11F929295C26AB7ECF21B6 + 7D4B4EFCC18ECDB8134175A7F198EB12 + F7913DAF22D73A4139D5B807C18310A9 + xor-digest = BB2C8E7BB894DEFD1D5A7D37C01E8EE5 + FD4E052CDF1DDF5FDA90C9818DE71B3E + 34392EC3858ADF718F463808ABF841B6 + 90F49D35A51BE5067B162E72D0101F97 + +Set 4, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + 3F92E5388BDE3184D72A7DD02376C91C + IV = 00000000000000000000000000000000 + stream[0..63] = 818C35D2FD72D12115F91BFD32F843E7 + ED4D7110D1ADF517226BE797E037AF93 + C190025A5E82FA0341667D68FC09E238 + 49D5A7A9526CA142D60F71C3AEE3A106 + stream[65472..65535] = F011E9CEE99D94BDD4484408A0FF91DE + EFDC8D8C04ED2B86C51F21058E912C11 + F19890E174018308962F5827D2FC1E2B + 82BA65688C111AAB5C749D8ABAEC022C + stream[65536..65599] = EC2EF21014AACB6215083F784E3ED65D + 774124FE60188930E1A90405EAFC8F1C + E75D54AA7D81400E026D799CE06EF532 + 8002BCF5A10D43E6FB6F80A9D72634E1 + stream[131008..131071] = 80BC6F7F6B0A7A357F770E7690D94A9D + B8CBA32EA36E124FDCC66ECE8786F95C + 22263F09645864087FF4AF97944A226A + CB63DAD316F8CFEF96504AD306C512BE + xor-digest = CB8D4C35D79CCF1D741B9DA09EDA305F + 5FA43F9AE9D0E1F576D5C59AFB8471F9 + 7822C6ACAA197FF01347E397C0382195 + 865AFAF5F1690B373AA2603C39A13CC0 + +Test vectors -- set 5 +===================== + +Set 5, vector# 0: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 80000000000000000000000000000000 + stream[0..63] = 04740F92C2470701F289669A25BF9092 + EB4212FEACF66DAB6B1D520977945F8C + 6D350BF26A1CA35EB37FA53B0BA2CBF6 + 6AC07A8C75D494B4B8281CFBAD4937BF + stream[192..255] = 5E47F5F506AA34E7D296C6911FCD3D43 + 31A032269214ECEFDDB492C47A51C4B4 + DE9EF0A63A6EB32AF1DF1C5576A93F19 + 02B7BB89F10D8C7CDFF9C097D3D49148 + stream[256..319] = 015494CB3CC9BDE8A2981B25C06DD18B + 52FA7B94CBE24C152FC60762290329C9 + E58C4E5148585F417733737059E310D9 + 309D0CEF48D2F1589994657A081BA6D7 + stream[448..511] = 3B67C1B37D96E1076595660D61340EC8 + DDE8F492134270951D9D4B260C8E2254 + A7FE8C10DE837A617A8E261FBBF42259 + C636B3DEEA0F373FE7C2CA2B01EE3FC3 + xor-digest = A8CC89F06815EFF6A91CA276BEBA7F41 + 75F842F85BEAE99F4335A3B85FB28394 + 8B7EE3C659274C6B784035B94886BF9A + 5C1483941B20170EE3A374E39006C09B + +Set 5, vector# 9: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00400000000000000000000000000000 + stream[0..63] = C25BA6DE4C87FE5360BCDEF864F3F778 + 598A6A584325D5E6C44EEA4464D7580C + 9B8D42B5B3634F739D6A53D15FA41070 + D1DD4621BF87F53F42107618D9742FD4 + stream[192..255] = 4A3808B0619C9D94E19F3AEA0BEF3839 + 21D7E2BED05F1128A82D9DC010654ECF + 65199A645606CC44FDAE763694E6757F + 8FF864CBE4204D45102E465F16CAB8EC + stream[256..319] = 3097394E0CD0A9DAA28EA873566E42A8 + 710C28366C2B41B6BF6687D881094676 + 9970A5BA54D28D7BF772C4FED13A9F5C + 6E7AD3F6948667D6C2DF981955F73293 + stream[448..511] = E685BC2ACD3A67791416E78699C83D31 + 852EBCB1C1AF71B926D9161CB6D894BC + 8C5E85C7E30A0896369BAE50C1112D4C + CC583E44A8275F44B7ED140E9721C7F8 + xor-digest = D9B51AAF4A9B75508FCD02443EFE2267 + 1148C73264776B5513860BCE8547370B + 2BA66E82CCDB15F3DEB0F0728411B765 + 1A098C23202745C19B045C58AB196309 + +Set 5, vector# 18: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00002000000000000000000000000000 + stream[0..63] = EE43BB5B79EAFB54B823DE95B71F3BD2 + F2A7CBB6D28E9BED590C20A2C52F9B2C + 74EEB9A1A48474D5DA4964EEE0BB98E4 + 88030E213A4482BD1A8CAD4CF8A962CB + stream[192..255] = 150C4D68BF29DD27A2E6FFDFBD6984F4 + 3AB56AACC08AC0C0149008F0882292EC + A5359CCF4C257ADD4FC535E41D6F67CA + E5210068F77A5D5F32A23B17F79EB7A5 + stream[256..319] = FEA319287C29AB84585D4BF38DCFA71F + A36253AD7F4BF58398731713614D0047 + F85A465C6915E05232A5FE5AE7A559EC + 42733403ECF6B11E4D5E8F4A8288A3E3 + stream[448..511] = 79CE66DD3F77D40889906EAB1F671B2F + 98D9FBF8693C1EAFC89D19209408F3B2 + 7CD83CB3B9F33151DD4A8D79911255FD + 3CCBA14918744B0ACB93A5F96AC9AB38 + xor-digest = E1E3F49B342F873263F585EC34969176 + 2CC46C17FDEE0B32224BB77A8EC82A87 + 816DC612439E998476F50E876481EE6C + B32ADBCF6A5D50FA16355AF63AA30D66 + +Set 5, vector# 27: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000010000000000000000000000000 + stream[0..63] = FB8F4925A4F922119A6F29F8DDC2338C + 0AEF333B55919AF0D0D9B1DB61BA2E5E + 4CFB394E15F6A78E01B5C4AB043225FD + 9C8F50AB1BFDB16F944C2660995AA4DE + stream[192..255] = 87767D451D81D5B40503913508C2448B + 7CC093982642089843D7D9C3DA05598F + 7AEFC5B70ECCE327B20658D6301F4D6B + E58FA5CE0525C9CE8E93FC0B387AE5C6 + stream[256..319] = D146E4312CC11F11916ED9FF8EA8ABCD + E0736DDD0A8AF3E067CDED397E429D30 + 8F2DBF848C5C1653EA969B608CE01275 + 53573C88DDD32937EF6F8B0864C581B4 + stream[448..511] = CE919096A83BF3702D8899787DA7BC23 + 43F1F10833F16E3EB467440B4921BA1D + 96845B6B4141E1CA85364E2D508456A0 + E399DD048E72685389FD7EF3F78B655F + xor-digest = 00333EC3A59AD0B8FCA054A08340BF91 + 906512917E72BED76BEFFE29FC011632 + 082CDCB1A656FB817F968E26063279CC + ABA796307912984BFC267325DB84F621 + +Set 5, vector# 36: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000080000000000000000000000 + stream[0..63] = 202723F8212AB20D9369C2E1EEF8553D + C468854873D04FDD32641E324DCB4EE0 + 883AC1D40D7C9C7783DF4132093724DA + 113B1CB12144E00509FD5D36957A4E1A + stream[192..255] = E6717FE0A77F9043607A1A7665716225 + C8D417FFE2CD7572083C7C552B79DB6F + ABEBBC2D4D36AB319407982187C248F4 + 83596AC071C0B0CED08686603B024E7B + stream[256..319] = 8C59D97F7A093EA2D0AB890923AE4DBD + D40C33508838A3966FBA360E776670C4 + DEED8BC8CA57592463781550BCFD1E28 + 818E7C33A3AEC43775ED0A984044E9D8 + stream[448..511] = 0A3DC66754E02423C6EC1C1DD26CE11E + FD70C386729C8290DF358C69087CA7DF + D11F5E0D37A313F74B09F29C552CAC0A + 5621556828B0145A6A1D43F563AFF672 + xor-digest = 6673BA5866E8E96FB48FAC88D307079E + 77AC03692B23070EB5BB9D04FA94B9C9 + 6C2F958E834DEB51C6ADCE432BFB9632 + 9B3151E0A89EB72019A4522233B8FFE2 + +Set 5, vector# 45: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000400000000000000000000 + stream[0..63] = 95AE241C4E9B6690C319D1FD828BE454 + 52F18F061C1B1E13AA409829E194D70C + AD5BBACA2738B508A5398DF6C2552497 + 6D143DF0405F68037C285A0E19FEC9CC + stream[192..255] = C0E2D5C6B614E4A498F46D5399DCE7EB + 7DFAFAC62794F5C39864C521B8DB574C + 149E35D1F0EA36EA7F24EF8FD855FDCB + 9CCC79F1ABB13EC33E00A9E137809C05 + stream[256..319] = 285907400C1A86AA9942ABD7BEA8EEC8 + BB6AF2F9667D424C1DD56349C99FC65E + 8A00893AE529D7BA492089EB6B525964 + E9CAF15221A342C4F88697D818AC0F1A + stream[448..511] = 13D511737F3A092643E94E74F6C76241 + 0007158FEF40C63B33E10360FFB3B152 + 8BD8B33093D722BDCAC1FA99D16D1C27 + 6E59E428601F256542BD3E7A4A135152 + xor-digest = 1D1352487AB5081A28DF23B1B19D5ED1 + 192F08964E4C0F048AFA9CAA8BF17185 + D7B97AD6003E2FD2DCCAD492FF3FBE5A + 5CD7AAC627DFE7CC6D0972D423B67128 + +Set 5, vector# 54: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000002000000000000000000 + stream[0..63] = ECA0F29C3F5C4D62ACBD601C3042673F + 6F8B17C946FE8FEEEB0089059765F067 + 5AF3E5DADF6DECDA20F72AF486E7E967 + 40B2DBF22B57FCCDFE571B2D8989C95B + stream[192..255] = D2BDF6ED912478A3C53713389C9DFA5A + 9272D030543295E8CF6F0929F1A56041 + EA22BD04E0DD810F43D9D28D94254F04 + F73DFF3B766DB55100EFC9697FA844C7 + stream[256..319] = C7CE1CD4D8C42FA36724A49107A78630 + A60E15673A42C57B609740EC8DE78EE0 + B48F2644DC0DD1E80FB8326DDBCC7191 + 5E6C8DEEFCCB1FBE1456532840A89DB6 + stream[448..511] = 337650A0B03D30C9697CE85449B0F995 + 668FB2B73E37E1A550E07632F9F5AA3B + 04D61AC41F8A830299FB8F70FAA0419A + 42C4589D71C965DDB3A9D000667616AA + xor-digest = 7A26C50BA37BD9F38281FD2DA3CC14F2 + E1FFEEC9D7776E87D99053B531EEF792 + 0C0BF834EA9A0065AF38422A40A31BEF + AFAA17AD565F685BD6E505C7E02FB895 + +Set 5, vector# 63: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000010000000000000000 + stream[0..63] = 567919917583CE03DBDA69907CBAE562 + 107FBBABB4DFC81A3A15438C94AC0C28 + 8CC35A91DED9A79ADF4EF2670A55699C + 000994EF33674B578F5D77928A43416F + stream[192..255] = 13D0EC5B7302C0D8AB329E7AADFC3FDE + 1D24A80B751948C4BCEF516D94DF7AB2 + 2B1D9E076BBFE367CBED341B2A5A3BA2 + D48735F83855460F9D9953279BFC2AA8 + stream[256..319] = 5EFFE922E2FE25410E8050A973C3FAE2 + EE372E9686B6E7B35294B52A579CDB43 + 9D5CA7F1EABFEB4303DFD7DFBCC812DB + 9D70CD0698D1ED051E1E32C855EB39EE + stream[448..511] = 91A01C0EF63716515DB8B71273CA4399 + 1654AAEF2AFD4DEF25E21A08D5385766 + D8C29514065FFF00B07DCB32D1A20830 + 3C3402963EF252A4CAF5CA31A50BE591 + xor-digest = 9232F83FB054098FBED8474939476CEA + 5E9FC269E7B248E56B14F56CB396BE74 + C2B2203D1802D9515EEE232FD612FE21 + 11C291A46A89D54B2E5437E643239636 + +Set 5, vector# 72: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000080000000000000 + stream[0..63] = 507958BFA08EB41F4D18F519E36FC476 + 5BB8DC6CFCA36290CE9AB8B165D7AF72 + CBF49DCF8BA2D145D7935EDD2CD2242A + 7B7FCCB85B4C8625532D84B4BC602515 + stream[192..255] = B2B06A7C3977D4A1A39892E832A32A55 + 3EE6E52DB24DC453835893A55D0FF3A2 + 949B8B96688237E13DBBB2D0C9038AFE + 8B9D18CCAF62019ACB908499D292F280 + stream[256..319] = 1D28AADF7B262A1EEEC11D39F4325CAA + 6181F9FA1A6C65F3BEF4F1614B0DF599 + EC92E5B6B42A931352965CFFC025F68F + DB2D6D0181F259F12989E5FB23ADAE8E + stream[448..511] = F60E3DAD5004E31F6DC89292ECF517F1 + CD18AF7E79E775334F4644A09346AAF0 + F2B4F5C1DD03555A6D27C43AE53EA7BC + 7167F793190071C7AB7B5330A6C6CAD0 + xor-digest = 5A65D44021E67626E62FE87B8547210E + F736490C0D51485A8EF0E1CCBB512DC6 + 0FC18114A29AF923EE3E85655771D6C0 + 7CFE342A52190C540BE3409853F12065 + +Set 5, vector# 81: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000400000000000 + stream[0..63] = 2416B634134170CB4F67F431BC94612B + 5F2F72545DAED2356081C91A26554614 + 5FF2526D8D8FC7D02D8BCDD9AE03187A + 9E404C360E115CE949667987AC73624F + stream[192..255] = 4D456233EC7E761891A56BF9F9659533 + 22375C169D7F16DD81D8D69B12092F47 + 09703B85AA3184827935B60C1E5987A3 + C4C2EDFEAD4F777B53989C469B575EB4 + stream[256..319] = 5F9CDDCBE09CD759B346AAADA2436887 + 0D47BD8859CB9225B61AD9F99197FB14 + B5D625F5DBE0955DCBAA5B874A7C89C0 + 07BF926AEE571CCD7E20635ED4FF312C + stream[448..511] = 642391D8851A9BDBDCA37B9587D5D0A4 + 877EDEC31D6EB78AA3F1E068B0ECE877 + D83EA29906D0C0816EDF7EC5BB417A3E + F3DDAA2145CB37CEEAF8C07DDEE0AAD9 + xor-digest = DF93E4E01EA55D18AB8AB1A927A5B5AE + 9ACB871B7493DC283581262771852013 + EE54288580A03B3991126BE8BC20C5D2 + 230F00D8216CFB632271750F4FD2595A + +Set 5, vector# 90: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000002000000000 + stream[0..63] = 4981C83E26859DEDB32D84C7BE32830E + 784376A12FA6D0077D4CB47ECBA08A92 + C841D45D6CDAA3F1FB48C6FE747B0F67 + 1B32C2B35BE69497737FE4B98770DEE9 + stream[192..255] = 1FA51FFD0360615EFEB03042AE8E4210 + D3D38B4EF07536BAFE43C0585818F012 + 8F8B3F8CA8DADBDF049688253066C74B + 01849C5BD85DCE27C0138D24E8B8B198 + stream[256..319] = 2D8C58008EE94CFEA1EC545C26466D39 + D7BFD5B226E32F1270B5BD3677818B7E + CFD98BDEA26488248B10418C1F854159 + 8F42C6CC237885A1DEAC5C33F22C27CD + stream[448..511] = 94502058B5828AE4F4CDC0516E5B5143 + 1F07EE1ECAD7CA266C931327BE6BF1B7 + A34810220CE00497D7BB9600FC524999 + CDEB6DDE8919B03064EB56B3766DAFCB + xor-digest = 1DEDBE0B7B6099DCF285B3C30E91AA0F + 7859496E034A1EA1AAE3D3D13C2061C6 + 0878E595B63D849B7DB77BE7E0C08157 + 94232B645BE946E5D8278B14427172AD + +Set 5, vector# 99: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000010000000 + stream[0..63] = B84C72BF69B601FB1804CE333C5A2C19 + 25BC8A5877DF9E574295380611D03FD2 + 46D2EBB58CC6E918F4DB1B1A0E39642B + D6B39DC76764E18108497E4CC4394057 + stream[192..255] = AA84DF8195B3F7564D0715517476085D + 1B40511A72340DFEAE5134C7BB8F39CE + 03E6EE15217986C7E4788453EF054027 + 8CBF6336073092EF661C13C7EA8B4850 + stream[256..319] = A7F0C413EE143F55C6356519AE620A9F + 4CEF8432C51E2677EB5D700CE333F314 + ACA374D86A8FD4A67BDC31C1B0DA2AB1 + B20E6DB91E7F85DC13E348314A4FC782 + stream[448..511] = 3445E08F13D09A1AC09EEB65451F4504 + 0AFFDE94F6C2667BC4D8FCBECD6C6565 + F09FD05EC660DD38307F856AACC95549 + AEBCF31B3FBE84FFB3261D7FEF7A3379 + xor-digest = 360199B22EB28401FB4F621E37800801 + FE69C809D83BE29A50FD1A476B6AAF02 + 54B1F4B048CB6423182C390B8EDFF1FD + 9CE49C26727F0D68EB837C19F58F3F42 + +Set 5, vector#108: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000080000 + stream[0..63] = BC618F4A557E5B7CB75B3572FFC31CD8 + 4DB96FD22E281C198DD33B5E9E419099 + BE30E84ED61C0EDEC04B1E16E06B40E2 + 372E0EA1A48DC55BFBFBE3355B566AB9 + stream[192..255] = 33372015C7E5749D98A92CC55CC22206 + 90BEC9878D3CA0AC50765D0B4457CE50 + 9BCE196BF0388599E692B99EA8169474 + 546F10891A3FCE22DFF0AF9733C2A2EE + stream[256..319] = 382684F74B0F02F7B987D37F6BAD97F4 + 20B4811FFC744CBB9F00C2855A609FC7 + 7CD24D0137304B95217E25FF45AFA4CF + 28E4335D29DA392D26DBD341A44C082A + stream[448..511] = B0B2B619708435C5DB45FFADD2FE4449 + E603FA9785E1F521E364DEA0B127F72F + 6C8A956CAF2AC9ABCE9772ECC58D3E36 + 2E758BDE3678D4F4C9804CAF11129BE4 + xor-digest = 80FC64E2441F6CA9C0F4C207007FD0E2 + 5F1C0514D203A1B01A6EEFD1055CA355 + 0174FAAD47ED0956A736A9404164ED85 + CBEB31F80561AAFC4ED8EDC9829D83A9 + +Set 5, vector#117: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000400 + stream[0..63] = 69FEF0D5DD7CFA6590821B6C12E239E3 + 5DCDE7B218A66CF3C75ED278092A6228 + 143EC00BC16DC2FDB8CD9DDBD802AB56 + A4011F6A8CF432F2D34657AB84DEFA4C + stream[192..255] = 312EBF427B3D22A22EE1F85D89E12AE7 + 07160C9BBF4073E538171365290B499B + 8904B01801CC897FF09A520449A44D0D + 34622DB8477EF1E73DCF15417478FA03 + stream[256..319] = 83CF222FDBEB77FFC6E282C1212D8D1E + 014865E9C1251FC07E901A41A50A3AF9 + F8E130394F621B739578C7E238866431 + 10827799C75F08C47664B09B477F31A8 + stream[448..511] = 4130A8F8015F082EE8712B6D61178CAE + B1D3CF90AC2DB9F2D402F65E8395DE95 + DA0605E8540E553CFFBD029AD5BA8FB7 + 5950C2FB29097E13ED4A1B1818E0D07D + xor-digest = 21FA07F8AA2FBC12F5B2B14E034C2AB4 + 54D7D8DA66EB0308D9AB024DBFA414B3 + 38F36D188D33C71E888FFE1A6AC620CD + 55B33C1A146AB8FD275584589BD65606 + +Set 5, vector#126: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000002 + stream[0..63] = 0CF41A77C30118D0931FF3142132A627 + 7A778D3BCF7466EFE56238B166A57043 + 2DB3B222523330233F81836282A27B40 + F6823BD076D84DC3B831DD78828F0FD5 + stream[192..255] = 38A0C28325566FBAEF5AB3D50D54F407 + 91182DEF4FC945992AA0D62134451914 + F07F16E86E20DB119692966E6CD6165B + 79BE7CE6C45D1248F2E0432393BFA726 + stream[256..319] = DE91DACF57B176EF6E59E485DF02A20E + 3A4EE5FF44B1AA3D7F36265221CC71EB + FB9565AA4F269B7DBF3CB9631CCBAAA4 + BBBB6BFABB97E52954958D4E7A283F20 + stream[448..511] = 8FFDC8CCBF864721D6C98E1896FA052D + 15141D9C3DFEB48AE91B2436C5C3D088 + 931470CE951B66C38998F15CF23BED01 + F6D95D84150D482C0C289A8E5B2C7C10 + xor-digest = 03DA7ADC3E5931928D3FD89E1E0876AF + 9D4CE659175E671D6D80EEA78F241AB2 + 86CE3C26DAE267D91DB556AE0CAA60E0 + 2B481282E6470A7A161AC8E84C2311EB + +Test vectors -- set 6 +===================== + +Set 6, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + 3083D6297CCF2275C81B6EC11467BA0D + IV = 0D74DB42A91077DE45AC137AE148AF16 + stream[0..63] = 544B400E28A1A4D9E30A3E5BCB5C9FA5 + CA066389C693177C4FC721937D0DA5FC + AABF39ED84E1FAD63ADD0C9A86749ED9 + 86759F8ACD0A5AF2E17B4E3CD5831B44 + stream[65472..65535] = 6D2242273AEDC611159912EE0EC5D023 + 44498AB4F513AAFB96E8C240C1F13B12 + EFABCDAD424200A53017DA7D34E9AB86 + 9D099D239AFB45D067BF94A92E7D1007 + stream[65536..65599] = 403105F52BF3456E08C2C698505E2639 + 4594A257DC6BCF7E26A9AE184CDC8952 + C34D29E116809C91DCEF4B0FE57D87DD + 9385BF387732E49E265E67BDCB138D53 + stream[131008..131071] = 86758A037E90380C2DF4DB0A7E13A115 + C0F83A664D5B6270306ED5B9A445D612 + DD0F9300603362F2574D8E262650D539 + 708E2FB5D2CFABD3F365E23783271D2A + xor-digest = 8513C47FCA708D9B3CECFEE6BEA39154 + 1843C72A2BB767C926EEADB4D3708537 + B24A36FBF20273487B312095D6C6D866 + C61B0E56F71029E7F71FD091D65C6CB8 + +Set 6, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + 3588DB2E81D4277ACD2073C6196CBF12 + IV = 167DE44BB21980E74EB51C83EA51B81F + stream[0..63] = 2C832BE30736D5F5514EA4A748E30EB6 + 57F418886DF2E25A739E13B6C1B24736 + 96B44CC2B3A054CE4E6D9817BCE6BE97 + E77D0B984C0F039329ADB559266270F8 + stream[65472..65535] = FD7637AC01D2FFBB5AA389D6E9EE4E39 + 4E81AF774491678E7A0181B1AD063B22 + 6CD1703ADE35B17F1A8D4E8B6E0E0138 + 66A75498C93A19ED37DC0398B61573C3 + stream[65536..65599] = 318AA03B81B6C5C334E80811384A07F6 + BB7D0AB3FBAA1ED873BA2E01F920C1EA + FF35AAB02AE0D4F9612E8171BFE63755 + 421ECDB540189C2A10027D4199E35959 + stream[131008..131071] = 7F688C0421F127D0CF5B773AA1B27A74 + 0ACA0254CABEE4095809FA854A06D746 + AA06E56EE3A6AB471F4C46B0528B5D94 + BBB9E3BB989E01FE459F3190E2942FF7 + xor-digest = 97D161DDF9E98C70E6B63BD4DA8629FA + BA4ACDF112E28FA029DA508F1709E977 + F57F3942997822020307071636BFBEE1 + AC7E3D9C97717474A8092576536DD8DC + +Set 6, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + 3A8DE03386D92C7FD22578CB1E71C417 + IV = 1F86ED54BB2289F057BE258CF35AC128 + stream[0..63] = 31B2E5B938120CA131A0635F2A471710 + CDCB494678339BFC7710746BBCDF2700 + A0286EA735766D17E9FA270C63AC1C4F + 405101CAAFACD6C2BC4306E37E9516C3 + stream[65472..65535] = E5AD2ACAE7BF99837475EFEB7C8F327C + 55811CDE424E7A5AFE33086CAFB6A63E + 6607C005DFDB8DB13181CD3FF8584823 + F0D6EC38083DFC3C7A8140DEB47372B8 + stream[65536..65599] = 662728BE1DA1099208BE1BDBE7E5F28E + 8E2F112E527D2F48E2C9AF565729524A + 175A37A38F5CBB1761D21E907CC62BFC + B3A4ADA96EEA24624C501D237F461E93 + stream[131008..131071] = 609AD32104EC8FB79D91299D3B3B2942 + 3E09F451597C0BBA26FA2FE97B9B3BD8 + 0A8907A8236E245E8BA2332C6D027F66 + 12DDE13BF4A149A1A6CE2DFA9F8A148F + xor-digest = B245B3176CE7C0690A7CFB4C61C84E06 + 041650BD4A199986D3AC4DDD80A1C806 + 2FD17F9EA40D25E86EAC53CA4FF8487D + A4379DB9BABAE6109859D9757A992100 + +Set 6, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + 3F92E5388BDE3184D72A7DD02376C91C + IV = 288FF65DC42B92F960C72E95FC63CA31 + stream[0..63] = 8863C707A53A4201F070ECEF33DAD759 + 712F20660A288C80E6E9073CD850CF84 + C96AC6DE9F11F0BA176C395E871C42D0 + 420FE1D3E9E23C8E9EB4DAAD6C677C50 + stream[65472..65535] = C9B8301378C62DC67A932B81147E76AD + 54A93FFDE7B04E82548B6344B8F63897 + 3FCDCCE6F69AA0A25BA0BD527EE7C613 + 5A89C5CEAA4BC69ADE9DDE839FDB47BE + stream[65536..65599] = 7079E98749DF66D72B8BBB1DD7A6B7D0 + 6094E8723BB74D38A7223B2557B8BE25 + 4313AFD06D79814BEED4F40DC9211D50 + 165A8CA279AA2CB8A1393099B72607B0 + stream[131008..131071] = 6C30F5011144AF9AE0D27E2D39E51372 + 783A5BAEFB58F43578D0FFD947457C87 + F138CE84D42891A4BFD1F438735771B0 + FD495DF941B8BCE83C2EE9F11C18C04B + xor-digest = 7E9DD203303EE6807075D16469FCDEE3 + C5BB95A359D4338AD06546061FA12F3F + C24AAE71EE63F3D892AE93E5E327FE7C + 1C168CCEC2BD1CCAF905E5CB2DD75C29 + + + +End of test vectors diff --git a/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt b/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt new file mode 100644 index 000000000..15554076c --- /dev/null +++ b/crypto/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt @@ -0,0 +1,3257 @@ +******************************************************************************** +* ECRYPT Stream Cipher Project * +******************************************************************************** + +Primitive Name: HC-256 +====================== +Profile: S3___ +Key size: 256 bits +IV size: 256 bits + +Test vectors -- set 1 +===================== + +(stream is generated by encrypting 512 zero bytes) + +Set 1, vector# 0: + key = 80000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 240146C5EA6C72A8DFC93E54E8811C32 + A85E0BF7291BDDC0DBEAE086D051D5B0 + 5CC9DD5C311ED2F7E8484CC477C68BC8 + C5D3F3450553F5327253768E958C0C55 + stream[192..255] = 26C5976C37B009E57BE86064A99E8F59 + F9536410FAA9BF625D8DD2ABC9AABF09 + DF6B5EFC76CC6200F9E321E327AB0703 + 2C78B351C5F7EEEFF2C6E374521CFF6E + stream[256..319] = 2F72E0E6E710D807D5120AD686DAADC3 + A5C1544557A4BA6B1D61F90FECD55328 + 3C8F91B801DC435C5FFB1F8B33A23644 + 8E21217C367108893D13AD41EA8F20F5 + stream[448..511] = 68320BFC459C78596162EF5FEE2CF46C + 79EAFC681AE91F875672350C59D33D6F + 9E0CEEFE42EA9A0485E3E41C241CDE84 + 9849DEC99219729D91270358B2F83F38 + xor-digest = 19E8083DE3499286788AE3A6DFE90AC7 + B77084682ED86D8039A67663CDC9ACCE + D297F22C10FF7E4FAD773337B008A32B + A7176F733045DE44782F04C1DDF28776 + +Set 1, vector# 9: + key = 00400000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4B1E2D728E06D7356F151D10DE9CBFB3 + C66A1E5B5ECD926E33F56B14CEDBFCC5 + 40CD6D1089DD8E5CF008E4AAA3C4C89D + 11B136FB5656B5D4818D1BD1E562BB38 + stream[192..255] = D5E6B5482535DB7F9352933242C164D7 + 6528DF7AA013A4FC2F2B8C2D7DC0202F + 85774C16FAF22D5071A875B6A671D4B1 + A8C396AA5D2F14AFF9C4CD6C1DB89175 + stream[256..319] = 3D0FCC3C90DE0328FD0C752458996FF2 + DF822E496CA42A7D7EBF3D958676A41D + 83A16EF3150B8C4C8F1763560B314287 + 54B4A2EA5C4F74783BF8809F3A624664 + stream[448..511] = 2D68526D25483C2A1F0B6F7101507804 + C9619E267F1FFF28C934D19201351465 + 31D13592BC9F1739A0B090718052E4A0 + CAE9E0FA4555F2FAD27EC8AA2F14CC60 + xor-digest = D3C3131E402BCBA54DCE0AD35C5FD241 + 3ED7056BF67B5163CBE6C9EAA9D27535 + 7D2BFB7B2843DFE92709F047675CE06F + 5201611BCB8FF15C76D0E328D46345E4 + +Set 1, vector# 18: + key = 00002000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4A0CCA5AD387D49DF33FE8BE69FAD669 + 270E3E6CF724F53FC3E509A2CEF1D174 + A67C2EF4B9D2C9B8A8177BBFBAA2C45F + BDD25CBECBDB59A402FE3C4835854CAF + stream[192..255] = CA0F19D9996E6D3518D28D8169968ED2 + B03D118D4BC1C5E1847BA6EFE6A32D6A + 32BAF71A4C27B0BBC9B9BA03FE044D7A + C9785A69E3B0E5B3B26AABE3AB093965 + stream[256..319] = 6FD1A9F1EA228C39625FC0CBB2D4BF8F + 2C0EF1F37D4FAC56D8024D1B4F2AF33B + 8AB0D452F5155ADD5F0FEEED8104AD55 + 9946D2E274ADE44170F5113630200B57 + stream[448..511] = 5DA1476A1CBADD0797DD7EB9C0E563B9 + EEA2C55860C42C2C0A6B38B9344BA0C2 + 345C7143D9A7E5BCDF9FA2606098DEA2 + 142632258F844AA1A77CC9950D5ABD7F + xor-digest = 0CCEB42D4045C09C45CD6C27B88606BA + ECF7F6B30F50004AB2ACDAF89849519F + 61482EC4AAA2CF58C4206A228FA23AFE + DD3BD50BC9C04744940A238966C2926B + +Set 1, vector# 27: + key = 00000010000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 77CB199A639DE60664225AD1DB954B5F + 70DC01305D2D4073BE772B0863175EBB + 64FAB80EF324DBC85A9EF827EBAC7A5F + CB088619C246CECE6F92B89A2122B6AB + stream[192..255] = 84C1E9B365F1CD23AFD5711BDF2B6F26 + F988A6CE29450108FD6814802355217D + F6F329FCB3F5997401019BAE0AE43760 + ED6B658FCB4280F5A070728411EDA4CC + stream[256..319] = D0AD4A851E7A60DC789762A554A8FA76 + 77FA610F4D868CFF1AB6025B2ECDECE8 + C554B4C0BDF543F58A1DD7CC68FD7AA6 + 7EFCFD59D55372E85131D6284E7949AF + stream[448..511] = CF7F791090D04350930AA1E1A53B70E2 + 691A231595E83F8BAB9613BDBAD868AB + 197D5E06B3397CC3D81F56B87BC7521E + B0BE346552DABEBA863D5C81D7245C8B + xor-digest = 2C77C0ED1F5AE20A97388ACA5300918D + 6246B04429F298E64A75828EDBD01900 + FC70CC103C31E0BB67B06D04128686AC + 5C5FA63FE714FC4DF18C551BDF81862F + +Set 1, vector# 36: + key = 00000000080000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 54A5A2E883714170B471C0651D74A9F7 + D51287C89FB345DE0AF7003C3871425E + FC885F033D79BAC9716B1ED5C637BD9B + 0F16FD8D613BFFAB634F0EC2497D7B3C + stream[192..255] = C7FBA70B19B749BBD0C84C7D31A5AA44 + 155623116C44CD53D2E640034211E730 + 277402F62D1FF1578236A2646AFE6108 + 2C958D9D01C065D7335EF9C29415AD42 + stream[256..319] = 2385E2A7070FEC7399BB3CEEA43C8D0F + 54D3607FC1C21BF173642287C1FC2C96 + D37695A7B1310E5E918EBE37113348B1 + 707BB39E401A10FF14EF020CB7C44261 + stream[448..511] = 5A87EF81C2CFA70D86B147E9587467B5 + 22FCDB4EAF0353E11F73F3BCC1EA6C09 + E962A87A0842B9225E164DB0CD1A3BA3 + DA8C02E6746CD3AE0BC4754ADBE7EF6D + xor-digest = A65BBEA2E397048E4714A8AB3C19EE6E + 91B9EB8048F35FA7AB9E003E9359BE0E + C3EDA827AF485C23A941F7D656C76CA2 + 5D12044923E43E61E7DDEBE7D9C87E3F + +Set 1, vector# 45: + key = 00000000000400000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = FF81E156907CC2C01EE23F79F936809E + 3F88AC15CC01BDDDA378CC1BD2317444 + 200E4E2C63E15FF07B0B40721970E7CA + 68F748A95A965EEC606318447BB31C2F + stream[192..255] = 4C4C42A330AD444388FCA4009CC0B196 + 84AEC3EE65138A747FE86526A263969D + 87CCDDCC4C9A0EBDE2D088CCCEBE76F0 + 52BAC07636937B1567637ADB498F7F8F + stream[256..319] = F550BCDF67C8E9C17B800487DF83A4BC + 73B809C4F3279D4CFE857780412F0F7B + B838A9F0322BBA84D7AC51E469C5012E + D774E52E3507C7D069F5169F0403C577 + stream[448..511] = 9D92715109A301AD47BF2376D65E2519 + 78E12098B0DEA5B779079A0FAAC4DB42 + 5BA9EB00301A5F964336F7EE9C0D9667 + C4F0DBAE14BED3E49A6A746FCB186C65 + xor-digest = AD2264EC651E311BAC5FB36434773F5B + 4A4777B2B7F811A755269FDA8339DC97 + 7A8C6A5F66E8737DD16A88DAB8545110 + EAE275892A767BCAC0757C396A690F67 + +Set 1, vector# 54: + key = 00000000000002000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3DC3C1A1A40E721F8A3A66960DB2C0F0 + 6D8B7C07FE90D67C26F86200D6A1A1D9 + ADE4D53A35F7A016A506D9C62D344D49 + 5C6DEAAE053247103B8F202B85A5036D + stream[192..255] = 9B83E56BB5E10B5C6C05C4B450B64FA5 + 9C52AA63E207592999CBB48355517F05 + C93EA878BFAECE58CBCB948E81BEFD89 + AE0C5C13359C6CF5A673B4EDE28FAF0B + stream[256..319] = 388163F9F26536BE1221A46834CC77FE + 03D021C570A9DA36CD528E887ECEB2A4 + 7146A8A930D6AC04694A0B9AE50FF55A + 41AD3B3D3E53F982563B5B458C078C0E + stream[448..511] = 3B0FF94C0C9FA0EB8B8CC1C691D04180 + 5AB6436BAFCE8C16A1351883C88E945F + 8F912FF79CFCEFF7374936E830C9440D + C676A5F00BB50EDB34F810AFFD9CA8B3 + xor-digest = 879534CEDD8CDBDDDE2E2216D55529AC + 1189B1C34A76ECEC179B8A240E890F8C + 640738DC37C14E4B950B9D8C507685B1 + 28CF4782EC424A3712F54F6265A41E7B + +Set 1, vector# 63: + key = 00000000000000010000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 12F0A17DEA167676992DFF2E7D812878 + 629579519578EAFD885F212C7E04F035 + AF03732C3DA8CFB7B73054662F0593E7 + E40133706F04B1329BC3155DACD296AC + stream[192..255] = 41BB89D0BE44055E23813783C3EC4487 + 2D102D6EE94475AAFFC7FEB8DE6849A2 + 6B50DE77EB9B0B96EC9EA0216D13D64B + 1264A83D6B571A92948A5E35446B0503 + stream[256..319] = 15E9C9168AF4AEF7F2EF1E832F40110B + A8C08DE71D4F0AAA3A5C2FC59BF41005 + ECA654EB7F316B757FEAD5B0F4BF41F2 + C6D035A88B5477632F34D7F904B2939A + stream[448..511] = 8A2D446044F7930B696DBA896BA6CE69 + 8F8B01E4282BCCDC4740BB6AB6ECF7B8 + 9CA1CFCB5745B6577D0F440AAB7985BE + BEC5DBEBD8B028B15DEA138F09018297 + xor-digest = 89CFE7E84993C6B608EAAECBAECD7847 + 472703F3CD97F9315BA9CA13204B616C + AAC0F37EBD1C58186620710FD6AE5EFC + B7CBADA19AF8C0F7E1FB24913C2300FB + +Set 1, vector# 72: + key = 00000000000000000080000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 7BC411ECF4AC2EF2C9B8C5B7CCFD791A + E8250119E08C1B7F7A82F576FF66FC9A + 9D9BDB7570EAF276A60A3BC7E7BCBB86 + 7A791A48F9E742D7D7480FBA67DCDA6E + stream[192..255] = F85A8E3219AE1E5F20A4FFC6814458C9 + 5A4ECFE7FE739E151A45247A136E3BB6 + 9C11987BB5D13B1B9A3077C8F4ADC9AA + A555FC9725339E02390B9C9F75E1F38C + stream[256..319] = 8A2E88E0A773EA00C11138710BF12ED2 + 7797AE7863B1EC84801D11B5B3914786 + F1D547382DAA9D5215CD4CBC783C700A + 9B09FCCFED28899D2F2EC148CEFA39B2 + stream[448..511] = 95E3BA3237F370A4E0850F2CA0FCEC89 + E9D832CA6DC6A062BE7ADA8D8AEFD55D + 2BC7A3F46BF81DEA5DD9155E8D8FE918 + B5DFB1926460AB69663856EEBCD4C338 + xor-digest = ECE252DA29D20602D138E13C004D8B66 + 8B09FD764B7D84FB83B8F4D924504D60 + 277BAFC521A8AB0464E4EFC6BBB9E4B9 + A206C38154AE3A57B84D2D39CF45616E + +Set 1, vector# 81: + key = 00000000000000000000400000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 139C2843F0BCBDD32C685F4EE2C7AF4D + E6BC79789B77B1CA6CD94A01645EA243 + 5B491F27C27D4EEB96FEA0ACE65C0D8B + BAA642B5A07245BCD0930588FFC92A50 + stream[192..255] = 5C76EB0D5323A7AAAA228F7718BB6736 + 5B344559C24BEDEB2CA66414B5E81795 + 428D55868611AF9AC7EA0E7424984037 + 3251BF5206C361AA3631DEDA52DDD519 + stream[256..319] = EAB18EFED266D4788015DBDD20A75058 + FA4DE35C1DC774ABABC476BCB0AA2CB1 + 214E5463F4E20E7B999ED475D77DBA9D + 70FFCA0C7971CAEC3B285EE8F9F37C02 + stream[448..511] = 081083D9AC30C9DB4E53597D64249D7B + CCD847495A928CF4CE876237D92ED5E9 + E3D723EFC663CA0DDF34DABB941F42C1 + B48EFD59DDCAE71A1B82358A3328644A + xor-digest = C08714035439EFBE455BAE68EEDDA0D2 + A6968F18827B214A097221C3A77F80AA + E1DD9F3C72FA66C16EE278A76C19107B + 37CC32346DBDD29FB30059A8FC732DED + +Set 1, vector# 90: + key = 00000000000000000000002000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = AD897A3C509B66728342A817D745460F + 6A258386FECF71DB95ADC716B8BC0462 + 22C4EE887334718534E719F36454E440 + F9EC44A2DC38345CEEA9425BF5F10123 + stream[192..255] = B32235522391A0BE105A993923760C6F + BBDA849213C628776BCC5364F28EE5BA + D498F186C3C57A8DBE5355C2A38DDB82 + 54B321636EAD186788DF1BFC5B6F85F6 + stream[256..319] = 499CC51B20538B14A05E490B6D5D10D9 + 11079F58E3603A84AE6689293E3AEC56 + 7545823F0B085469CAFFF01D2AFC5076 + C155F8B4B7DB4C49A9A993964928D11E + stream[448..511] = 65983D36E97AEF89C3A75616F7C098B7 + 5CFD9C531AFF8184010E2CFD45163312 + FFBCF5AC70139CF12D97325CCEFD0B01 + FBE571FFBD7DC21B54D4B277A2205E56 + xor-digest = 90CD243B35747378B85B99474EE0BB3F + CE7574CC19BEC5220255523276CDECE4 + 5A16EF44C414ADF1D1CBE264872419CC + EAF664CC74D36072E9B975FF40074006 + +Set 1, vector# 99: + key = 00000000000000000000000010000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 26F731F36F626943D4CBBD605CB67FBF + E9301F24AA4E93EDB2D0DBB3FB17E8C8 + 623054B3003BB12E1C8607FB53315AF0 + A139CDC381753A14342AB90AFDF43E67 + stream[192..255] = C3B755D009DE9965D36B4111308B25EF + 39A137E373BA0E90E5AE2748115F29FC + 562A6F6894BFEA59587F991DD105DE1F + 67F62A73A72A4802ACE727335467F503 + stream[256..319] = BA815578D19B3B384BA7AA7B972B1FC1 + 7244FA75A4CFDC8C30ABBFDF6861F356 + 6A9B68A6F60A61E6DC8E046FE75373E4 + B45EAC193127CBA3AC4F22345BFDCCFE + stream[448..511] = 99C68AC554291FCDC03F300D69CE68D8 + C4D4DFF5FB2D4C3079992D40FFCC9683 + DE471E6F2A406DCE03AF8EA17B7AE905 + 12F1368B8EFDA838274812C4F134E2E6 + xor-digest = 01AB73AE53306196763ACB9ACFF9A624 + B83A7B339DB517AEB408292627EEBC43 + FCA6397320F50E96ECC3595B13BFED85 + 1309458EFE35FA1167C2CCCC6A4CA83D + +Set 1, vector#108: + key = 00000000000000000000000000080000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 031A1BAA02280255F0413D76F945138B + C0835BFE7CA64B16AD090454F098B8CF + 34B1EE138E03C3CCD9FF918A58D06AD9 + 2D7F3FB57D2E161A863A0C25391CCABF + stream[192..255] = 6810368C2B2A091C6FB3EBB76E960AC3 + BFD678F028EB6FC0F5B36C2D386A21A8 + FE46A5AE09DB0BD75359A8482EB6F5DF + ADE199B796520807D60D9D93995EAFE7 + stream[256..319] = 0F2CDD428FF6DF2A4621A8423E09939B + 014BEBC0ADBB8CE71B5E587DA408ED43 + 04A12BD535257322122EEA2840A9447E + CB1B6D3550ED14EE31424F5404B2B5B0 + stream[448..511] = C63FCB06883F3AC65612EDF28C875477 + 1D383D42A553EAFA37ECCE26061EC5AD + C6FE3BF23E06CFDB14EC1DD996A7D4E3 + FCF7A0B9ACC69F37ADF428B434994595 + xor-digest = 463386D0F7A1306E87F3221C4ECC0597 + 9474F620AF3563686ED5DEE291155225 + 56B9372496638BA1631982D6B3F58CAE + 27810BB7AA93351B838D54EE761A8C94 + +Set 1, vector#117: + key = 00000000000000000000000000000400 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = AA4E7E8171A8E0AEDA6049999E0A06C2 + FFA43B9ADC5E9DCE4ECD8FC1D27BE792 + 6FBE2ABB69A6B69D8C213A793C77096F + D4DF7BBDBCDF007C914B7C817837D99C + stream[192..255] = FC90E3C82B8E7228C1ADC2F555068372 + 4307902A0750149CE0B2EFD2CCFE9875 + DABE60E1B85CA117D05E4BD4F45B42E4 + 55A9F42C60910C9BFF8DF8FAB53C81E1 + stream[256..319] = 9BD976B88E9E5E23D0D40779644BB3F4 + CE5C6B16FA6D955C32369DFD19D632BC + 7730683D562320E39F75D8D8BD074968 + 9ECAF0DCDCD99FF4C3939092E9576144 + stream[448..511] = 51BE9CC1362669C0F79D2D88A42DBED6 + C3315002380AEB647C8F9C4036590527 + 1D8915B985B8BE9CC1C5C7652139E609 + 651EAC8A14DF661D9869982AE5735E9F + xor-digest = 0B0C84D430687F488F8E45DECECD6D7F + 1947E32AC49BDD2139F5413E08A88F31 + F9AF6599498431F155AA10B7EC09F095 + 8A5AFDAD486D2E6D50AF77FE98E33738 + +Set 1, vector#126: + key = 00000000000000000000000000000002 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 52F49050156E957C605656B2DF88EE1A + 5E3ADA99F9793B65456C4C6C322B8B5A + 28DCC91EE0E711BC33E0C13354542227 + 613665CFA3A825B943444401EFB06ACB + stream[192..255] = D0907F5D5939D7B544476E299605972F + FE422C64BC6343F9C81093AD0E3ACC72 + F4B67314892E36764736C0715E4D3438 + 36BDB105214F5F8925F321F5FD865EE2 + stream[256..319] = 96EEDA75474D65615795185B1BEE8D44 + A687420304B260E4C70FE7F542967325 + 1826EAE010981F6262EE6CB639996467 + 5F6B23825748128617721752283C16DB + stream[448..511] = D926085A441E507207850AFF3008D59D + F7C9D3B69687D18CCFF2C2E09D4E4EA7 + FF0B72C04A86B80923DAE187FFB99170 + DBD4902AF77EEC42866A83B519F092FF + xor-digest = 1E068ACCA6062CF26ECEC79F149BE139 + 24AF8BF44377EAD1550B1560E4A1006A + A6986C61581FF9E47D58F2E52434911D + 5AFCF914DBBAE183D02DDA3210768984 + +Set 1, vector#135: + key = 00000000000000000000000000000000 + 01000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = EF5BBD7A620E8052F05DC269309AA7CF + 8AFD4AB2B941D905AEEFC721562E00D7 + 04CA70113C8A90FA12A0C9B9CD1B9F9E + 6176602CC08B66410A8BB0F5E9837C27 + stream[192..255] = AB843B43856FC77C1EC09C0DD2248617 + 820344BD2CA0B025C39B0EBD5A750A6C + 7BDCE863C068E0D3A937A5B2C5B6ADFC + 609F6DF7778D88238B89288B2768DE99 + stream[256..319] = 5E6AFBE41F47F35CA9298C973E613174 + 529D9BEFA6D0713A5BFFD96B70D39044 + 413E24FE57B01C426E8988EC365FEFEC + 1422CDFB956B12C6A799F5FDD4EE43D5 + stream[448..511] = AA960C189C0A20870901D4E2F1901D0F + A28AF3D974E14FB70736C191D4C9CA26 + 48EEBA776339F80D57A8B783419E61B7 + 52541CB296B4CD31C55DE3D34CEF0D31 + xor-digest = F163BB7ABD3914204ABAF08B844ECF05 + A36B7B37B8345115EFAA2AB2E7763E6A + E044A83597C023FB41EFAEFBB63E4195 + B60AEA6399DEBC94C75BE883B3623733 + +Set 1, vector#144: + key = 00000000000000000000000000000000 + 00008000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 9198011FAAD874AD77CD0C98DD99C7BA + 01B75CF9DE1E26321EC6AD293C73C675 + 69A349157FD47672C5326276BA40F4C5 + 0CF8D98134D0BC13879E9EC267110FDE + stream[192..255] = A9B3BEEA161ED996C44F6D3B93431C6F + 54DCD5DB88E62CA10D1067B9CB5D21DC + D7E04C48D88DF54E1370D1C24C871BD3 + BDF9B956315996F95867D1E2494370CD + stream[256..319] = D09ECB5DF5B0526372B57CDF5DCA6AE0 + F005D2E2F27D50398E3D1D7FF2100BAA + D6F2C03E431345A4F41CEF3E8D3F14CD + C76A423720A936D27322559289F13D92 + stream[448..511] = 5E8FE7964B052B6D27216E37C49CC913 + 450FAE159C087E34CF67E8B0B8F516D6 + 3C0B544CA29F9BCB2B48D3894D69DE3E + 1460783E82EB67990FFB7F92DA48E449 + xor-digest = 5515E37A3F274746847F551ECB7DB4BC + 2BC32237050BEE9AF2AD1BD8577034D3 + 4A23AB8A2FFD00C7B8CB7D5CA0AB2421 + E7CECB2801A1B73A44FF3E798ACA8443 + +Set 1, vector#153: + key = 00000000000000000000000000000000 + 00000040000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 02858548ED24761DC0AEC6752076D095 + 7E78EF1FCFFD8E756C747586A3B59C22 + F42A9FCA9F103C3054E0B4F6EEC82101 + 971F2A6F9611F7541152FA3BD7774474 + stream[192..255] = C32ADE80873D1190E9807C25D73EC5B7 + C208AC693D98A664FF4D11205650F7FA + A36B153BC1A3F0EE0F4319F2100F7F27 + 31856BFAE36110C12EF0361259641D74 + stream[256..319] = B8F74AD5930D1F2CEA6B9F7E4E775DF0 + AA97744677E5C96B9E55AD77BFAC5E8E + E9BA7A19607D9EC52DEEBECD185DAE13 + E304743019D831849F111602EE6EC34B + stream[448..511] = 513303A57165287E793DB91F49C9A8ED + 522389F03634930512744884BCA45F4C + ACB60FD077BF2C050D4002162FB811EC + 4AA855793CFF2E30665188471FFE0847 + xor-digest = 7EABCDBDA34E51E3A61D2F3340884BBB + 600E1D30216B7117081B3E5D04FD4523 + 706D4F34C5FD604134DC89F570D6119D + DBB7C5FB7CA90E38AC157832C3C956BD + +Set 1, vector#162: + key = 00000000000000000000000000000000 + 00000000200000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 689E48A85A40BD161BEC710F9B2457FD + 276F1156EBC10BB851A8517AFDBD692D + E4827BAAFF218AF886439ED976147EBB + BB1074BD599A80F6324C87BAC987B8C5 + stream[192..255] = D9BA3E74CBAA58CA97DA3D3B1051BDF3 + 29F6CD837B72022D2EAB5D20B02F53DC + 4755C764C50756A7101998C187E4F0F8 + F17A0C6797976C4FF1BA17B3D03C2218 + stream[256..319] = F6F9B6F0F6E1D756C0242B48BC55EDE3 + 3038BABF72FCDD5122C61804996F5ED0 + 86A78B33C517CCED9C34580AA54AC03E + BD0F9698A234787DFE97FCD3D9B7CEBE + stream[448..511] = C31091C4C5AD605BA90963B1D469E501 + 412FEECDE3EA8EE834F188793A98F830 + 81F8C941F11676E007074B40EB15DDB5 + 67D93E954422376F2E3039F4E4115D70 + xor-digest = DF047B3EE7F2AAACE9D5A2B0F6A1EA0B + 97E815E9B9BDD3B7862ECB414E9C08E9 + BA0109B1D6866C9D7D6D3DC9FAE5F51A + 48DE7B9077DA489B7982BA69228483A2 + +Set 1, vector#171: + key = 00000000000000000000000000000000 + 00000000001000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 1F8F707DDF0121AE4DF26A6ABDC195A7 + CB9CC8479588D2D436C52483DA54744A + 2880E3DC622180D36B64CC053CC245D8 + 0700EC62ABCA6944BF89C7DE1A532A3C + stream[192..255] = CB2D934DD1414C60550CEA6FFA776312 + 3C9336F99F16F8B5B8E60D5D0CE54A35 + E752A4887A03EEC95050E50B58F5C8C2 + FD814DE76D3F66B907C77C9B646EFD13 + stream[256..319] = 10306DD8B3EA307496D7BEB7A679D53C + 3650ADC53991D0565856F51DA82CEB45 + AFB460D6F90877557E17F534C3375FD9 + F96D13AB77FA3996998F5DC6F5D3C9A3 + stream[448..511] = 42F4D1F669741750B24A44F82990E6AD + 065E7B07B2194C96E7578F7A754E52A5 + 86C820FFDDBA671A7B08D65B51D8736F + D0DA8E81CC69BB8A56565C43845C0AF4 + xor-digest = C0535BC269BB39AC2ADCC50C62F87B6F + 2C9351DAD49813529A27BAEC163A1D8B + 778670F0FF1610A4688F86851050C9B7 + 275B087A0B5CE01B602F8D1D25C29392 + +Set 1, vector#180: + key = 00000000000000000000000000000000 + 00000000000008000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 899C1C50A80E374AE884F10BBD17D036 + 1632D89938FDB7E4BCFBE1050D5E948C + CF4631EDFEFD2F140FC3FBFCC096CD68 + 1F6C1B0CE9E395FDEC56295AE331D8D0 + stream[192..255] = 2F60CFD4D07E58DBC5127A98D2B1DDD6 + 1F216F61F70AF12427108906AFEDA4AB + B439A99765EB84E43D06EB7B3D984A3B + 53D8C054745A6E3B61F8444C84C7F30D + stream[256..319] = 1A92F3B4F6C4684201FA4AF201259AC2 + 53637B41B734062C298E6F932DBDAC5E + 999FEC21B63539B5FAFC312D0CCE6137 + 04AB3CE65E241A1C34D12ECCC840973C + stream[448..511] = 83A75C2E2C6D40FAEA049322DC1B2251 + 306A8906A37DD30182C328D50E7B7AAF + 89671DD776C9C730EEE0DACEAC7D7038 + 4A93426090F31EB851976B8B2ECA1FBA + xor-digest = 6D85E7DA2069F1308D20A56DB17F3629 + 09E80EA6A045DBE61FB037C3C8B9D448 + 526A37A431A8BE49CE4F10B8CF6A33B8 + 82E6ACD6309BA1B716810715666C6CDA + +Set 1, vector#189: + key = 00000000000000000000000000000000 + 00000000000000040000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F9E151BE5EA0F532E56958F173B8F104 + DC9E73D8FA289CC2F84C4BB10E8EA769 + 57FBC8F539365B9E9518F8787D6CF927 + 55F0C2B2845318337F36B80E22C59FD6 + stream[192..255] = 27FAFEBD2EBCD2B67AB18BCFB7F8DC96 + F54C8A765B0E4B3DDC3013B599DEF791 + 287FF3C0F48F339DA04B667E54696485 + D48751A001B548727338AD6FB82EAE42 + stream[256..319] = 09DC2AFADEECB86278C64DDCA51EEF97 + C10B9852DB5F33A19C99C0D4F36D2959 + DE247E4DB356E67F2951E0309F18D6D7 + 27D2A1BADCC44DC320E2AA80E1834198 + stream[448..511] = 4103D8455B6DAE658915FACFF2F3F1F2 + 856E2343143671565936301E9D1F635F + EA732C9A096C3E955D33770E244ACEA4 + 094E390239489F4D4F0A1F3C26A1589D + xor-digest = 8DF4EC7886C386E5A0D7201A3E731E95 + 5D1E281321C2B592E31681CC95D173A7 + C92E6112197C6A605F494F6E9C4AE73A + 21B966CBAB1628794F0E44202742EACE + +Set 1, vector#198: + key = 00000000000000000000000000000000 + 00000000000000000200000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 8B9B0CC804CB353F49564926E3FD846F + A4758692FB110A428FAA3132F4C606CC + A41CA937FDE463D9FEC51F419D60AE60 + 1E8EDB30AB09E0B08D0143D885161B16 + stream[192..255] = DC6DFDC4E36FC1D4BD87F731F761BCC3 + 9837A790DBB766040B4508778C5CFC82 + 8EF9EC4D76BE3AE0967DBC844A2D252C + B942E97A2C6A185ECF4E1200BF9BC826 + stream[256..319] = A9DE78C2204B712A9803594B872F29E9 + 5E8962D7D719702FB3279F053D311292 + 26A14FB06058AEEB6D283EE0A272C6F2 + D392B102E294A7CDF24928D5281D024E + stream[448..511] = EB822D7BDDA456BB6E109ECD330D4FB5 + 1259D7042935BD5DFC787E903758C27C + E9E9B191957E721A7013D36E5A29C09A + 3433205956A55460D1498124B2800423 + xor-digest = 10128D9A5EEA1D93E65462702DB15A8A + 23D0FDFCC5B0871639D704DEB9F580C1 + C88213CA166F3BBB89D0926CAE7E64C1 + 0A24041A42B9D50CB0537A0585EE574D + +Set 1, vector#207: + key = 00000000000000000000000000000000 + 00000000000000000001000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DD4CCBD0B5068DF0193F50C11D2576E1 + A70040D6C2CDB98061498891D1791E63 + C4B5103A52146CE27D8F721E147EA612 + 7E5BAE1FCD3DCD9053D5FF5EBA328BBF + stream[192..255] = 541F008D78EC1ADC5D1B930CC99D4A3D + 61BD60AAB9DDC8AF8594FCA129410232 + 92BC44EE064E44E88A07ACD1B742666A + D147F14102D23578E3B7DC00905586D1 + stream[256..319] = 6834D2FB6BF3B46C0552AD83275CE6EB + 9482C2DFE40C6B1FD6F743CAC8F40A91 + 5BA9A90FBE7CC0153D53C444D3F7A23D + CDC3134E237F63E5A07C99C10B8EE87A + stream[448..511] = 9F75BC84091695FDAA2579AF9D34B2A7 + 2B82D39A1E7FCFC4D18D6898A9CD3296 + 0D50AF1B720E1347A0848782BE6AECC4 + 684CCA05B893951A65EB7CB37F5FE240 + xor-digest = 12F358C7C4C697199F9AF17040115522 + 062514A5DC3584BC515AAA4474A1D85B + 47A6A2D8C39E8234A5D11860BC1036E3 + 957920C03E9A47E61AAFB058A9850559 + +Set 1, vector#216: + key = 00000000000000000000000000000000 + 00000000000000000000008000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C5958694DB1D54B95101A9F48660CB26 + 8EDADED85C6239098248E0867117607C + D5278E5B5D9CDA7BE8A6BBDCE61215B6 + 2A93FFF627B28B271CF2275E54EA1CD0 + stream[192..255] = D9B69B25B5729759F3180FF17421092B + 0740B2E1307FA9141915CB8C30C0C322 + A1E4710674EE715DF3AC89F447442A7F + 845E154393273BA47F2322BC661D1755 + stream[256..319] = 49412E5F3C9B5B52FF790CBE82D6F037 + 217A13B7744740A887F7C1FBE3714DEA + 2A4EA4A5F444B2EC3C0B160A251CB44F + 8DCA914FBB80F72BC8D009F1C7E001EA + stream[448..511] = E1C2BE8C64D6BFE081EDD30681763928 + 85939DD7EBC13E16D83C8E7FF65EDBC5 + 90FA3904068784806E20F0A61CC73839 + E3BACD410F59D3848F5A628EE030FC4E + xor-digest = 54092B3D64197BD598F9050B44D2E785 + 029F29F46822B72ECA40182E8ABDABA8 + 751054FC50250DF5AF5AC75F4C51D1D5 + D2BE298770C353A7C5D608D1149F1452 + +Set 1, vector#225: + key = 00000000000000000000000000000000 + 00000000000000000000000040000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 633A6CAC516B7A84CFF8F5702CD9BC81 + BCE328741675EBA0FD1368190AB6BEEA + 7C8B0256CEDF9E5CC6F9249511AB87AD + ED95BF8E11182B8BEB75FFA279C3F706 + stream[192..255] = C3F700538A4EEA17773E74D10CE4493E + FB0417B380ED4229F651D6A9BE0AC617 + AF66C576B7D06F2210EF226462004D90 + E753D805AB198B73B0CCD752C7E57A2A + stream[256..319] = 30A11289A9E0C854B980BE044F07E945 + 06D772861896D0F75D739647FFB939C8 + 13FE4BE5C8DF84F64827306D0DD82415 + E104F787F30CD097EED7DB9340A0F47E + stream[448..511] = C2134984733448DD577DC48B5EE5D761 + 0A54AB6C32E3BB782849D8E7E8B522B8 + 0D6444342ADD9709D7434F9B4C18C6E0 + 15AE97DF8F3D29FA6D85DA387157E223 + xor-digest = 8613454AD0B424AB6EFCEA96C0802B6F + 47F1E98C52BC68DA25E653431CE31078 + 1658BC45DCC2EB43C4ACF8395727133D + 12A127D4CBAABAF24BA44930A58A87B6 + +Set 1, vector#234: + key = 00000000000000000000000000000000 + 00000000000000000000000000200000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 6A0F095C0E23FD6F8DCAEDAE5314141A + 0F1CE1C1BD6A16E81FEFF72F0753A5AF + C1C54DFC0DD6ED99F1D416BE3C5EF341 + 454C18D49729E80EE99F37734817658C + stream[192..255] = 05A4DF5BE8A35DC623D107728F28C789 + 3DE0E75268B3E1F94C07AE50CA0891D6 + 2B1E764CB41062391B33929273CE6B6D + 1C9CEFB35C37AB2FA8EC18749B5292B0 + stream[256..319] = 41C8AF9ADA46F7BE8EA72BB3B8661B78 + 2BE5649F18F216B75A0071A6617200B8 + 463B08F986D706AD140E27C8F4E040BD + 6BFB4872D758363281C62AE8C4B64E33 + stream[448..511] = 58CDA35476767EF58748A504B0E4A38B + 64162AD422A0DEC0434D879898558C77 + 1A8243DC43B15FF996B4C8CAD3C47C6F + 26F00C71ADFB538D9A983B7B624D6E62 + xor-digest = 240A699AF4DDBB56A4C502A9175C0E3A + BBD654D0717A1F6F6847381B978AE8C8 + 0EB7CA07A481DFF8606A31BD6B489AE7 + 89763068D641BAEADCBDA9ECAC465ABC + +Set 1, vector#243: + key = 00000000000000000000000000000000 + 00000000000000000000000000001000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B3C91DA5911D7D7A4BC16A66988AFD3C + 8462A9E9BD0D95C9B9884DD14801E464 + C27048FEB5F70B28013099F0A31255A4 + 9EACE528A13CB5DD067E520D183133BC + stream[192..255] = 756EDB0542FE1F11B159C7081D9CD742 + 2F0E5862D39E2CF1517B2F6F39AE5245 + D659A5B93EB8FA8C8FB751B378BB0DEB + 481B874663624C8DC15E6A1A64376340 + stream[256..319] = 436613C9293D5DCB204B46899CF23E65 + 698BCC3003FE064FD1263EEBC59DDBAC + 536566855510FA802128F0A968A2E359 + FB68EAFD6AA89D394B32BF6069E92EFC + stream[448..511] = 033FF40203ACAEDFBF561A674EE74D97 + A535A448AFF94C8C167200E5CA626388 + DB1BD6EBD4A1D83CF352E97CD8F02671 + 18E57B71D33930EC2752D2F262A55F9D + xor-digest = 2CEEE4705688B20B3AF71F285DB9361B + 0EC945296B97F3A050C31C54E9A07CA6 + 498B92917617571928E2663CBBAE21AD + 8DD880A037A024E46B6581974838AE1A + +Set 1, vector#252: + key = 00000000000000000000000000000000 + 00000000000000000000000000000008 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = A6AFA8AA02C3AE7F29E61202B4A5C25B + 6F74BCC176702C9C1D610FF722527A6E + 721ED90B871AEEC71EB62B24A8F24357 + 07765F7724BA03173F51C9B66C9F4BDE + stream[192..255] = 002B8929A54C1370067A36DB9057807D + DB747C2A4CE19BC085DDC517AADE3B97 + BB1B35F2BAA6A18E8154CD80DA6F9F4B + 0DBFD3EA5F69D5ED3B5770C6221A8D66 + stream[256..319] = AADBBFDFC6FCC6072747BB528EBEEF34 + 6DA76885CF1616ECFB89D3A134769902 + 904AA12744DD404F268B0B4B34700928 + E3C4B3665B9CFBAD9C528EA06F89CCDA + stream[448..511] = DD5453BD0D99E7D2CFC558EA969A4E35 + 743AFA96D570026106C5CF40037B1325 + 40C909C1278DAC8369B1AC257FD8D868 + 3648B4F22F7C66282BAC49D8D23626EB + xor-digest = B3F2AD900155FD5D39768B4F4B7F8E5A + 1C557936F2B5F06966DCB884AFF7F01C + 7AFC073C20EAF85363DFF41357E626B3 + B19607224467413D185A05E7BFBC5F0D + +Test vectors -- set 2 +===================== + +Set 2, vector# 0: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951 + 53F06534801F89F24E74248B720B4818 + CD9227ECEBCF4DBF8DBF6977E4AE14FA + E8504C7BC8A9F3EA6C0106F5327E6981 + stream[192..255] = 30DA9453A90909A5675D6B691CB0990F + C423CDD8222EB47245BBB67BCA2B9C10 + 8D1F016DF0CF8CEAF6829910916DBC1E + 113D11E91BEC3D85C47E3042EC865658 + stream[256..319] = CAFED71B892EDBE13388CEF6A3365797 + E0D88C0D3A5B91BE4CBAF5162F69558F + DBB45CA6F8C8D4C371D62736EC244584 + 60131F54854F3EC804AA9A38E6ADE281 + stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F + 2C3EA0F56AF46ED93DFAA4E16F5F0831 + 2D77BD0E9122043CD6A202CBA9351F6A + 0E8E6263F4017355136A0C551E6FD0F8 + xor-digest = 023D719F61C193E4CCD87755C87F9604 + C5A29DD7E31637B3DD70D43441D48CC7 + D474013C85EEAB1897C80ED0A0272543 + F951C72E3954616CB5D6B51FC24F4B0F + +Set 2, vector# 9: + key = 09090909090909090909090909090909 + 09090909090909090909090909090909 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081 + 2145B56AEA46EB283A25A4C9E3D8BEB4 + 821B418F06F2B9DCDF1A85AB8C02CD14 + 62E1BBCAEC9AB0E99AA6AFF918BA627C + stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58 + 11FA9BB02CECF7440239FBB0497347EF + D8F1A8AA71AFC70ECCD64E81388E6E87 + 9521C2B47AD84F9CFD9E240D8D2F3001 + stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD + 3C8D6A2EFDAA9CC11BFCC61D94F6104A + 4091B3634FA57AB0AB9B209F22DA5529 + 75C3C322DEBE4AE68623BFE1B2BB7F0A + stream[448..511] = 35B290F85EBA78A978750690C4747E8F + 72621951483772E8B89876CC5D55F3AB + 02D9B8FB35C741279FF9B5B571B26329 + 4D011F813CB5B209CA1A22D532BF09B7 + xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34 + F6CD0A795B8347E1441CEBEE35540D41 + 64FC2B95D71FD47A2C4ADF732261EE52 + 8125BE374FA4A90132CC1063971A2862 + +Set 2, vector# 18: + key = 12121212121212121212121212121212 + 12121212121212121212121212121212 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD + BD8853C329B3A881B489090853FE0F43 + 89DA105F0ADFA9CF51DA2521C40FD2B8 + FB0BF80B93E3F2B3D8A8EB1C615E0FA6 + stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D + 43A82A80DAEDBF29C048639BA38B690B + 7ED11323E3C0A8E77A16356705431EC9 + 9F2CB7F7E1ED3B83EAF2CAEC00B00755 + stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417 + 376F334E6AEF9C187012C8AD2B94BE7C + 00A876756EB232510FD0798E72EEC87F + 75EC1467C07B3A1EFB0D51A5FA65E382 + stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B + AAFD131432CFD7D2F675E03320395313 + AD4ED96E9052FE6B2D2A17428660A25E + EE642B712800BE3F7E44F21A1E6A03AC + xor-digest = EF4E84DBD66497B142EEAC56B830FF78 + 0465CEE20B9CFAF5727D4B3A588F4D00 + AAF718330CFF35508C44C1ADB8476625 + 2CC3AA6AAAE74F8BF1DDB6D4AADA425E + +Set 2, vector# 27: + key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676 + 263C1CB9AB941119B19D15EBA3462F56 + 2F69220595DE5E0E7C595FA40F1F06B2 + 6EC32252AF05310809DDDFAE2E24B170 + stream[192..255] = B29A740B51B4EA1080666337D5551484 + FFED6860A5125DC0573C8F90F23A98E0 + BA7B3E4C28C2CEFB1C33D2C36D1B7625 + 64B9A67240CF174347A4C8D868F00F6F + stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6 + 537C06AFB23354F054E25457B729B534 + CD10B2ABD45BE3E38DAF1B7A9103268F + 4FDB4C0FC9A80A003FCB907E8F249AE0 + stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39 + F62D54311207B617B727FCCE1B2E762A + 060810C4DEF672E7D76083E3E4BED0D1 + 0BAFD27CDFD2C937E660190D36B3FD7B + xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C + 18CC5E1E3F6A317ED7257887446EF734 + 65CA15F51AF5E077B7915062391D8497 + 8F437985DD08F5FA3A8D74B3227A6EEF + +Set 2, vector# 36: + key = 24242424242424242424242424242424 + 24242424242424242424242424242424 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C845BA29D542FBED2D021C85188E119F + D34967B79D9F44635DD45D2E41DC5AFB + B237AD2FA0E4CF4202D83DF3073C578D + 2AA8A32D30FB45DE28F23CEB85E50FBF + stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297 + FD12081B4B23F0A32CE5B3196173C7CA + 7EDD03F9637E08CA501C4850C15B207D + 7AA724377396CED2357B572BBF9E69AA + stream[256..319] = E484AF567EF80BAE77461855294E9280 + EF57E7366605785034D639D6DE3EBB0D + E21886D0E1E0679BC2E2C9C2D9201484 + 4A452B6AD3F1AC8B7762FF3C0E405B3B + stream[448..511] = 595D9855200786BB575FF7977509F395 + 7879CA1F19619A99174BF013CB62F85B + FF2C3C4FE724E26DD0C10D7635A2491A + 9E7E868D9DAD9201465AA178184D06AC + xor-digest = 08737B82505F46F4FF282EF42F387AA8 + 0450058F5314389BB73733BC163D75D5 + D32FC6408F8DE5F6ED2050027D605FAC + A7119FC2DC1B6D3E84E8048DCC42FBD2 + +Set 2, vector# 45: + key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E + 6E6320101999BCE5550C2BBC9BC65D91 + FAA2D72FA4BF46B6EE916244048B1D09 + A115E3AB6C00BAC8EE382B58859E8157 + stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82 + 0C18B867C561E96DF4ADADC5A4375E44 + 5A34F9457E5F8C9A337A0C88DF0F723A + D4509F1449DF2C6AEC0EADF4C7A8139A + stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8 + 452A1A893EF034C51750388D294947EE + 3F505839C69C1708E8323C449C39A96B + FC9EC91B0E1CAA8112057EB0389FDFD2 + stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC + EDD92C4461EFBA5CF1664B9AF54857BE + C3D00319E5E8A89A8322831151EE1D52 + D8585AC79CB60B61ED2C852D04BB0FB1 + xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D + 2363BC12259B0FDB2BD8F052A572ECA8 + D1EF62AA9A48497805A413742B5AF5A2 + 6DC9FF624B49E5D6FE58BBE5251B4983 + +Set 2, vector# 54: + key = 36363636363636363636363636363636 + 36363636363636363636363636363636 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340 + 42D4F07DA4D5EB05554CB7426D65C5EC + A93C2D321175B6F72FCBEBA6E38CB098 + B72534F7D534B1AADD97B77E8513B482 + stream[192..255] = B2466A173F436C8433F264CBF125B8E4 + C10BC81BD46B5C21FA161CB2AE07D27B + F66812A2C2FCB2B14C23E413CEF4E591 + AD52EF810A000B42E5C1B76EEBB17739 + stream[256..319] = ECBED2058DC50223614EB8635B834C3B + B176719C18CA5E3D087A93E5CDF81123 + C6FB819CCAFB5042AADFED5E3C33116A + FD92AA21031165A22F4751C423B8B945 + stream[448..511] = 758BD9435DE607867DA256064C304C8E + DDDF5B64173CF2C98B2842992F8C5FE1 + A37C3227B7F37D49A39F9FF929A883FD + 56DB8B1A174E1E55FCB21C9E1164C20B + xor-digest = 31761A49503946701D35306FBCBE10E2 + 02967E7EC14A328B4DB19FE79F03553F + 13A012B7297B2D02F18A216AD24A682B + 299518C3769123EE86A4937DAA9FC39B + +Set 2, vector# 63: + key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B + 26A4E7E34C0CA9CB9399F655E566383E + 246143F57776C8E08951E87F76091FE7 + 2356CC901F09A07895A890AECF047B3F + stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF + C862100A07E55FB449BCFA2D9BD48658 + 958B37B3EA3565FA66824102A14B5770 + 5E3914E0680E116ED58212CBF61028E3 + stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701 + 057710F24C01E680F58090B8E949AF01 + 8970A43A698A04C0C8639FAA665DA3AA + 562B2C5C3A03BCC38FE75DC1821ED718 + stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948 + 821FBB049DAD15B988A77C0247868A38 + 2056B66F47B0195FA30C9DB5A2334A9D + CD7C0D22E479FAE1BBCDFFE60F261C7F + xor-digest = 94D41CCAD940CED3C854DA0796DC62E5 + 6B566A980E34F353CFFD0F53AE9E34FF + A6A057645FE66D86BE30F93805D9E2B5 + D78C68EEBF61CE387277A51EB2EF835B + +Set 2, vector# 72: + key = 48484848484848484848484848484848 + 48484848484848484848484848484848 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E45194379659D1D8904DB3698AF8B245 + 762910B7FBD019AD1AA20A6C433B4C80 + 308A9EA68697631646BF3A2107C4E7FE + 2235E8F3262A9DFD3F5CC23FEB0B2DAB + stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA + 4E947598C4757976F6F61DA5F0DAC8BC + DDF72F08BA2F446FA37F9A490F6A2B6D + 79227C93271D6B763DA7B2A907220A42 + stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74 + A43D83AB8ECBAC5206D108F869561D70 + F151A0037F8E28951B5026643F8B2D6D + 56A62E259F04A5EA304791A9468E66AF + stream[448..511] = F70794C084E6EDC07BA0347413B05FC9 + FC46994CA820CE4FC037ADBA50EAA9AD + 55064ACB7308CFCE3F35AD5C7C628362 + F4210FBC2D3264F734728626BABF5356 + xor-digest = 31815B36BA034BB1941DB1E45A941A59 + 7C3882F34BD3BF441CAE8A9790B05BCA + 72049FD10C09A14AC9DB867A82C38A5F + 524C72F783DFD16980DBCDEB486FAE96 + +Set 2, vector# 81: + key = 51515151515151515151515151515151 + 51515151515151515151515151515151 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6 + FF53889A9979ABA8F23AA51DB1EDB8E9 + D08F696C1100799A7D004DEF1CA94110 + FCF0C054B0C131E6FAE0FE2F2DBF22B3 + stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC + 55A5F3F19C5A10E12EBE46DD84F10385 + 33837693588D584FDAF86E3A217C3CFF + 020278736F1A90CE07F0DCE4329005B9 + stream[256..319] = 135FAD68B5282FE59B28D2DF66463632 + 06CA92E84A73FA131EDDCE89A5C23B4D + 08FA57D455BDB32F8ED58DAF3EF288A2 + 7C72020E35DAE19B446E4C52DCDAC5B1 + stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D + 18F2111002891D3229102D72605B9BEE + F5DA36059B0DBBA7646927650305431B + FDA4A97570CD0C484BF1E974B157ED7F + xor-digest = 5125E77698C0DAA89A7E47DC5D038D40 + 7B732CE56CEB674CE653A1B6661B2740 + 0C092AFF83BEEE4FC4543B9D725C9387 + 2F89AA338222ED677BF59397200AB304 + +Set 2, vector# 90: + key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21 + 75E9AD91482965B651B495AEE819CC6E + C42AFE2C20EEACCEC4E90710D17210E0 + 4CC6832905985322C8007F872D3E58E1 + stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560 + D692A020F0A66F609374ABDCD1343722 + 05F19CA04EBDD3009844BC540C1B2B41 + 66D45E8A2E822B906DA34649E7FEEBB3 + stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF + CE2CFE99506677A956AEC86BD290B6AF + C5298A448D0DEFA99AA5CD26D318982F + E786D809C713D5A55B42CA6650191DDC + stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225 + EF6E3C21705EC9FB24873916A2C24668 + 963C03FE097DA8224A42A99E5DFFDC17 + 68CF518DE49CCAC8A70216C62C9CBA6D + xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5 + 5FF58B296071D5D39349A531E41F0BA9 + 893A1722B6102740BC5FE394A49363B9 + 6A626AB43FD6A288CD9B23F7255279F8 + +Set 2, vector# 99: + key = 63636363636363636363636363636363 + 63636363636363636363636363636363 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333 + BCB02E3AD8797377AE1F1B4D6DDB86E6 + 2A59791CB553550E0492FAB42C7A2C42 + 3157C5092D2DD37D46589F17FBD86584 + stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91 + 4122EEE5736BCD12061C77DF5B0122B5 + 1784E946B4E93470170ACDD7E2779591 + 57BCC9B9F3E11E88BC2F740AA0C10C97 + stream[256..319] = FF22D8196AB3DF662210D12D0FE79255 + 6DCD39611C07F089979CF7D693A30CA3 + 5B795B7F6D64931916E717C8BFB92114 + DB75118BDB51D142CE8133415C6B3456 + stream[448..511] = 971F007EFE17662D95F47F4F28266516 + B22A1E50755EEF19149DE3A3121F5FEC + E0D9DFE7A055026CA44193542D7687EC + 695B97769BF02F92C1EF3D904A8010C6 + xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163 + C8D54A4CA36748C74721C7B6E1649A31 + 4B5B7A4BD43E7C3D2A22F0C8446C7892 + 90D54D421D37CB16400E59CC86215CC8 + +Set 2, vector#108: + key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6 + 54BC11ECF0010D2AEB9F899130F4AC2A + 38EBC15C8831D591E6675DC1CE7A471C + 4B869FE83CBF37AC70BAAE5D4AC607F9 + stream[192..255] = 518F298A6008532EEFECB3DCF72103BD + 5E3F84FEB6EA2311E8C19A2E93A9C3C3 + BB1DA7DBA78D5618D1C4FA5B0B202728 + 62645A361E55494D66C9359E41E5809B + stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A + 89BB20CCD92E7F13FDD816DD4E4963C2 + C5FC2570CBB8BB5C70848B73001F508F + 47AF179528200F51CDC6E4854EAA63C3 + stream[448..511] = 844B1D15FBFD1264169279ACD525611F + A39C7BB41F1E7A1C09090625F7926E51 + 23A4CD7FE1A3F37ADC67AC437BF0A5AE + FFFC6FB0ABF39D9908145004AA5B958D + xor-digest = EC67596C9DEF4012A2D543842829306A + 4285A3B8038818F265065DC848BD80FE + C27C2F66A57B27F7FA8AC912001EC954 + 05BC6E93D7E555C59060F5D2E294D103 + +Set 2, vector#117: + key = 75757575757575757575757575757575 + 75757575757575757575757575757575 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 91D2772A18995DB3C0801DD3740F4466 + F9535E5BECB93DDCA0E94D19C0B57BDD + 0FFBA9DAF0B11D55C852927F8BA560EC + 4999E25848D08FCA7275E7E8571A5F1C + stream[192..255] = 72E64FF10CA9F07CC493715724DA7610 + 9E4358E8B0CAE451348B784A162DF036 + AB9796724D17FDBF356031D080A6631C + D1E8D217B041AD2EDF427972653206B2 + stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3 + 344956C29D10374E502C2EDD177ECE5E + 6625BAD9630DAD57976216CD69865058 + 130B132FEC1AB0C350DF4DACE4C7724A + stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90 + E402466550B518A177CD05985D238827 + BD92EE7EC22C274F19E682F85ABDAD95 + D0EBB3DB6C6134408353C8B0472C9A1D + xor-digest = 9A6C893F2108D13A29373DEDA65386C4 + AC356BDDD4A3178952F9126E322B7AE6 + 83C94F1A131CBEAFF26549D9F84CF04A + 1241FA374B055B0ADE7E49E8EC669E65 + +Set 2, vector#126: + key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3 + 059C5CC575D806B9029CCE3FA45A246E + 0EBD3AB2F2E324FE36ADC3B56AE2F7EF + C710AA964CB87381386C2A88B1308035 + stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E + 20BEB18D9C84187C347F43B17E0924F1 + 2348F825E106E57A00258CE4415294D9 + 4323A9812D8A71359CEC1001BAA0D567 + stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5 + 32D62E779FA0D2D08F8ABB6B0183A4DA + 4EE0329215F261D953150B9AB9FCBE2F + 568AAE361EAA8636ECC01A63F007977F + stream[448..511] = E7C44F44E06321A20E25F73E2069757C + 90499DB7E60025CF6D2D445E53A665F3 + 08EC96F6FE73C0AC90D7E4A712E18C2D + 3DED46DFBAFA24C4B0B329E52C525976 + xor-digest = 22035341489FA6EEB2A6488CA42F4043 + 57477C3F55569A1224EC39B1019E90C8 + 21D37D78ED4DCEAF6EA70724C3751760 + 38CF25DE4F84BABD80424D83A310881B + +Set 2, vector#135: + key = 87878787878787878787878787878787 + 87878787878787878787878787878787 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191 + 3C69F2275EB97A1402EDF16C6FBE19BE + 79D65360445BCB63676E6553B609A065 + 0155C3B22DD1975AC0F3F65063A2E16E + stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB + 3373B816DA256CAAC37914B0C161E4E4 + 5F5ADBE444098A5B2A4CFD4251D79918 + 987BB834BB50F0834EF4985F356B92A2 + stream[256..319] = D89642D25DF97D149AE07EA18BA39497 + 8935978AC34C1DF9F444986D7505DB4C + 7E08DB3616B84CD52E7DD7FB108C36B8 + B50C2573172F4D3500B6D62A9D20B82A + stream[448..511] = A2C17FE7371604556F796429C6BE0688 + 8611638B310F3E9FAF484BA9EE29C16D + 2F842EAF33AFEC557B68D2F453569187 + A6F4CD204A0E7A733E81AB7CE9FCAE81 + xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B + 6E3A61977A7C6AC2F033B826AB9A9957 + 66671D2A1025CDF8E2824B2F58CB221D + 2A68679239D90152FF7D0D39B33FAB93 + +Set 2, vector#144: + key = 90909090909090909090909090909090 + 90909090909090909090909090909090 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6 + 71A6D390BC7099A708D370DCD0E3D143 + A0334619EBD5C7DA9EF6301F29273F85 + 2DFA3C580ED65C6E952F88A0B7FE368E + stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B + 445792061AA0539DA69ED0B77B970C0B + 482156A5DEE4082A61364BF06E692399 + FB9F4411FEC515291F8949B20F57229E + stream[256..319] = 993E815F299D4841518119BFF88F6EFB + F3DB9BAE60238BDE2845DE4DBA6D79DB + C9E42BA5C3C004AE4546FD86C660FFC8 + FD6A8A349669FFE3D9E5BDF8E50A407D + stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2 + 1274F4A6D814B5440C74D53A3FF0735D + EF01B14AE4188E215CE7337C04871688 + 7159695A241BFB9D6B489FE9E23B2AD8 + xor-digest = 0BD5739ED28778023E6303FD88DAABC4 + 0FA0A211A1A5C5F230D9E67DDD9EA517 + FEBCDF0BDBC107291B6CF3ACD8B862B8 + 4BF15400493A54036E97FDEBB9A1DB2C + +Set 2, vector#153: + key = 99999999999999999999999999999999 + 99999999999999999999999999999999 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC + BE99E7E515650511FF7016A0EF287ADE + 5A03839C4F83F05FAC3B0B24D4E3F602 + 3251F8D9CC4530A805F8A6A912EFAB1C + stream[192..255] = 792823ACE2C0DDB266A118068AE295CD + 716E424D3B98A9DB2501A3F5DF7DC70A + 3BD2C6E664D5E13317D6F57B8774C903 + D407D2BB6014E0F971141E89569C5868 + stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB + 304C81FA9DDE0C21592247C4098D9347 + 1DA30294DE8C100E5B17A199F744CAC2 + 4E33490FC7F223FD6B4923056117C6D9 + stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59 + 349AF2BB1DA2BA622B9824F729929098 + BD19DFC05D0D9454F604960C027752F9 + 7812E53DE6AC6CD2751AB331703646AF + xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2 + DC458E7E517637596FC8FB710E2E5636 + DB1F14848CB12793D54ABD0856B22F3A + ADFA8C33AD08B8CC5292DD76913CB105 + +Set 2, vector#162: + key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229 + 8A8806402755660C4A30CD216A500BB6 + AE975E08EC62D08425A8A62A71B00215 + DE35E5178902348698528CB82296F009 + stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C + E4F7E1B3E78C3A5DF07592F45B968BEF + F95B8B257DAF2B468284627AF4481FD2 + 67BE0B164DD86721DC8C1607A0607EF0 + stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3 + 9C056162B626F383F3E77B5C98C0FBE9 + 119A7C335C333E6490126AC2510CDFAA + 86441C72D1DD9ACBCD3FEFC0D0C794C7 + stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754 + 246C065AD23A8D709161FC74B34E23DB + B918EAFA4465125D3780BF0B5803AACA + 037AA0A14D977141B611A6CA2278B634 + xor-digest = FEFDA1A6E95920B93380CC24FAE214C5 + 6B009ADCB176D519CA4B8538EDFC95D1 + 6CA06B730B28A230F0085FE43CBEE2FA + 2EE5DCD74D66F5CBB59F256CC1ED885A + +Set 2, vector#171: + key = ABABABABABABABABABABABABABABABAB + ABABABABABABABABABABABABABABABAB + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 22E1A884ED2C67CCB2977105649B6544 + 367858D1A730AA2FA96703FA406B337A + B2159A389BEF48D8A215D870B2968E16 + B11571F12BEC0A07FA7D3B9790987EC7 + stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74 + B27776E9250B8B063E52E169C7B76A15 + 0D699278AA4124427B5EB6AFC4AD5DBF + 600FEAAA98A88DFF297DACA5ACB4878F + stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484 + 976B640E60CCD6ABFB908583ABEC3E75 + 2878371EBB5374C9B37A63E0768AE10B + D857253D940AC408EF49EDD590E806AE + stream[448..511] = F012E429C44D5DC03B88123855B62C0E + 90E06759306017B5773752973850531B + C480316CBBAEDE6353AD5FB298349AA9 + 16AC0221A4CE1E4729BFB9C230AAF9FB + xor-digest = D73B872315F9052C67C4CFC5CD912DBD + 60DA32FD06D9C8E804968E688898200C + 1D979DFFCE52E1C3B3309B58D12BDBB3 + D3EBA2954D1587D720E004E12EB4A13B + +Set 2, vector#180: + key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88 + D2EF924014F7445ED922E9C021571909 + D7E6BFCAEE0724F2A9C522C4BDE4BBE9 + FE53FE592C0FEB80D2C7A51FB8BE9EF3 + stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484 + 0D22CDDFF39EB0E3D5FDF74C6E7B3394 + A0A4271D780DE6DEE9AC58B4903EEDD2 + 6DD14E14A4DFE506748D5DCA6DDF4C5A + stream[256..319] = E79D99119996FBB5163335E2F79F0502 + 7AEA5372136E7B3C5BE1F4A673A2DC74 + 60834B81BE6C4976C4A727C8E6046A64 + 4CAF42EEA6A068B7E532581E9037BE9F + stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614 + 9F3EE55A136EFA3B417DB63D2487DF82 + 794E161B3153DDB2E1E4F385E1A848C7 + 729FF5CB1CB58D5E73FAB1F2DCEEE5AD + xor-digest = 2F3C231B0228C274255F3BD314ECC7F3 + 1B9C49177009AFF2CD88F807092D77E3 + C74C1B9B8650F581EC7603F4D6E70955 + 1B00C3192414C04AB0AD8B0B9BCFE988 + +Set 2, vector#189: + key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410 + DED6D4E331633C5621B94E7EBD15E856 + 04AB202A553EFED55A548C7AFFCD2550 + 60315FD50A305D8BCAC9C077229D34AC + stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF + 3CFD130D5B6A9CE37BEBA429AD137A82 + 44D0586FEB16D086F533D1885A82F73C + F2AD2C645591F80ED09942F0A08D898C + stream[256..319] = C214B6AC700164FA66DE346A27A99463 + C5B6C0E43A9057384BE168E163058FCB + 6E7DEC871C6531EFC8B8D581EF92757E + 219294D39E0C9C8276440BE56C3D9941 + stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE + 4C8D2171695C9CF97E2936A8BB320670 + 015825547A508EB43D96F2EE1EE2CB34 + 4E120F001500F8ACC3E19E30455D09D0 + xor-digest = FE5928C74EA21F23E29171E5AAACA20C + DD8571E907763C96B99A8C11F9A1D2F5 + 78F68A6C440996995F7AB6E69B3CCE33 + CF8CE0C16F54355696D47DBF82EA8D56 + +Set 2, vector#198: + key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 75559677D7C762F6CFED942D800F2FAB + AB5F3892DC2C79922E96FD34FE511C11 + 251C8EB7C639E531CE08A8C99F62E7BC + F68FBAFF99D62348FF91CCFEC2710055 + stream[192..255] = 149806A4D862EEA81F0208D927339E5E + C98E9C2A6E0DB85CC0380DED7EC5B8AC + 4ADAE76AEB9C7B7264C3834316209615 + 25221D58C0174577110596FF89C8FC69 + stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B + 3CDD19BF89B31FF75A814F470BF97E0E + 1293B750B769F5BDD750DE5025D7534C + AD541A1F26C6AE9AC2FD3237C156AEBB + stream[448..511] = 0958243E88921B81F04AE63658E52D76 + CF2638495B3A6B970633A7C8F67B8CF9 + AC378082F72FC63BEA02881CC5B28D9D + C8C261C78B2872B5EBFC82336D6E1A28 + xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7 + 0028A08A00EF935C06A8B3632DAD5914 + 84E44E372A753F8E630741266C0F4218 + 4923608103042C70ED4ECC5112B9AF6B + +Set 2, vector#207: + key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28 + 98C701CBF5E88F1F3DCB6B873E5CAEEF + 23024ADA678E1A2CA9E25AA8B476CF4F + 9FCBC297FF03A9B94A5A736274EA776C + stream[192..255] = 73B9891D1770289A67D6338909FB6282 + 9A425B7947FC30DC52B11E398E85B1EB + 537E1C02898FEBFC15A9172C254CA55A + AA1B56EA856F47E37E2F252D92D94ED8 + stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4 + 38B63B9F436FE00CC075C585297B8F90 + E6062358D29641FF9C28EED4A23FC53A + 6B5C60C2AF1E8146DB27CCF5F43BA838 + stream[448..511] = 642541A9733946827D79BBD815C03C17 + 6357BD6E81E9A61FFFD4A0BF6863AC71 + 72AEFB92C1F235641BBE1457B724A6AA + AF9FAC687552A778B034C4A4F8E41ADE + xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668 + BD0BC5A97655978E79056B3D25DF3E79 + 5D5D8BE5D1AAE877F2E7D03225CB6609 + 6EFE11CBCB728039A243E326437CE73B + +Set 2, vector#216: + key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F + 1F7BDFBB81428FFEE9FBE14DF5F5F3D8 + A044EF53A868D989E16165A0F2B95E8D + 83439BB4805A125AD0CA7994AE11B852 + stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184 + EE7A7F4B822A1C955A69E238022AA313 + 276C2003E27AEF1B4F94B33A6428685B + F048B357EAB297B7DD98E612F054A317 + stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C + 978B976BE1B6CB0D15C0324D6B70D265 + 385B615B3EA97A55D94C47F53FF40861 + 4460857AC9568556AE54A52546B41B5A + stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6 + 5BE2BF56D2B78A401D5761E2F3AF8B18 + A2B1089864999D9B99E5BF6959F8F802 + 975FBF204D6159CF23F3706CAF0D9BA5 + xor-digest = 0957D6887501D4360C430614B67D99B5 + 32849E2F5C69CE8A9F3F707A2B5438BD + 0C1237B5617FB525CC9C043A10DBB265 + 3C3F0A353E89A19838B8F68542E09526 + +Set 2, vector#225: + key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A + 50CF101BF065F69F3E78BEF5D689B1D1 + D306FF41EB3E78BEB75C4200937CFE60 + E89E370680C519B2F64E23516ADF8062 + stream[192..255] = AA30580A210B87727BE17EC52AAAD037 + 3E0DD11FBFC89B37825CA4D6F9E8D433 + E3EA54C37D678B58CE834AFA310F6D4D + 06B4603F12DBF38595AC76511D0B13CF + stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC + 8FC9B09DAA6F418D3434BFBBFF6BFFFB + F93F8A963F2F51CC487BE868F010EC0B + EE17A480542A301E33B36F59BEE13D91 + stream[448..511] = 672048756C221C12DA6178BE711B3371 + 525A92BC9A219CABC5501B0DA4CC248B + 8742E8BCBD6F5A1CFE522F3DF3BED6B6 + 5D60D1AC737ADC582C2CB9751521828B + xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB + 3F418EBEB69509D69B2594E964759D15 + 104F674CD44681AFECC3B4939CA0A0C9 + DD7AA5726653ED3FBFC833DDB0C87B42 + +Set 2, vector#234: + key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 2479A8F2872A813D16D15F060D300237 + 25297B812F6F3B97D74D9716E4403A5A + 684D2BFD1E15275470FEDADF1578277E + 44C6C06B8A5FCE3D0CCC5E13BF49947C + stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3 + 132D4B0065A563288F848E05EB45E48B + D15C069C02F90B4FC10AEBF1AF4BF90E + 2CF7F48C8CD7A8091014131EBC21FBE8 + stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C + EC170B064429EB832924CDA9C47B5174 + 9BFEF80D96FAE36DDA65659FEA1CC06B + 4EA3A1601A3304AA4DDBEB62381FD4DB + stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145 + BFBCDBAE19F5281CD0E6AA37419778DA + 64DDF68726DD7F4D78BBBFF4576C2AAD + 93F477A2AB2C3CA8A381F30BB944C7B0 + xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070 + 9EC7E9B89DB8EEA11045ACC5FF003DC9 + CD3318BB6F9675EEF20E15490F525066 + AF8380C663B60EDBAE30663C94C39892 + +Set 2, vector#243: + key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CC3701E703946194401D1BA23AD99B5D + F3F856138E142D4B9C23DC9F252A277B + D62DAA33A71A0C61079AD5A20562291A + B6EC92C66D7BE6A17E27D4DDB48EFD31 + stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903 + D565423614409AD11E821B83F5B35D83 + F26F3EF9EC1766FEA9C21C09E0AE248F + 4BA01E48BCE09D06471593B3466703DD + stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF + 96CDC215EF1A62FAA29A5608C852FFA1 + 18B473C5A7319446F3ED2E8AB39A533D + 714325D1B14E838C9EC6E037DB0DD93C + stream[448..511] = 4FF3B43841B17A279002EFB07324625B + 7E937D480DC73F12836195110ECB4DB5 + CD31CA4F92F612A95E82815328DA7D5E + 4DCC5BB6791603EDA64C57B5A5AAA04C + xor-digest = 9202B874C48D4B1A9E857E645EE8F884 + D971CE97923AC024ABEFB944E34550CE + 31712BB832F9174F86FCD369E75CA9AD + 85095F43A4B7F33AB641BD6912D2C59C + +Set 2, vector#252: + key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F374DA745A5CF93A567027609E5D3B1D + 5C3C8A4D15203705D978AD42279F6548 + 51FF713F5120CC93D044EF717F5A75E4 + 98DBEF559E5F157A8C819E213E93B3F4 + stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9 + 175AEAA99D55485954B265B5CAB86509 + C810E664766A8E6C90D4BEE3A58B1815 + 9076959FFFA2F30EEB12343E9E7778C5 + stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC + 418DA96336991A27DADA74FDA987B867 + B125C53C0E4E2889FDFEFBFB48797A22 + 2836B2EA42793CE2BFFD568F6234B368 + stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36 + 4CD2D730DC8D7E183EC55A777C2445EB + BA7E9CD95C8F3A206B73C422AC2E2C08 + 15A8C6FED156FFF93B63DE512EF69725 + xor-digest = 467EDA43B849054EE747A532ED0D9AA4 + 6EA1BF2B6AF19F481D6E3D55EBAA96FC + 6629FE65B5EC4B5EB6A155A6D60FEA32 + F04F8230E26390F1C8FA53D47B68FEAE + +Test vectors -- set 3 +===================== + +Set 3, vector# 0: + key = 000102030405060708090A0B0C0D0E0F + 101112131415161718191A1B1C1D1E1F + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 7CB997D6E1B46DD7C0A9629B441C3771 + 14D6C18F230291FA7EF0B039AEDCC9AA + A4AE05BA13F3931E3F8373AA320A8BCF + 28E825B2084D0FA486BE52C92C3C6F14 + stream[192..255] = FD4DC85E176D76062323B2F5B31E219B + 786596F3DC0A2AFD31AB48C5F911605D + 556399114B0779F43221FE5BDA899627 + BA6498C210D5AEC5FEC8733357571F77 + stream[256..319] = F00E84A92BEA966DC8359FA63B12E8E4 + F5611F6C8CDD04CE9D605D770B2EAE49 + D6976272057CF275EB5B4CC434EA9B0B + 8CD9FEA22D7E919097CBB36C5D239BE6 + stream[448..511] = 110560BCF38CC42478036CC228E9DBD7 + 4C44863DAFC81B528AEA2893FDBAC7BB + 2F68CCDF566E1602623EC9AE283EA69C + C032E90E409F368E28401AE6905BD4F8 + xor-digest = 9CCCCDF3F7D712D6E3931068138F9A9F + 8640478BEDFC3C7CD0802954234DD07F + 99F4B072D9847DEC2E16FAD0ACCB3609 + 16243175C84A317191A98AFF5EFCEED2 + +Set 3, vector# 9: + key = 090A0B0C0D0E0F101112131415161718 + 191A1B1C1D1E1F202122232425262728 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0889D6D9E155FC208941B945F2B15362 + 3CE5C79122C1085FC172836FA9B06C0B + 50910CACF399EFC9CD9CC484786AAC8B + 377972E9A90D7EDD40A59FE1B942710A + stream[192..255] = A540BDE9860D8687A45D8CF22E00299A + 36BE590AC92E70BA03B8A5F2898C2D1A + B9B1E5C87C4B10C9B6E08EB868AE3B10 + 3BB95C30831B903A3A9620ED16B96210 + stream[256..319] = 90E2A684D3960A4B1DA5DF19BF569288 + 5A23892F2003AF2319FED9C8D37B8702 + 7E61290E013FDF93683829DB99C177F0 + 222EDD6A0FE3D5F7F903D3CC15C6C6DF + stream[448..511] = AFE7454BF77E3CE1050ABFC2E25F9B15 + 011F33B93660EA4AB5E7BFC513F2D787 + 27F8008ABC1E14B06C36F7750AE88C1D + 7AA2F6EB9F2E925CD6CBDEC5FBA3EEA8 + xor-digest = F1A8C58EA8459686DC5BFA2A81E80653 + EF6141903898D1A3C7298358A79D674B + A971C106CAB035722F246D3E67D34543 + 3E71DD374DAF73036EE55E6C0ECE5FA3 + +Set 3, vector# 18: + key = 12131415161718191A1B1C1D1E1F2021 + 22232425262728292A2B2C2D2E2F3031 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = EB11D29C989FB09961A673D8412360B4 + F4E6DF0169A3CE207656A7C72D6FB8D0 + 95CB3A7A6CECDC2E167CD35F62A00110 + EF09FD32B61A8B405A3F55A1313F0DFC + stream[192..255] = 8ED27EA005A3E298560C829380D4F1E9 + F0C7FD5285F04AE6FD66C94CC07C8C51 + EE8163B7414A52B0594C5F7F80104D95 + 0858C9A52F3C156ADAA025C00B180429 + stream[256..319] = 12DA63247282599F2C50B172CDB4F31B + 20952134800FB8BCE743BBA90E6485BA + 057A9C5E0989A8FDCEF1C88DD54E920F + 7028EB284306FE6A87B0FE063DAB9557 + stream[448..511] = CD447E9F58BAFB77F6E02AB5A692120D + EC4F7BD597DE5C54523A7944DBA6A3C8 + D00000D3E70F7D9292B7135A7F054812 + 4B98680DEF6631D2D10E0E7B08F188BB + xor-digest = 6EF765CB84937D5E829A1A1664EBD23C + B474FEA3C5AB137F2D9B35BBE0816EDD + B26EC14D74EFD0F9768C521A6FAAF122 + B5E34A36344FF0F0DB3CC2F2780D05E8 + +Set 3, vector# 27: + key = 1B1C1D1E1F202122232425262728292A + 2B2C2D2E2F303132333435363738393A + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = A71D4189D1338531D3C03D00A480C8B8 + 49C779B7E113FD8D59516164C161EAE3 + AEBF74542FFFDC2FF8C2666FD5AAE413 + 19072673F958F498F8FB9743BE46863B + stream[192..255] = B0B3803396AFF1646369B6FAE62EDBCE + 5254E7C8FEE88F9EEE5D8A7B6D44ADC8 + B89895198E3C147FAE0C9B8325EB3501 + 6EADF77C5D7F402CF3168448D2A59E23 + stream[256..319] = C1CCE6956C8257947C004528F568E3CA + BE9ABF891E2FC2B52D9A1E6EC97A22B1 + FFD1C77E50A17CB47014C9EDA1853AFC + 11526F6268102780ACB3E0F120398AD0 + stream[448..511] = 765857312C8994EF6BC7259673F02E38 + B7E0A764FB70534190033FB1BA86D5BA + 3BC6851DB596970A2F60831EA1A31CAA + 96085680CBCFADD9C5F0330CB72AB5E2 + xor-digest = 30EF19DE0E750BBF6AB3FC924742CDCF + 62B2FE5F25983BB9777C727679CAA39B + 1280AB468051463E7EB287AEEFA5AD0B + 9C9DFCA45A3124D5F41F4B0AF5849E62 + +Set 3, vector# 36: + key = 2425262728292A2B2C2D2E2F30313233 + 3435363738393A3B3C3D3E3F40414243 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 2B9B987B7CADACD2FA50A53A9F9F44CF + 4ED11B3E25FE57F1372C6D570B470AFF + 5FCF3BEB89D0692D873EFEBD26EAF3E1 + 1B6892913F0CB27F3CA9BA20AF7A98F8 + stream[192..255] = 0148F54B1D24F3D69A2086D6938898F5 + 25BDB1B1F78C5F92BA21FCE803A52591 + FCEC9A1AFB0FB3B081CDB1D79D254845 + 40EB9D624B5E113A4F143716722687ED + stream[256..319] = 271FF1107AA8968E0ADDA5371F40224A + D8E134AF80D5ACDC9803B1B3A9819BF4 + 8ECC3A68B303E1275FA97222F7E984EF + 9C73899433230FD746DA6101DE37ADA2 + stream[448..511] = A66D3BB64C35C71BBAA3F5410F388253 + 2B32897B1CC1AD610F3AA195CDC1EB82 + 0262E817374384BFBE200339B284ADF4 + BFF6960B6A41AFA9D7C9B67B19C14C37 + xor-digest = 3CF10A4A8BA3E0DA3C0B63F1B913B57F + BE47580DF7D90B13459A9BC98B93B014 + 1185E910EDC0A5B37206542B17CAB8CE + F050A4ED3D7097B6A0738095E4BF7A77 + +Set 3, vector# 45: + key = 2D2E2F303132333435363738393A3B3C + 3D3E3F404142434445464748494A4B4C + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = F32665A4C73608E133D85712D2CC9A76 + 6D2B83311B3F44564A56A97ACC9B6492 + B282A2E62A435A7B7799073E010C78C9 + 4B7B5BD1B25994D1CE31B51CBB13BE90 + stream[192..255] = C9F24592930A0A9148486D77C1FFAAA4 + 4E4EECB088D6AD38D73B195E576BEE56 + E2CDA968FEB85D19BF89391813501B02 + EAB39A2E78B8CC7456EE60EAC3454051 + stream[256..319] = D8E1D09F074708379189BBFEB1E24053 + E0BB5980FFD0371265320C3047F0ED36 + A65CA8D0DDF20DC25B552E1882811C77 + 6613DBB4297DC6C89E31529DFCD17C82 + stream[448..511] = 8012813E7879B3E99C40821A97469BF3 + 9D2EF3B888E3118275F47F8C78A5F7CA + 19A98B1817D2D7734E69C5ED43773D68 + FA100E2C37F40FF8E018DBA52C5C239C + xor-digest = 8AFB9CD876AF4F9693FF4FF511D89957 + C8BB31D9DE3F21B726667681F805FFF0 + 4B50850696D6C2E5C271D199CF49F1E6 + D366C7824273E99360BD5A294E415F0F + +Set 3, vector# 54: + key = 363738393A3B3C3D3E3F404142434445 + 464748494A4B4C4D4E4F505152535455 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = C72B0F98EE5C2D44260E929C70DBF174 + 02C03543483178C8BC129D67FE2746E2 + E881F8439E2A11EBB3716ADB16207BBB + 91454A71C444445CE64003F0BB1F481D + stream[192..255] = 5590F4278E78AD19293525095C2F76E3 + B35A3858CB5912B62304180225BDC985 + ED955521436DEC441B9C742B3C5F4CBE + 94B99689048AF93E48472980D058807F + stream[256..319] = FBAB34E9F432546EC8C52750DA4D2278 + 4C1323D4E3F4E9B63E65A7E3C8B2637B + AA5D0A3B897113F68C63CCB78B5AB40D + 0A0DC3EF1EB09DF5C4770B343B6B5155 + stream[448..511] = 78B0144CDF2692F0D0F164ECC8621F5D + A00C401007B82AAE7753712FD6185E9D + 7ADC8CFEA6D5BBC2F3EDB8BF2C77718B + 6A424BAFD30C30934FC645FF05704BB1 + xor-digest = 835B5361A9C1F88223DE7BCA09030CD4 + 67065AAE99198645029CC0AB9B9BD579 + 14332392ED7A433A64D95B44CE228860 + 7E029235580276BCAE88F37418FB641C + +Set 3, vector# 63: + key = 3F404142434445464748494A4B4C4D4E + 4F505152535455565758595A5B5C5D5E + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 804025A410EFFBA58647A9F4B443BFC6 + 1CDDC30CA04DA8DAB3EC6A098A830D68 + 2683B59B76C60C09938E67CB41385315 + E2504B024DB808923B0909EFC25F0927 + stream[192..255] = 7A4661190129E3F349DA7B44DAAFC388 + 5E4BEEAC9308844DDA45E8E06637246A + 0E6C8C7D94C5F710CB78CC6E0CA82870 + 8CA77B6266B41E3ED6BAA2940F1977A5 + stream[256..319] = A3EBC22126B6069C674DB604F8C22B54 + DA68FB4390617E86C4FF089344BD0DB3 + 887B3438E8EF8207FD89B2A485C0B383 + 22AEB69750AD054F843DCA7995BB58A9 + stream[448..511] = BAC68211F125B57B8CE5E42E644997F5 + 2FD4B8A7D5CBF89ED2F6B5F4D4C7FA5D + 0CC34212160C6BA536BB7604C184367F + 2E088528F3B3A0A1B20F9249711162B1 + xor-digest = F628E74D1EB94591694631F1B2F12234 + 38B056789D5C2ABD8CF34D9FA7B8C304 + 5A8C2298B7BEBB90C7CC86895693118B + 2A43B7E8AC7E534DA7965EA720F19180 + +Set 3, vector# 72: + key = 48494A4B4C4D4E4F5051525354555657 + 58595A5B5C5D5E5F6061626364656667 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 40409D9AD4CFCEAEB8FF613D32B59180 + F5DFBBF44C1B7209AD1AD5AE94DBBF3A + 83EAB34D2617ABCC396880BD5F5D220F + F434DD575E66CA74BA32862293113C5D + stream[192..255] = 42D9EDDAF89B93DAB4AA790BC9C45BAC + 5E94575E175C2EB1CC08BB39019E25C0 + 9B0F4F435ACE371BD9235C61C56A362C + B1A64EE58F4938D59073C5A8A1BA679A + stream[256..319] = E40477D1B6C901AFCC4A2C429845C7B9 + 0DF890C317A5B9D6368672C58E0BD5B2 + 7E42DA77BDC2BF47F9AD195F7C192B53 + 24FEF88E6B3DD1669A068E3FCB58B203 + stream[448..511] = 7616AA094DFFD4BCF94E03C9CCF95C31 + 8F247AEBDE281334F8E6F46271070BC0 + 1AC838D8FCFE18865DD30949C68052C8 + 6E93815B4EA9480B2D0B6A5D9888E597 + xor-digest = 1FE60024F188CC243F7D8221D990ECE3 + 29E89847C9BD60AF23061E9C27C4908F + B00D8813E680F00665658CEB077BEFAB + 5DEB41D3547DD645DEDBB3BF5D7B651E + +Set 3, vector# 81: + key = 5152535455565758595A5B5C5D5E5F60 + 6162636465666768696A6B6C6D6E6F70 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 1B8DA47812BF2353C17C89AAA8695E9F + F553BBA44087D262FA0C710B69765F12 + FFE190625F58DA899B56FA7AB5E0E674 + 4CA2B073517B9577712D7155E16A874C + stream[192..255] = CD2BB4A6C3D7211773421014611B677C + C0A8107544ABF4F914F825891E52DDDD + 76EFDBEE614573FF9674EBC154A3283B + 439ED8197E1EE0705955A8B6C8AFF8BD + stream[256..319] = A626C40CD2C48AAB016C29020096DE28 + F03842E785BCE9D9E385D0B13B63F82D + 789588FFAB07B8CC0FFC62AA86D37CAE + 5CF8FD43B575F9F4D6E07465B700D47B + stream[448..511] = 16A3C84858207E141022D228079D6067 + 2784EBB56E3B84F7DF07EFC69060E27C + D1311E51F5893AE6BFF80D34464DC60F + 61985F8F88164CCA69EFAE568BEB546F + xor-digest = A24EEDA74185884C5B287663C3F5F031 + 2743CCAC657C702A29E0C20BDDE304AE + A54A9292B447039D50479B6CE475115B + 8791854540E15D642859D10561AEF26A + +Set 3, vector# 90: + key = 5A5B5C5D5E5F60616263646566676869 + 6A6B6C6D6E6F70717273747576777879 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3F7261A3A4691A73441762D113EB7817 + 4C515A96C5C93C514EE559E7F78A633A + 01F0891910D44A7EBB18768E3B912488 + 6069CB5304E79ACA89F62EFEC4EAC11A + stream[192..255] = 5F11904F72123CE29D1D883AE5CD2A89 + 2AB26C9167A24A57D6F64BDE3A8E1A93 + 7C5347C585226DB44B6252AEBF3CCAAF + 2D5E60C56FBBA6068B35AA6A61C84A44 + stream[256..319] = CD6C5B784854E0121933E77C700D9C1D + 7452999F859798499A339F78FCF84615 + A3190A2F558CC529E636922A1B75A3A1 + AF280FB3F486303093DC1564EA0B6D3F + stream[448..511] = 61B8163A84540727204F0B18D9CAED3F + B5FA87089FF4E721D2EC34D21C59B93F + 95297725780DF04A5FE405FEBAE80AB9 + B8307B9A74774E76063F9218CE243002 + xor-digest = 944EF8435F32FF2A67CDA5FBDFE02C81 + 0997D9C8192633A193D6122A051B801C + 15555BDF410917B9E5DB86F4DE8B9874 + 3E9F92F903543AD14087F4E13A915DE0 + +Set 3, vector# 99: + key = 636465666768696A6B6C6D6E6F707172 + 737475767778797A7B7C7D7E7F808182 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 71BA7454CF7F6CC93C89EB22B9D608EA + 0FACBB4358DD007421DAC1E65EE99161 + C542DF02611AF497B2D53748D0129C0F + 5B9704C8A6017507EEFB26B6287662CB + stream[192..255] = 92D5D35B2E02D204E68C1AD6C018DBA6 + 7A1C90F563AEFC3D031FD3F7D4F5E2F4 + C47D326A9C49A0B2ADF03D9E7E429AA3 + ABF253E623BFB9EB040B5F5CF1FF68DF + stream[256..319] = D6C22BEA96DF94CE9D5D34E6231CE4F9 + A2D2F6097540F9A9160DE139E2E80D0E + 5AFE08131FE10F0DD7367E43D314D7F2 + 2321B5F89DC64F286576BA599A58F48C + stream[448..511] = 43DC3ACAE02DBF68AB5B65A81630474C + 639FC4DD36FBED518B6471F7C3E70FDE + 23CF1E128B51538DE0D5A47F20A554F2 + 09668FE28B0C4884888FAC438960CE7F + xor-digest = 7B0EF650F3847E3EB15EA1CB64EE7189 + AA5B04F527661C00F4603E48CBE59F7F + 48498D80F6C5ED956ABBF97E6910EFB8 + 341C7BC2E81E66A4B9474BE420DFA5A6 + +Set 3, vector#108: + key = 6C6D6E6F707172737475767778797A7B + 7C7D7E7F808182838485868788898A8B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3C4CBA573D803324D099BE1F436F944F + EE506CE77EBC01FAF0060B76FA5D2005 + 05CE94AA15F3C4B1E0194264CF13878E + FD36288EA4C2ECBEEB76828EB460AED7 + stream[192..255] = FFA464FA648309E295314DEF7169DC60 + F63C90AEE9F27B534E11D25AEC454823 + DF6BD39C1F9CB46276C630C129536506 + 187251D638D3867E96A84BD570F78461 + stream[256..319] = 6BE88BD0D2257CF7EBF7100B442F68C1 + ACB94B6F8991C1461D318BB80E59A6EB + 8009DFF46B8E339A0CD4FB285ED1E433 + 5FDBD65537D9CF1FBB0F9F10E17952D0 + stream[448..511] = 909997D084DE4F6C910D57DB89E1EB56 + AB3F9974E3DB5935D59917CACCAA31CC + E009324E52334BDD6CA971AF49982122 + B195229DF0BFE2C508E981D303061B2A + xor-digest = 8B2B49D564662BFB29A9F4E1A3DC7664 + 774D41168EA27505A2A518DD94C2A507 + 0D28E1E69DA2F084DAB024E8EE2D022D + BC73071B8559BE2FCBC2AE3605696482 + +Set 3, vector#117: + key = 75767778797A7B7C7D7E7F8081828384 + 85868788898A8B8C8D8E8F9091929394 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 6EE8B7E51036B951205064348C222881 + 624E9FF59DFED40AC6CDEA0945A39E72 + AD05FA929F7AB69BE8234567734F8F96 + D74DE6038A463BD8FB86224F5CEA0D45 + stream[192..255] = DD9CD1757A95E616E99590E76620E9DF + 0BF811F73B70C5CE982FC9CECEFFC6BA + F7DCA30517A9BDF44515262ACF297AA2 + 2CAC3F216C12A9D0D6912578DC672D18 + stream[256..319] = 0B7DE245062DCC9B1D8A945CD9A04938 + EB9BB258B4B7BCC263487B3599B1C6BE + 7FDE752D65345F00DF90896DF53244A5 + AB111134B36A99E2D2200B4D2003A520 + stream[448..511] = 2566E8427BBAC7F0A35C6E4BCDD326C9 + D7164A9E1F767038A09A75B5076E05AD + C51F008E9E3184FA4DC6E4764B381944 + BCB96B57FCE2339A01501BDEED46F8E3 + xor-digest = CC16803D36710AFDB1DEBC653DA7DD12 + F45B02349B87C3006DDCAC1635956846 + E4D7D6064D19012724BBF836A7DB7A3E + 3C12E6288F546EF316406D9C5E844BAC + +Set 3, vector#126: + key = 7E7F808182838485868788898A8B8C8D + 8E8F909192939495969798999A9B9C9D + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4F4169DF51C9865A20D7E79DEFF7B121 + BD61F4C79AFEDD0598F55E9D9A3615AD + 19292095DDD83904B3683722A3337BF3 + 4E98F63EB19927155E176F2E8D5560B3 + stream[192..255] = CF82F8F2A46A898915B3E371BE941811 + 682A8A0A20837AF471B5CAA4B4FB01E7 + F2B0CA9ED3BA70BE305587F1ED995946 + 223032F94BB2ED7D418C95F202887E6B + stream[256..319] = 219C121E08F7458BD657AC4131221C78 + 43DB5817B17344922C54A002F3F67574 + BEE5F7FFC7EFC5615444B51FDDEE8B71 + 981FBFF658D2504BB53C13D0342258E4 + stream[448..511] = 55C2A93F43F260EABBC1A173AAF80A95 + A7EA74CCEF6E29C52957AB2247126336 + CEA5BD0D08F873AAF733B3A11885F04C + 58542B4C8ED3E1BB7F7918C4E92926FB + xor-digest = F69FE6EFBB4A6E65B517445069859EAC + A9C19FCB9C1771E75266E5B4C39019DB + E959AD97F2B8D7F1688FD0AC04AA7C2E + 602F28A63DEAA49A7BE1422B47CFBE00 + +Set 3, vector#135: + key = 8788898A8B8C8D8E8F90919293949596 + 9798999A9B9C9D9E9FA0A1A2A3A4A5A6 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 3305344A71266B450B2CDEB049A048D2 + 6171B39A88C25CFC0821E4F4EFE378B0 + 702DA31652B5E1BAD9FF4C19C20BF329 + 639D5942DD2209DB1D1474B6A7B41B76 + stream[192..255] = BBD9714BF2C343B11DD7943DD8CDA8B4 + C6A913F1DBE21A0582B3FCFDE91B61A9 + 8863AAC17D07D8F98AE8E71BA5636251 + 49FAB3EA775D3C7735BFC732C3C42571 + stream[256..319] = 473F161607321838FEB9359B0006068F + 9D88B1A073DA14E60AAF1501F3A27350 + 53E3FCC794893257CC3C1D4E1E3CF609 + 975E865CA46C892823C838822AF0CD2B + stream[448..511] = 89F37A53F18778084307D0BB71E5712D + 32F0F3B7C2201D01D892F6BF6068E4B5 + 394995CE6BFACF08587ADA39CC647DAB + 9B12F5505055F372FDC4607F0355DBAF + xor-digest = C9E7E4A4D6782C02AAC4F47AF1D142AF + FAE569B755E880C6B8A5773EFC0E63D2 + 3D7A113738CDB1A0544175861401149C + 753D723CC1EF515A9323DDE4B4A765C8 + +Set 3, vector#144: + key = 909192939495969798999A9B9C9D9E9F + A0A1A2A3A4A5A6A7A8A9AAABACADAEAF + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B7954C45CF301CCAED3F1E7E77DCE45F + 2D41B3B1C1F28F0308B8AB4293B64A60 + AA7936DDF062613DC1C454033D2A40A5 + E99BD975A26185A7F419E7B337028FAC + stream[192..255] = 27AF957AC6C514514C24664AA0C9C23D + B1EE30950177389876FE4FF2E1739912 + A09E20A2098751049C8925334960A324 + 5ABB50F3D333587B67F153DB145B5F6C + stream[256..319] = D94FAF9FCB753E992B898178373A36D6 + 23C6BE2420AC2EA848130073F086164C + 9B4E69B024991FFA8FAE94E3C2FB16F9 + D747320A748DE9FAE4FE9E6A7E7D5659 + stream[448..511] = F664AFD3EDC0FAE88016C8A028E98D34 + A27843372C6BF8F51C7B49B94A11274A + 6A161D776E6C1FF05358F28426C3579E + 053B4137F8C4CAE07B994B80DA06DA27 + xor-digest = 521594487B583F5F71DA10E2316187F2 + 2A4885A69D522F82F7FD0D5F93F69B2A + 060EB60965AC010BC489B401F02C26E4 + FE3F82B83C964B4DB4E0E6BC2CE4B865 + +Set 3, vector#153: + key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8 + A9AAABACADAEAFB0B1B2B3B4B5B6B7B8 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = A5E320FF65811FF5E8934F3AC73B3733 + 77D3AC52446F64646946BFB8F6DEFE3A + 04E859DCCD9F421D2DF541F588B9C204 + A9846C7AA1C017D637D7C5E244602105 + stream[192..255] = BB16A9BDCA0D4BCA589A34F9278AE55D + 6A7711EC87563C9F394638041CBB0E40 + 4CD2149218D501D3B62421CBF81C6576 + FA659C2878839FCD6C8DD1BA38F46E6B + stream[256..319] = 58B4004C53EE64CD45BC4A1F11F700AF + 0EA5ED86C4BBC145C8F588B7F708427C + D2292D76329E4DB1F289DADA687B7784 + DABCCD29B8C464CE021856FD06554F76 + stream[448..511] = 1113D37AB2964AAE6586AEE1B060F0C1 + 02EB3AF048A59CB709792C9080183CFD + 2A1A47277F413F1219B5AAD7C8BC8079 + 246BD1D6F98C11997E4ED0F68E165D9C + xor-digest = 512F4852425DBF91234DA31986732CC3 + 1F9649A1965E22E18CF38979EE6D92B0 + 83333422A92F841C25F827782FD7BDB2 + 8F4B40AD5EE53C37192651A86F03A17E + +Set 3, vector#162: + key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1 + B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 96328CAA099502092359F397972568F8 + EE2FF1C4305EA06FFD8CC125CB10BE85 + 65EA30B621437AD4CF9CE731185720F2 + 0CFE17DD45E6361A8212EECB346D391F + stream[192..255] = 74F26B7A37D673DA0B78B38938C5C1EA + 2AC666612468F63B540EE7B17548F8BF + 60A9845BECCD7222620FDF7BE904FE24 + 7D2B7EA749C9590133CD6A218F6EF624 + stream[256..319] = 8F8AA7A4C64C3AEC5E85581C53E3FA64 + 22CEB927E370C7B0F98F038E7ACF4D05 + B54430D91B0A2CDC001BFDDDCD0081AF + 35B67E5BEE6B8E113F36E3B23CE29F57 + stream[448..511] = 53E20B4B90B2DDAB40DC30643AA5F539 + 70ADB65DD0B64CECF3D3B4C0567DC818 + 0362FE9CDF920526C59725AE861940A8 + A32C35382571F2FF20E7FBC504E1DF9D + xor-digest = 8C7C45F50A151D551E9EC81EDFDD5B2F + E676E14253FF38EBEA12395040643211 + 3254B0B7298AF77F8F9F4203B971EBC9 + B9850152A96C97BD4FA7BE8592670903 + +Set 3, vector#171: + key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA + BBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CA + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E8DBC8E5D18C5BB2B152A6AE9487AF35 + E2044F30EE8189659043923E579C70CD + 4A5590968600AAB0F021F7AF283D61B4 + 13C739DCFC22632E1F6CD553D4F21976 + stream[192..255] = 8675941731B385016430C9A157007EBB + E9BD8BBBEC44081C1F5E73C7E783AE90 + 1A7F56A20E5DECD1E94E1C92A07CD2B9 + 91619BC3358AB812D58E0B98EA288D03 + stream[256..319] = 8D09462E5B1154175513CE7FAE1AAE89 + EA2AFDFDF1B39D69FDF60B1954BF81E1 + 62F29468E07C251E2D174E9CE924A5F4 + 8A470D1808C68ECE534CC08204C5A2E6 + stream[448..511] = 60C5FD4C1831F0EFD70EFF86A5D38D96 + 2C402453561D0021A51F07D40A7D3B8A + DF455CE484E89437DFADC52A52741B80 + ED0EFA9AE4FC39659F8300AE9292B9CE + xor-digest = 12E57044A8E7F02EBF6912BB73836FFB + C4A2F47AE1B824AC97C1237B1B14DEFF + 12B5B87DF14A8B5B6C85C0481BD69DDB + FD76FA307F4C1F7D21E60C0BCFECD3E5 + +Set 3, vector#180: + key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3 + C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 540980C2A3794C04B93696B90E48999D + ED8E1D3F4720918C80C95B9AC0E911F4 + 6593C4A920AB291D98891374EF286286 + 2386B5FE17654278EC413AAFF1C384DC + stream[192..255] = F3E036D7620669F851A1B58BCE57B079 + F5D75829EDA4E68C36F086CBF2E5DD78 + F7F30C1AD9E4CB3C01B7F2FBF53A8AFE + 957786B2D3E9CCFE7D6FB24397803BC0 + stream[256..319] = 1AADB95F07E6268BD82ECF3453DB5014 + 9745CCEEA9F1887B5F257594ABBFFF43 + C3187BD9A9FFBCCACEBD7A21FF90D18B + 57FCBAA64B8FECB56D5A7FE05BF03E3E + stream[448..511] = 4170D41CAC2A7AA5A3C9228BF386B9C5 + 57795DB5D1AE547A31C553F55DE02E6E + B69D76A984F4F1D84F29D5CB98190C01 + 441DEEFABDBFE405F22FFDE734D9497A + xor-digest = CE103B99AA95B51D2D6CC54A15833E34 + A11778F5E05BB7AB61505D473228069F + CB40015BCFDD3E1D0D5E1F832791C8DD + 3184273D1B4C67D800EF5FF004660440 + +Set 3, vector#189: + key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC + CDCECFD0D1D2D3D4D5D6D7D8D9DADBDC + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = CA30678AC97B4591E287FF8B5E28A838 + 611D654A4EC592328039E3A1DFE90FAB + BA5A37133E821E0960520EEC850B6962 + B0378E77770681ACC0929D16DD260925 + stream[192..255] = 79FD1893EBF30CC2CA9C5AE92B0C063D + 894EAE4BD50BF462420081D1CAC57A5B + AA92E73D3B3CEA147E1F7127AE1F6FA8 + E9B302A068F26157C904E0AA7B7A072F + stream[256..319] = 6880FCE56677345CF1CFB2D38F890C15 + FE33D377922AE43348F5590B84426EC9 + 0DC2A3863136790EBB7BD9493D2F0808 + CA9287CF95AAF366A11D6E7A556FDB02 + stream[448..511] = F385299A7038DA8A90058C510727F3E4 + 524A2D95D217A1C199552753F253D45D + 81DA40431910DD54B619A15C5C302411 + 613D28D53493AD836251F0047FB911DC + xor-digest = F3D10E261AC596959B4AACBCF335D043 + FFF65E2651F046D300C19510E1677F1D + 45F287DFB8C17055A012C234B6EB04C5 + 76ED2EDE12DFFE6EBA4A39A64DDC573A + +Set 3, vector#198: + key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5 + D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = D5EC301FD496586D54D9B21FA23DECB2 + B25DCC0784BF77DE84898AF96023647B + F1618234A239F63FBF3478FD6EB79299 + 66BA9B670C64118444C95D31405873C9 + stream[192..255] = D455D37F435FD0FDD6E1EDF8BAC28D2E + DAF587F938C49A5F58C32CE8D5B8A4EB + 884B016E54277300D461FA21512E7695 + D2D7489A4560FC7A72A510219DF1C5C4 + stream[256..319] = A7B93D8B7787B6C8F80EDCE72D4D644F + 0C6400C3AD0443FDD19C3F3675083F4C + E5ED87032B1813DDFF758854C8D889A4 + 6FDC61C210058DB72D838A0913D80611 + stream[448..511] = 94232F4284F46DD2E7933F9635C26C48 + 6CB935031095777F59BDAECC4FDB4109 + 9037C38C91620586DE93B66EC7376502 + 6853B7390CA516B694583447DD863310 + xor-digest = 8596C088FA66361FD90A2132CE33FD52 + 34910610DB006D223B0574F21BF1CD4E + C282C67B24AF6DB0DB70BAFF65D5D8D2 + 1C3955D466EA2B49C5E8EB7E07475919 + +Set 3, vector#207: + key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE + DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = DBA2DF9ACC53C3EDBB566C28F689D7AA + EF631CB44EA91610A94685FBD862C9D9 + BFCF512BCECF36E035E2E577F6BF6EF9 + E4B0E7623E0DB23B10055677C7B9F857 + stream[192..255] = 8C78C9714577E497E3CDFE3ADE19F03F + D2DAA3211C1E9E5D9F21FD1ED696354A + B7552BFC7FC675FAFE7A739F6E60A839 + 547F8F15BA5EC6F75BB05606BBF209CC + stream[256..319] = B23F187B1BFB5A728BDBD78B75C3265B + B04C6B350A4DA4EB021D6191263F052B + CAE73E5776002FF05DEC3D341AA20D2C + FA523E6B92329A979BE06CF4F848A1B5 + stream[448..511] = 7E2ADEA91939388D36B3F97DC87C2A86 + BDE7BB4884C40D8A202964ECC7440987 + 1C64B03EAD0F46A3A1CD2CB935DCCD67 + 0B43292D5B852B7A1B3D1F853EF22EC7 + xor-digest = 1AC1E42C2DF9858537D0A1BE3B2AC094 + 54136E53AE56B006395969C7F999B2E2 + DE1DAE62740FF339DFC8769F67AEF352 + C4726B4AD4BAAEE56AB8C55FACE34860 + +Set 3, vector#216: + key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7 + E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = BB00F8ECA9A10D2B137257E86B455DBD + F9A6A861F19533E38C3C9F54195AB803 + 171D35043FC9C4204AFC9A8E72EDA4CD + 60220B2EDDEBD5482D7833979C15B685 + stream[192..255] = 6CCE94C2BEBFD223AFB7AF1110F0F6C4 + 01AFC533BABD84F8C4A54E8A239A194B + B56E0CAFDCC59B9B5103471DCEB9F706 + 7801D79530B7CF40F2DEC73A169C7481 + stream[256..319] = 5144745E042B76A6B62E78C92FFC1C0E + E59979CE4B2E4B2CAFFDFCC5E75510A9 + 201E8A97A6A1729E35CA81D8645FC118 + 177DA5FACA0293B972AC0957C43BB1FD + stream[448..511] = DCF9B6116FA5EB9CFDBFC8C97EFD89B5 + 268C0D529141FC3C8262B8BE38E94973 + A21919D498FCC3896B0FB4CEB24D9E2A + F728003C36838638888FFF1D0D526B37 + xor-digest = 99EF8A7D0B8D08E976EFBAE56F7CAA91 + B1FFC7428EA56B7A697AA3B621AA8DBD + 52681C7A9A415049AFB6B7D8AABAD024 + 0F9C3112092816F4C69D36B1300ED3E6 + +Set 3, vector#225: + key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0 + F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF00 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = E3DAA6E498609DDC5A31BC0B6ACC880B + 695097D2CE2D1FD162C7802DC0D00BE3 + C0126CF947CEDBA7833421D70A914BD6 + C33B0A77BE8BA10879D664F054C29302 + stream[192..255] = 0015EFCCDC554D042531FD570C6B26D9 + 059F4F4DA675BCD12C038E4A8D16737B + AAB0D7992340F4EE4324959E96930934 + 21234D41F56A995C928F82944B46BB19 + stream[256..319] = 8CE7098F4C64DF2E8A170DA3D02CD99E + 0169B99A261D1072FA116ED39244EDBE + 73EB9F1CDCF8CCDAA9E94C0DA9C6EDC5 + 426751AB8300836435BC6F727F793281 + stream[448..511] = ADF85AF30894BD0207DB4BF72D9DBAC9 + 144EF6B24E515D96475897EADE40A92C + 79B818499B8CC328859561D79D727423 + BA81055F3387608E56173AA27D286924 + xor-digest = F47ABED85910334919B5868D4531FC15 + 24D61CB16C23920750C73E2B08A4B5C8 + C621482F6D9F01EB59763C5F89AC1514 + F6CA4C40216D6385F304E9514B014C02 + +Set 3, vector#234: + key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9 + FAFBFCFDFEFF00010203040506070809 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4728A29A2F2BD276FDE176CF4A38BE65 + B84BDD41F065DAFEA8302334CEF92A5A + 306EF904DADFE92E3E975EF9EEC9B3C8 + 4AFC167545A0CFCCB6B1CA688967D8EE + stream[192..255] = 734153A78089B6E6EC0F520D39BC3FAA + E1DBAD30CBDA32395E51E500CE4E118E + 23BC8CFDB08D443F1932EDEC52CDF3E2 + 1D021DB791A56A7C16FDA02912FE744C + stream[256..319] = C511914A4BD9B29488B7FB1E62DBF905 + 01C0D85C5A238448065C188F0A4134CF + 6A1FE1DAE57DB8BDF89FBF7FA66F3E32 + 14CC9658DB292E4562A1761B9EA77570 + stream[448..511] = 946944DF8E41BD585723CA1C03909E01 + 783617D9D1129220ADAE7E5487AF4B54 + FF6593B37BB77AB0025C28727AE5933E + E3873824E46F2209D26936FC5566B21C + xor-digest = 34E04FBDE6E3DF6EE14BD179226D51B0 + 1513510665589CB794C0C08391FA5929 + 37B390E86BB4A72D427F58A1EFE10F6F + D8A14A6F38ADE34331C8AC6AECA5DAB3 + +Set 3, vector#243: + key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102 + 030405060708090A0B0C0D0E0F101112 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 2AC7F22D838F68107877E90869F98797 + 493171C8A5EC2E51D536A1578659DC16 + BB2F644C290B0F006BFE3FA0FE0CE917 + D32E94643848867B230270F54D0037B5 + stream[192..255] = D21F7FE6E368989CC75E8D9080579385 + E31680302BA8B9B2F56984FD49B01F4A + DD36AE4A28EBE23B5567BF5A539E2621 + 1AA8588507916CCB572611C352E73E42 + stream[256..319] = 25823586A7212D44811C75023193864D + 85DFA17EB7D5A34BD1CDD3260B5D53A5 + 56EE2E2A06F84E95CC7323379FB924E9 + 9E1A3F724F8C480A1F40B2C4A6FCD433 + stream[448..511] = C1DA25F3B4FBF8B2917103E6274FAE81 + A5BF4086A161A7786BBD5A33662E48AD + 6EB9A944CCA57C51AE266BAF756EA506 + AE077AF0AD8B577A5A02F5563FEBA2DF + xor-digest = 6176BC64072356BDF719676CD2ACF288 + CE2DC1272ED9C4685A5CBB7327669724 + DC8BB64BEBA04564A7879F7B9AD5A936 + C4BC1AA4007A0F85A5B5B945B418BC61 + +Set 3, vector#252: + key = FCFDFEFF000102030405060708090A0B + 0C0D0E0F101112131415161718191A1B + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0854D9B674256934E204484C6D59668E + 1C94891FEAF6E08A92038E41EBA38292 + D19FDBF852400123237BD7DA620767D3 + 43C2FAAEB08A394EFD1E7C1A3776B1A7 + stream[192..255] = 4BBDDBE675E0F9D7DE0BC1B0E0C64FE4 + 52F95ADE61D5CF2EB805894B3CC3285E + 6C6AAB72DAFF826D945B05FC4D4A6BF9 + 37B352262AC12B7E6F92D5FBC4ABDA05 + stream[256..319] = 7BD11CF4273EA16E01154EF9615B88D9 + C52535D2F0C7FD394D94AA7EE542B448 + 9A046F2625011EE75F874641D1C5A709 + B7FD1DDDCCB2A6F1A47B65361A9B0D6F + stream[448..511] = 0AB902B571D11B5F2F24CDC7616143F8 + 45E7DF2050B263D7A841DA170E17C00B + 4A20221D7ACCDCB0E131108D94D903FD + 7E2F7988445A7DB54F653186D69F3CCC + xor-digest = 1266CF54E8BFFC95F1CD3C532BD8EAE3 + BF000577A811DA58A41AAD9164CCDEFC + 401C1B6BD2BDD9E992707718A9802B55 + 33D7A8F490DF116FBCD8C85E9B580487 + +Test vectors -- set 4 +===================== + +Set 4, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + 3083D6297CCF2275C81B6EC11467BA0D + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 1C43EFA7A2CA90F5E8F9A4F09D4C9077 + D5ABD79341FD75BB2DF9F13CA0B1CD6E + 065FA86938D971D8FAC8A3C34D08CA2D + 1BA08BE56D633951BD0338A227321CAF + stream[65472..65535] = 428908B703282E38E1BFDE62C6B0D8A1 + BD2AB1F5117C85703E9B656FDEAD2660 + 4B7B8EAAE16423A3BFE542AB13748DC8 + 35D81F981CD344015E0DF47BD180541A + stream[65536..65599] = 9D6D72F46C846D9BBF3AEEB463B9EF42 + F84915D664A20FB78AD94B61FEB7D63E + 5411A81D1E8F32BE3044E109C68B9EB5 + EC0BF180EF18BF3191D933F86045036B + stream[131008..131071] = E462CD92492726928381769FF205DC17 + AE7D31E1B82810F3CCB541B58C5F58D1 + 38DB708C5F5BF07A0432868A1AA40A07 + 601FCD1A07DE3071E8CE082833F0B02D + xor-digest = CDCA2F92BF75499E49B586BDA7D9306C + 12F111D1A9F183A83B5A07549D5F976E + 815F96BD716CCAC7178282CA8BEFF4F5 + 85DAFA9BDDDF8E6420DFDBA2573F0494 + +Set 4, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + 3588DB2E81D4277ACD2073C6196CBF12 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4F7D4E56036A57A303A9C7D978290216 + 297AC26C187E4F07678EC0069C34F93E + 072D734DBA239D81E566D1E6DCD09B5C + A132714291631C227E391EC0385A3A64 + stream[65472..65535] = C508DDD76C070F712FABA944BCB0F5CE + EB645825C520197867623ED5263E22B5 + 6270F0A878AC7FE03145DD2BF528E1AD + 784086FEFAA0D82F0F3571CEEDD3341B + stream[65536..65599] = B10CF49FE9266BBCA007C8DB526E760E + 79AA4D6A3B29FE82B8698C732FBB81AD + 1A27B2AEB06D05F3CF17E875BC0BBAC5 + 67762275EE650D03F62B29529F3C3E23 + stream[131008..131071] = 42B4F20EBAFB2C792006BD163064EC7C + F363DD996CDF839CCE61E739C3817B4E + 36D311A4C94C7918E82F5158D3A75844 + A5603742E33D7FC3AF018660E6B1185C + xor-digest = FB3EDA7C75E0AACEDD95B625F7EEDA62 + 3DDC94983A9B084645253C0BC72FBF9A + 67072228194F96C1E81004CB438D6381 + A5C7E9E7D134FB8B67DEF27462AD3335 + +Set 4, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + 3A8DE03386D92C7FD22578CB1E71C417 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 23DE914D641DC0DCB4F818C687803858 + A6673E284F8323787756DAC9352BE031 + 28BC6149A59785F6AADF92FC68761E8A + 862AEDF29E851BF5422A83EE5EABFEE3 + stream[65472..65535] = D12E0C470A955DDAA7E851F43DA35B08 + 15D442DBBEDEECE3ADE18FABF08B4443 + 77ACFE9F138F8725CEA27B0F0ECCB4E2 + E5D6E476F88CAB4743E8E43CE2D48F4B + stream[65536..65599] = 26635796620003DE67406BF741B93D68 + 318F9A23FE823B2374E8BD8008EDD7BE + 2F750707A3835BBA7DAC45E06537DF8E + 53DFCDB928EA34CC08D2841FE3E492C3 + stream[131008..131071] = D3DFCE281FDC69F7800E765CB0B33D78 + 8BBDC17DFD11F929295C26AB7ECF21B6 + 7D4B4EFCC18ECDB8134175A7F198EB12 + F7913DAF22D73A4139D5B807C18310A9 + xor-digest = BB2C8E7BB894DEFD1D5A7D37C01E8EE5 + FD4E052CDF1DDF5FDA90C9818DE71B3E + 34392EC3858ADF718F463808ABF841B6 + 90F49D35A51BE5067B162E72D0101F97 + +Set 4, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + 3F92E5388BDE3184D72A7DD02376C91C + IV = 00000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 818C35D2FD72D12115F91BFD32F843E7 + ED4D7110D1ADF517226BE797E037AF93 + C190025A5E82FA0341667D68FC09E238 + 49D5A7A9526CA142D60F71C3AEE3A106 + stream[65472..65535] = F011E9CEE99D94BDD4484408A0FF91DE + EFDC8D8C04ED2B86C51F21058E912C11 + F19890E174018308962F5827D2FC1E2B + 82BA65688C111AAB5C749D8ABAEC022C + stream[65536..65599] = EC2EF21014AACB6215083F784E3ED65D + 774124FE60188930E1A90405EAFC8F1C + E75D54AA7D81400E026D799CE06EF532 + 8002BCF5A10D43E6FB6F80A9D72634E1 + stream[131008..131071] = 80BC6F7F6B0A7A357F770E7690D94A9D + B8CBA32EA36E124FDCC66ECE8786F95C + 22263F09645864087FF4AF97944A226A + CB63DAD316F8CFEF96504AD306C512BE + xor-digest = CB8D4C35D79CCF1D741B9DA09EDA305F + 5FA43F9AE9D0E1F576D5C59AFB8471F9 + 7822C6ACAA197FF01347E397C0382195 + 865AFAF5F1690B373AA2603C39A13CC0 + +Test vectors -- set 5 +===================== + +Set 5, vector# 0: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 80000000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 635990D909A80CE2A75E521ABF588B6E + 85320D2C722D1C93B42AFBE6358D6E2B + F2BE933BC961FB50F9A2B55389A08CD7 + A0131F89CF0E61D0C7071DEA6D8DD4C2 + stream[192..255] = 0F92D4DCC222BFC7020CA6BC3D044F69 + 12D9A93668C65401C570A01D6BF6B3BC + A6F00F6FF46AAE3C09C6158EF05A520D + F8D55FF27CDB7AEB5D03C1FFCE7B95ED + stream[256..319] = 664CCED71B27680F9458952173BE0043 + D3C27F35F9CEE7AE9D783ABA671C4FC6 + 8F2815DC904316BEB39020F646041276 + 5BE5500A60DE2209961755C1BF96E1E2 + stream[448..511] = 8F02C1FB389DD1C5F0CB730ADA528D37 + DD778C4782C7B5DF1961F97CC82B63E2 + 9CF4BE512EE27B50781E297D1633D700 + 1298F13FD8AF9D1EA83F831A70EE50EA + xor-digest = 3F9A4D249220E1AC8E559399FCA23DD1 + 1A250DCDA841502F5FEF0F5D4EFE7E46 + D9B1E5E4312903E290D695C2B681949F + 480D45F78FD69597570338049464FECA + +Set 5, vector# 9: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00400000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 8E932D78DCDE35F1E5B8B2E863859A64 + 7AEE8B0867F6F221B09C37B7A78B4043 + D055164B1FF1608EC17F3F148FEBBFF5 + A9FCE4158B33D2CAA4AC5FE5551C788A + stream[192..255] = 7034BE31CED03DEFAB3F69A24E622BDD + 9B202ADAF05D0324EE933064ED6D965B + 937FBC8405F0D7236AC28C320CE66C06 + C5B93EC581FDD59ED40102C651495EBD + stream[256..319] = 37C4EB0E72191FF0F70C8A70F475061E + A0BEDD8A9AF1901FC6BB5482B5A29469 + 06E8C40249E02784896D5D42387127DA + CDF1657A66E0D43E6F69632519D1D3A1 + stream[448..511] = 8CBE98126AE27A51146FE05F40CEA89A + 39781F515D621DD48B6D6234F9AFAFF3 + 6FB862084F5249BCC0018E8FBC090121 + E227FF494BC180FF68EA2B134E7B00D6 + xor-digest = 24556A29026E3CAE101E7112B2FE5BCD + 3D925460B66A9EADDC271E39C317DC27 + 51DC9254491F76F9163AF09AA5372F34 + 1B76D54C09DEC9419F839E5C50F1957C + +Set 5, vector# 18: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00002000000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = AC05D72564EDC8EB439A95579D04BF65 + 592AB1024152B9B14D71B18FEB5374A4 + C07AA2F58EB2E45F737580241CFB9C0B + 842F8CC9230B540FC50A590DEBDC29D8 + stream[192..255] = 48AB7E018380336AD0CFF37379D9E370 + 5B0C938600C6713FF4CF5C142F640FF9 + 72CF147E7C38389DF426FBF560E7DEF8 + 41B4B1CFE6A4E2DB4A85505C931FFFBF + stream[256..319] = E9C6536F67F4B3053B353170CC5B77B3 + 06A47B759A5FEE5BE45842C01E11519E + 5746B056C86D8A6712446949DFFE6935 + 8E4512E7BBD6E6F544CACA98BDC723E9 + stream[448..511] = 731EF8977E1307CB5FE80BD4F89025A5 + AFEE3E54F7CCEE6556A211097498827F + 6219704F96652420BB9EE830DB3DD940 + 96987BAEC5A43526FCBCD85C9BFDB209 + xor-digest = A37E582543E75640DD988C7FB5579D43 + 9C41669EBCCA5580184743BD54D24CBE + E32F2B1433CDBE51E8208C78FD739CC5 + 4E2A37E16A7AE4F2193ABC4F04C35D23 + +Set 5, vector# 27: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000010000000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 0B295517E5A2E100C262736DAE920F2D + 26C40787AFEA87FC34C27D6E0BF98A62 + 53B695751F9095C8766184EA44042F2D + 6DE099A80C75DB1F33F53EFE578A8F0B + stream[192..255] = B54C4F2EDF17A1EC22F536586A5BD691 + 2008DA6642C84AFC8ACD35A7DAE73F79 + C835D83F4C0C3B1E510D1BB42013A872 + 8E4899A8CE134625698CAB31852AA7D2 + stream[256..319] = BBE2221921E73DC79E795AC0AF9B890F + FE88A14DA29DE45FA38F4C3E94E6BE9D + 98238BFB181FE664B4147CDDC125FD06 + D11A65F1975A0D781024DE1EF026DFE7 + stream[448..511] = 83E61FCEEB1367635632B45BC73B8B39 + 165015E7A6B8D9851390D4CA9DCCB935 + F09BDF52883FF37BC77DE94842E39BBE + 0BE530FC9D3B4564E11B7EBAC8083818 + xor-digest = 55242D44DFDB1A747071F1C825DB5620 + EDE1AF37B6D73A22264B14F7D35E4412 + 4A6242C5AD34B54E98738D6CC90FE355 + BB9402DD017B6678FCC0EF27CF5D67C2 + +Set 5, vector# 36: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000080000000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = B89065FE0B458C64FD6EDC6A893C8C81 + 83578E7D37BE97E6FF82E45110A25960 + 49A817CDE859B67B56CB80768D6DD275 + 6EC368FBABC35C8B51C62AC92F913281 + stream[192..255] = 0E0AB045409ADA1A9540504550404B8B + 2C38384E577F2DCAD5316CE7E806A0F1 + 21D2A3298F71F301340F3C0A9CDD4815 + 936F16B4EC229E63451980646D45E3AB + stream[256..319] = 1DC37BCE039878BA2E5938E4563D2523 + 7350E41C8EF9262A9EF7D7FED7E22F45 + DC3E98EC981D2BCCC1185857C627EE20 + C86DFEF500756B241320798764C3C09A + stream[448..511] = 9A0082CDB35BB3CB1C74CE337D944D3B + 2C833B4F786A92DEA4445A2E5E101384 + AEA834F5E01C1B37EF8291D039875A3E + 21D613FC71212DE686AE52295B773E42 + xor-digest = F94584BB343C6BD6BE3AA1EF799989CD + 93F6DDB6A9AC7E2EDFC92460F0905E6E + AA3E81F6E173C7F9FCE8FB5D7B261A58 + 3FF006AD017A09FBA3B3D084285169A6 + +Set 5, vector# 45: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000400000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 486343B348F2A1726617D6E93989B000 + B41FC9707E2A99C7FE5CE9423DC3004B + 67EB02F45B368F87FF2C4CC0C59D1728 + 9F713E714E049CFD8E5D593255092A7B + stream[192..255] = A1A3127E632EF47679F52224E6D5A16A + 6E0598271F36F4DAA98B115535E77C71 + 84170D2DB4B8C5D804790A666D105108 + 81213A0684DD4AF03DE7707702F4F73A + stream[256..319] = C917B1577463E05F34350C4C7F6CBB5B + D63B2D74EAF1500832132CA1A1F289C4 + 3D93BFDC5E9D91897D2F7E05740F3C95 + 0AD872A93DAF3850A452410FBD706A92 + stream[448..511] = 11646E84240BB95D1B14694785E7E119 + 848855E462DD14176442B8595CF602C2 + D1F4A2E09B8D7DE28382D1DA4DB3B1E5 + 910DAE6ACC02E79FEB07A8E55747046B + xor-digest = 65E9982A725056B8FBC275052EA48C00 + 69A1BA0939831C4014E81AAF14F66FB0 + E01FC0C70A49C4533ACBF304A5309F4B + 60D6B310BC66C6684BD5B9C83F994E95 + +Set 5, vector# 54: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000002000000000000000000 + 00000000000000000000000000000000 + stream[0..63] = ACAB34102EDDB67B8A5D8B135BAC15CB + 1CD52AE386364C709C2B9D6BD322D7B8 + 477577B4958D448A3BEBA473D861E592 + CA15371AEA0F500361CBDD865488A7A5 + stream[192..255] = F25DAF77D7D734E5486A1AAE01794FB3 + C17099E01489A5B4213EFAE6D745B798 + 77939C7A178D1FF09EB2C42A8A3CE51D + 59D501B36BF9E4960BF3FC8D50F5A847 + stream[256..319] = 1C9C6F63998627AE1AA7E8F0B2D73A99 + 707256CDB12E3AB239EFA72AEC516FBD + 6DECC9375EAAC634707A139E59B32B51 + 5D25ED6951FF4228A11DC87E8DE61385 + stream[448..511] = 6A997977A25F4E9E0D9AFD8C20B56EE1 + C702C301528E332BF8F5E7DBEEE5CC28 + C9E12E1A8BD7A2118A0F31F800B574A8 + 2FC44FE19B20F1D3396432DBB02DACC1 + xor-digest = 0B2BA364EE76F0549A10200D129196B8 + E2B69667999FADFAD55CA479AE679C56 + 54A453C43898443B9DF2835AE806C2A5 + EF30CB8AC25DBA756A705F66759029FA + +Set 5, vector# 63: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000010000000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4DD010482D0DB2D09D76872D25F73B26 + 749FFE70B9674587FC4CEDBA5966D217 + 489244D0177F676188A1762C430DD8F1 + 5ED9F7BB67F2E8A79F7633DB7B45CFF3 + stream[192..255] = 3587F0A7B9F410D45357626BE10B4EAB + FF8798FECA5F91F3AD2543B301B5C301 + F84404071C7BC77AC31E423E1AB1E2AC + 2CFAA37DBC2A1316D16A5C7BFED1A77B + stream[256..319] = BFC632891511228ADBA0211EF390A7F8 + 08A12AC6BDD7C2E29DF27025EBA1A6EE + 00B9718FF2BC003904C1C28878894AE0 + E5CE5E9F55CAA522EBEF5747C755CB73 + stream[448..511] = 513D9FFA86D8AFC20E4870DE0E9B330D + 76F02E44A6C4D7C5270B89C6BAC9426B + 5A12666244C0CC5A641118B93F72668A + B7C53CD7FAB0940F1B37A85015DC91BE + xor-digest = CACA8BD50E28720128B57B37D45DFB02 + 206D53785FCE81205AEA085466142DB4 + A17F841156916294F3B7CA93CD99CB12 + 93FF593B5105D2822CA9BC3BAF178935 + +Set 5, vector# 72: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000080000000000000 + 00000000000000000000000000000000 + stream[0..63] = 4DB6CB1D5BA89BA45BA8E3DFCEFC444B + 7D97C73F53EBC50BC46047CD76499CF1 + FAB51AA6C8B24118AC4EC8E49192B41A + 2812AA1A4325418AA6C69F6143F0A6B9 + stream[192..255] = 33FB647044F3918513212D3538C31662 + 1DD9F3A10C0589CB718564CED7ECC391 + D9701C7A23AD48E05A79BE9E32F60819 + 3E57FA8D8EDDF9F43F38BF8BBCBAF52D + stream[256..319] = 79F3525A6EE300764DE481C20A40135E + 94362F56DBF4C5AFD214F9D4039A0899 + F74A7D7C27494B39D1B0145B9F691B5F + F436F2AE8B335EC62CCB0FF506E0240D + stream[448..511] = FFE0E6B8D741377FF1A02764FEE3D681 + 6CD020C6DDA5097989137E9BCFFFD35E + 0E6379AD2ED3D9D298C6B98DEA82DE6C + 2B66529C860DD4ED56265CA09B16A8A3 + xor-digest = BEC66A4FEB220D732F04AE0B98FCDE2C + 0B70613BAD57D7590E007E84AC546B09 + AF1D5BEB509CFE5523254B5FC8CC2672 + 215C67477AFF14D0788DB166C5B4B12B + +Set 5, vector# 81: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000400000000000 + 00000000000000000000000000000000 + stream[0..63] = ED4C49EAEBE78999C0DBC4674757D435 + B056A45036DC51B390A6C87B3CE8BCE8 + 2C7DD348C7775D2402EBE359E7895FEB + B9F44DB5D0F7B40AC207A3CA750EF25A + stream[192..255] = 32F897ACB5CE63D1A64781524B1CB4FF + 9E595EEF93A3206A0D1B4E6F4ED7501D + 2DDFCA31B4FC1A33F589167B070FC003 + F67C528B6AB99ED308EC3CEF82B4E2F0 + stream[256..319] = 57CE29261DAB385309C97955261874B7 + 676349DEDF7582B7654D1A8DAA570EA5 + 9745D2167F2AE1ED538F1D0ECE53AA38 + 379F9AE542EBE229D561E34ACB28FA14 + stream[448..511] = 667E22A8BE7BB84CA1B1C0848E5F22D7 + E98E54A79D5A960C33D07357199AF1AD + 53F3F803EA698127C22F75F31C40656F + 8C28818775B3D88460CFD29798187537 + xor-digest = C68E7F4A7CDB68892794933392C1BA84 + 5B6B7CF52B8421137EE0220BA67C91E9 + 81B47F9BFC39FDFF9DD48F3617F2D523 + 0680B87D18A821A09525FDB79DE6FED2 + +Set 5, vector# 90: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000002000000000 + 00000000000000000000000000000000 + stream[0..63] = 80FC6D794178A189EC423AF926622982 + 60C44DC5DD5AC91F779D02958366CFE2 + C5551DE2A5D635353757AFDDE68DF592 + A034D87C871D7D871264BB0F89E99536 + stream[192..255] = 0BEF31DBC3F3DBCC5B3D28BE296384D5 + D33DD0AD9A80D4AB8F58274B4397A658 + 94F67376AD8DCEC19BC2C74A835D9F70 + 1F4C60DC256DBA4E83B21D36B66F5DC8 + stream[256..319] = 625DDFD8D922D848380D45D6D7E730BB + 049666B3900E4305218BB7089D059FD5 + 825F9EAA3AC047A006F1353C37AFD11E + 0143DD68CBE9543B959E26ECB4C649A1 + stream[448..511] = 636E6EB97E3127EB703D5170D2C8FAF8 + 63E8C333F5EFEFCF9063E3D770FF9E0F + 2B37396CEC935239797FE430DA4CFFB2 + 9B19D833687318DF01750DD2F3D942B5 + xor-digest = 0865679CB53BC2845A0B71AB820F61AA + 9B99E100AC7F0358D5B610C09EC52C7F + 8C7C5D973CB85B18F8990F3BDBFBDCBD + 13071BB3AB3F329E75A44E80320BF86E + +Set 5, vector# 99: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000010000000 + 00000000000000000000000000000000 + stream[0..63] = FC2DEE44B15BD914C17DADE6645A0250 + 2F40B39C0C6AA26C0250D328112AC67A + 0C55D48700EFE67EFBCED927B62427C1 + 41DB8089774E2DE23C5FDDFD66D39BC3 + stream[192..255] = B6A4D34FC81937580BFC32E04C8E2B20 + 309AF3E2152B98BD748A344D4537788D + 35B16DD2C01444CAAAB8684916705C88 + FE75C53D75713FFFFA2693E91395F919 + stream[256..319] = 9E619BB0045C58C2D303F79E659CF5E2 + 011D619E0CB10CFDD53AEE6812DD780E + 36407CFE9BFC1C73C27CBBD491BB6A7E + 8918023EFD6E2227C0C840F1DFA5924A + stream[448..511] = 2A320747019AE86A59D5422B634448E0 + B43C41457428AC7A4E5D0C9D7327B44B + BBB6F64CC2423299C009E5B24DDF10C9 + F87F2A525ACF803C50837EF6C2FF3D34 + xor-digest = 3737C19DCC04C7C72EC9280D53C17E64 + E9F4B1E47980711DC64FE6D3E7DD05E0 + DEFF339F38868B1F7CFFAD4298127949 + 11EAD4D34047B22B07C397A37F6BD2A0 + +Set 5, vector#108: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000080000 + 00000000000000000000000000000000 + stream[0..63] = 84F71EA20D46B3802A787C1322DE6A79 + 34587F447AE7FE277362497E4FDB69CE + 129EC4D8D80ABD0C15026EED3DFE2B6F + C48C5DF09CBE035E348A22F8A2AB7DAA + stream[192..255] = 6444791C6DE062EB9A494AEB910A458A + DE3D834BD6F87F26A9D6F99FD970C820 + ED9FE0DF88A924F97945B0EB10E5D464 + 559AA278DAF6A942651E06C66D33F7A0 + stream[256..319] = 1878644E35B3BC562F82647D45C84317 + 769BACDB95DCEACA456727616BC90FF5 + E78FEE1EFB86A714CFCDE79AA9E66FAC + D600B0FC5C471569BBEB5692E7D9616D + stream[448..511] = 54BD56C4F0F3A0CB89A678F2912E5B21 + C2B225030E82A90470EB6040F50A818D + C91F65BFFCEA3F9041BF110A762DE3D4 + B41A8D1E18CAC776063B2DC93BC2D02E + xor-digest = 52E18382B88883C5648E067675468200 + 2AA9AC5C18A856E89175C449A6033501 + 87FA4C17A4D36269340F0877385A35AC + 4B7FEF6E1463D34BCDF3597618FAF352 + +Set 5, vector#117: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000400 + 00000000000000000000000000000000 + stream[0..63] = 3F40E9A3C872ED15A6AA296F716E095B + F39153C7C6F4ECE6F550AD35582083A1 + CA0DC3CD817AE3946E43AA9C8700420F + F0DFC21B34F4E5E40B3EA14299EF468D + stream[192..255] = 853C4A895DCBE411B9B2E340B0AB55AC + 8EEEC42885768110ED7E1CCADC10121D + 8DE12AFD0DCA4507A8A7A2650FF68C6B + 5DB1DD670C8C68365E846934D16A46CC + stream[256..319] = 565AEFAC0325093EF87FDC51413BD5E8 + 56AB6C90FCE7D3C6EEB7E58F22AF63D6 + 73BCF3840D611A5E1102E9A4108CB902 + 5A1D837510A971536231CA247965379B + stream[448..511] = 887287B62116FE2A28957ECC71DE5BA9 + CBBC16DBFA4EC141EB617F9314FCD238 + 91C4237FA35871C0C795E2F3A4197DB4 + F81BA4A29759BEB5FA2277CBB9169734 + xor-digest = 78E564BE9E7102E2CB009D7A540395C6 + 188C8499B7E96C0AD709C3BA2C341741 + 6EED55AB00AE5719F25CFA06F1488E83 + 798F18BFD755B9061AFB4EA5D864FC24 + +Set 5, vector#126: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000002 + 00000000000000000000000000000000 + stream[0..63] = F4C281D9C88A7FD6B2CBA9EB0366C594 + 59327932DBEF8118A7A680D0F0AA41A3 + 735FE0874F047D2B071B5B9E755A7B6A + 9426353B923A5913C647A88B642B2C00 + stream[192..255] = C7DAC2AE7631D11EB21EF15FDCD3EEDE + 7DC98A7060613A643EE8A944EEB6C7D1 + EDE08538E1BA6092ACDE0C648D29AF5C + 309CFCBC4F40A713FA58D93C954961AE + stream[256..319] = D1647D6453798B7E15A49199134384B5 + C9BDEBF7F859F6460C2666F297410070 + E68307CA78790EF01D160D94B69729D6 + 90A4FE477A27AFF8B254875C98116485 + stream[448..511] = C6D3DCBD0E9D4746B142C819867E0A14 + 8B81FEE3D1007E907F8E9D597EAD63F7 + A87E6F224C67CF8162C4E92FC1BE44EA + FE3715B3C1C432CC660CCF1536A20F46 + xor-digest = 59FDF05B6D16079B7E18F6A8CE0C58FF + AD7C985C01A12C07D1ECEA740A92F761 + FDAC3F96357498B5F5FBA91DE6502A86 + 1332A1B3E85C5E72444A2168C25D6FEB + +Set 5, vector#135: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 01000000000000000000000000000000 + stream[0..63] = 494BAFEFE4FBF2C406F55FFB436105BA + 09211B71DA446A0F5436E6DBF42F8E1C + C805E797C9987C14997083E9004473E1 + B2B3729DE9B483361CD38CC78C982533 + stream[192..255] = 3C04C6633F7D8B714E8549AEA1851035 + A520EB6422F42B2C840C74CF51A13FA2 + 9C1875212E8DC07774D6911415F1C305 + 9826A05DA9F09942273CDB592F7E3A6E + stream[256..319] = 1FF6BEFD79A7E5BA0DF64948BA0ECE7D + ABFB3883BF8A95D3E76DEA30550F5C3A + 2B67FE2AB78DF091E758E498418EF514 + 089283275588A41AD20D53E6394635A5 + stream[448..511] = A4D10D3B6AFDF415D49FB6ADA1245812 + 1DA1365ECEBDB6C2508F1EB92E91E8EF + 90892E6FCC9E70AB9A2EC4D49A11C197 + 68E6B4C154A4D65C55AFD38B2BE3F4DE + xor-digest = 91D4EA4C6ECE28536C415A6AF46DC432 + 3B6DC2DC98C3A3FE2BFE53C8FF556C16 + 0197D655357512A808415BF757AB3A84 + 6BE7865622D32B7DE3867B3B096408DB + +Set 5, vector#144: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00008000000000000000000000000000 + stream[0..63] = 521913EA655235FA0E713B0DA3ECB98F + 7AB817E70827D29E75E3BF2729EC2AAB + 8747B8FE0FC9489B6E0EFF45EF985980 + CC0189D9D0F2EF34E809D992E7695D9E + stream[192..255] = D265AAD80EC96DFF08859F93B236136A + BE146981E919C0554D64FBB7D03DC9AC + 9021F2A1B39866567D8BA1DBE2C3CD21 + E5C4C94085F7083F4C640E918C4004F1 + stream[256..319] = 7DCD3CF623332365E6CF2D92FD147BE4 + 1E532F51F939C921DD4492E026993E56 + 843ECBF0925CC52D56084E7F2B538653 + 2020DEE6FE7E85D4A89AEEBD5F3EAAAB + stream[448..511] = 00E20611C7ADFC3BD9E59B9E6D7ADB03 + F87FAAB01D7771B89299BDC59E1E2EAD + FC9FDE416B62FEF07AB7A816AF261E77 + FCF79DBEB09323D44B5956CD93AAA990 + xor-digest = 0578B3E20EBF98D89E2DE82A6EA8E34B + 424E526CF419713F0AA662B852E58BB6 + 7ED570D75534E1F23F85F160690A464F + 122CCBFA5CD1DCC0969F2E57D65D64F8 + +Set 5, vector#153: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000040000000000000000000000000 + stream[0..63] = 2617095641B825094DE44205319CA853 + 418588D5B6BFC05A2713CF898DC42B3D + 6ABDDF4C287235438A48BDDA49E5ECF7 + EFA235A23BF667289612893708704F08 + stream[192..255] = 04F668517ADC1AF6E31DE6B7007ABAC3 + 59A2DD6DD61755C6CA7053E05FBBA2AC + D9AF682EFC71391EDA4A5872B53D7CFB + BD35ACB719169283EFD9FF9E172269C4 + stream[256..319] = BCBA3F15D83B9AD41317AB9EF7DFDF0F + FF05CDB058AB08D7BBD720723E969CAD + 79F16D26DF0222CFF4249B839EB9F9F1 + 422EDAFB8EC285F27E347B7B4C9B2C23 + stream[448..511] = F15F17F38917DFCA9141314047595C17 + 047F91E4859D849E9A6339F640E3633B + 6A1B62D089B24062BA5987C3FAAB6633 + 99698CDE6FE7A461F127AF67B2C5CFBA + xor-digest = 68B2369B45F059964A1FD3822DAF61B7 + 82A9FBA7EB563F83DEC4D058CA5D8931 + EC74AF4043FEA803B696791C8E0A675B + DD8982AEA862BB76847E1DE12F2A5E86 + +Set 5, vector#162: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000200000000000000000000000 + stream[0..63] = B090CC267B29A95ADFAF6BE3E147D647 + 21ECACBF6B7D0C4061D17FB7DE0A6662 + 6D6F9FC167FB3FFF237C240AA03FAD55 + 13B6DA848F22796DB501A8FB89F2B85D + stream[192..255] = 1CB95ED9AADFA0E1FFE5704BE69CBA3C + 9593746AE87F36A786E5EBE18A1D3B25 + F4785EEF4DB439472035BF053687C5F1 + 0B60EF55A76DD1994FBB482BBD250755 + stream[256..319] = 826BE3D679C872536D55C3F0E49C2624 + D41726A4525A50CF91EB71E7CEC5AC47 + F3834358E2296CF0D04B8D8CE8A701B6 + 6AFBBB8776DB2B75F1CFA01231B365FA + stream[448..511] = 244DB28A98619907AFFDCCAF303A3795 + 3B6D21EE6D22780C4D3C939C084E4181 + 1FFCD8F2DA2E6A2243BD0B5428FB86C1 + F0EA2E8C8B6950ED961F4FA8CDFDCD17 + xor-digest = AAAFCEB42F2EF40C4B5462307085434E + E4399F87B4AE5CA828A952A851F47913 + A51430A8BB9B3CD0A4B2F12E297F51E8 + FE0B1A6FE0F21177EAD9284087D3706A + +Set 5, vector#171: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000001000000000000000000000 + stream[0..63] = 0F4309F63F237DBB51567573126F09E8 + E49990F26E541EF888B9F2922FE9D280 + C8FF4874C0D4FA3F41034B82E2E026C4 + 594A79C2B689BC502C41244DC1AD472D + stream[192..255] = 95DCF9685E429DEC2833E1B5E78823BB + ACD9332D668C4B342B89A290E1CA6127 + B0E5125E44445A1156A70B27966C3E0B + 4E0BCBDD9F4561998A5CBCFAA05C7459 + stream[256..319] = 0886E9887182156005548CA1A08B57C0 + E9FA76C2A694E1CEE22E9B715E99B115 + 9AE064DE644FD580E8356164A45EA1C4 + 3DD85E16158B5130AA103267C8118105 + stream[448..511] = F8AF6F9992781BB09808B7AF404F6546 + 6FA697C2A1BC9BF64F8D6B6D8CA0B856 + 6B64E6BF0500F6D80113D9457855FDCE + 1791C7436F5FF41ADA87562C175942D6 + xor-digest = 8D32FFAA409C8CCDA6892C388D5D654B + 4AD50ED00BA649737BA8F350811A2AE5 + 5C89463C7D63F1F1F16C4007826C2CF0 + E4BD9453A60D88BE86F60BADC3E71E98 + +Set 5, vector#180: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000008000000000000000000 + stream[0..63] = EBABC8B756971D46C1A5E86CC7AEB329 + 4DEDACFC795F2AE02CCAF68B933DEF4A + 19E96BA64DF14EB6FE67CA48861B49BC + 16052E33C8B47556DFBD96037B7DE5F2 + stream[192..255] = 0438A8CF718F4C52E33DA087FFEC01E0 + 459D26757D5DF55D5D7BC9BA88F57EC0 + 4B84D854374F95317CBDDEE928A2CCAB + E4BA1BBBF47776B29890DF00D864FBD2 + stream[256..319] = BC4A80F9CACFE63D2E54044ACFF39F97 + 2C69015058AD3F81CBBA28FB0987FFCF + 9CD1F6AE4F0602BAE2B828D3FA162936 + 23CF3AC2950BD651F7E467DF8B454BD6 + stream[448..511] = EDC95FB80C9FED4A73D6EE9B2CD74BB7 + E6DEB9E7868D40FC49BD1C52838457F0 + 88DCB29C2107066D55A80908EFD1392A + B4F2F13C0A79F67E58C91A89A5C88991 + xor-digest = BECD7FD2014BB9A25701E69F9788FC84 + 1AA9DA56CDE1CD93DF45D28F29D32E22 + F488B0C2D9FE95B267CBFD35EDB2F6E3 + 05DFA5A2CF09D7E2D13348BC0C9405E2 + +Set 5, vector#189: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000040000000000000000 + stream[0..63] = F28A15A90386237127A5682EB09E0E58 + 30709455034A7189AC9710DBB50D5012 + 9EB4E0E9036D4504054B281F3FE9F45F + C80116B8FFC0B42F9A636A399B7A8BD1 + stream[192..255] = 1219EF9BDC250E88BD0A62DDCF9AA1DB + B62E19FBA748DFE1035C6A5B3B94954E + 1370487A455916F7DAB451F79C5E1298 + F549CE005A1321E6B136B59BAD9EBCD5 + stream[256..319] = EBBE81DAE5637C4C7EE6FF9251D5407E + DF7E8EAE384D1E588CAD39AD9F763004 + 9A8E028120B5065B658EF3E2B357E52F + F18891819EEE3EE021BD1AF08A4B1F53 + stream[448..511] = 50086FCFCF5EFFEDC4A52B0212B7321A + 8664F2976493868F13D7CFDFB7583E99 + EBA70778A83CB88850D45B300F7F6A80 + E721860560B2FA642B2E77C7F7AB0662 + xor-digest = 336516670616300FD5FB014C1076B53F + 6637AD0EFB453615924396785CA4D284 + B03F526FC2179FF3BFB0A1A2ACFFD87E + EDC4C8360DFFC132CE6A502EB173A0D4 + +Set 5, vector#198: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000200000000000000 + stream[0..63] = 93261A7231FD030CEAA974BBF8F3A721 + 33334C5F3B25D5831B203C353A566D80 + DA578081A047E28DDF8E4BD5B68BE4A7 + FDE4BB3A4875BA84553AE120ED77C9CF + stream[192..255] = DEC4B603E6A6F911B68E5C1265FA2004 + 71B296A647D20C13E42202C1A3AAE880 + 305F969BB88002C8FC00CC5DBE40AA06 + 4AF85646AA8C7F7191FE26FAA2918A95 + stream[256..319] = 849431145F27957D53CD355501363E4C + 5F191DA666B77364E5866CAA16A9DEF0 + DDB9BC266EF41DB0C2A7642B9E8DD27D + 60DEA6E69052D4BDE9FC83B2578C72E7 + stream[448..511] = 5556EF9874E3150FC539C9BD3BAFD308 + 8FB347D5E38DB318A72AE0C6B6FB4163 + 082545A9AD8872AC383A78230729D083 + 31BFC3F2C80DA20617435FFDF2529A7D + xor-digest = BA9CA5F3C27246F931824A9A425F2390 + E183188FEDE5BE3591053ADCC933E1F3 + DDF5627A94F80F8922F53E951490E96B + F51491ED2D6DA26F3BF69CC41B8C0C98 + +Set 5, vector#207: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000001000000000000 + stream[0..63] = C449AF4CD437641A3B40D0E0E7B5696D + CE973B3B217E02DC20B2F5573FDDF78F + E6E55D75CFAB8EE04C8962376D22A843 + A80BB79C8B8D8B500C4B6DA27748C398 + stream[192..255] = D5C92B62B0818165096551DF2B007F66 + 2DF953742EF0BBE97982FF9D3EE83E1B + 87EC9D710CF1700262B1CAA9C68A897A + 8AB4A162DB0443A43962EECFE5B4C0DF + stream[256..319] = 3B8CC7E847669AC6858B7BB716206386 + 40D8C2DD259EE4970A5F254077101271 + DF745AD7F57712065E2D03B9D7220591 + 5C8C033A4F9146EE561B4179DB465989 + stream[448..511] = BA4ECB7D74CEE56CF1D5AB636BBD6421 + C30A51DABDCED17C8D50F5293424AFCE + 33AF71095CAAD3913A8A3A12286A8E91 + 89DAFCC1E2E744FBF4B526E910B5F2CF + xor-digest = FAD57A608E04CD71B176BBFADED7B229 + D855A8025E963B55FB83EC7311427779 + 490F25D34C6385FE1C036FF0807E136F + 40C10588678E2414163AF1819EF7D3C9 + +Set 5, vector#216: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000008000000000 + stream[0..63] = 989F302DF6BF8C63F9EB69D2625115B1 + 2CCDA42A2D33BC6F21BD55E0594DBAAD + 9A294DDFD6710E36000C27FEA7E03440 + C8A6E728716D0DF14E825B798A6C420C + stream[192..255] = 3F3140320AA02367512E7C1789F5C03D + 83CC634354237E78E16B1A64DBDFA6EF + 0697B28BDFFAEC311C6E2089BCF64203 + A2EC7BF3CA922080380241A47A673634 + stream[256..319] = 6049048A5307D55D6DB387A6149C7B23 + 0AE33195D53E0026103EB44489BB86C6 + BAEC7A0D920CAE25B1E7B9F07C07C4AF + 6485FF281C7B7FE1D61E660AE55C20EA + stream[448..511] = A6DCBEC85525FA19FA6066470B4CD83F + 17D42DB3353B327BF3DD6E7D047CD752 + 71E79CCBD46E757F3654C2506C2B593A + BC93B8985C491017A8E616D69E8974FD + xor-digest = 55BE97FD8317A47742F8F3BB762160AA + 7FDFBA371864823D93EF6C029D457AC1 + 2D679CB424DA9EAF8E4FE28271C66F06 + 1E91D8F2EF41733AC1084F54330C9786 + +Set 5, vector#225: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000040000000 + stream[0..63] = B8989CF76BB1AE894699604320C14706 + E20C8BD86C016B5E2EF705AEC54C6023 + 2A9AA961C10914A8D910D517059A93F9 + 78C537767A057E0E11DBB5C9BBC4EFA9 + stream[192..255] = 83FC232D21D0DB82747D9EDFEDFB58E2 + BB37362FA2B4E1AA0C9A58AE521EFC86 + C512831CC6D2E85FBD96FD3B60D1D153 + E83DDC6C5755899CF96FDF69E3732E4E + stream[256..319] = 201DDE5D82B754341A3452BF7DDDBF6F + 167B2A087900EF40E4268A80217D7310 + F1E9E25C707A1EC05219E3CCFEC0F6F5 + 28CD98534F6C579A1ACD3171D131D87B + stream[448..511] = C2F68B5F03B0045FEE0FC92DA08F8545 + 762F73E553D2F539C64B88D4FAC9B011 + DE0504D66007A115E428F627A667FA2E + 296F222734FA0F905548058897DEA990 + xor-digest = 7DFA65F57FD58891C5576B3CC7002513 + C1A983E9D31317B681604DA09F176AAC + 4FD78CE84EB9427BE8D6A63058582F16 + 148D55B3C2544CF4DB9306699CA74D80 + +Set 5, vector#234: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000200000 + stream[0..63] = 307B13F3D3EEEA4C8FAF34416689F354 + AD26336D6B33DFC5AA004420D2DEAA69 + F69E531EB6D672AD62B2A6A136046373 + F70272E84E14CABA9AEA3102863A0B10 + stream[192..255] = 8E4DA19FEDAD4C842917ECD5E7256097 + C2F524324D8A974D4185D8B11B611C72 + 6C39DDB5E58180971DA181D36A289CBC + 1937E8F020645EC8D0363A58C6147F38 + stream[256..319] = 012A99871D6C4CB7328C1374F37D0BE3 + DCC2232F6484A22C8F330D77316A1756 + 71DF7CB32773F25D772BFE9DED5981B2 + 0C3F0DDB2879AF61E7549F03AE26D233 + stream[448..511] = 47C6CA462D35580BC0C78C6427FB96F3 + BB762662F5B52FB3938CCCEAC35884C1 + 54F5BBF513970FC08F51C91059A757B9 + A8B6F1EFE467FAADA8D4DF68C6AC1942 + xor-digest = 6409F8C255BAE6167686F5F9C7EB2349 + 0FC7BA4DCBC80006B57A5F56CA9F907F + 849C2A0FB0D74CAAFC0E2D4367E2912E + BA6487D8A48DA60E48277A20E326266A + +Set 5, vector#243: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000001000 + stream[0..63] = 543BAEFA799FA0CF5295B92EF3FDC07D + 69B87C1B5FF0A9F25B32F8FCC473D04D + 54B6E467D6183F25E3664A330889889F + A530E354B6E53EBC78354100637A62C3 + stream[192..255] = E15997D1E7C0FA38333DEE2EE2477A4F + AD32F0810E8D3D65EAFB110C2B8D0948 + 59DC45C4AA38B8050A87C23782E1A26C + C193985BB0C3E754A528BEAAE1508D76 + stream[256..319] = A94F1BD38219097B70EC0700A64B0ADC + 7BA8883B5C2C3BBABD0497E80D53121A + 2DC5A5C6A77913330EF5469871BABF86 + 0A09F1474D893ADC28B473EE508F473F + stream[448..511] = A43AC01FC186AB42241ED3729E7EEA39 + F0823D124E8CB696E2F4B047A6B71164 + 5B803623CD0371C4975217B3CBD7D9B2 + FD89D3B6BD23FD11FEC0B03B9CC22AC0 + xor-digest = 792A5EDB6E7FDBE99B7EC2119665C2F2 + 34038F561BB1923F3BF493AE35CE2006 + 55B8EE47490B53EBB481AB7C6B82FACB + 233AD86D74385FA108C94666CD34C164 + +Set 5, vector#252: + key = 00000000000000000000000000000000 + 00000000000000000000000000000000 + IV = 00000000000000000000000000000000 + 00000000000000000000000000000008 + stream[0..63] = CB4377099B2D7CD6A982A1B1A53E05F2 + E097164EDCB381468C21D8F0615A654A + 45A4D09B7C0218A19496EA71CEEEAE5A + 886307DB0026C96049B60E5154F99AA4 + stream[192..255] = 25FCE0B7E28D5D0D1654D912DBB21AE0 + 288CCC71396CA5AA36AC44AB08EC72A1 + 01E5B189535C1987B79DE4C4E32DB7FA + 48ACBC8F854868FC287E03D54752230C + stream[256..319] = D3B02A39A4E467C44C109E1E25593278 + 2E9B3CCB02D6F107C9263A24E113FAEF + 847A9064E1AD1EC8881EFEB239CAD6C4 + E90ACEC36A7E87E002F35D477CD63F2B + stream[448..511] = 7D4282D7E11439C04ACFF087708DA22D + 236F1A08A6343704DA4D24EA3582253A + 35419183A915B571DDE80C1DEE2B8A13 + 76EE973234FFF6A0DD91D31037F51C72 + xor-digest = D52720D8DF114235D99E5292E14DE96F + 9D8478E016CD40EBA25C4B9D8E11713E + FE9AC151E1F39377FCC07D06E9BF6931 + 6EFD7E27F87E9F76DCBF7831CC3FA98B + +Test vectors -- set 6 +===================== + +Set 6, vector# 0: + key = 0053A6F94C9FF24598EB3E91E4378ADD + 3083D6297CCF2275C81B6EC11467BA0D + IV = 0D74DB42A91077DE45AC137AE148AF16 + 7DE44BB21980E74EB51C83EA51B81F86 + stream[0..63] = 23D9E70A45EB0127884D66D9F6F23C01 + D1F88AFD629270127247256C1FFF91E9 + 1A797BD98ADD23AE15BEE6EEA3CEFDBF + A3ED6D22D9C4F459DB10C40CDF4F4DFF + stream[65472..65535] = CFF0058C45807C1F4300D118FDFC3B21 + 370936B39391791C92A821E1C8E8F248 + BBBF378679468218FF5F6560B79A6015 + 82B81315DC19D8583263958B068BEA48 + stream[65536..65599] = 871A09D393D8888EBEA453F518BD300D + 8233E906A31631D29A4A1834E268C3E4 + F65F4F65B1B9E55606BDF28A571CA4E7 + 59BDE4718E1E13731663F5CAF1CB0F1E + stream[131008..131071] = 15360407DA7B389DF28C08B2221F5E0D + 96B34839325795A70A3F65D9CBB3848D + 8C0793A53E8C4D71D8B53B2923A90B37 + FE412A4485F0CC741E65743C6F1ECB4A + xor-digest = C08A2B344B4A486BEB4568EFA585A481 + 64C90A34752FC3523C3A99D764AE33D6 + 825915067FD64D90EE81175416A3B4CE + 780426A44A4530994A1A8A83A5E9E243 + +Set 6, vector# 1: + key = 0558ABFE51A4F74A9DF04396E93C8FE2 + 3588DB2E81D4277ACD2073C6196CBF12 + IV = 167DE44BB21980E74EB51C83EA51B81F + 86ED54BB2289F057BE258CF35AC1288F + stream[0..63] = C44B5262F2EAD9C018213127686DB742 + A72D3F2D61D18F0F4E7DE5B4F7ADABE0 + 7E0C82033B139F02BAACB4E2F2D0BE30 + 110C3A8A2B621523756692877C905DD0 + stream[65472..65535] = 5989C607133DBC6C0F2DD022D4812ABF + 91111E266BBC8EF91F1759B3CFD73E12 + 432C1334E3549EA54917BC0156672E13 + DBFDE5F0CE6C504EF4AB69A9C311FC79 + stream[65536..65599] = 0D22D9DD0AAC594F812839C7C4D0B690 + 7A19FE4985E1A0DCCA5930E6F5A70055 + 452978828569A28AC62C30274CAAD865 + F4F8BC7E3F058B50C454F3CA360264AF + stream[131008..131071] = D17E6611F2754F60629B7CF29CF35888 + 3765A08C62167AC620C1CBCD1058F527 + 4B2D4335591F7962A0A76D5F430332AD + C16B13E7EEA80188974860D2EE3BE81F + xor-digest = B7163FD0F8A41562DCB10212DB9C97DF + C25C6BEBEB6331F072118F046E508887 + FB82C0A3FF8B0E0B5765131BD58F3181 + AFB3803A2C1C8C70877AE29F74D433F4 + +Set 6, vector# 2: + key = 0A5DB00356A9FC4FA2F5489BEE4194E7 + 3A8DE03386D92C7FD22578CB1E71C417 + IV = 1F86ED54BB2289F057BE258CF35AC128 + 8FF65DC42B92F960C72E95FC63CA3198 + stream[0..63] = 9D13AA06122F4F03AE60D507701F1ED0 + 63D7530FF35EE76CAEDCBFB01D8A239E + FA4A44B272DE9B4092E2AD56E87C3A60 + 89F5A074D1F6E5B8FC6FABEE0C936F06 + stream[65472..65535] = 85D7E59D15760E12C5E8D0D5CD9B46E7 + 00F8E821C91CAC8C37A6200E61A71E84 + 15932834C0A06DC7E5738E11A0F9A9C4 + 38ECE66D8D5A654A754FC5858B28EE21 + stream[65536..65599] = CEC10B6D37543B35CE32B152BE2928FD + C8476E341F23AFB3B404D40EC0657A8E + 95F5CF7297EB1948385A5FB2FBBFAF66 + E252F35AA1DF199FED99DA532E5858E3 + stream[131008..131071] = 9DF7785EB3E69ED977E6DCC59EDA18A7 + 41029BCCC4590A46B8F9FAB96B5C4268 + 2FE49EC0BF79FBB637E6DEEACC068E4C + 93D215555CF876E17F37968576C5D5FC + xor-digest = 0B36039A89999715A7F53207DD60203A + B397397C718C7057E82E36C05E49506C + 911F9596F2A5818E0ABE6BE666086DA7 + 9B18E89A43C64B9227BF9DF65CD55C35 + +Set 6, vector# 3: + key = 0F62B5085BAE0154A7FA4DA0F34699EC + 3F92E5388BDE3184D72A7DD02376C91C + IV = 288FF65DC42B92F960C72E95FC63CA31 + 98FF66CD349B0269D0379E056CD33AA1 + stream[0..63] = C8632038DA61679C4685288B37D3E232 + 7BC2D28C266B041FE0CA0D3CFEED8FD5 + 753259BAB757168F85EA96ADABD823CA + 4684E918423E091565713FEDDE2CCFE0 + stream[65472..65535] = 340CA4A2B985CCB5C07964B36AB84409 + 679FFBC616ECFCC672A0F61BBE94AD0F + E6C065CFC069BCA7D33FF35BB2967D0F + FE84BC6006E46D7CA0C1AAEE279E8C32 + stream[65536..65599] = B5221331961267143AF1A5EC7D1118CD + C96A4B088404F5B6C5BE7320C87C4E90 + F5333906AC759D7747EA06903525620B + D05703033C5F1973809B9D674688461B + stream[131008..131071] = DF8934D8386B59B681CC9146E6EF9A7D + 765366267B4BDE3DE8DD15B714A397D4 + 08432F2B975F6274132FECDA89E0FB32 + 379023ACDA101452D30657E6D5059828 + xor-digest = 36D3E252F992C30C76818B3364613BE3 + 7F84FC4B848272404E7D9E689BCB945A + A85CBA790187A4FAF9811CB0824F2F46 + 6DB05D3F96A0AF233486AD28A593AC24 + + + +End of test vectors diff --git a/crypto/test/data/keys/README.txt b/crypto/test/data/keys/README.txt new file mode 100644 index 000000000..352170fec --- /dev/null +++ b/crypto/test/data/keys/README.txt @@ -0,0 +1,4 @@ +The pbes1 and pbes2 folders contain a series of encrypted private keys generated with openssl. + +The password for all keys is "12345678a". + diff --git a/crypto/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key b/crypto/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key new file mode 100644 index 000000000..a765d9c62 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key b/crypto/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key new file mode 100644 index 000000000..40b449b40 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key b/crypto/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key new file mode 100644 index 000000000..f54557e4d Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key b/crypto/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key new file mode 100644 index 000000000..595ee5049 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key b/crypto/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key new file mode 100644 index 000000000..2eb164ac5 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key b/crypto/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key new file mode 100644 index 000000000..c724d63e4 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key new file mode 100644 index 000000000..4455719c4 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key new file mode 100644 index 000000000..efc0c1e00 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key new file mode 100644 index 000000000..ba349f1f6 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key new file mode 100644 index 000000000..a9098b7f9 Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key new file mode 100644 index 000000000..71dafa9bf Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key differ diff --git a/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key b/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key new file mode 100644 index 000000000..85a18e48f Binary files /dev/null and b/crypto/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-cbc.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-cbc.key new file mode 100644 index 000000000..8b8fa28d5 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb.key new file mode 100644 index 000000000..a30a3e384 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb1.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb1.key new file mode 100644 index 000000000..9b3515487 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb1.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb8.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb8.key new file mode 100644 index 000000000..dc974b0fd Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-cfb8.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-ecb.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-ecb.key new file mode 100644 index 000000000..1a9dbfa0e Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-ecb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-128-ofb.key b/crypto/test/data/keys/pbes2/pbes2.aes-128-ofb.key new file mode 100644 index 000000000..0cb9df7ba Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-128-ofb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-cbc.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-cbc.key new file mode 100644 index 000000000..fa9b39b9c Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb.key new file mode 100644 index 000000000..ac21ae937 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb1.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb1.key new file mode 100644 index 000000000..c33f3ea04 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb1.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb8.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb8.key new file mode 100644 index 000000000..31016341d Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-cfb8.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-ecb.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-ecb.key new file mode 100644 index 000000000..0a061a073 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-ecb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-192-ofb.key b/crypto/test/data/keys/pbes2/pbes2.aes-192-ofb.key new file mode 100644 index 000000000..cdc4cb48a Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-192-ofb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-cbc.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-cbc.key new file mode 100644 index 000000000..393f89244 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb.key new file mode 100644 index 000000000..7e88cb710 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb1.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb1.key new file mode 100644 index 000000000..9a8e33fb3 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb1.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb8.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb8.key new file mode 100644 index 000000000..84643b610 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-cfb8.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-ecb.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-ecb.key new file mode 100644 index 000000000..293bde51a Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-ecb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes-256-ofb.key b/crypto/test/data/keys/pbes2/pbes2.aes-256-ofb.key new file mode 100644 index 000000000..f47d92f95 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes-256-ofb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes128.key b/crypto/test/data/keys/pbes2/pbes2.aes128.key new file mode 100644 index 000000000..0711ff29a Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes128.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes192.key b/crypto/test/data/keys/pbes2/pbes2.aes192.key new file mode 100644 index 000000000..6fea76e44 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes192.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.aes256.key b/crypto/test/data/keys/pbes2/pbes2.aes256.key new file mode 100644 index 000000000..b449e07bc Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.aes256.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.bf-cbc.key b/crypto/test/data/keys/pbes2/pbes2.bf-cbc.key new file mode 100644 index 000000000..4b2601e74 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.bf-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.bf.key b/crypto/test/data/keys/pbes2/pbes2.bf.key new file mode 100644 index 000000000..7fbb6ed8c Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.bf.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.blowfish.key b/crypto/test/data/keys/pbes2/pbes2.blowfish.key new file mode 100644 index 000000000..2b19b2446 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.blowfish.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.cast-cbc.key b/crypto/test/data/keys/pbes2/pbes2.cast-cbc.key new file mode 100644 index 000000000..383b6d447 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.cast-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.cast.key b/crypto/test/data/keys/pbes2/pbes2.cast.key new file mode 100644 index 000000000..208cc5fa6 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.cast.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.cast5-cbc.key b/crypto/test/data/keys/pbes2/pbes2.cast5-cbc.key new file mode 100644 index 000000000..728de6fc0 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.cast5-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-cbc.key b/crypto/test/data/keys/pbes2/pbes2.des-cbc.key new file mode 100644 index 000000000..8c8f4bc6e Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-cfb.key b/crypto/test/data/keys/pbes2/pbes2.des-cfb.key new file mode 100644 index 000000000..0cdba7c57 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-cfb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-cfb1.key b/crypto/test/data/keys/pbes2/pbes2.des-cfb1.key new file mode 100644 index 000000000..9474026e6 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-cfb1.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-cfb8.key b/crypto/test/data/keys/pbes2/pbes2.des-cfb8.key new file mode 100644 index 000000000..c5d5594c0 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-cfb8.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-ecb.key b/crypto/test/data/keys/pbes2/pbes2.des-ecb.key new file mode 100644 index 000000000..1798e4d0c Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-ecb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-ede.key b/crypto/test/data/keys/pbes2/pbes2.des-ede.key new file mode 100644 index 000000000..0ca0df8f4 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-ede.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-ede3-cbc.key b/crypto/test/data/keys/pbes2/pbes2.des-ede3-cbc.key new file mode 100644 index 000000000..dd3579bbe Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-ede3-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des-ofb.key b/crypto/test/data/keys/pbes2/pbes2.des-ofb.key new file mode 100644 index 000000000..d92de62ca Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des-ofb.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des.key b/crypto/test/data/keys/pbes2/pbes2.des.key new file mode 100644 index 000000000..3b4f3cb1a Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.des3.key b/crypto/test/data/keys/pbes2/pbes2.des3.key new file mode 100644 index 000000000..78ca4a517 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.des3.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.rc2-40-cbc.key b/crypto/test/data/keys/pbes2/pbes2.rc2-40-cbc.key new file mode 100644 index 000000000..6f50f1381 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.rc2-40-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.rc2-64-cbc.key b/crypto/test/data/keys/pbes2/pbes2.rc2-64-cbc.key new file mode 100644 index 000000000..1a70f9721 Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.rc2-64-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.rc2-cbc.key b/crypto/test/data/keys/pbes2/pbes2.rc2-cbc.key new file mode 100644 index 000000000..c8778c41f Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.rc2-cbc.key differ diff --git a/crypto/test/data/keys/pbes2/pbes2.rc2.key b/crypto/test/data/keys/pbes2/pbes2.rc2.key new file mode 100644 index 000000000..fef0f143a Binary files /dev/null and b/crypto/test/data/keys/pbes2/pbes2.rc2.key differ diff --git a/crypto/test/data/openpgp/dsa/README.txt b/crypto/test/data/openpgp/dsa/README.txt new file mode 100644 index 000000000..9abffbf27 --- /dev/null +++ b/crypto/test/data/openpgp/dsa/README.txt @@ -0,0 +1,36 @@ +This archive contains material to help verify interoperability to the +OpenPGP DSA2 design as implemented in GnuPG. + +Keys are located in the keys directory. Included are: + + 1024 bits, 160 bit q size (i.e. regular old DSA) + 2048 bits, 224 bit q size + 3072 bits, 256 bit q size + 7680 bits, 384 bit q size +15360 bits, 512 bit q size + +All secret keys have the passphrase "test". + +Note the inclusion of 7680/384 and 15360/512 keys. They're large, +inconvenient and absurdly slow. GnuPG will accept any size key, but +will not generate DSA keys over 3072 bits. I include these keys +mainly for be-liberal-in-what-you-accept testing. + +There are are signatures issued by these keys in the sigs directory. +The filenames indicate the key used to make the signature, and the +number of bits of the hash. In the case of the 1024-bit DSA key +(160-bit q size), there are 5 signatures using different hashes. This +is to demonstrate hash truncation to fit in the 160-bit hash size of +that key. + +File Key size Hash +---------------------- ---------- ------- +dsa-1024-160-sign.gpg 1024 bits SHA-1 +dsa-1024-224-sign.gpg 1024 bits SHA-224 (truncated to 160 bits) +dsa-1024-256-sign.gpg 1024 bits SHA-256 (truncated to 160 bits) +dsa-1024-384-sign.gpg 1024 bits SHA-384 (truncated to 160 bits) +dsa-1024-512-sign.gpg 1024 bits SHA-512 (truncated to 160 bits) +dsa-2048-224-sign.gpg 2048 bits SHA-224 +dsa-3072-256-sign.gpg 3072 bits SHA-256 +dsa-7680-384-sign.gpg 7680 bits SHA-384 +dsa-15360-512-sign.gpg 15360 bits SHA-512 diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.pub b/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.pub new file mode 100644 index 000000000..3fec64eb8 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.pub differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.sec b/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.sec new file mode 100644 index 000000000..8ee1179a8 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-1024-160.sec differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.pub b/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.pub new file mode 100644 index 000000000..4f931c657 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.pub differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.sec b/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.sec new file mode 100644 index 000000000..3c204bff2 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-15360-512.sec differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.pub b/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.pub new file mode 100644 index 000000000..1c8dc6984 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.pub differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.sec b/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.sec new file mode 100644 index 000000000..776edfcb5 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-2048-224.sec differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.pub b/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.pub new file mode 100644 index 000000000..307205cf2 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.pub differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.sec b/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.sec new file mode 100644 index 000000000..66008cb29 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-3072-256.sec differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.pub b/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.pub new file mode 100644 index 000000000..6c888a44d Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.pub differ diff --git a/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.sec b/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.sec new file mode 100644 index 000000000..b57f5d9ea Binary files /dev/null and b/crypto/test/data/openpgp/dsa/keys/DSA-7680-384.sec differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg new file mode 100644 index 000000000..c90658540 --- /dev/null +++ b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg @@ -0,0 +1 @@ +$xp=)O'gT<ꑚ_(ba~IbSZ/겠պe, (p̊=sK \ No newline at end of file diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg new file mode 100644 index 000000000..8485bd335 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg new file mode 100644 index 000000000..bebe1fdbb Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg new file mode 100644 index 000000000..f84c3035d Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg new file mode 100644 index 000000000..f700ce473 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg new file mode 100644 index 000000000..bbdb44c2a Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg new file mode 100644 index 000000000..d64c8176f Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg new file mode 100644 index 000000000..2da027129 Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg differ diff --git a/crypto/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg b/crypto/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg new file mode 100644 index 000000000..f313c6aec Binary files /dev/null and b/crypto/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg differ diff --git a/crypto/test/data/openssl/README.txt b/crypto/test/data/openssl/README.txt new file mode 100644 index 000000000..03d993374 --- /dev/null +++ b/crypto/test/data/openssl/README.txt @@ -0,0 +1,8 @@ +Some OpenSSL-generated files, all containing the same DSA or RSA key, +with various types of encryption applied (as well as the unencrypted version). + +The password used for all the encrypted files is "changeit". + +The PKCS#8 files which contain ENCRYPTED PRIVATE KEY use this password for +the EncryptedPrivateKeyInfo object stored in them. + diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem new file mode 100644 index 000000000..7af858e9c --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,3D7028A746BE6B09694E16A222C543CB + +RkTEJRJjGfaMfNc876Tx1hD92cblJRj7TvUafRKnH0J3Zv7l67MSG/6rY5HD91HP +s9i9Se+H8Sjn/HaUl3QTZv04egloNlL3MPSkI5fusR6maZGPVLRJBLfVKYQZVDja +9YRe+ZhXMS8jTe/IhYMcTlQLBnnwmmgZC09Y9Wm39idu7lytOl3JBMgz0aUNA+P6 +lN2MtaQyIBXHbaqfNDGFn/r7+MH4CGw6MtrPzGqRJgGMHhV6T5o/x0nEU+loQVOK +mPkSZTxBbn7xUb4JvFPnLTbsI4Cnre3QmfmDwkCAklQXqAIT9Ex1Slq8qaCc6TEf +mWJQCYPUkpQOqyinR8o1VbYm3DFFvE5F+CktJrppqkQvAct0dQNjMTBFxUjCkZum +qGfAslGPBREmmnsExm5GThYqA5LN+qo2prBtvt6Eso0i2jNiXA8bi5OfDzDr24R5 +/RKUdFPf7keaAjg9jSArwp6EfM3y3sj2riibwZlty2ckPJw3SwxIe6QSMwKRbKlh +GJoi05/cO0NxQYhMmlwVN9v5+YpvWmT3CsFvCA+Zb5rXPx2AZpFv8YoHdQb0qyEs +b5YuVoavL58+BWIPQpeYy/jttR5pEPpgM+C/6/1o4Cae4lwppP2OYFl1fsqyqbKh +iadErB6QRaJCnfnhG6511CxY+vZtQE5EM36blOl/op+6G+36ApuqDtfA0C074daV +uHfcqA/g5dODEJP+ps6yoWtM5lbd5bZZVidWhrU6Skbt0faF9w5ECF0qkYDGqF85 +qqFcaoimq+NP7EtUEFSneOee72zYALXyzjoEU9InktzDi0Oufojzc1gjhh7LbObw +UBANPHTsbaL6FPTEs4a3JYSyat9m/R5GAaT0EBynHxvdQRGNhtEWFPkpGYUrAz9W +0A9mNX1as8Jsxkh9wqjgOR6Xpbqh0aFHNnkodwV72H5ROga5EN8/bbuCBxInNzy8 +o9z19AnajR7vCW/p42QwsGfSolQgE3KBdqWsle81LcCPVQPQshXzcjgBHZbH9/mY +M4bX4iEsC9yeNgoMcHtIagOKipsqd4nuPskutf07Mh71OXFuxsVyGcOBVhhdZCb0 +3ZYzVi+nzORPRZ93nPXipy3+NmoARk7mhXDgX9p1bPI= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem new file mode 100644 index 000000000..de088f91e --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CFB,C0CCB782DF620FA388D9A356F8B7C346 + +DftIvr+HZuCHBanw4n8P5ZajHAw1ldQkSgLxtxY0ZYhhVDLEqEqh6z+4ySjZz5SR +KY7kYFo6yJnURurg3DAGvJ55s6jgyrRHQZkhiO1fBxhyarOfcBjJauJKDT4uhFtC +LWZ7dqft3PlcHi09mFKjK+BYjULe1QkdrKQlV5FBpCj7ENuHqtfx//bV+IWWVnbu +QRx4ec2nNCiS2qiI9Qg7fgMdXWrpJlr8Zvfmn0Mta3Dn9SWR9hK5J4d3xiBtaF0F ++BNuszy9poxnsRaORZYAsBh2vdLaQyn1gGdehlsWG4J2Zb5RHApYczJcp2AoPX4K +j9wAzlfLRSZ4Lt5edShd1zf/iDxegBKQFFHTfPA6uu+fe38qckdxVyBdGaCCBvUz +Quu2DjjXdCWWo8To5C28LVoVyAy+qJaX86vn7yw03/6n0y2dkydiB3u6wnucsom2 +HfLX+pdyarFoNvtCeSW3Y/1Eqd54dDhz3GrSTh6c7G+wiRziKpTduEmoZ+l+CIrl +tWxmh59YTSeX4mi48+fxTA8xaVwD/j3VuA/jTOQWDW+DXU2z6OcAQ9rlOnT6Jad6 +P2El+vgLrIFbC4eJs2ry6bszqFJ4wieBVnazPCUADLSsXVwbFuO9oB4129y3Yg+U +dE+lN24KV0kC/YIdO7c2PghaFY98CVrBX/oocHy4j122fHfboiPNh7S7n6cqJHh2 +JKKQK1qTdfULAN5ypecl27gWeM2i3ib2C5jJiOFUlwiAkZWLRJlsiJOk+b/rI5FD +tM7yFanhEtcYumRRoSzKII3tF0h+z2AwzPdsyJDdASCzo/DmhB0fg0O8G0q/isNi +VV2zL+w7mNmf79QsrGVA39Y+G/uKS2QPf3bGFthzYZwKH1M9hTN/do8wCCJJv7MR +Ejnd32srumBOvGXnYtGuHnT3qRA1mj82B00bdfwCd09GGUr6mEQwfvsDOR3q4OfH +eGCn9NkWKYvf/QAxCG9Vh7u62sUlXKS08hJcVAgBOzN10wFISTIOAvedt/q5GMvm +nRuF/ixs6f6LNy/VgyztHoQ4vN4HBf8teDsbWSMDvlLkU6tQZjyuu8JkTjeDaqMv +GbCzrRBldS3zMXX2OaWpZohi +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem new file mode 100644 index 000000000..4f69fa7c7 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-ECB,174C8C70B397BCF00CAECA7AAF7A0A73 + +wzs0bJqGg+Scn00TgtgXyV6hopQKVWMEFnMpu6R/Sp1tbPVlr+m5+SppJFVyW3WJ +YeFSwXzuVAsnbD9qIZpAlco1ZYpmRXaY6IfXJKYf58v2IrqkxVd6AwjGN2FloSNp +b/DinJXJe807tNAkuBLQ/7QlkCv/BmZMeYBl60XYIH8LDF/T/ON2hREl49zr/GLY +bwmVzgRpfl3c8QIt6Yl9uKOqCFJmMHD3YS+dT2RwuQwqY+U3DNzVoCci6Zjd+gL3 +eb/S6VstodSR55qF8Fkwt+sy5yL6XmhQaGWEgCwDwArN40MWIEpx4NaBxCcqHF7g +o26bg6CZwY7Rv42RTHKHNPETegZneAMK+e1lNassSijak+A3ng9bxiBquWSKHe0i +s265Rptr/GvQX0hLxmfjEjvL98dKVDZpvdBaWRqV2lS26jDPiFAHtVsXvF8uo25J +1aS8FDHaD2DghC5aXTQRaVy1jlMTm2YZeVfiU6+7HVXBkLsVbShqEHxKylxgtB/1 +OAui+st60+o8lvRmn5dT2xnxLn81Bt4qron4pz0LdzC2xl0DqjhXyRsf7kdxr44h +YN1YzmdU3fYFzQw+VmE8xECIjPukp+0HSb4n7BTGsWvqzntFIrzWGeRmNhjtMcwy +YJoWGnz+WbxP3DJqSGNdFME7mNI/kaybIkOpbHLLlmgD7XWpeyGYtsU/rzrh5NXN +YRj6Nf3TWI1zwS2xx95+/5vc5Df+sb1+/33J4hbGOx9KdfqoVlJZ16puvdTq97dF +x8TVYxk2PfBJpvpChCsFlYBOB29F+kY2qoBKPbrvmFPsPCgI2q4gFuJ9pq1qyDbK +pq9d1oewOOxR22VMQNGG7tL0tMmtXJ/z0n3Y1UE3aYiSG7apOhooBAQ8grpuwqbn +mGTz6sYB8fHdCnedcxEUxxuFjXupmBcT2ulUjFZgFrG0SEMElgTDjtG21eurqPKh +ZgxfkW+tM251WTi6sqjiQO8WYHlU7+XyO3BKfH5v3kz4qXxsmvKfh4UOfRy5f9YT +Ft5oi1bos0soTvms0d8ckLt9Tph2wgoz3Sc++4DRcF53Ks9N6iUgtTpkEtmd/Uc2 +5+xewYmlfYO2qfiqiF/6dSVfDPjJYR/YLx8KBZ40/e0= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem new file mode 100644 index 000000000..cddcea9fa --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-OFB,B32C602DACAACE3A4C55B4600D974E5F + +w1+kMXURdxpREW3giZg+PooayvatT1Pf1bY/h0Wcm8z0w7zRtQOyjCOdEPNxsdd5 +ZYn3qEIOO+wkw0v0PdK1AaegJfYMbMpSp/iEyFXU/LHS0FpO7o8zmUiAvdeEKAFt +Qk90gFBiyQyvWEWsp32KQH1/eDSeSLeQbfRfDbh70DkB4nUjYMW/eFL9E/cHCmdw +0LKUpEycc4s8i/mWCYJF+cQd4J8RHK+Ose2+5z86kHTrbFSlTBEZEXPDRHl8ZsZE +477A6/Ndy0Mq3+NgMLSl8xacs2v3itdza3AJREVOzvnRmV+NmWtYQ4MQrJrLg2yv +wfAf4b2r+k8Igbpzn3NCEYolecGfyEWftzTsqTutlFO7RfeW8go4v2MvEsmHTphQ +k2qaQkdSTFaA7a2O4PKezJap4RRCJhq1d5bw7RwkCpbRshsvrKQqGdTGJxEZZfGY +6pOt/qRL9LVCGUVdTTdje7fx9okx0LvKo62eKcUBh/AwZGE+ue28g6/77iABuVtQ +6kgJ3lQK3AQwKislF5cBC9MAkiIomsoVOKiP6+yX74XIa7T+3aWXlsY1oX13+kMW +zijwOrc114Sus2eS3xSCOWLYN+0GECMrh2NDGDW6tx7i3R20BuEF/IwHob1qjbkz +hnS8KrRY+174avQDeF1lMSBz4Wfi0O1IDuxWRDRT2z31E4E8EIoJh+73NZr7w6JA +8usK8RkiJ4ypoOPtRegXX6GBG5UYgI5bn1Ms2X5xSUGIXgG8IwjHDbAAd5xLSWp+ +01HzUsR+6wA3MxYiybTU4eOKNMviM1G4gGsKeuGrDsNnidrHfSzVyOGVVHr51xRI +9Xie4FX/VX8/7Q5RMsA8Y2eN/yeVwXup65JRhDD5LjILVMy7aA90KX7y/s8KIYae +n6lB7PtcpRWwhdYSYtnlrJmYmrl55d6ZQtJm2/xjnOBd+igY4YKNjh11xBL8YNo3 +wBjW4/lgrlvC7kbLxO6JIWipPr/6F3bjvmeLclTAZxjM1NU5HhTScGaEA8A4bq4+ +6Jiw9ZUw+TDCOmntkgEublcCMjcAxrawWYO/5EWuOAOkyBsa7BbfsUv3pgPugz70 +qa/CEkshP5e/1VZgFq/BNFtb +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem new file mode 100644 index 000000000..9b916321a --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CBC,7FA13403627D9E1FA02FF88F6D594679 + +hZYB09uY4gjQFEHX8KGI33EzcJijYhBMNJCR9v8UK8IcQIITOfZxYV2BmrfQhuVh +Kcar1JrQdnc4S7+UDFIjlLV9ErBCvIUQEflP2ByDhxl892EtVcoMKB3BJ2Rgi9mk +32KhayXo5V2bu2kOv2nTAjp91LebDz/ylmhhJhI86BL0DLjnjTEl99v9OHQsMtb9 +cXZb51mwIynmqU7Wf+PchH83Yw0WOKs4MOrCtsqO9lL7Mf/MiSSiE+S/rpKLPXY0 +4aBxP6fw+HG57gPlNAvv/qKtJu8YgZDqVXhIKNDZRTSRX+B9R1Yo1tgmJVPhk/7x +mmYUxIb7w9nqa5OrxzFHyNvo1U5dJcXyCEhvUZ3ImR1DZt/oGJYgrPd/8YcYbsNP +LKmTLUKI5CARZ5KcOjfM8vpKqlfpCg3Yl1FaNIjM0eAhD6XrepLj3faAJW4/YEoZ +SGMO5atbM0ERT9sNDJTG0iMW6xGL5l/6pzfsTKI/2yMaAeWAyvg1PySNoSH7s6CC +CfqF0w0VpQEiOPb+qjtmjBDB/VW5kNrRiBQqZAgpO6mED0jAdg9o31tyuuaFDWzX +41C2viVvxTx5A/xOtPvaDo9EMecc+7MpPLM2VhWhPDiDBYb8PCKqBOEwIyH119MN +gQEC0IN/itc/J9ybHLCjrF1Rp83T3/XhAaXNVU9msBBpKNjawnwsUUj8gI0JRbx/ +5ehO32sQm8wkMyP/8iKDAqBRkDT3RIEmLi8ms+ZZRmLwGBkSZZzvOK3A5Dder4bp +dIhOOetvoN6Bs9l1i6Dds64pwsy8IcnLLeNmOag+Qh8+pVUBNZ1zUV3KSizRKh5U +dyT6VMILd2EAUJYLXs9HNFTtHZglRb96jQ3rkHGmAepeIVnJlNGKByvDUsJQDGl/ +bGNk5Ejz93ylY8JzR1GaYyFVIUU0qY8khbo7bSn/o6II+KjyTTyTkV28jTSD5dYe +upGHOzmqpGi3Pzaz3DXpbLcMzwYrMP9FuXuqkVWToDs87DCfGqskKtko+zlTV7/P +eBILwUawtXMJfYntkV247FffKgS3/BNkgEE+iNthOsFMSoqX/3ESBKJdJDfKRH0J +BkYL8O0I7OwYzfU3gCWVZ8AvAhd+nSqp4H3QUK0QM2w= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem new file mode 100644 index 000000000..9dd5b153f --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CFB,3E445502677C77AC6ED115F8EFD9BBB7 + +fJXVVcgxhZJXZANfEWDbVmz75ocICvntATRNVgt92sHgl1B2c4cgQC4Xmu7WM/Bc +ocUlcSpWnoHtWRDumw2cwB+fDb5k3e9qb+aL2juzHkK+kYd2mkRjW8KSG6D8HIwq +fpvV6NQmVrxI5+n+uabwfil8Ecg9V7GD6ta0QSgt0lc8clp01se+VDacX1uCB7zG +NtJsr1wUM0SQbEWPEcpLUoYfK0qSO0h8fpnagKrNQLfzFbk85arkpD9XBzxpNO2p +2fYsc3xZ0RkFauSZGt6ehu0jh1TZNPYDURvSn3uVrseLyR0Gt8LWp+hjIUp9Kpo2 +fLUVaH/7wxpdCAYzo4Ub/gHPfbxo2E5qYmE1oTJyAHplaDqSg8pbwJofiXl12gMM +IyIC3SCHZJph7xqbKa+W/X4ChxYuN23ZMZ72cmqH4tH/j9IpKrpWEeqjxaj0EwDs +R06Sz/qAqs9iDMKTkuFTMxGhc09DV9sN4NYczEIEas7gploOdryJGMCM96RtMDS1 +gjW21w0wyfqa7ogsDJJ2/HqKL73Zfn7l0jzmqya7YwcToEfKOSP+a2Q/y3Exr4KO +FY5PLwKvpBaFcFzJoYhAaPphUzzAQuQFgXj34f4JU9bAXbf7ol7Swcv9JP9tN/mF +n7z55BbPfC1EiyGyDjeUDWw4XIYF6LtRK3lnvn4uSZFXLmYMJJthwwC/yS+D65LW +vsW9uuQ2qEfEC3hVbMPP+1KMgRkb9CVbSXBH+B7UoaUkGsJYzdSDeHZHbwiHgxqH +jb6WcjtUjh7W2VO/MnHBrLg8dnC77OnR4IiqJq/6TenuSu0N/4mm73SH7BtYAugu +ok/2H7GYfGfWjOnd+QvG/Vjsb+l9gtB6SXYFiWuThjB/sU4kHH8LUUOmGRlC3NDz +w4pv+cR3tS1zX+evPL0BsZ3ynDSGRbMpss7xVooxIPacFwDN8kHUnWvIBpQKAizq +blt1owc97vidf9OnZxUMpzw28/PZ+y/vRYSPQrde3kH8mJmu1FC6tLZnqzuCSsgR +SJSr3/8qqSj3XrAW+nj0Y2P8lItNdFXex7j/RuX3eV5QIyK7uY+z8ZP4gf5q9w54 +p+dQi7Vx8acRjbsU+r85+MRR +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem new file mode 100644 index 000000000..c7608e02e --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-ECB,C625A2E97BCB192B31A8E33CB0CD857C + +jM0PVjU2r063OACSZgLkaS9ppOj4idZ9hgkdMi58Oi+C5bfhZavbjROyxCG0EMGz +HnAIRJ4pkJeZTnGElmOEFbaNPb42NAvcrYXAP4XNu5FbZ2SqGKwRnjjN8z7s8+Ip +MrCyJsWycYy2BNaksJRaDNgazjKgqQxGFlQPJ+j99E4dk5QaduOCrf6YQ2G+1Q+m +2/uqVujTwmverPnHDNhQI0ZYMY+l8+oVcPHIY3TR3ufecvrGkjFgKH0B+/L7gWSd +ASvldEnWuFtPMiYnqCPtLgJNKSXO2nlumLc4Gz2ruvYKI1qGPXsVLIGnxISVLUzT +VQz7NrRYwlvSLWdQNqbrEPvEu4q1KstqIkiPRoC98vG4+VRkf9AXAGqxA+vKYktP +2Ui/SLhoC/seh9pxYXLsmqP+8bxcNM3VsJQoUUFM2PtfyvzBtuQ7mJQTSFSXgBym +qXvzx749S4xOot+H6r/bCh8753MMEsgsM39jBsRm1zbaBjaNFG0UBdfFigHWh1zx +4I44pIHu1AQDexjnfaUVrZFbys0CtM/Wy/3y0I3+mar1Wg3Rc1XL1PJzwDqBoZst +vg1h0L5OPV1c4CekFnAEx+VI6ImxENoYtZCpbpt90kz3GxRY/eS8roS/SRJ7KizC +p9bWEsUMwJ4Jl+xvV/VtVG96nKzlU13gkI6lMATYzImK4Fh7hH/LBy/UhNVL8X76 +3fo64CCwE3YkrWEmBDdxt/K8Knj4MUPjBgy/ETVRC7ziG0rUwRSd7zLOoEALMHig +AtNX+juPvPU7yARw317Q9lZXeytf1AmGiFGjYZR/mduAa9M415uWm6zutIJEz+q8 +KV93bm18JUaQSrX4D6m8IgNhX0EfmRYAIFnB3rv+1rsb61q+4USk0L/1vKT/fGGm +yvXMCA10N50wGS4wovMYQIl/giMEU8e88f+gqImU1kporgESIOUYUm9tOZ80w4R6 +ITlKCzRuoptMQBGZeJIWfWNLxwYq7NXKpvjNeSOeOqQ4fxhkzEetFERG/2hnszmM +pqwoZBZQ8bb+T6cmJD1GuxoO3ev258WIUkEZTkFYK2Q/+QKymPZO4ATSAO4N2UqQ +4TXRqUs4i+1f/BJU0ahnSgmzrynGmskUonKxt6T87lE= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem new file mode 100644 index 000000000..501003586 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-OFB,7E4DC037A44E5DEE4E005CED36B18C16 + +hvLtWTLg0+cMFDo3jN0yZc8S7fE6cDdZcBK0aRy+Eg+9kWlnmR/VYqG4xaich3VQ +wkyhNpBSAoUHY8OKkB8hYsqbGkuKxQ6Db4IJlahCTFgb0yO2C7pUrtGDTvmXVq2n +qJ4c+4CILeyzIp5yfy0dE8CAsZZcLEdSpPvaNK0VPZEPhelm4WdqqLozYVibR0KS +2BbVO+E7yHGC/G3xtdbduuYpID1pLwyaebUCNgblggn6FJ0G2+Iu7lndmMU4B1Wr +phvb+Fd1kL5421u8OOKRVLS2yMtlzbK2Mz7NclEzEs1m6K/xJUzztxImAxElBiiB +YfOw5WLy278DuD1GCBkSuAKB4XWUtlq0+tJnCzAG0yrdMloKH1m+XF3MXFiRTXgE +k08PcZchoNgGP51Rcg77skATP9OMamcjnkMx1B8YxTx9O5Vv/oSIjGQrr+t2np2t +JU1dHTr9QrCeadSz+My0sjlZrL3ZisAwBbu6C0Zta1P1eB+i8ORZvm9HvmadcyyE +y5oQWv7XwSfAQup/4uuAJ8bQBunIH/ajMF1WmD8rzLcUjG8W0rnBWUtjaxxBdkWv +xBzgMPm7Q+L/5yhL/TMH3dkUBq+Cg5VQSe9EspNRGKBUgfKYk67Y343Mv91xKtX8 +8Tmh/WlnYXDv8QBnFJZXVnf8HeSFHsHDzfTgAmWHdhisTNwmgSFvBK5ghvhvkbXI +UIPi+FgeB7P3ccFYnmoMq5qgK0Ki4lU6v57soDrjRl/NttfXdQEhLfWO1zXNANLk +lqEhJSvBPZY4/FiOW4kNaZg2oRswz/+Bmp3amsK5TwBcI72rnH6SW5ADqPCcTP+h +IrH4L9wnhOXw7QLk/h58JwiEc8suj5n0PJPQeHKajizd/EpUzVAuRTAl4GMvxLCY +rALxeRaEXfJH5i/0UQydEvdU3ZP/LTibAqStXyVlSBZmKOg0GNQ+aAiHZyBnI3oq +QuD0KuJi84ETMLU2baRydTbVlQDr8O0vxnCNlPkFFOqVpWyOyBgMctUfFJiM5c0l +1UT6dc2F7NF5WOuoDCVw+Jp974CJuBSRGpdQKGms1Dvjwrtnf0ycstswXHvp2ZhV +IVeCbT4WWh4f9bp6STkdquSc +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem new file mode 100644 index 000000000..17289b2db --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,307CEE18F79CA333A38CA90E75B248C5 + +qyg9Q1cX/FGOoP0NFzrCRLwmR6bai7JzDiCLFCthciYkMIWLIVzvyTg850YD3dw3 +Wusli8EQJig8DEpFSM0WBc1Rne8U4168nKuRnFUaP+VWuD4UpNDt66cT6dMoqATD +kZGdd+p8ReO9TK9gO/ZZU4R+q3OUpjxX44szxj/EIVSgphi8R0rRSxl/yFRnGHyO +xfpM9NxgMvBYlyxl5w1Lp/ictuF3D505nF/uuhzGL5a+WWhSnssMFHF9vxXTu21/ +3Cy0C3Qah9eV/C2oyAU7GGsXHIfqFqsgMjQN+cTFqMyFeg6g0J7hytDAgZVBXIFw +UuzMbxUUZU9VHcZzwqstkg5BmUI3sgW6gibBUzuJrmo7uLrCvHyj9oehSMqeuPUC +EXFqhw6Nb+jZMkvW9J9qFYG9eg3PQsDErIdVK8aWdLrLyc+O4gycOdMbR8aq/3Z4 +TlV7Ye650EvQ13bwZghZyKel6Rjt4P1MagGriNqCcLVVsyrRXAiqjq8cyJgYtoXF +1VMBZz8ob2FH9+kvk2sb4+T22sTYwiqAVaLnCsuJ4dmS5wdBrhfF4oyHYV2KOVgG +64GqxiF9/whvbAWSM4cU+KslKnWGZwz53LKleafrgeFJ2P1ldqnl0on5EQ/m9bzt ++GSGwzZGRmhf5NoyhaH+OCkq/h1UP+LZ5kDJCqH/l1JZbvJQkGNKzt1OroW17GnQ +EgihXAmhy/xOAIZkz1XKa3bNvgS1F9yreAxJAvBHB0QzZ1HrablsaTKsZOtY1Qvq +e2OdpJFm+SrI7RUtbp787Yl9pH2cLEdto+WH8gtgXloS+b11Q7broE42w9MIJrno +kzs6eDWafSExTvpi+29OJEtK4PNezmhOxzTUIsG0/8d9Vd2WYqrLD34ze68X8qUa +CoIXYP8VsQLoXVzX7VnMBYTQ+YOR0Ntq6pRj07RbJrNiOt8qcWGslzE17ERuCr0+ +ZFTGy77KOksKjLksvRj4oshQjRhVYZscPNnwKODFDvOPsGFjDoU2Sg+W8kcfE6Bc +1RQwk4N0cjkC2JXXk61QQjh+efWRBqPN6va+ixUcsZSxndCIoBk4qtqtsyTFEcC7 +LdfCC96RGnXlvroiPHvrmJYN69JAyyRrnhiYfaaC98s= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem new file mode 100644 index 000000000..06718a55b --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CFB,337D3978222A1367F5CFE08611416E9C + +GVmy9WG3oR1Vpfxnfpv1hFvXGzBgE+c4jplSw2BAlKnbznCPbZLc3WF/ZMv2851O +iE/8sdcetzoAlm3jGPoDi6Y/FqMFmcbqtro7vUz/SVgi1HDI0FXjOTPtFe6xfzhv +84qt5lz5VAUueTKFXEZHqM9tV7lHt1FX86VutNObn8pE7nAWVX/Xvq+qWUsEx0ik +YjZjLY696pyz61hnxZE4jKZLRx/9a6vWYaVfzsEi2FLw9qAsw6ILp+xDaAeKa+Il +YVkgDPi62NPr7cRX1WCiw+/feNYPgUfGiBNkd2mOnAr1yOXFM+YALw5V+q8I6ZKN +k8R7skAzRZkwTJ9WaaFGD/UypYmhe2b9Jp2n0BMEn5RpW4o1DTIHmfMSUmUPp5w3 +HjbtdDUWIiuplrz7mUE2sez/3bMbcoiO2Ym9SInJKBrMFSvyasg403u4QESYQhC2 +Lwcocb5ixXoczHjef3CogL6BhL2oZwXCl3OBqpMOJJJKXUPRhN8bvgV41UIsiGtN +TFUXqYdpbmMkxJNMGiD3mKWpSm2MMdQYnRlxNh0wXLi5sHckD/WS4yFrNsCIMVDT +W094liK/Z7BmplY4TyqKhsRlFVQ4VOo/W0WNh7Ayp0siIfo8vHDyoQsnUkn/EUER +UZG1lIy6/y1RSg15GWpdi1bvT9URjElh/U944LSYD28K2VU8aPKaRBokk+K3AyR6 +YhZRCBr6uIVZ8HDkBL5OW0eP69/jdbyc4MnWRa6C0d0boA7N639j+NQz9erYT6wu +RkInmBbVfxQD6HLkMwiuU23qLP+QQTLkH7rQJmnRPSwAKEE8RiXWi4/TnYW7d0AC +Bj8oaK6DO+J9t1pdj0IGluf52iUwAOf2Pxwvu44ovaF+yb2n3P7S5maDGLTV/xBW +D6nEAct9cYj22/aRDTLdpOfG0L242vjQLnjrgezBLraa9eTy29hR5FU5ACH5sB72 +rxUSwoCHCJuNFSxC27QwZqeCFw51epwXxLv1CjqsQi2So12qH+vFVtL/1YrFBct0 +dzwbdNk0S6UyPRqfiOE/+Iszzahmb/GgskPJdfT5Y03FnpDWfOotpaAebrY4t6kz +/gs8pxupvdKw4eWsxVCL9KOP +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem new file mode 100644 index 000000000..ab0f64d8e --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-ECB,267E98B92F05ECECABF28790E81DCFA0 + +MkVFB5/gKxAksBI/g96MmN+ujdt0XFXC+7MI+0/OJ/H0LXlHlLpwfGlx/Je73Imt +rOZveXf4I8sBCF1Z0Fhzb3TTTDxcastJGKWAVKaPzKkWdxNeUjx0kinbrkM7Spfa +yG+wW+Srtfyi6LzEsbCduDK7hzfDnLbgKymdDeP0TVeJzEdXgXcV09a01GA+CEVX +aHesQLNHyYm9nxFxK0fAnKo5r1I2JsozSWNTG3VNbiItxtfoJdXTn25I16qXjKzn +MOn/A+RBpO+P01j4uk0q0SPJMlIYIX+RjgAoPiI5R5vSeucsdUJo1sWnSfqLc4yP +vUG5wD/+lYrxsXiW61KdwIg3vy/ty5+GqwNgNvN0FZM8DvK+NQ9K/IpoW5RE4ioS +ZNm1JpeGJiywsBf3Pi9mwR44tTVY0Jwa/TTQp1kEYGjhYXMIEvf+LUHwG5KO2wmD +kDediMDUPaUx9K34eSpgIUln5d+1viMpC2VcDIg4tYjAODtGRxzgDUr3mbuoVl8f +GqusTAdsNoIyilY44XxA2odHa4S8yXsx1f54P8fRYbA4Xo179LY1Nh7PwQPm+rI2 +mERkCsvns9jP1zJRuS1lYW1Dqjtxxq8Nt5RAsEwKQYLO4DfsuMZPblEXPAwSGb/N +69xNs8ZFHm3KT1r7FdUrVpHk2vmqsetNa/g2wRTEuBmRCgrtTtEDWgdBNtDoHlBR +pDIWgwNvt7oJIU0EbQkUgW8bmg1p7jxXN8Bk2QKZoOytxA4TB3fR1p92VkXzrkxn +l+Z815BNfqnNCU5nNzLwk3jLgksZrDnLu4sXykIBC/bpP5fubnT7iJYh9h6ZGFeY +QLUP//ssuZM2auNjTVykWUtAiglROzxnFZjMXEbujOKbm70Uj3YvAHjoKalkti9x +MTj/vpR0xBv/iDtTFl12HIg+IEGL1PfX4xy2avvJO+XGFD4zcnrLfTMwtUJQjdQH +dUMWP8VI266u+B6wGfcrhdCYqtvuLVUvbISU3YD/tP+esXh563kPnXd2UuaS3ErE +/7Y/hzyUkDjJ2g37Hq3M4wbaEg/a6osDtfg73thDMadsbTLIDjHKgAgBv4umNtA8 ++EaP0stzRH3ayHL/f4I5bHC8bMIAumKM6zap6tBiork= +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem new file mode 100644 index 000000000..7192ffc10 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-OFB,A2D4D65382905DF6EEE7A315B10CF2D9 + +CpLeywQMv8uZGrgJYM8rZ01awWHJWH/ZKkNi1rpQhaI1BAShQbIUvpY1IsMLa0/E +g2+oj+Aa1UE4UDsAlzcfsKG9QHS8nOYWuLpU7VAyjC6wUPn0yI0sxxKRd4dmPIgW +w3r0xO187yqLAjIZCj4y+3ANCjw+rLpZ5Zq8KAN4j6H1NEmzNoNVQbwY0hpsyxwE +Tg7TkI5IyNKQSQC48EuZh16cJR48l36gzFOmZKr47gzS0zivvED4Vxdaey+WZkoF +1XW4VbQGHRnLEn/I8rziic9E5pvvcZt6K2NwvzXrkS53ufFYZcgxNRxrdM4yLz+r +20Unn2F2KqumB1RAliKo/PtudO7XfsPNc7rbF/stGhlxDWTyPU2HMX9tw3JkWDfG +rRsG4RJOQgsx0Q73/7XPhgu1J2Wp39a/QI/IHwZ+rWIerdUPhs/MRRPoduAfSSZo +r2z8OPJAlMWLwAjmmKDGhpTp/21n9xLo8tbvqmy8Frz+kAxAHXeHCTWUbxA+URKb +s5NKQALX3wYHT9Xq0A27A/Zrqs5elqc/IQL58nU/Da3a3OfPB4+MNWeWU781ohhi +VkBgMRbnQNCC8OPoeMd/At9GDEEj1rDxx49pJdMMwxXS04P43LiuNSmndCei2cQh +/7cho8YTbdgjKF2kVCZvYXBVsu7Nn834kJw7eMH6slU+VM45jTkOTr2uLzKWrBL6 +YONiK2xdD9NlDcTsX4YRkt+dByJEcDAuvprVdnLKpFXAOWDLW6e0o0siuFIGBtgX +NR5vA5llpOkladJk+j+dxX4u5Ql9KFPtD9uM05ik5VQCZN8pxy6On3GUeSdoAE9i +i+rtgZofs39mZOTxhYr+Djnq3WiWntV91GImwhqiXxUBI/fs91+yy+FWphpGORaT ++Rab+cyvauBsdTAoSjjd5cNXXsztfDxEhLnZ1yWMQZxVgV7tcLevVo7e75pSZrN0 +/gMQAH1Fcxtbrdzg1fehLiqTEWp14lFyDCkqAqQ5C9niCqwyf8+6Axaukk4ImmP5 +n9eIykRezLizjA+GCe2oC1jXpVEEYVzOJpbBAwZqk/jlyNd0m01URxvhOaW1/M41 +uWDeQp7ljJrtiyMqD5P3STGR +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem new file mode 100644 index 000000000..8b71187c2 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-CBC,B23E9DCDF6361CCB + +BTPCHNUVRgsKo1up9Ktshx00vDANb05S4S0LPU/wzG8sj60db3bX7Uzr0PPy7ShH +1zPv0PECYla1dh9nVBPOS4EQE3uHyzuDMTg0AsiR8TpysuI+a4y8XJeAhkU1DTD6 +YzmaodjbCrhautYUCzvcui/sWWXTUSWH/yrFOxaaxLpccacCssGlPc3Tmr5brPmO +xaZvO32ii6z7WAP/WmyRoYH+BSqmUBhObolifBD5kg1ilPfCk3xMtz4lbJRWANsS +r6YWPwo+qh1TIQWw40Kz4oQOteVNiwh/dvYGxMkd9Gs4J9nY5deKYExoWlYcci6N +VOrGA6HBWzfFx/QWWGK77xE8yQ8HeeZUgkWwYoSyAmxjPWgCj+BT5gbYV3W9E6UR +T3lsKGtI/lMW9N0DVcLdur0lLIBFiVbzxoUAL1SteLJ0mbu/Vnk4VhI5z5mOmSxo +bU/HElXdjIhk7hdTU5PMNSKiAsxNh03NiPsTpEASMhz+oP8BuJZh6Zi/K3qMYH3u +6BYmA+Ua23fFYd/kz2TclVwiQ1HQjO3+9l0aSgLhHFb3t0spYbx1Ld5+bAb8b30Q +9w/fNab1mB6hFgaqruPErfI0K8BZ845oAiakZBfKnTRQxAlKNY5gWvSiPDWlkfIb +uSBW6csh62iQM1/bcW0voR21NGS+WdQ3eg16vv0HMhmEXmEvtAuCGb6ZMqY117s/ +VciBymZzwdLKFjCqrLn6enYrT7uneOoq/8PaXD1rdMuKGL4W2LqGH+Q0RU+1hyBJ +7ipTQqystqi6HUU2R1/PI4K73X0MMTB0Jfkd81S6GmjkMYCFCHmHXCdNULjbjzT4 +gppgVW5joIbLKNPHJ78lw4BuMxcAgptmtQBADnWZQNF/pBnIVAY/pdHgreIBTQ7R +KL1/ATp3+gtGd37FOGZilhq8C4ML+w18M0iTUUfGg5svUvmtw+NpNWMijTJpu3Uo +KqjMj3NbwCwu2b9qxwalC3qWOgAJf4Z784+i2GOvACk2Mw2QyXoZV8Qm520M+idR +rj6DIfzEf/86TWH9IrGukDbJNB74QHgdXd9upyt4sL6uHMxPwz4nnhBB7I8B/Q59 +oB+3CBpYIANihDscUbiNSsw5/AXNtMuA +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem new file mode 100644 index 000000000..8372cff2e --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-CFB,A39496D20CA5F694 + +A9ZO/WPm319cQ3hoxaEsmuGVDkMVhCuRzFfSWC4hVBsxKHd3FIw8xZpGSkEI7+aL +cMtcyxTQn4jVV71Sw3vyb4N1+2i+DAd+63l8LztpTBQi1o2gTBqmqL9esV3shqWB +JV7uyOi94olPea0Rf5PMRXx1bAZs9U0TV+5XHAQxM04lXRJajxiN9LBZ1OMRiUVu +SdoHdXh077ylUQmgDaGQktWYuVH6leq7Yc9CF3nre6njFiUrpk61iPki7+/FgWzq +vToqiYaWffy+1lB7sXcL88BtFaMWAOV5A48Mv05miTb00VbJqdKL+SDmu6j2Soxi +Qk3k6Le0heXFHqqkURMKOrr6tepqKEjmy8WTELwMnuT5vNngMqDKpNyhdsIEJW69 ++L0imi4fWIelCd7PMI1bbPAp2QsB8Rndjlfj3irVm0AtubL/rbep3JT0ezukoScd +wLYNTlDdaLfEggry/1kYvPBMolU4xqDxg7C0quwYxLuycEFzU2QmWNtRn0xkfx+j +ruApr4getT6q2fJznW7coiW+OE9Ik7JgtYUGEZuWFUeydDHa9PiJ34w9t/aw50Sk +arATzKH66zM//g1zgzg31SmziKeE375skyQr2+1S9RajmdZzEUDL5ajsdrbALflf +UPQNr0YEF92DRHsI4O39L/+k5fesiiU38u0NoKv5DDRb5T1lQeesDZCZBowQP5KP ++6o6lnj8kCeccpGX/eUukPXFl6mdddAJ/vLptHC1zaRp2dlKPRfedZkRm4Wduplh +vQ+6oGqkjep0Q/LSRcVP69m91CZot86lAn9Ct0jfJu8o7Ua7KBeOB2k/rx1nUaZG +BOjHQRaSvPA7FVKCP1UlT0GR2hTb/VcW3UQJ7fCY8E4hc1kPfoa/T+mf0JrHtlMm +364YQh6KLgcsgVjsPBXnTN1+POH0Qy0xp/0VwQIQFWKwU7gsXprfs/uYx0uD2Ev1 +w9kIWLovIGmBh6HKptqTnjtdwhqueez5kb3MkrCMi3kqVmV1TEQoklz6eBbloXbX +SyR5jivLmuaoCJOA3oQ/A+75bwcvUP4iULZbdTpM2rnURyljKNU9Hwxim0neZ0Zv +4kiOZuhQKkGfj0gv5bRkDAZC +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem new file mode 100644 index 000000000..58acd6f7d --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-ECB,6105920EB281329C + +ungL+71R1VG+DP1CKuROEP1pESqlLeGoX/vupWbGTWR9VoK4v/9e1Bh96r+hEobm +LvgsV1xhWrnyRMMw+W5bSJCfBH627SxqHltgxPhyKCNAf76cTIAdxxXgLZAxjtJi +mjuBDTNHdJ8NiAxJKLL6dr/hh+Vt1Lk9Gr/x7UdocQnhxG+IZLDSOFdXnFb8EBtK +kmAXXyOL14Rerywi6pmbxaculi/CihuFm4u6GXvunFjtP33eObzKLRub5ktbCtol +97rbDoAAUsPPm4efu6Fs/3CE/BfvjUf+cmOYu6pIKQil9VHtxXloXwkeykI9Kl92 +uZVT+e9WEn6oZslAzCnjT/r69+V0Bf06AP0zkdTK7lRNBhmcR9fAgHpxz52GC2Bt +xsqEzU7d+adCy1M73tT+bA2RBUnbA6BoCDHkvtmZTGV4mkAv11tVxU9Zqeglvi/w +6QVDQYo/b9U8GVkQFo0oh4xNaAUNdT/i1OIy7d+6UR8k1S9+r6SGVwS3er20trWN +8mAJ3dWiy3yLreggSqEvwHSpwrUQP8uxdTZOlFAy+xmwuEb3AgT4/sHQN7sJjAN9 +ISdzp+B5tBbM3kQgvEXUZckVykM7jgyv7SJ9DoDaYXvlfOVFo1oM3aWf57DcB8KH +WIV94r4USVElJERYHH9sR61YtTi2lIi1zuAQZKCf3ShJcgU+vh2ZZ3vRPQhAMXjZ +0Doi5uxi7HK/MVenO1CzNmsc6XQtyTtONqlJVmBoSq3Il8phMkMXnaOeNrQsT/1X +PzbQ6MpWEr2WkKsQn5hNA9b8BIZ+cwk9zeFbhwLH5ewjO25BWJkFra4gGFJl+HZf +vMNFjlnxuMjqM+Fjn3YH/O08P3nF/3ZGezqTCV8OJigB4Cdfbf9OrNtJSvCVsH1q +YB/3+KOO5mKObH0Y+k1pvwZsXMkj7exAEHh+nFLldjo7tBAycqUHK0RaZ29TOjqH +J6/4SSzMTJL5PF9Ayjtx0Vai4sFrjRGgnvdd8tddA/bWq6JC5i0yWIWjCEu0+b1q +q8EHdE39+gbANJn2lKsEAOOt242bsjKR+bblijaaEgZXHZyALOThcEXxn1RaFFgC +4Iv+DftZrU8lOiEvN8w00K6GDy9gbByG +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem new file mode 100644 index 000000000..2558ae409 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-OFB,56A8F965C6533468 + +91TyUkVkBxdl1ZXkXezMngH3YsE2cuXhiEFySx+dWZqFWcOQ3S6izXXqvk9B5sZg +O95SFlZ917dU+SFACzB8dqwYo0QmxvH0zaAIMBguuYib6YZVCd8/ElX0vyEEo68O +9V856HAks6w5WZk4zTC/75skb3tdLRWgG42oBlXHW7GsL6y29Dy3xvaWHJ3vpKXF +HygbvR/TiSzhWj/jJB6V4kCQAAm99yyMxpmo3e4Wis5AwGgf9XyHJx0gUCeyNqez +i6UJMGnYsHl1H67ltpN13trIXRcXTUDhFTadRz/suaR1R8IEefkpsnBEPnJwBuPY +tUQzlolPKuwbPXFukpJrhi7It7dLsDsw5DUYvyOnHkDXJ4vFAIplCKdG0+KLaYKJ +pXI8FH6X4M1YbIPTF+k1dhCAz7Cz+cEBA5hfJfSA4p7L6f9NBPWso3DDsyAbdPx9 +JJkVPtu0ofZHzYuD9nIhRsXjK9zaQXU0szLBdtGw7rfmPp3ftXeBcXDnO2ZdXL+j +PK6CJm0ktjnUMKY8gpWahUUfImwebQ8+uQYv+NNn61rtfCaGQWMStXaNYgq54YLs +D5ImRdvWm936tNUCeoik0yhPVlriNC4gKswRSUxD/nNIetsPl4FB4DIS/W5fvWZf +WYKwW1UlpC/HagbUVIuZcOrAMFTG+zLYS617lzZh7Y7K87GJH+jVwgbYSbHHFWCp +V215NLfofwlV5pFwq8djbeEnBhKi9SbGlZUyaZKKyDoIIEnwaxg8BoModBEWHyWp +OUmw/v81TQu6RwJYxl1C1U9n5w4yjtXr5oowgu6WRYXwWXZtevtLkHrhcuWt21ud +Cq42ojFrb0GqIcYWDXF3Wjp4nLZ4pIqg5kadpJpcFYx+fcL++Jnxs9l8Ohqwn1br +/UvY+gTmTwnICapIwovVjN6p6cT6MAok82oemWPZNPYXVwVkGewCH3DWqfeRYsdg +6gDWeIwyk2Eqn4bxFz40NrNZaLqcmQPaJVRReCV7Y0jQuQWqSYKkBHgFodf2GPMg +DRqs7doN2MW7Is6qjyc8CDDzPcSuaqUz0gzohupDfD1vAtuoC0X6U+m/8NM3yuE5 +CKE8rofcKcxmFAr52CUUsJBL +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem new file mode 100644 index 000000000..f6fb1c9bf --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,7D7F5AED62DF7398 + +PvrGaVyP4qWxH3LR5bOjrjTZN9KEZ7eujPyBYWV8pE7+kBc01RKaHuOfntMncXPj +cTvtvPq4z/Odrme5s5fem88QAoxB2BqM0VNviUMcCcAG+hgsYjYWjUDdSY+piAD5 +dhPcTHfSwgkA16c9pd+vNojdDKHEXzIci/gdrkJQXi9z+Orfb++NluGFUjAvQNlh +n+wi72AVwFaSPfguwAtWAZNmL37dZO8VzuCTkhciHaJSZFtS1G5rLBIo4JzW6AZI +PLEENN8fE9C60WYkfQB0PI27ksTS2xPF2b7MeaBwdPRU++hwZ2QwXH7nYlCWn522 +8wg3/QWuFIMdqtKaOjjlwvQxApV7OouRCxIFnolM8HvpZ7HvEVVT6oqcsJG339FJ +Ru60QxuVsnz6ykuP2OoGTtGZNYo5cgBSpXrpUSmOp8HHblWa6+FSatNkBf5MxJvv +pMRxcYJ7ftFCGgpKI38GgeBPkpv9Rr8PUplZlgnXkZl8trhjb0hzAAJrMqPkMQ2m +rOgsIWF+gK6MdnZdSnY1DktPYSFCkfJt0BZMGBDXcbr8RKHeV1vJNWAPOcmTsV/y +nwzv9EA1KHeMnT+wQ54q7jkRtDLIS+zSWt3qW0fJQzNR3BrMBrsij6GfRZ++PL3v +4y9D+cDFVX6LMXUDLK8kxZ11A5rSuL4HROtNnIQf/MItKNK4Y5c4PAKAMGLQpPS+ +5dgmKiu6jAIKUVT4BOEjMJ0P03JZKQkPxVB9GgLQLGCq77vz6NaTWhJmz+qTdZoL +JCvAAShdkVa5gl4hzuvKnmY9VftsPVlOUthuO4NYimnjZs6p0sXZKnxQ4J4BpbkX +mX5Fs6RU0YTQphu2v+NFhcPpYwRiwn15CVUDW61Sb87HZ5xAzwQrlpFY0LI4TqE9 +6ITUYzgpVVAlslKHNePMcjTj78V2MImHlq7xHSVPEGkkPlsDWxG0snZRkmM9aAu2 +g8kqf8MVngWbWhxqXHA35wunnaBhpBxAgqE4r2yAhyfCJNF3B01zwjt4LeTnduj7 +1ZA6EPechsSQUGQNGBoSbO5zVbIQaRZvAl2MwPU1YWCCbjaiDDRp9bHhX8vQbI/v +4TRfKX8FUSai83qORQ+Ncshg+gYkeCJc +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem new file mode 100644 index 000000000..c3af8d5e6 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CFB,6215481F0FAE54A9 + +4ZA2xcGT6hS0kQObPwTWmluIl2wTnoL2jRMbxrr7usOZSLYISprcATZWieEKLsu0 +kNNzIptFCmRDt0b8VlothTS2jBIh5nlu9LqvaUlIrVuMEn7umslWrLK8JWnHVKOO +dMfqNcgmYlkbEfmmXLtlCbfQHT2kVlopD58yxf26FTQ+27l+hSX4wn2uD+xFUAcn ++9ZxAWQDhi2PYVKqTTPfhCPaKW7hjYdocADnIZg+1mhH++8fPxlDmBQBmMOid53Q +WV9LI4Fps90d7GumX7qSUFZTkBKN3v+E2ahnoP2bTBQGkqWamKFTc/4uLCEGlSWU +qXaGCy1AwPa9As1+B/jLkTstoslJppqvOooWW2R1o7JHqN44luXXQPZ+BcA7dSdf +zRcMCpudB0AwHBy3mnUNuBlUjsf4rEpq51HPSS8duYow2I127uI8m8OCoZCaUVid +msxVMSJIiDCiBi18EfCjMfGLtQVxJefMv2hmcAXQXSRDJTEw8Lrtm0Mtp7XK2B0A +v8Kqpf3x+VBc770Xoy0K1/fe5oLdvJrJOLO5PVcVXIS9B/DTqIQ8ObABJPZ1sCKA +sV8XebteS8fNXmFrVKBTmHBpUY8H5Z++VfDtKZZUBYSOqbFT+UU/+xJKlKICzFTo +YWsmPTgFsu0Z7/PMyg/rccrb9fMWRXa8et0JGoF2NlYu+lkRb/nYPe84oS8RzZT1 +dtWJMiiom4xRgENDhV6/AmA9IuyXT3QbDfFB+ntdyk94U+Ms0ODNcdA4JmEa/f2k +zFjtEGWHPH8Quit+zUt+8JnWSSFp0mjyA2ZtEj/6Qg5rqAZMdlpTo7rcuYOTHScn +ic/H7V43SuMlRAM+xx1bGrNzjWUugHrVb7Kar56pSRPtSOQ00Dmz7gB8V5LU63n1 +YX3faatiPUNRG1dArcW36o9dZ5x8O5TErPHRJNYG+96UNoAzHMXoi5thuRyVbzne +FpOqgxsryobcht7fwHuYgUq92QoY2qG6qMwHc2A3NrVFi8lJ0R83SN0lOzLebulu ++zDvrvkkRyH14uoAWi/o5IGBv1yIkO9vYApntrSO2aLnbevht9MuDJqW/Lkb579Y +LG/sVwxTmBT6jdCgTdpd1ExE +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem new file mode 100644 index 000000000..d17a90f37 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-ECB,1040C4105685E404 + +66Uasevd2pON2SFWljlVyWqmErfZn4XomzLHlUoagIwnQUEgCBCCpUscES98fini +roGF/iaY59JnUCMieugke7/GZF1C0aXbIReqds7S6VFfu4Ni1OQTkL4rIauHrWab +vgoE4+18OlWw6Rc0wwJ8NT/NCOmb397yTeb0w8VYERyzpwSLXxQ0BCOq4vOUX7BT +2ABX0moazjUSyTO9BQZpABF2SshxaWFbAc3QRwH4QnO1bm7Pv7b1rvjrvPZ9LxgN +fwjXG+yfHFBBojbEtFvgXRsSSyV5WCmAgYLgk5/nIDFSnRQGty0OuP+itX7SUK1I +PH/ZjdIwezMKbyuon9D1AvdOEC1xiKEdmJCWSokm0djIVNmYbv4dtfrQE6hYdMtt +C0LbsT7ef+jl0xG3k+WK24OsBVhTaqj8axIPZIVLELOPlx4EMfaFQgUjgqf5vPhO +x6RSSRy+poFwtjI6ip/xu7ygqmcY9COXCcSffk1vpw9v+6WcMaYmDLwBTrTCNsdI +7i6VJa1GiCrsn5o6ydGgdRNkF0N0sUfGnSzRUgd3BGd/fvxhBmcxHUnr8srrHYm7 +D54VL0EUsP33F1VF2ELl94GlWqfAj8NGBDkTbpUcqOeL/ERxdUWfX5IEc3h7fprs +UjjjQ+d3GRliRs27m4ZuLtGeDEhDtlTC6qtKyqgVziPMwG46tcqyFzhbLCErHNW1 +07JcoDRc1LkXImSeWgjjhskUX8nc2/q5giTVtGmiWMQwEc7aYQ1wPbVAIGPQ4PE2 +XB8zvvPEaj0wXs0JjicrfzUBo6cRbdfmWIfp+ZoTUfr+gS/aZm+VYt1G7v6u7Qel +AtoSdpN623OvqIP5ZDjOKROmAdMbXkxwwusVNQhkbdTzDYNy/yJnJqUUlhsN0VTQ +y+O8Fz7Q7fEYIk8Euz3Uf/BTVGbLSNSA9n++CJYg1nam1S51WhCXRDckDLR0c4C8 +v3zpJvaQYW+xZUmlzrYRQgxkfzv4+j9W+kZLgvitQizXfTsuDyO8gwIt2csfGkaL +EgX2+oITD/sGoaSoGknY42ePI3pPXHlhBjPq6ZWZ7uh6Ia90nV1j/PAcOEoAspAh +pEdIAkFJA76qN9JBnK7lRMFXu/EWtBjD +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem new file mode 100644 index 000000000..2d36cbfd8 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-OFB,BB20E846FFFBD3EF + +WeRgcZKkDTSxqvtZvx9WwUZYqXUUpY7siLG1Vm5jXPaEFOEQhmvGuNYn2cwwUYKD +RMN5+sE51urDgI/xk6jdS9oZE6IlfkGeQSUoEOOfPVyVD/0/E2G0QTcKAAWB56K3 +setBb2ORbM2ZhetYUp1scaLObMEMQ5LrZaqtA/jUd2Pbs9D2MqafEH0Gde8e7mXy +1fGNJWlj8XtAdmi2BeDKZHx5Hu0r/BOTic++L0Sv66wbjHw7RDji9Rdv/vyq6DIi +0v0ZCexiNVed4mqD/3+8eGQ2z02UD7aZPy6T7E+b8kBuBi2ouB4HqgexVtz1L9x8 +VBBOBdpOLefwCZlNaeceg2kSIP9mMK919hlH472BO615YB4ugaCilUNLpvv9T85K +s4hTB5oDcQH6W68mz44vWqSwED8JcdMYvivWY+3/zBSUvkyI8+8AErnVr8tvTX29 +aBhfegKV0MbRRRirj/EcxhUhtfgbAtllZ/Wpo0LWpIsHT0GeUfWdUerbFyh/8Tfr +OQzC14xoLHdACDz5IDrLaLd87hZrKDJOELvzoSugg2W9NAzGbfoWJGVlvZ0miZcO +teULyYcK/A7Wcba+jmFaXMrKVhNH0IuGcU+Pf1lYcchjAsdnrFMVRsNJ99QWlN0F ++dTyRgaiCInnmJqT83fI58dMmaJPpMeW26jItPWZWAA0vlQB1RgZ8C7i7V4keuVc +0PYolX8WpLrrpUpJKOTdW6rmeHokJC46gOZoXEwZCSKUUgreROLgRN79RMBHKjoj +0vSZWowgH82fNWYWQbJk5z4ldulWEVye3tQhRNsZarAWPFEteiKDTSkawmBpaA6q +dJWiA+EdrVvnNmw5+xkbciMX0nj4xKsjRgPawdMFZaZNE3xu2LkrfGKDa1ne3JdL +nDeyygGRDsl93oJ799maHaTLDyub0CMdyf2MssPLFklJdxwbtxNzbI0gt0NhZu43 +FDg91Z3hlAjg/Q2h1dVM22m3pnju2ygF11HUQdNExHlv5w8LWMeqWQ5j7WhSbM4c +s2v5JURZ+jXFEf3jCs9h6pLlQNaipDkUQA/6DKHf0VbZJzKxBiRCwSP/YuQ6H3yP +dHGRAd5CQnNc3Vv+yyRqQT56 +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem new file mode 100644 index 000000000..98d36821a --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-CBC,89A720DEE88FA71E + +ozUacsBZx7E1NCxbVYJJHQ0VTWl8RX0z/JzYNP58zcCIi3Cab2qlUshZP+Zb0Na9 +vlHabEqQCGsP8uLzneN6LDDaLmf+ucxKvCRrx5h8wl7DQcA5cAQhGofZuqChPqLj +1lExS4ZaAi9lRL6aZhf6rgI/apkj+9Ky89sOqJxNhj66NgoOOh9XH1Uvrffv3jT9 +RxeVv5qYcAgfX4aIAM6KjC6iTZ8NyWmIoc8izYQycOsSAn6cqtdjmyc/264OZUd/ +1Tj5PG0q/Kinh9UBJ2F+pQgU4pDlWczXEIwtnmJ2mWyHBe2zuGWtP1uQFUIfwkEz +KDTTFB0lm/00Xts+vGXgy2q+IvhqlOXfCkJGcP+OArLoyE8cu2xU4KS4qXUITSr0 +i3seUuTrda4aqrfyjNuM0tL/cUSEuT7aSlKdqSmRtYl9fTsmbCbndLKKuDJnxUrB +ocXfuCEZNMQ/q/8DvwIX3l7RRIiJwqEg5+Ue/s2FTFJh4Iar/1gNQSApwToFHHhV +XOU0pLY899B+1z10Nop7ELgJEKBK5+zMMBhB2t6nlMU3YojAH5qWEPa6D2Wr0Wu7 +x4DHqk0wEB6cDZ0PZGlWNOBP5bDB85GehAWKy73A73wYZCi9eCQnLh1Zjcjl+6T4 +fli2K+944sUKaUnY8sVT/20aXm1CRqNvgLknZMsg/eGZWX5F9+Jn/MviXmsH3LfE +6VShEkNTFEsRUqF44Tvd2BZ6pObDPRDOkMgapzqdubujUesvb7LU3yNCRPBPngRT +ZTXQynnbH0yfnFm6+0BYWtD5NeIzILwZfS6IRMSsCBMas5rCc7O2Iv0yhk/8K0f1 +Og1YH7pctbz1oAPmN/EgKZ1K36GTt33zfrwHpmKZ0jOWF90BQMgZ9dL+VyOMJYjL +MiyetxwDdiP5TUUAKxXdr9t3AvxVPxL8aVjLb86kJ9HD+IgWUDqiROe88sD30Vww +7R3sQhhl7drDGwUBj5MLCVhtE8Uli7HdaYC5CvuvlCAQN871whhk2gN27eqp81ou +RB4kNaDK8qSn83ISnueg1jsQhUGy6B2Rx+rePxx3QwDsrMGf/u/tFJ1VcLlhmOJa +svVKTMq88OAnZA1Hg6QlB03obSF9U6lJ +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem new file mode 100644 index 000000000..edd5d8b3a --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-CFB,AC1BA482ADC9EB3E + +tPu6t71kZlKyKaRiXgAMCmyxL/P6dVH/sPVY3KDFI0FsAGoPZaD8s7BkLLOy30Y1 +66kmaaWiaPjQN2g5zMrszrXh4AXazrjMrmIJ2NksNXz7aiySFafyYjyCPA+LIu/n +KnfoE42KYEmENgMSUV9sh/nlwYS8I6LWva384BIWaG3qnFgfZ4gwgiI/R+1/lPXa +olOpnI5szYMiV+som2E+I8lgd+Ahf2rempMnuwyWTDmUvYWwst7F5bz9XbmJyeWY +HDDaTPy2Q1yRYBRvLTm64iA0J9j1TpJnSNm0uIRTVOEIZfOwOx20tFjo7RREunAx +mEm+kmn4AIYhw5RQE5XQQvD42X4MLyc0M94k5pQHvgJFypXeJ4VsH8pkd4bqfy91 +qiPiKdA7nWnbedExwiwSPOhjOLkmQrXjsMVmoqqexhckJfmNOaXYtnQ8cZc50HjB +6ccsjyLdQbLx1KT3e/NgfH4VxW4/hbbt3p0HMIxTnwt2lNG3AoKmLlOYSecuA4PB +EE6oOauIKyJM8pwMV0hfBQ/MUQOnhHG+dbTn0kW91fRZiVPPvJiJ4NmEwD3ks3jM +pLYZRot1Cd2ksJ79G4NXDFakB2bZ8EwtlQUrQHwW/ykPwiwpqCCha1PUzgsmG3hK +U8bDWWQMqXtpSmItno1mF0H2TZzdbLpRAZe2lu8/mwww1qZfPE+MLPnCp050+BCw +Hbq8fF1WVpJvsE5CKzi7Ll7bSrJ6BslrlzL4mFnnGmuz/mbBIL0MO24FNyVGKQlI +hEzGu8lgp53pG4oSUZ+79CWBkn8mesk6iEOWcFojLKrlhnxZ7mDxBYfDp/2Bmna4 +lFt53zmQHJeYiO4J2TEXOQxvDWvcOK/SnAoLXEhUCRP9vTQm2Ahj1QMmEVvEybOd +mRpcaJXUOgirS7Ulwc6ZhW7MoFFnS3UluI+gS0oXRW6hCm6l9poDem4etU+IsG2m +4k6MoMLrak9lSheB1uL+xC0S9k20CZH0X8Hj5atb4R7T5+lTle/fVw1RGdfil1NK +/ytD+CLpSV15Z6VGVGlzfXTIXYgCIgbZpFxOZk2tsdUm0dPBjR/ZhdUh4ofaxA8K +jE8HLuW7kCkvmEfdsJxuRVVQ +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem new file mode 100644 index 000000000..35c220f7b --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE,3D3D716B17DFBD33 + +XDCVsv17xsOpLWONR8xKRYxnxvWs+bdU+2XCqoqH+cM/vR4+g4lqSPSAco0/LkyX +q0/C7/BE7mN6fzUMiECYUKS2c739CBVwDJZJBVGbMNFexaQRmlSxqhmbQ60oalaG +HZfpCLLHQvrOZ3O82aYuEfsbqJTEPkGm4lUn/5psQwudmu4qyv8GFR4wVpNcg9JB +rDzesxi1aU6dgHSlLHrG5ot+lAITh40SCBQdwkcvixyDIi6l4FX2AyNrcQYmFGp1 +C3XaOn74ADLyo31Iy6rCb0KId6J+S+1aPUW2r1Xb6irI13/QYzIe8/fDfuyV7Ofq +BKtHdu/oIfzl2X8BkuxJ0CEFxyyEE9majfItPnUEjX0Sn2PfOEwzq5LYYExpNuxe +pHr9gtB+hSXC5t1b6ifv9PHErMNmBLdgLX/FT4PuL6URrn3LtydPcfW6XMkHtGgH +zD/nnn8Kl1qXmkRbWHbREcOJB/O/Q53UwD26BsX+Sjwn2cfsgwQvZFzvmq/RwsCg +Ej9FK80Tvn3ce+Kdt7LGUc9+KaH1OIn7qLcYu0Fhid/TzPCBPQffxpUJ1HylDaUz +v1txJe3C//rg/42e5GUlKqf+/nzCmQeoaqZDG+VU3UKlngIYitlpwEq5fq/E8V35 +JeuHzFjYj0k9VNsOHY/4AqmEm9qi1yxb7WGINsysO+29RvfRD1bm2Zqhi/Mg7YBo +8K1GowhW6uGFf+VCPORihMIxoT6xBU4xn2kX09EKrVdekrAi23QzslZXM6Ze0fxH +7LlktJwah4/QFHwB5qXwmHq3lN4Nj1id+CElVZXjvbKvc4+mRd7VSn++05IFjTK5 +2r4FHifwpkGASJtVbF/7ZseaoOz9sHARx/MFSUp8kRZjOCzstWj6I0Fou51BTtRn +1ZCey4e1eKVnV4F1XNdo27Aw9aZjF4Zn5hZfUPuUYBwN3W33l8FXRdYEoT/JpiQO +8LS36SSZGVA0c6nanZoeDZsrPNtPJa8ANHR0QMwBDOwNr22uuJEG/nLvBfquG4HL +Iy7nxBebe/0MXvsxK4OjjDzmYQL2msMlYffOABOVLCbtaPC/HBKUcmcpZ28WAzdN +ArkPEcJFTgzI+hCAVG//uV59MkDnUZ+e +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem new file mode 100644 index 000000000..d06c31f16 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-OFB,0472499818A0CFA5 + +A+t7NfS0c6IsREc9+AzXRaMGW5GR2Ao+WBBxXdxNJZ2n6DWTcNHYL1VZsnVOoc9z +N2PBfTjYQkNtehp4LDnypbooUI8gJ98T33PLkJ0/L03fs5iEiULcrpBLGc9gsNoO ++f0JcI4xNfE7bGvtveliBWBsn6KeCdwrdcOXziWGQCge0pftf7m4HZ/t/0ISfjXK +x3ftgiwrvLSnCHfp50xXdN4FGRaIj/V+C50efu/hkAaZ4rCcTxgEcvi+TKdDjmcy +MfxWmUmeGiT0MRongCZB7XH6g4sI3nwiDASLzvZ2dBysLD0wOhR+g8yumSH2RW5V +rTr7JQANZzdZm4MpOv2fMCHzDcKEtPd+OlYMHegwE3p0y4CLeYByT4IdyKHVLiWx +lwAKtZ15VlREgXqBIgrtG5ooEIIjdlabIckAhRc5yOX9sXsMePRyPgQSnG+nSbQ7 +6Y1l+3XueWXjsnr6SIXI5wbszM+TFbZAU6d9tb7B63R8ancHHSUgAbmSL7QpYZxD +oNYseUzgPv62oMbX9VxiWJ5ZgwzS+D0zGALw3Tb/YVTxI+/VZ58ITZ59I1cg26HT +H3P1thNPIee0zz3zewMdILgQLh5RWkJhn8/oawDhVVPBba72uw2nGF2aXwbLWx7G +eJ94GeikGHOJby/J4G+0D2lLlI90jP8KB2fVqHxENGKSMLjZFERGvpiPTgHxWcgI +SS3ORTxuJDzqG3qFfMhFwQnq6tbOsny27scEQZeNMGecfqGLWE+oclqfKKDQDm11 +JUQnsnFAT3cNFyd2bKefeN9co9NS1UTUw1m3gDH29kwmggFLwSccTFobrIoh5/le +qiaHdEdmd1Fvp2nMAVufwmb6G1dizT37benyr5Gzc8CHZUMibFEIhjkmG8RQ4dyb +Byai6j2gf6rzsbKiVtKqgCgMCw5LG8xypzitCBc0+DsYBnlAyS4hXYm41eqMtMsF +vrP5uS50iDbAMBjuIpWdlRewjxEqiLPZofjbMGwbrvDu45LQ76rwLww5OUj6567b +FJRcXQdyt/bWqB47GnAZq8NABCtY9HG77nTgqstOqYOOsdkuZC33JHAwTwa+b8tq +2Y7Zo35CmITqLxfjr2IT5Yeu +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem new file mode 100644 index 000000000..f73edf131 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9BF24F7ACA100D50 + +71AQTQlq7BkcUMR0+Ghc8O2ykT347aaFUD9BYHXBW7SzEq4th3itEQQ4QxflbgR0 +2XZQE+dNK+s891XnEkf+8ZIIQc4LKr4m3P1t8UeAQvMbHRfAQ1u2/fMf5xwYMqsW +BscjoQ0lFOcb69nb24E4taRu+MRDF2+eah2hlbHGbsTezIm1VzFRX2C4mnWyfffX +2WyJQPlZpvOY4kkv8tRvW+nbZ0P7bRjjxrSbCeUVI8X3m0fiCJ0fMVg1MMaj8JxD +AgIKBBIJV8SYRw3NqiGk/mIlMq4Qtl8PWEFBRf30DRD8RIqOO0yV9Czu/u1hcmxN +x1/ZExbwOFAFwE/GU+NMegFRXC4toNIU2Xo1C84URpAvVAwwe6SiqWFTSTEHnRu2 +N/tfJlaL2yFrfRnp6mcNN3T8Rk376skXk1zml8Deh6rNU254yK2CFRgm+79W+CeR +Gb1wxDw0GQ07Zr6/hNBfpAND4qEdyxYAfJQYOCufXiFFxWp+99TGKN4T/+Ab5D2j +zKmpYFPJj2vuULLPGIJPnCVNjM5v2KwbFY/95Jh3JEF255TORfj2P6HETcjZr0pD +TCk13jxgKs3mq98Vr5LGEJ4nUcm4GoZayIbeaM7heJTWmvQyP6PRZIDWi5mHs7K2 +wGUrutGZcxzLtaQkavQPf79xt+0CI9D8Nuz4FrKMS2ng+rWLzT3be46f6hJaX1KP +cy8RLQfaWpFGBPHr8UKhicOpdbGjxxfBUM7Jlg2o1hQIWmSuj53SygZ/EQnqBV7E +GG+Gf3RDl1Ab9ncOr2WAA5TOQ/yVBEYXy2W3TDmxuwf/fWvwF2z4DLq/J7pieEM1 +b1IuOlcDWNu6eKAhsrq0t6I/wYNB/7qOmIcMxn1dzDHjic3uO65IMH2swXmk7tuZ +ExdHGutPDZKYG3TgMyMYk3W9YeoEZAjF3TodOYNpmtaDmftjIuxlaYzmtkQCFHGh +cRlnPXJwaExSYrySX+1zsuqU2QaLB0AyTlAgkUdiLQOzfmHtiHt4Pgyv/o1z/PgJ +VTVyu2IFh75H6CnSQGgNHIH6QGN3mcMIZQ5G0U2r46X+7+nnodOky09H2Gq71nQf +vSk1M2ZoaOuo437zG8SlEuPKimz/d+PH +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem new file mode 100644 index 000000000..eb957ba43 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CFB,DDDE26F919588654 + +ulZ1WOcK/yY3ugpb4uN9s8ejFImurz+p4en3zaCfEMdv93V0JT2T/49e+OvIMaOz +4ShAD3AO5zOXkZd5AUDI5Oi7mMIH2sUmhiJ+0xZMWITbAduYvt69lCGFchpQ/YRD +G4jT1PY4WQX9o7nN1EYyPnH/vx4Rk6lnOZz7UNpK51SBSBk9lkF/d3bH3J2+pYaN +G8VET28OIVTs4nqNdu8nxoE8u/Y3aW3FVsFCA/ZhmBD81Odb4rHAHCqJl00ApW91 +nvpTkTjfF9+EfdOE3mfLA4R7CEVWaqnfzvNrVCOILs3qSFGKbIBPBBBJbc4d4pEm +G+8g5gimV+oL/Q6njSi8s8yV1WWf/nqK6EKd2JJglW700V8dbGHjhGChNTM4Px+C +RfTF+kXcQZpcsax5ULUz+4KKD2Ub5EcWumg+LAe36VVTz/zDTxhTzsm0/iN68KTM +jzKjIY9PkVIhZikVkp4s8pL97rL9Tota4OGMacPx3C58MSwJSg7fdUehAcnj+GC6 +Nfi+iHxVpJP4QnFi4BotFxlb2FoVhoh51YdaUehqD0IsoBxrQCmT8nVaz9asJMCY +CRXNO/2pUpNJY0iGjHfvdmT/aRf+gmat41bX/1r6Xxujf09JF1iS5v/fpYQsshZc +N+xysjZ8Bps2Kx57XSUTz3NrwMuliJgw6ZbDYBHGSSl2lueUanNArE4iLakuf5BK +zuf7iVNTZEww904RhnA3HnivRH2b+Q1mWxTezSYZTs2Qr62mJ5ewiFjOlv6hPUfx +T8/ka54Am8dHsgc3LUDK4pFFR0Nk82yU52FJPbGsggKZAde2tUnDgup6gNmzEjA7 +rSWxEfg53fHda79SQzrKaPGsuWr5b+cl20rGycqN54qZafKFah2tfCzgGdVZG+Yn +Wq5wvZK7Elmjz+URvKitFhw39yscj4TLlEQ3K/jZVu5/lsyyu3imiUholwMCSuhV +fg667XbT1qSw8KPWoloOSDQr60d2cK8Olg9DjfMgqmDxVHMuALB+O/dhJq4Jaa9c +e6ycERign27Fv6j09/aAGrsaB9gMXCOmMhYGSoBUptjb2dx8mN/z3fEG9ykvaDiq +i1+9GnfRKIYzfxTa3PCpA0B+ +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem new file mode 100644 index 000000000..1dc818296 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3,695F5DA31042DDE2 + +dzOyRB2M6CfzgilwOWNhrea/0Zt1EmJSCDPXO7kQz0LpP3/keHgFL14NqxQU6puh +gYn8TKE+H2f+l8xoNhT6kdRI5OZP85NlC/RvzcIPJkriBgMeLwsRCvhxg0EujRa8 +popm8yF2E8N9YPdz2CcrUW0mttVYeSy2YO/pi5rTJBeqqIjqFYjHPEmlnoNqboQk +aflRKFw/rZgsE4gzoMKR/yso/GmSIXj48h9G9CyLWPFIDi8LdiiBG62wxK1TDFDI +FIcU4KY8QyHSYc3DdYJJM2kXxvSy5BxbvWkD9cZS9+CuAvDyGI9dfF6g60f2tCA2 +AxIHRn78StCNbRN1xBfkqw0BremGo8G3H8w6FrdeS1rKzzYqAe3XhDO/uN/0aRAz +Yact4CIYbZgMRhTJh6YhWma9UfYtxslmTNkxmMptS2SvOVSbhPFSQJFIVWaN105f +HGmLwoRwV+Xd7nLX5hcR0Sozr58m/1FYun4c4797/bcGA5nDKQ9+u/GvOtqGhIU4 +EY5mkMhqt4MdDdKozQvATqWeSlESIFBZgG5sAQWuRJ9g2Pn1N2GTveY0ofIXV575 +WsharLOALP87zUur0E92LoBrbFAS7/nJ7T7F1Ye8ZoG88qs+vJy8SUVCrDjUqfgL +90YHTKvmq3fJ+DO+40pLU+aiRBPin65h+5J0jW7f+eGpJV1S5dxIYKW0D1+PgcP5 +URVYuN+cGWROH4DN7zyIFPh1lls0GtAf1to+zBy9QYUFAjt2lB/oL/d8RRso4rHG +8cUdXilKzAApI63nq0pKN2k9hAH5wGzxg3vWJCbsrXuqExsgZ0EFLR1IOX5ISCCZ +g6TKiLDDSFBfWKTsix169JzCCptFwE+u8lY1b0A2ApCClXeS5+HvWlC/vtkuqCKj +V51xSR7ltzosktG/gSc6wesbp0RlldK3Ee1l5Ld3sgoxFZd8aBuMVVfvqz0Li0ac +883Yr9+nSvc9WspdytrfjcbUxmWtBxsDtVqhuIM4eNusUPY/L6FJhfX2kgjc8RNf +MNJXiMOaTmQfVCTmKZDF1EN+4IZfdrudL+UoesTzasdlDXGKc5gCecWiQpn/hKto +6YwKToh84r1R4gDcQGM+DL6wa1W5bVbD +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem new file mode 100644 index 000000000..86f201939 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-OFB,BB994897E99A8F6F + +Gx0S/6H98EIJK9lM7TBQrFejxjBVE0kcbBTVNTCJCuJ1Ik0s6+OqG1OFOLdXJWva +M+k0WEWKhTAXtrrbzPiu01u+OVpIQ3xhgzt0rcU8UigfLLvMdqXoyuUTzCYHBraA +ByJ0+Z9nK5r/OAJkq4gnRfhsDajZgOy8rZAdyIui9rom5emcx1GsnpW8WdRCuu5l +kHEyaG5nHtUyZobZk1kNbkqelByCAFndV/eook4kycEytZWNPpFP+tUaXma92vDV +sg3h2qODMr9ElrbvKYujOuFoO77BYM4oxlE/WtWpD29hmxaIgmnlvwUI7HerpZg8 +DbKYV/8ncRolxoE1GqO2dM2nLKaNKra+n5REJBpUDjwe/eV6dwcj5Uvk9nocEt55 +3qtmPbevuXga9mL5iTN8dm5RgrkzCX4LBu5fB3WviuseUBAqpKgq73RCutNM2gDm +5CkV7Iar6tV+LgiUcgoo8RAnJbysFT6jQkGPYhABFKzdzrFFDDQUBpcLo6hgHpyb +uQqjVXR69JFxdQpJSuc6cH60jzRQOvgwpCzpRiJL0mgXNXv51K87ucEzM81Z0UpG +O4GYnsbo7PQfeLAE1PjP2B3xj8kgcRxWbHkQ/vIHTEAtJcXmAquULi+mNKAFb578 +qlBs77sLICgtpqBUzfoiH1ozcKHOJ3XB3yPYt7WKIxn3/rwqrgRDrPbyrrDmV+FC +veepr8m8ZssbZjKy3z1js+jcvjKJOY6U/7Uc7IfZ6AjBXrkJIDEtn9RPoexG+av/ +P/LDsCF0ChhP44KZi5q5TLNvAmbvNL/7oogaSq9nw5hJYLiu2gScOAAv1h/j9yhE +f2mz/xTHjr35m3Ax6wLPk2yS53PATS7XXQtWY8E0LJz7gOkSDvolwnyc5aRgS9WF +H8DyqWi8vYzVLNd1qM1mAR55qrVhWnmlDmw+f2OJmP+6MNAoptW9nsUaeOk5xJVy +QNSwJCjzp6ujIn5UhmrS2u59HW3hiW0J/O7aalBXYQxUv/qllKkrNmX8HlB/1r2C +IniTw/Rd33TsNTBx8tqq9IpnAG4s51xHBeXT0+Sd4zNh+fIqAYLNuMllHMlM/oFu +A7+h4TYAxEccchEha3GD6CMl +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem new file mode 100644 index 000000000..8a7d018e5 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-CBC,B0CBF8975CC514AC + +eH3gBb3Shpdi9fkBr66H3xWR0XnIrKhPU1KABtoaYxE3N7su3duXHlx4zpc3YyO3 +s2YwjN64PdGYgFdwrznf97SjdI+MSJgu2wMxxTwJwOltEPBdbvNWEpq8SLdfdlDv ++zndoR7YnMIhQPp5Hch07dhwpY0hn3RELxYf32ALEbe4+xG8/LZWUBoKdgOn+trk +1Oh0VB3eupjtsdxDWMMN3Ar+l/1AfdBoaQcHg3UdO52U+mTc38QAaMA+9Gplkz+Z +YwjWz4tyltvTDWGAYGuhxTPVt3IoSewGVHWxKezFujNEhj6wuJBTlpN5T1pALfbD +JUiGEmBXOPcxwa3QKmVKJFcA+p5eOYY15sqsIhcaXxPgzjO6JQWMErkaOnyB9sHg +fQTXHwMau2HqzjOM8Qa/lQyv9nf45IFupKoTT6Kja2WzAVxd9KGW+NZSAa+okRSr +GQrsXrJBFl3+wKpXN3alj94GK6aqCBiyd3d+pp2NyM9TorZhfWxbQamPmQVaU4aF ++nJjB+lW30wPZM6Ik4UqsgXolYXZCtV4cOaZ7g9ub2AYmYCA6yIagRFfjuEs0/f2 +MNN+qu1Z0sg0oCCpqO9kVcnnC4jIaXvU0egZVlGZ51GP7iR5VsLmi3VTbebnsvT7 +x8XYI1WHYuANsSBNRJj7vmrolzVErsX90FInNcnc7o43KQGyeR4E+vSdqoLHbk3A +2HL9YLDV5cdvGafL6faVKFxUaA5CWCFVtrV6MPJAm/xWs5nu3wr6aNsDk/0R4mqi +vzQe9EjkMprrihpXqFGpTaehJQFgLaE3FwnxPeUFawqdKIqaKf+stx3i24LkDSPs +ukLiYS7cPcDYXN9kI6a0fqGtT/gL7NVa/jxsrl5+da/alvm/Ai7TJsUUi8dMzqIy +85Hv6xWyPrwCbar4Ehq1CopxWvINo1AnvajIkBHvh4EtK7B51stOO6yNEV7spYxb +nze92IMAtRNWO/yp/p/nccy9PB8/e2v41T8EN4MJuDxGX4k4cG0k2IGzBDcBM1pC +YfmkHzMBGPsq3CQ85balLEWQTgR5nr/8+TabxyloED/Sw7mLM4gqMmn2KukzMxT6 +qeiFiGtmv2TbD7OWkaLj1Mth/ns1Of8U +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem new file mode 100644 index 000000000..acd0a47a8 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-CFB,CB9482EEE6EC0DA2 + +Bo62wJPRVVYQKoP0egdW3dLX4yU/Dbkx8TtIsNxNFhdwpGWtEGzervoU73+6aaWF +LME/HVPUh+iZPKh9HuwSiP0GtwJzCv8arDp09mxGJ7XFcqz3AS7T+K9A1OclVa5o +LwQ6ynBtCsmgiVlS/haNjeONqCtpy0kERgathUclwQCLTnQBZmu/l2Pk8Gdtc1Tc +osmKc6BDlPOyofTt/UnrhVuZxasrS7tKEnVn/iZr5mjUZAqmC2mJcWT5YNahJpfO +rawRjukIUOm0feFwov45+joTSIGDsNTYD3OV/+BF4ZgBMm33ApAE31JFoweUcI03 +2l+WS5qtmcwuOYGp0Np0BWg09KVwNbIghfiVUEjnqy55PCVOFH1RZrmHhPndCvHQ +BwAaac0yAtd5vFWjeUf+pTbDmkA44g5f5aO9uQuB58WWkB8JCFpGZLizK4ISy5ay +dE8+SjVGiMSZBDfAmiEokoYymc7L8bkTIl5Jo4TuMmtFcHnfohZd6Nue3aRzNZHJ +E/V81IxIytHRlMl/dZjSujPw9FgmXSip/U1s8ESIVOVoy93HnaifgRfkkGggxp4l +S8QqBvJTAJrQ9ygO3PBjgdKGi1XWvhH1Y5EwPJ6Wor4zzltftELEs1O9xfBT/zeV +GENfUZZU+5V5ICm4K844WoiTkH5OIWAi/ZLK9XRqchaGWvMpv9UwBy3c0KOx1O4f +j1/8pbXDv1iey2USNL/Nbw3nanIG0dIbUZ2g2U/FeKtfCfVHu5LJY+v6njKl58X4 +mthqvCZyyJy2U31MYUUDN/lgNffwLnzFc1AxYyxDZwviKmAIN+Ylh5jbxuElCS1T +bpVd1+4aber+qv9Ar9G/PJEt9ZdHR3RB/tsEXv7ORke+fVzlKFQu9PKo4k25U/mn +qfBcwlut9rMu19xsjbowqHyYJbenyrF55d00pp6P037cOKLStJECtpgir6HgTpo2 +Oyavx3OIH7ypvcyaqhFUqZI2EiGOdBwbSBp/jCqOrnAwTKo9uMcnmrsKj6EpjJzO +VGK0DoieTEQ9VzGbqZKK34NHidE4j/MYW9lGKAADSy7Ey0CllvumHiICWOn9aJYy +ObB64C3p8NFEcW5SrTzPtXeD +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem new file mode 100644 index 000000000..1ded3d7bc --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-ECB,4C5CF049EFF2E116 + +M9XRNeRQW2K6U0bfpl3axdvsuTmsiFLkZ4C/76MLePY0HxePs3icSW82+t6awIpG +gHfei8zevNlF331hGPW81XZAl8OaXWi+iGhIfKAInLKY//DBVI5dMTQUKTwBa87k +oby7hLD+V4lVKr9o/tf2A43QjEkScVlxcofEnWUG84LkgXalsloaIAt7iu4qUMTA +C1gTbkwex6bId97wvPQLvhFiOyrpsi5Nm98vEeJwMdb6dMNfLAd3Stjvhh5dGGaR +BsRwDqgrkycYj6pOT0Zvg9fBxwLYeMk7PPo0bTEdY4itvpHXaRHcogsBJ62qnsFM +mxk1opz6U0W9xKSNTCwLzg9xinRPXGDP5jz0zqE1nlQ1lrsPcsY+omKdaL/SGYlN +vxDbm725eOoi1H0jsTGJsgcKJ7sKd6LTUEIAEsUvRAN+ro2zLhxteDP+gpCxTNRr +ElOLddlDm6TB55lBkZVrH/0k/QQQ+L0lBi5Kgg/hE6oanMRGeKQvxhxRuBbK6tZB +e0b0lffgZR0m49i3A+fTxa68lb6Lexggp6LAkheh6qOVAzSDWbk00fJ9SWNWO4oC +9FNqu1yafLt3Xiyqv7iD1EOyGhYF8NDvbMpu+gM7qwbTPMjgXf9N9g+AxSbvrmHR +5zGtJd+8BtU+139ZlsEv+cux1yxkYEypKm5MHfaa783b2zKuyOTMgOStvSOUgGhz +c9dlWYPkgdgRkAMHzfIigHr9rQssde7pR7ZMlw75PxI7BI2ZF1Vj4weIkwH0SKFE +fui/C67Uf78OHx4cVPANDk6cf4Ow8buH/vWjEX0p/jpOfNT9ZA6Otj0CyIQ56MjU +L4nwFU7GqCbVkJtsHLI4sZmP4kH/3zuqVtwRTzQbQAWeTi6RCSwa8/amAStTPcX2 +WPRezgAtNzS1MBhileGuTP+opGdGOOp4AeCCJdFBzkEacRXylxdY7PUsCZI7mRSZ +7AL1n9jbUbbgnl6zmqn7fybigjaTpLNSkVPOvVBxnNXxOW4n2HD4vA+q3a4d212X +fWI+/y7mbYLLRs1LPPgjSLfPQ7Ye1Cj4KWy45Z9YBUtjdsEbaaHNp8TidgJKJuMJ ++sDQ3lvtJdIZZy26tzLf3ryE/+2KMTwG +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem new file mode 100644 index 000000000..331542c4e --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-OFB,F01B181DC9520301 + +azqFQnexfYYO2tX4qlC6XLU2tPX5EdwOHsruz4uzVJmYFyRLlrgG57KkahVjWupu +AHkkjhr9d9m/0/t2vFy5JEnF9WWcNA1nxqzfsaIKmnuCULzYzMWu1cFfTV2DZoAn +npdxa/eYmcGRZ0u3aZHRGpGtP1y2sKvWmUInYCc69oigiEn1qyDkRE/tDAREh7C6 +DWRcva94GLj1igIHc61lBugZKBlchv+q8t02Ga1slM10QRg2dgAlF8uCPZe+NLUk +8uOifATkKTsA8OsUgn9nRK9dH4FuZeD64NMCszOw7mYtjJ7YW0J0wYgC9BuEUcNm +QTxellBcs/qSdi4pZWsO9JXxvoc0lTmvoiS0rL+JlB/UfubVQYq+C7ScVJeTUNKL +6fF8hvfQzqDDjqx+qP4SgboAmIbL7tTJBeABnnhCOtaY5vSuT0l96rIQm/EZdlWD +hXKcrhawaq6pqh/mV2S16e2gDRQyUX+jKvumTQhjN1+AkIb7EMR1ZLJFX1l343Fj +5/V4D2+H3EZhbCdkz4uI6I0swDasUjtigcn19kOy5t1r49zpTJ3wxQptLRx4AXUZ +zjVXVebGyFYSdu+Lks1VC9WDeisBW18kCg5IpOz3eo9ULBBQZnzSKS30OXlyO000 +/1Em8FPKSKYeST3SmI1aDObXOG/s4tyKTCj+e2VKROq8hDhJQUYUP0AgYkAnwURR ++XylYEfUrW9v758Kk3u82ZhEen/lLUQhWeXkzhVi44Lgih3Bjsm3jP5f7KO/5KfM +UqECKIHR/p/H/klXPNmdFo919AFGcnxFjQCyhlv0Bl8FSc5FUkRl9TTLu+h5m/p2 +ONV63odsVGt2q/HmL+3hojX/BxSEP/8Mq1JHR4Dk0qqUpSxRtDw0XE9/LU6s9NZp +zm6lkr5E2U6EN677bmem5QoxObNvc88EXGr0EvoWPnhh20lD3vQok7GBucnycoj0 +9NMmRUIflnj47quAGXI6LuTSzKqOOCZC4yNvdyRdil3DgyLLefr99m2WEe0HolDu +pIyUsgHMlZC/YRVzqP/6DklhKDcvgWbBeqqhV1r/30rRkegHdsWiAEjmJadlBrJF +szJZpa9obMH/q0xUH3AXXCkS +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem new file mode 100644 index 000000000..d44bc8631 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-40-CBC,7AFE1927D7FEE9F6 + +WgKt23n2XggL+3rzABzjmOq8sdOYfFuuYUzP6UNH3zdXRt/fh24/WRgRw+WCa5/l +3Tt0/spkkMsgkkDwPPVLu0MUhfoUQyErK0F+8HeEdA82C7uGIgst4E2MS4bRXPR6 +w9U2R88xdUaljjahEbSMUG7JXecjL0WG+zLVDpDqMdlKNcMz1tnQbO1JNLZCJlfX +ZlVPslMmTTxs1sqYgDhkAgh3FwSsKMj51nvedVCq2bAtSmgnz/bFDLT4c6N4iLf5 +MXP5ZUMUtWCac1hXayVw4koOkuPELKi2/1vWe7qDWJfqhKmRT2DV0Z1GKPjQp3Q6 +kGnD8oVxbKfCQDI6PSMOeBcWu40Y1yTbBHBFJO5+MdWsNOQI6CZGJCHNu2ZbOd+w +tIcxZZjy5d4uY869PxxVxO8TmCRUn9hham6qfTw5Mmh7bOyxqID3fXlyrcE7KRel +dlL9eQuLcA7wtH5vqpy6V28yWculvP7qmXAGUd1gqSYHUs8kipf46ecFwieCNPEH +x/6hDl38UsuixchyyJTp5u9L5cKPy5PWXv773xcPguk01YhlmqrpTNZsdoJ/CTBg +gal+o01rXd6snhp7IwSAppCPwh4YJumwdPjF6jUlmB/2AStF6kGaOA6BbJ/lQlCa +cHAUaVlTZEyzSGShBGJUAN2AughiOq+2POgr5IgeoC0NL8ieMg7bMYjn7+Np4yZN +KGmT1jZo7OmyVdh9mheahXTT4Axihfmy+uPTECuGjq4X3DVv79OvSFRpHXIXLnX9 +QkizsJKZc6v3FM6o5tbMDbJyelzaj8Xn8ANrugYMC1R4XImDSel6Bgxni2gHuTEc +WrrILWnNSmNjz/yziFdu5VuQmYaJ1e50uenmOxiSQhL+53UzhhGCrw4ooAOSF5or +s87oY1HO2aYq784A5UZVYGA6mYFjDDQSsbwp1LYomjoTrwoJML3P9x5SnaSrkEEC +3Gm0R/t7SkdMmJhRc28uYarO2qdwyBuhoYRxw9Z6bXeaUN2WhJ7hILCL0KKZE4vB +DuKxE/KgD8ijKpkUn+6fizWau6Lm5mqxyMyEDnCDkvlvv7DMoqZRJvVWSddNMd6t +T94SaIiCDOY3SuQCi1361GGbVH2dXH+X +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem new file mode 100644 index 000000000..4a1ec9823 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-64-CBC,6646FC6A291EFE41 + +KWLSTeo6nX30rQ3WbgL/13WAEMCtaC32ksYorVhlN4ijjiDu5gEnmfLRNYK4c3LH +IUJawIdZvHSVxjrKNjmKA18w+4kedYCCL9NbNswd5eO18wldFR5NlSI2FGggzANN +OwJoHUOXggYxhc2/xbYHpQpl7gvJqZtAjyewyTDYeTC3VDFoB/JywQ/8vv1MN8Ce +Zx1k6preAQrnqo/LEIm+GPUa9flzWZlCGTIC+obNkjJGZPuUKLM/1TqNsrum33aa +gFwnz//khQULylIRwxfuOMCHTslFmrs/7MLLbJQyTa99S9kc+s2VDlaKWUn0BVe/ +MoCseykcuIcskavuj01SYySJU1YHBTu7RvhuYO8AQmnsAP3gWQUMvKy9aXmzsoC2 +0Nk3QCZiG+1hN423So4NPOh42OWbqrDls9PKhXvQ8H+58rAxW2s7OTN29Klo39ek +w8SFjMEtt9kLNpwBCJrIlolXvhD5WQu6XbqI0CtoOrh2Ote1c4uN88HyIUi1Y2Op +QsfLkKyx7yJcJrz356Ab5lbJKVpKJW+frEHI7rLlfJrj88uzsh1B7oPL/4fhaj84 +vNUfadRJ25ZivBiHHdUTrKk9CLsIDS/1DWM6sDclYjXiA7kgGNwJupOb2L6VEKPv +eimiJ9ooKq00E96Dc8s23FteQqySNaUAcqDnAkS+ck6pXQECZs4uD79k4pck1SX4 +O20OIPo79pzcWrmYOrTIXH6ttOcB3lUQtB1fmcMT5RSJYVSKtgBxLPKhLcL18xfb +1HbDkpdUqS0R/nK7ecMd/LP+UmMKPUyMUTfTUnlXZzsNsgIBkm1eDn9RkOGaV+oc +wau6FWmxVSPs9Inb+7A+B/2bP0qyYnciKX41I/PClKGitm52ScJyrEN0XJhQ0O+C +mPp9weJI3IwpDn/Mc46NQO9uk4rC2P9o1zfJXC38PlEDEC66a1Y6SEQOVN6iYkYm +rVytxWjD4o5vC+GwYJPYrmkOg/SQK1AlK8TSpNC5TeRcZ8YIbPLRfKRUQvUVtFS0 +fyPK9zdariwubkiG1a9/NWCF9gN1/DPKFYy+p5Au2ICD0iTtOND9I/Yw8dqsjzsF +4jhYQ+No+ytLYc4Zo+8s1RO7yduFz7XQ +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/dsa/openssl_dsa_unencrypted.pem b/crypto/test/data/openssl/dsa/openssl_dsa_unencrypted.pem new file mode 100644 index 000000000..ee815db16 --- /dev/null +++ b/crypto/test/data/openssl/dsa/openssl_dsa_unencrypted.pem @@ -0,0 +1,20 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIDPgIBAAKCAQEAyKItMopMK218pcmy6PkrMVXAv5dt07TdGBuNhVWpQ52ldK9X +mL7CPKpo4Dy85EZRPvRNyOnhe+LRJZ+ReKntpEkEiar/ZsKVkUthPsiUMpoM5S79 +JK8iT8F9HdFjIFKaXGySBZ4xcrj8HQ/v75iolYCso+66Ybgjs9/nsWS0UQyGE6rc +ibx7xPAtcbaGZUBaBtdkNER7+P2ueJwej89aNZxj+AKuvrWrArq6/5zOIhGR12wQ +EQQjj7FQ66ZFivJ/AYsv1yXDS7mZBNp5eMuxk8Kmis/++HKcP7tdbVRnlfTGdBuN +BMyOcBTIsE11jwikcI+KIbr9cEZoaikkm4KyuwIVAP4DZEC+/JZJ0PHSEtJTt6uz +yn1hAoIBAHhLbqDib7zqaFBrNnbaBSNiltY3GxWM6uQT88NH9YWz3wXRb6i4KJFH +9NtLbK0RF7MoQVprJY6LuGQHZ/e61Fs2EabDwT4vB2HT619fVUvDndbuSW6qfUR4 +y9kbG7zLkE4Mnym/ikmUwLABLA67cZUS9yjtcRXGpOkiTAQfCGBeUH6nWOFEaWjI +fGNMQ5awKvZhIvGyN4Zvd+mE+199s/kAsCKFux2Sq9tYw3qS0Tw2IEebHsHvX7A3 +bvxV6p7czVxlO9+O0w7bBTekPpw1BnCYmPyy0H36g/7aF2V70UCWzER8zT1Pfh7d +3P0hLqHYzX375l/7oxuDawtcDAV++iwCggEASajPdllHVQ8JvKdPH6qDkjC5XJTZ +RK46mYm1cCu8Q9Dy9ZfL67CcJBpwKVHNC3sXmk4XPfs91AZf/t01qbMJvCrR8NHs +jRyJkNIaMyDeWcFmO0KmMi374BQpFyIDQ6mK1y9BilneZ6gHDdfHMsKniLFW+SQf +9hlwlArIPYuELu7riJhNcuRUTJEfybDHwM4/ht0IFbyUIFl00mMdTrozk+e/esEs +QdWbx2UBjNs8meZPivFbT2HpQF1I0qZhtn3e7jcR5YatBQ3e4abnu1RrDc73q7d4 +g2SYQK3PmIWwxiFhJQTzeiQtl5rKzEn76knAydOtPVRgjXWzHUoW6Az0qwIVAMvw +thRrEZxNdxELdnwW3rpYBm6B +-----END DSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/eckey.pem b/crypto/test/data/openssl/eckey.pem new file mode 100644 index 000000000..8ceb3a8a3 --- /dev/null +++ b/crypto/test/data/openssl/eckey.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMrjAwPp9R+KMUE +hB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus ++w2sY8OIPQQWGb5i5LdAyi/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2d +no1GMols5497in5gL5+zn0yMsRtyv5o= +-----END EC PRIVATE KEY----- diff --git a/crypto/test/data/openssl/enckey.pem b/crypto/test/data/openssl/enckey.pem new file mode 100644 index 000000000..137fab345 --- /dev/null +++ b/crypto/test/data/openssl/enckey.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIpII67Pp5Vs8CAggA +MB0GCWCGSAFlAwQBKgQQBpkbyKLxdtlBlp6tm6lZoASCBND/h43o5NNNmTXWHN2+ +N9ncoFknxohgShAc8WHKMHt0SCEJab8E2IAxVkYFMOMpvi1KVldcveLlg7hcMIDm +74pJmvXOW6b0bENvPMOxFadzr9NjO7j5ZT81dwNLz2pBLyiUMYElWl0LVnxKThQF +qijJTDPcmTpFwDiUyTxzHxMx4DsoFYQulRBsZbRCAjsFpPM+OrOekSAyQHKMSbHU +LvcdWCrSDRtKOyCeCPbBA4OzPJFyzep6trhbQii6rkddf9o54/oJut+LMuUblrHE +2yMStfW0G5ZyI7AeOxAy1gKG/CQrvFHn/yhtyjkvPa0sYVGtR4pGew+cs9iIsdFk +nXOf9frJMA2agQZKc4+rf66NPv+dxVecm40HIR3omk7EnxR8s6msXOOn4qnY7qae +aq1M7pKNqCu6eW5560mW6buLpOkpm/kDbr4v9rfCX41b5rIRzOdfAt71FSJcHp6K +FNojK86YsNJWYh9pnfDbjEk7346cCIeJVgICGTmL8Tg6TUy9wIB6eKUXmIG3fKjI +Ep8OzYAU3/ae8vdmZqD12l3v75muRPs4bP1RdjaVrux5Xlq8TkzU21ixWG6Odj7I +1jusSUjz16iR29XhLP/HI80GKYQMc2yHWcYQ1YVXyLzhnHYydrqjW5OTKZW01rbe +9BC8XlRzKZJ4IOQMfSiZxcdERtImO86Kprl4du7gvWaTUGTyiQ721Q08GfFdVuAn +OO/J8stTLv2Ee7ugTeAFA2+qpz2vAo5JIPOmqjNqI2ytPjLRb80B3tSVXT41OodT +D4v5YbNpySMDpw2F052Wx37hl2wNxIP98U6aw3ZjJdM/YfLdGOJhdoRTBDAvygRU +Di6F56sDvX8bdXDUZURMg+iMx3Noc5G3TB3JpYunm3BL9lwGWesrkDzg3Vs1J/6c +4AMhAsw9+5tzvyGEDHnGZRg07K0eyWskDK0/Qb+vjSLOj8+QphM+EPCmugNnXRNo +AdslIFoVfrcKruS1/DeSIesXvMd7sj2RH/xYDcAIGzmwbc+Ki4JTPuoZlF3pGMYE +YkkYj2KHjJeX7CeUjCmU9Y7/jHp+fzlKsQAMQLVm8bRjDpvLA84RDJRoCPav333F +YqRciZzMjfx2f6AJTCT+/8nv+DBiWcRtab1u6f+p1iDUa8bVt0Y8PB71gwAyonmY +gp4A3fSilIlKEGsP2Hb4aU9V5vy1EZT0K0PuAY4yxGPmhedLCKdBqOuwQBxsLDP2 +YmXR5wQOsI0dVE8zogpgOGOEE9RXNAf7QV7pBOPNu4HQLNuZi22dKi+wkyMLsIR5 +dGEz7uDIaGQMvlprtOA02RON3gBnQTJAp7E/YMd7OldSBShRRGeIDw7yTrLoHwLI +YnA5+ZwFLBPnOrnBC47CwgB2X/+ooL8/+yigoajZIIE5RvzuKRQGjC/ZgSHXSHrt +mJKGerOR/3+OYYCTctTa3wTPVRc/vB1hZac9OPmnKpeywCJ4Q+jX+ZOhHOM671H6 +h9fLPd0tSE75gIkSuJqBuLV2TB1cp7BTnrZxLywCxC779lZBTVLctXu60kiIoW46 +zgEz1dyf22vfMN5ss0ybvBVCl8ROmrVr8ZWObzkj1MUyifDM8Tayd3uZ3SdHPo8L +2G24+4bjyVdFjUvrBdzB5dNzAQ== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/crypto/test/data/openssl/pkcs7.pem b/crypto/test/data/openssl/pkcs7.pem new file mode 100644 index 000000000..6104acd72 --- /dev/null +++ b/crypto/test/data/openssl/pkcs7.pem @@ -0,0 +1,54 @@ +-----BEGIN PKCS7----- +MIIJogYJKoZIhvcNAQcDoIIJkzCCCY8CAQAxgfgwgfUCAQAwXjBZMQswCQYDVQQG +EwJHQjESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYD +VQQKEw5NeSBDb21wYW55IEx0ZDELMAkGA1UEAxMCWFgCAQAwDQYJKoZIhvcNAQEB +BQAEgYAikb9cD39oDYpMHzLuqA4BonNpPx+jYtqlUIaJv30V03nUz1MLm7IH7TFt +ZhL6BXAbdC2iwk62KVS66ZCLBKdsqtD3w9N2HtxTEW6AdaNHKNUb6z83yarNQGzB +67llZjeCLeipP7RWIvBZcV0OoqCgLcpZkpZqzrmz5MjxTCmB/DCCCI0GCSqGSIb3 +DQEHATAUBggqhkiG9w0DBwQIja9nGhuQE1GAgghocswhe5MZRov9Zo1gnB25S0P8 +Mw3463VaOcb+ljX1mXkT3fivkBv0plLlmVT+m+CRgczup9p21+t1OqsdaITNIyrG +hYSVETWyFA/Yn7dQupK+cdCaVLKC3lT8f13iPrU40wnbeo4ZKi2vbv/X3uU4fRMZ +wSlyczFozcviUYURtA5MZaS2e6/2r1eLZcUlcZ0BDcuD+FNdryGbKztSWa2ye0Ym +Uilu+GAZr5CQi3IxpRxDqrS+RUQZNllcg8nGZ2UP5W8FjH+Z568NJ7djoziCX0EH +yd4vp+g0LRG2dkhGXIff4ufO2U3QOAgCIOuZmG5YSpRN2U7F6T8W/FwShFO1u+QH +YduA3pA/5K+IDfCbEZDMWznd13lTEZQlLSXV7dLNCqpR30JWpGg956rJR0k2bT7G +KFTXhSUK/Puac5y6IVmJwPxqAkjH+xjXpE32/AcRHi77La3nKp1aQEKo5uHg7HEg +w160S1LUenJSqcmOuk5XWvM1wdsUJl5Qk4m9a0VyovLPm/RrnulMtUjRugxJLfZK +27NivOrLl9h/Wm6BXYq4PohM5d+5zPYqupn5ipKHsA68Ps7rnDEGS3VzOQ32hqu4 +kdm6xI2zLWK0+6mQnusBPO0IAxtja6BPz8vTMlWjZtWZgEIMppQMhQJKBEQG6HTV +z+/gkFds2pFO0v8pLcMBy9+8nqhzwGacymnupXJzB6l3gon2t/e2zJjAPKUSCbHI +QhCjW2JK9tGKTbF40uYMUGMIPhxr7j1u4LKNEhKCNhlUz82NSsdJ00YNQdwuDMWN +CTAE9/STmRGF3ZHT9KWmz5MQECp/pGORD7LtOQslbUYiMH5oCYP1jD8eM+KxCljv +1pFPf+sZdpboAkdaXKcZVnKqOuPBP3Y1jBkLCZykgnXkVbEYM7gSdvsCGK52GcxH +yi/gOhfOIgywmFB3B4Yk4mDtU84WpK5sVlrZ2vZuTaAmOHaTIkVMvkq30F/jpVy3 +OF4v9/EbEAJGv6rqHMhKmuIHP530CKtWkUUfGv7qQilZ1Qi6NyFJJTfb1bhyENJt +j8A1QQFIYHDzMolmUoQgqOXJ/6xc9AtCv0fU2LijLUNFjB4rapJggo5UnZE98+Iq +UAT7tWalpbFisOdX5Dy582hhvcFn/1DDpISXpF0kgE8TV/swkJ7zuu+hO/Yj1HNd +cwG6NC9+wUCjaRqAobBtvPQyK666I8C12pnW0AeuqtznnZve2B0/a83ECS0tUmxC +PO9zv9RNwcakynklrupw7B4PcXEaEbxpvHE+/zNLgfrPRggoFdqSIRFS9xQRPE9T +uO7jEh+tyh70eLqce2jqKpRwxItZst3ABT5XarJ6vfGxxcs55sJG7xjv52xuMikY +gOagSKpETRdkeE1aAmKwpa/vEFu2J4Oq1Aiv+D2Gc7G04cOsdc+6P+N9EEv70v0R +3NA4vg3gTBcO3wxwnJZAS7GwUJOcrqC1cAaQkc5NR0lUx0lMzgWWDDS5qKX+YwIU +7KEQiyhqQ74rkf6hxQyfesaBxqxCZZkikbwBHlDZwoPfwnfrV4X4/xyo3cqCqbhf +FFlHOAXissz14wsTPh4XQumj5RZSnwj8gGK2xou9H9wMrwuZ2eAT/3L3OtbIr/Sz +Cbp8Y95Tz8FgmrJXvygMVO1xv77PA1DzE9SLiLyB6TL8lsxFQ1ZF2D8JhpDeIPpj +L0k2vTrmCgENJ+tCc0ngZO55ZgRbo1fbB/RUfkTRgEKF9WmJYnlXUVoh77kZ0cc9 +Y+KsueEZp1woSTywJb3tc/jXeRGSmcaWe6pa0DcfM50coV0y4lw1ednEV3zkA1r4 +zVtUBw8Xvr9GKcNfWdmqgIJKsQraq6WCeIxCPPJw708+/RERQBoUobXI4+Jatw/z +XiV9SjrjK9nJ4H1YKyOjyz3SAbeYrgdgrTGvkETCPAALb+4Rg1FHymSMfDquwOsB +63Mdl63DIkJpicA6CY6yk/LgOADQzEipjcdKqzQOjlb4hsQZxN83kzGJiWB0qZOL +XVLrGXP4xRYS2bUFB0T8pon0K5qsZ9oKKf+HZaHMYkni43Ef9IRA0qeDl4FfAupA +kL0lLnBjgGRHc6rMBy4qL18xRjTtR9hsn4Z/pYhIgqMm3QEVkK/aOgTOlwXHdIwu ++Hvzx0Y/BgMdCZSlrspPbQBDgrlWzr+PjcjEvDf3LYj9whtRJP5cXVxiYqi/SpCk +Ghy47RfNYfkkJs/gbojlO/lDvM8oo+XPi22zAN6yFLuxr65lJZK7QIvabHvTkEIN +wmpnWcRH+MwcFZO3yKt6lxY7nJWuW5hh8O7k4/oN0pNdGtv1/2XgXFOCREQ4CcPn +Zm/vXULLCCh7oP+RyklnwyedvfeSfY4lpldwyHCIsYyYmfZHMw32zqH5jCnSxZA4 +fHBrblr4Mj/5jyHLUF5xGsJdm5RtDfwJWe6NelO/kJMs35UjA6dhSOfHEkw73M5P +jcRo1OtYZGu19x2QguhILpZxuAvNtLpOt88z3PtsxA6Fc0BGpQXPJTYwtXiPf1lj +fUd5KFsPohPJOIEJAaFHL3GTwmWFtK1dHofPQukiOTb6pC6yKlM/zGWLOyzTM4qP +UvuUSwg1UY8GplCeqhCJNTieNmyY70vzG2CWcotAwRPeVbpa4MEWRXHf9ft4Mawb +qn2J48iW4Zgh82vFHNYcGRjKRJqLzp4VBn/qpRaX+aWEsdXq4shRgFOAOKyQNMex +GZyd9amkblqjEOOEzzxPUdmt8k+QEm+JC80NR2sv1mw80PqU/his5zUJ1Aj4tzkF +fi4jy2nPNvVSpjWiAI6cpZsbdhdh9iayij4YdQg3HB20+1K9VcFnTmBqLKiBbG2o +4oX2oNPE9Vr3H9Y8YaVoeUU+Kiqo5g== +-----END PKCS7----- diff --git a/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem b/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem new file mode 100644 index 000000000..8111b0d69 --- /dev/null +++ b/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIY6+Wgj6MqdEd +Yq6FgH5xMgTBmFqAonR/eshjxY2C6MHs+WmCmNSDik2NgZWIaODvOF9uOEK2U0Zf +JEG2LcZxoeIEgg/mfII2f4DLy1JYajm/llzwFBzAd/Rkcs3qwP2ba5VKn/pSqNLl +nKHMXkXO+9SjfHDx95x2dK1dB8eGQGculOMcTm3uK7UlWNO4TSlwG9qHZ1aoM3GI +g5C1fIpbxJqDVjFq6fFAapE3KRIWIQmKd3E5ICcDErqr/AapxnfO8UFNxVWSOLW7 +ZAfis4w/c8/EAgyQHw42R0dNyjUOZsToF8McCsOpRjGolSU8aUyqspvd8IWJPd5d +6HBHueXNAgMBAAECggEAV3q9MpVVPQ79TTjBO2Km0D+nt+QMzk8dUHGHfZbGejmm +Pw96shqJ24rK5FWHs+8lEwmnD3TcGsAr3mjzjtZY5U5oXtNwoYwFRElRLqZqIlLt +NugrVltRWeyD8j30CuGJVQoYOGWyX9d3ielg8NjO3NcvMtembttLoKK68/vrbH11 +9W7wr5p8/xyMfyl9curnmCFk5QqJ1FBpjPWY05NDIBCUJB0tGAqViCpxEeWPSlvb +xcElqWfdbtnsYUxYU+iOTHHotoKnz4nLHYK2/njMhlCEyMXfu1DJOd8rg5yXewJF +v6NhXgWStSexAT1bZ17LROazVcHfWB9QmXF1Fm7vOQKBgQD+dZxPDOi3Y4gCFegn +Z+epNyl2aPTkseEZxrIqPKLHsGxUfYjQqkX2RdfTrq2vf4vFlN6uCXhSlZKXfLH/ +iQ8FAzqenhVVHK2fv5xB0SE5zNmcHDrHshl+/zUNI2u5AMFECVO2SVbgoFjvgkou +FolK8XUXfHfb4f732LUyYI0lEwKBgQDJmkWHhzekz3P5iWaAt1SH8bZpt2hqa6Bx +A4VvMdtmjCxEDETN0Rb3CPYxw3qa3xGfW1y1j/49xi4gr69yaT2Tbca7PFGUmWRo +OJwfCUB5uBUi6UVytK19OVKReOm4666x8P3YO4cxxSI/HeoSU0HR1kkX9rGmrsGN +MgUQ15+FnwKBgAKf6/DUzUG3ARwkZbSiWb1hGEhkZMJHI29EoWnWHke5BiUI9nRQ +jVAxADzqvFfnFOYA1xssddVEPbLaUmu0WjdPBTfFoaqzFQdkzpPPOGyENGpr0B9n +MuQgdceg6eeKnnO5NOfYcdD3VnOCAInhKaFgRDjty7604hBkZ9oRLOOJAoGBAIJ+ +dmUMlGr80XADjTLh+DhqsA1r542DDv44LkXUetS9BOYjHuIuZnQO+/UoOBNJMsn4 +xGDNzN7FihQkRCeFkZL9arbFi3TpeUGw6vV38qEXE69eWVKvOuEkmpqJLphBDfom +KNmvZopDtTAvt9SWybL+xp9ZUpK26ZfwebD2MU63AoGBAOa2Kt01DxoqiWiQP/ds +Mc9wOw1zJsSmIK7wEiW3FkCz8uw3UgjF9ymYY/YAW3eZtuUpuxEzyENb9f21p4b2 +zYoZ7nCUo4TmVXxgCjiEWglg3b/R3xjQr1dAABhTeI8bXMv5r/tMUsnS79uKqwGD +2Gc1syc3+055K4qcfZHH0XWu +-----END PRIVATE KEY----- diff --git a/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem b/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem new file mode 100644 index 000000000..fa3cff6b3 --- /dev/null +++ b/crypto/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIleYNcQVMEocCAggA +MBQGCCqGSIb3DQMHBAjb8ZXri5RWRwSCBMjR3ICOxCzBu74U87lV1QXPNlnlHD2v +TlRv2LNLPseEBAMiJkgP47rYwpzMmJjW5bNzCLxT0pYv2Z3/pXPUqy6aNJmOgCmU +HvVGdz2jS+WYBtfijc1J6MkuvkhRIBxL4CYJidVurc5X/ebRu3BHbj9Kg/j5Hjx7 +DV4qTxZR8vbRFH+ETdnVqj3pCYNOeYXvV+S0W7IN3rKmEk2su3u19YhbwnZH7Ny2 +YMjAn9FaYT8bK+zlPBZBiQ8TuZxm/jxvW2ScQPLk1pRUs8WkDsaYY1gdg5XuKDND +xA+mq5xskAMUliQmhJaYxlmv83QZ89JzSd44lLvnNeiaP2xjAhj10ZSVQ8eOXP63 +NfHr9Ehqne5k0CI2fGg78pp8vIihw5D4WjHR46NvmbL1KIlxuYi4nFMtc9aK1zgq +3rhDL9m3fZZ9Rdd6lb1LN3ZOL8e54tL4KKVkl5jxhrThHujACB94remv6da2z6K1 +LZPuDwI0njzC6Y6LgyGgAP75NKNAH0UzbpPncZxBdhyI5mOgRZnTMNt1XoToXOHP +CMR5JfKqpczhoJnfcQJhFy44E1NH+qBOsNQTpypDe7Qiz878e6ebfcmXID0OyU/j +o8czO+1BVT1S2LoN+xpeWcyNYoT+BnRVC99G7vKUoOeo90zNzQQOAEyoAjAg/52Y +JWnOqnaxDqa0uJ/BPmESFvxeYZypJtoTd/g7n45J4fGBSwiH05TB9PbLHD3YcfxR +NorFiq/RVXMXkgOGv+2ovJ/A6GK5mS/r1xr4qKnnO44zqwaie/xdZpXuQfQ8ZS7H +XLVWgbdGP7fbTW72mAG5UzUr6c6gwPo8g6aiOaOnRU32SswhLp4CFgiKFhhgZ4YW +tLmWc1Lz92D8ctTMvXhV+z8NEPF+livmfANpyhXl6ErCr8jEnhGgj4r7BA19dUXC +Tttq+Gpo05tMXqom8/6PbQ3Cg2iCT8RGk6v0p2ne3Dg1LlbnklEfV8/DbYO5tUD/ ++BXZhF1otr/ZaSdz/jJ+GzmD9KvhheQHBikj1/KicYp1KHYfo9oZJT5ulBO1UX/w +JbpLaarntLOqb5im6OdjkPFkklVV9m6EByrfd35BTEfowNaasEvrj/VpchGPo7yf +eFB6HGeIFHNloG7xXn9rv4npJLJOleqmBgyb4cQAk2KwjEJ38LHOyXQL/+tfI5DK +NKzoFH33dtHnP2ZwaAE5ffMYv284y06n09yOFqPi8YkeFs+UiFeV4Kcht1gUNkPo +IOLhwfVxoc9H5CbIBC3emckvbpnuBT9+EefGU3pU9e9et60mQ8sp28vtx16rN/e9 +CiXhRXcLyQZxucmoLKXnyXgJbf3+nXcr4zMkNurqUisc+YVMALePkJCCsqRWPCvo +vDqwMl8rkG3jAqmMJbtZCx7+vvnRnFQSE4BXOlzEQNPZK+EdlfvY5uvksIt93FF+ +E6CIPHW4ki/X6gTIR6piDKiNEle+2e/fJpYqk/pFuVfmiN50QXzrnLrPCznhzQ9V +GN2j9/b8iKzBk5y4wMNkOS8LT2qdcJoJRzZBb4VV981GwFxhAagwM29wko4sdNG/ +vU4hrrm8WAfmp6d3/UdG6VdQj0O57z7BX6Vr91OBNw5RZKRkQvMu3Q5vCH7ZfYEj ++YM= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/crypto/test/data/openssl/pkcs8test.pem b/crypto/test/data/openssl/pkcs8test.pem new file mode 100644 index 000000000..17606931b --- /dev/null +++ b/crypto/test/data/openssl/pkcs8test.pem @@ -0,0 +1,175 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBvYyk4LsBVS3S +34GZc8uuddHq7cUJx1lZaxWK7C6nnTNKJmJEhxW80VIukpo2RODL1hPFlgCJY3ch +/4437UoG8ZNAE1BfuVMIkS1AX/l/KAyqUIX/bsXgvZch0Joo92KaPfDB7QA8VCGd +NCcRaOnusDdsFDdF4/Mrd7/x+Ipkd56FXVEk14QGizFc86aNJrzXjy9ent34PTcS +uGPXUX7pbiZj8gK9f77pDuH+JymqXdfBKz/x0T54i8N4QFfVp2LbGzeRnduaX4Ff +79ikdo/XQYTPOYoDwgdiAR+n0+mvDNkI5rbukSLcz+xbWdkJ1ReHW/QQAiqQWK37 +4D1fFNrZAgMBAAECggEAGbH+GVAE/WRCs5kZIzUMapMNyE7It0dNPmLJdKdmeKyM +xOTaW6Re6bAJakvfUBtKhT5bWPVQFOiwQD4Yqqo6Czm3AeSN4GQ/8v7uNX+FI6w4 +Ic6UNxCGBgyfIsj76TsGRNa6O74nLdkqrCLim5iCjjmo4Bi+S/Kzqaw0NO91y2Um +9XyCzM7Oh4LukmF94pd5gZBQjjVEkEsw3+oQlOznm3rCNIhYSjfStnFZT5stvcIw +BscQg386Wo+UvXV8zDI0qrAi0pNepVGsdpGGGUIHkogaF9HHElcSIAVBOQLhxvf5 +S27j3bvHBzWmmR/MgOsBH5+ZqQCTzVGJdzIzXkCRUQKBgQDkQIQNsRv0V44UriNr +nageBkbjVFxczl5k2qN193qb0GalSOoeKcT9jsBO32mcaBd84vuueSNS69rGlj8+ +7rKyMsRAnjhbMJ0FCWv2muQjxZWEcTWV38wgXkbzos4fon19wQo3JPg0ikOjmGbK +Z4EIJE0PIw6hjGrTXqc9wK4kgwKBgQDZSv2KVaTX80ZyLIOlbs5+CTAzlEde8+u+ +7LcFOvrrzeo86i6+65yvu395Dlm6PAhz0KocaUECeEDakdQHEDfvEf29BsU+p7fU +kfNPotacAD7kNo2WenzH0mIhtBWchSUz1P3cIbq4Rxm4XPlAzMEXcDtFRqf+4wVV +d8Thcjl8cwKBgQCKVGczfRC6Bo3/DoI86DFI8PjpMOlA/XjLmo3SIofWAnkS1pu8 +aAgQuwDlTBTPS25gq5doZ9X2nSXbkJcH5tW5lXbGypzQ9ydSNCGQNNLqswYoXAvj +ptwpCbnqUdKl7W4sVl+AiBE8lkbj0KsLI6tZadahw9dMJLNhIk4s6KchTQKBgB4f +PCh6GODq04AuVY2QX8WvBmSQEJjEHZEZBYIPHAumPut010gWJ2FhD5m7eIrNmapc +aciIer+Z5fumrYrRH7/fcZpLnvpBi8VG+kC25SM5EX7XZSdQEY4txva/HSPWfULD +KvHiJx02lgUttkvaVoYmQ8Elu1IlLG8drEhIalmrAoGAKLjcIIAcAhuE0QkstS/z +ZiFhp7tCCrH5sVvXPJfxuKtEC3iTfgOoMywaX3SQGkOP5kVngziGemv1b493Vmek +T8JLbnNbkooCvPsbMlMgcqZcb/5ckymabMaJBTqhYP4w/uRETNyjmb0uxX2CqXk0 +RoIdgWsw0IiLCNMn16z5O5w= +-----END PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIGQp1RhqLV50CAggA +MB0GCWCGSAFlAwQBAgQQhMfC5lWjUndHWVmSgLGLMgSCBNBZEZlGvXV9XjzWo0di +IJof42XSh+mrOdRvUPUS0uPzctmnXZjhKdu42v5jrbyNdruqZsMXTnnQC/UW7Fox +fp3JzOM5w7wEmgrJybOZgA5spNkiWDdlnmqKme34wEPKv+GPEuHj7w+Z4hc7MSdg +T6Q3CJFLJDCEvfK70Gyxp6X90HN1riQQVxFOTSg9TJsnsvkOJ9Ju3VCTOqt3jlW0 +FEzrC3lV4AcxfWZct7tkqOTXygWMGinz7OqLxIcmlrF3oc0bLxEQzQuGCJIzrhKo +3Lb73Xto/kC/uqbCdU+v1zafdKLI/0Uj3/GOGLUu/PeMo7VaHbAj/AOX63Yvj3zm +WOgJwnOis5iP5rqL3lfdeJrkmE1w7xTLn9fUWXXr+qcVBLeZY30TE9wW9gRCDCka +09ZVw9MnrodTgvWVSI3xHxjYin8GcxQ+VZTxQMQFHA2cyR60yMG+eGm5t3TZNHVW +h3uqVxjbN7tMYbjUo1NdbINntOQZhqMje39ai3mWIhGPO09yfsw7ZRX9hhKlrIYo +UQ4LcEgMZsZDDtAY+Mol7pYB7KpM2iftBT8KSkBLSlqpndl4PJHLUaNBgbNDP6py +PB8FjPO49qPybeVCIgg3AswxJwGE9bXtO9SLcf/p6S0IWvVcWn+VV5sX+9Bav0eZ +nCO0WJYrWcjUBzYJLWIDcPviYkoMkFrsFGUP0DA7OneLlW84YUh3AeqqJppb/qve +UeUXZipLEHf+Z/ToGW+RzPQmFTVDqIx0FdQCi3EefBr3CbN/KtLdRjbP4kyeRGlw +CUS+BWQ+W/NtVUfVmBvsSLtVfW1pevemt4FE9rP9qUa8KeRpOJIzF4kHUmHyDfp6 +rvQTSS6d3a+N1GyJA5/N4UM6g7FbVnbngPvM1hMNfK6xbIcxQJudBQa/bHqf8DXu +61npKQYir+TmgDXlc9iD23M+TH2VgeunrFKuVMNVl4igH3+mcHyXpZ/EGM0KyIhq +PJjPRKD0qcCvs4mPRiOx1wJbCYMdYfEF7sIlkQgKjbQZQyRlDKLkLl4pGWXxaqUm +iyo6VpK2phKcA/hPYz10isRfy1WrKdNHW0B5DPyreko2H0akapfqMjROE0JHtVGs +gKg0FrbZXUP+QuKm0V91ShA7c3mRfN2XNbxEc9JFzkDJs4JBxj2H7MxvPQyRrWE3 +sKsQWtr5AFpFb5p5kqCtyyu7ag9pGicqlaFuLda/PR0ykMrhMU4RBO0OulOGl8ZP +9RC1GCArbSSUYH9xvwthGdaDylONVmHwunFMHs8pblTyo6FiKn1q7lIVXYO3AJ/5 +NfKgryp50SXq0p41i8Dtu+4R6CKx4xTMilPYKYDiDPCRtnwvckI/PshGMA/CHLzr +LLZUlRt1iup5SDjqRIjquw/aDRe+Wy4AXXniHOnlSrNynHcJRWz+pnLT3Bi6Z2nQ +ERY4pCIQ/ZdhAHHldFZ7WJ2wrwhf4MQ7sF20HLgXeUN3qj4xYcwR3CykU8f7dfI7 +TIo26asqsVDsVL02tr4dUrtm4J8yQsH8jD0nCpvGwJ9gswUBPmo9YreN82Kt/LSy +YZISyo2BnoowEcAEGnZBf+PLwBeePeXC2/vrxHlMl7JPkPesEHtTuET034woXELi +wO/DuStXmiIydT29G1n81zmdVw== +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI7ITJ8AdDrO0CAggA +MBQGCCqGSIb3DQMHBAinsLeB93eJ2QSCBMhi3oBwLoE4PNYkIpp3FVk6VHzs7SGQ +u/KcyYQk0Shjbe/ykNJx72OVfzYemlcNpr4p9Jt3VbXxisiZyRs2m1Edqxzdt3zb +AcRSVNIbph8V9mSZNBl2hR3GAsrbSTkwM4xzXCQRvA50z1DIABlVFR9AB/52JQ/f +IQx9NrG6SxlzcNjJMzHpR46ELG0Z5EqPLrdyScVX7TEFWl2ue9P/MOhjfZH0/Wgk +fFCFNoPsABQ6az/lTj1f7hkYMOIw2tayHAuAXTbqyuOVWhVfAqr3H/XuJvXspjDC +SmIr9jIdJKOTNrJD1/rG4wnh9U0OHxceQqf+TJisWd12WVjwMZ1jIqjk0g+BQeId +JJvuJTdVVGee1C3enPjG5qBiSJpD+BEsfk7YQFRzW5TzlzELIdkjru3k3cqSp+dX +Hp1LT6E8TTcdX4wdhKWf7VV6sayleiaiB+9XufqU7FwnOJbe0sydnn8L7A07qFcs +9WrXmCSCpB2bH0MYDvuauqHjpIZmaHUAUpXYUjjj8EnuhesJAz2bzO7fQ9rZAQ0D +6Gq4SLbjTtOlpS2LZeNio5ibyeQkgNs76Tq0zdS+5fFnL/6tIIsJUbdZdLz/5isq +j+SO+7TiGL8a5URZO2pc3Dh/TtjV/lSiI8qb/MMUAmCL0vWe/FKx3xx4dCrRfDX1 +GyeclEl4pWFqnwSQyHadr1nvnvGrG4/pcwrcnhNNb+Y80RIw15A/kNjsKP1f3XWr +eHAp+YGqDbJ/RuvoVunoAx3PwA56NTQLMmzYakgQFEPtModtvHTQnLkGozg0VjWk +TdkB7R8GS87IHpOUyrZcxKYDwOmhR2bHgtosvZ4XK+GAwjIGUzGKtg6MyMh3ynsP +68Vaj4PgkvmItmdZKrvkinophdFqFlqCLLNf6NtaVUMfz3Ap/vmX+EK+2YWxezNa +qFMNXO76xoKj+piF47vN7zjGsJ59yLLWZHO9J8hFLqSgArhVcV69j7JVMD3XugbG +YEFudiVEwE8Kl190CVP1BX8DXYhMrrDL/4QD+jccgLfK20bWdaCtPOs6SxahhsvU +wRX8hwf3QLiuZxfAIlVCn2eL+9QffJYETjfhAuvPK/HwM6+/n+9GpYc4Ezs593KJ +9/mZLuMKc0b9tDc0dQ5ld7aNiWuWyP46Da9FWBdbjoiBOHIUp8h5METE1NuH2d1l +THWYaD0OyOgyi2gosRkjJxqDp0IVxIymsKhX0K/EBcYuKiPKZLL8lCTdrzGlhRC7 +M7N99j2elk3k6BJYewdiklmWHEXFOFo8NWwLKKQPi/rSQHcJy1o4WBiXV5UOYJ2b +50DAF52281ao7BZhYTt5JKy+KYvP9Znkk/Kklx79SHx/bSrXHZJCLoVJaWRFp332 +vQASx042mXMeNDPy7dC9NP3eSyv/niIUWI4t+ktUds1OmWIAMs+2gQqD0Eq7gAfu +i8SKjiAXPADx57dg7loU0O9IyErJpY4HrvDLLMQaxLLpJxl3YSrgEVkrkEQvP0vv +ktUR9qQbIJ3BGD3YuQ3cxAgKWaaZWdEJjKqalTYACS3mg/RHYAb0xnTUX7nkUch6 +D79p6fAhhWe9KG2f8tJVuHfUOnEBi1XR5755Vqt4xgUqMI82z4iqAU8ieBvYpy8G +ImM= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE6jAcBgoqhkiG9w0BDAEDMA4ECBztmnlgZpEhAgIIAASCBMggv6vLTkuAj/y7 +wLaJLezGOWe1JyFmhxfn6FMMNIZruIYUdoVNpsUzeOhedtawTszOOLtDtprsqvNz +/oDWQs2B+JqpLjalfRfkjJjtzkkeij3mVNZH69XPabO/QXnHxjeW/S0Ps5gsIpsf +6+eklLo7LI+KgVMWVIdZ5bC0P/FFi+Bf+sI20NQN3RchJMT8lKcV+2PHZQIb7diJ +UuYPf3GRg9XtBb0pXssAC8Do84y1kKYj8xil3g4oe27jn1wlQ0+c8DeqXrXAcnIk +/tFAfvNyO8EMfaP74vlDC4aATXY1O8UEAStTothbtahFNpFfB/9UbvKG0ac0KC4x +43Ftv1H3xtyn9vVA4qDCmLK0cNDFKCRo+A41kEE6AKYKctbthhC0GMoj69EYPMhE +Yg9+1Ev+qI2l8jB9kGbN6YlAkM4bUDHT98fFeS/wrCnzxmmiDD/rsHzv6cdkNw0z +G5F+Wvf3cT1sVGd6RexVydmfzjEeP/6z9Xr3oMqW2CVY9mHFlq2dBkR1LR8Kju+l +vWspR2YjzggylL8CpCpeCWzd7O0Q3sni3onHFwEen9fQ0GxM9FS0bH7Ty0+gf0jm +ZFxwcHnH1mMOS5W4yg00Ri8QDgvz4M9BT+HLu+yId4QwGQFlQqg2+tLKsm9mVAnP +0Ew+dV90r7/cRUCV0kUmbYissi39OHw5sOs0GDMUiNck77E0paBnTb0s+UzBIdnq +wy+ojiDxhANB8iabKnfF/9fJ6XB0pxUQkXmKfFJZqpVzEq7ZVQLFPfyjJhQD4vTE +jOG3PdamAFOjiBBqtxbBF5s+pLZL3sZhStugqJ1l63E5tgMcJ8w0czifLjjUULtG +8O4V58yAkuqu8ICyhXXOA7Bhmn/vymBIS5VmxvR6NZA9qK9XEh5it1ngNZt3oc/e +vclArrVbev8Q+Jz6X6aAbTsDleihsRrugGkWeZCjkFIYPKlA58FKmfB7xRcvkpYn +8iuI1DJCiT99mF0YUjEkKWsbShUElR4ok474SsXt5gHtCtykXrncAPtouYPnXRuY +MS9pYhgtoMhNPXotZwMsj+YvoWJBbeBgc7WgxZkcxbum3I3ns3E0+RCz1gAI6u7F +ZUfLogdk+Og/wbv7B5NRncRT2UnWfOyyxlGtxrwqXxaOyIF9007F+Xe8NbRO/EAH +1yFMdL1jA40lacQdbxrVDQ1nVXRGL6l0O51zWC2E3HkZMclTdWp1yoV3F4r5EY7b +OLjdZ3ip/vWuMcaHpkP1lp41Q00oZpxkfhq6hrw5agpv1o9OTUr260nmHALDZ6dy +2qWNqyFYyDuSSGB7spbBeuLq30WuXNO7kLBW3Z1MGq2AmOimUR8r79OkMBkZzZol +IHgfjedxE/1uOmU5vcEnW/rGrFavTu9BvjoDLVV7/5Gc9z/q8CQbYW/cK77qD8ZC +J22oFudz2qjl377LRIjmbZp5FvU1fIPy29/7LnuB1b3xfYvFwk/6YSM2FlT57HIL +PmAHNYzW+Uwst0khEkzcagqqMDERcD/2WKedXUDNwxAm5AU8v31FYLLjeZfkmeNj +NVYXzstYWgLPtUhODf63pGuILuxQFth4YrdZitda3RRCFI2F8NVFTADbwQWKZUMg +KSVe9u9LXFxPNijyRpk= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE4zAcBgoqhkiG9w0BDAEBMA4ECMpfoO3NymimAgIIAASCBMG1ImpwNjYr+SIa +FEBPpj57UpoC8FqFKe4bnFkYK+KVapykY/p6KRlo5GyZZHycWbLhQ6LDwCgsgPcp +x/BTghqMvztLDtO+jIaEqcudX/dp0VhDZazeFJ3hYhjgmPCfTSEBYXAKmtdEPCri +eRqO1FLw8rAX+n1dJg0wnPly6M8kY4KE331G87+IAynsbieaAVkVAFm4T5+kqLXz +dC36WzcrpaXln15ydp4Ok7i0/TLcTCfVh5zGvlujKrogJ4EJyFzThyByrRWYAx+H +3RdtjgL3zoMs7s8qXDVcmActX+PCdDz8w4lqkuG362TTdewDnEc3PQNJPjzWWhWk +QZ1vbUa2lszxAnBSxHMEs0pvXy4Owboh/FCRJ+0kpZrnEzdNumn9jWWkFxkhZeZU +BD1QHEyuVN4ZzG4Vr28uZham74RQOHZwv3hiLMKXC0K8A4VSfnWZGGXaa39J58N4 +LpPwORBJOv5haLzi1VZj/IzfN6oc5PnCS51+MYOFcLYf/2qvoQbB6SNw9PxpNf4E +cgPxXMYJQcgSf2uDJwjsRLmAe8ChD2xvo357fhDZ/y+j4viB8pzKhX9uG16c1Wbo +7BHnXdqrcbgeNgk4s9elWSr1kKb0gTSkqIRh42s4d51Zrb6qQjgwM0UfydfWyMu4 +y1acFtQPicFoIfvrKxnHEjwDLW3nOhxGL3ORL42U8ICJl8XzLRLYKMQnH6k/Idod +thZO6v0habuoPp0ozYml77BmmFkdSoR9CZKweoA5Xb9KjeLGIoQk0Kg9Roxw/KV6 +3EBLrP6HLTex/QhhribaHUoz9i9tWKKWGwOl9JXeV/BM3P+JmW05h5LY4THBG68w +7P+kFvmUAXl4SOd7AVMQCJeUKIbif+Wr7UnRM/G3lJtg3VSp3IkINW2WuUgfWSVw +T/OUObFOKRZUKqEmPd3HYvlguVJM76jQ0uVi9XiEJtpNVo7UJWw5dk+V8obANxcu +qNldaXJCDspJe9Ep0NqkfQIuXMZGQo3hcbirH0y3HlBBXdE40Oc6WA0fu/L2D/Ff +sYCEaGZ0mBOuOi9CP9HailwAEL8Bf/3LsYBLSqKR1vjSC8n2bfD+Sy598QQ8Ti7C +7XpuKBCAws+cVUnMQVuqckuEm454tQxlWNnmTqoKnIwlEw7atE3Fi7xd0Yk3xO2Z +m/1+jLMfvUsYr9uYFWYt0SV7GTOHyfc9HWFb8Mtz9XvlA7RQ3gx5hNoovJeeK3Ho +3f6h8S0BYFWOOvKXk27ZF9OgEqeRryH+B1y32n6AtgeZspnOLPlMTgmvjvqYiocA +4iaTAoX5PGZuNKRqBhfiCLUT2AI6Coq+LjRdHn1mwLqBnagJFYsaXcTjZNKUr47M +7kbXX5JC12d1lcCxkTqkhV88SZhgvPzt9J/3Kvx6iOMRinWfxGGFQqiTFEwvk5zI +64aA80Z/N0jkhiibbsl/quQqi9Tlvqd1wpHcJ28t25H0eKWfiktvuxWRNj86JzHk +ZMKv1ReqWrihQyfwSG4nvMKaSJSlwuzbb7D5g71bMCHdj9ZddgsWdu93mR7xv8Ok +tatasiU0x4bZvqaOk7qjgHJCsK0dQHsfF5kIQJ1eC0akqRP1KfDs/Jskefr6e/PX +1hql/nLztg== +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE6TAbBgkqhkiG9w0BBQowDgQI3TbGvnzF0LACAggABIIEyLCaObV7h//eWCwg +detit/l8jaBe2pHs/JPd1qJjnvAjqnSBVQjkbXjxU6ERAXC2IhQzF4ZlW29RrdLC +ocxhHHM1Pt2+E2T+wiALFYidQIfawiobru3Tb8FN0QaFoyVZgUHzxeZUdot2ceW5 +TrP3PaNSWTnPl2boYy/TBlbw3W5QvmApHvA5RFR0uVqO6kASCPmThVTrutPVPsRo +Z5QZCTgZWrPXzQmyUzF5z0uBY2i2jWDwZWso63UZh3A+7Au7hn/NAqKNDeN+TZqc +nniJXD8PTJ8eNtrwk758lhbbrh7orAzy85e+WmHnmVWuZ88kULBiDdUFu+uUNaqD +gukACGRDe0tGEq/CFKJVkSDvKPKrnBLHo4uBootK+Chj5iY8KMVVJ/IWGjgYL7Bo +R5zZYos6qubuzfycRCWXHnR5cp3qqgO6oRubRXvWaYuOx5gf/trCK7dDVptYHSzB +dK5CtlgOQY9mVM6THkgzPNKlaoaWXcAz2YdROMkqEvhGHWTnREuDRmqlsCQKSDkS +ljyBFHVLEGFrqChnZmIi5x8M8rMQHTjQYYPatIUEr10suWz9So2fSNtrlbzXrk4c +rQR3XFedszYSCoBVofW4Nt5iSdRldkYh+DGuKG40UKltCfu3EYl3xKgf6VB0quqI +l6CjQY/XlDirwLVOE0zPTqKeMGsi4UW6Tecri07/48JWBZtYPLEj7LWTG59GmLPl +LFMZd8JO0au/8UESxFBIg8lBVjGpNV8F3YdI0x/inZFaESKJqK3eNccBMSCIZVxY ++gE/8iNIn/bBGFWGxpJSVAjaGMjXnkRtYCcriTKchvWq8gljhRpTt8y/hEvHzmaM +rUbY6jJyAJ9Jeso3nzpBetDUImZ89iN9LC6Znz0g2ot1iLEL9Lvtnayn4Aik6wfA +Ha7R8qy8JjCpSJtV8/COtRrzbzcuZw5I3Hsm3cTCERP1zmNZbm0MFM7WJVMdXPUi +1OS+vwlUvXt12dfxtABJG+wbsTQ9lPVGph+aixG1QvZVTq7eq0MWo+dJRev2656a +5VcdmtVo1YiNCG2TniZjcIugksxbjwRdmOaxei7VPn0GuD+4oi5fon8IlpjosJJW +FEc17IO7rqidXmeFttnnPLooAO5wajNVdAyuCs3HKJsnVLXZK42doWnNm7k+/uca +K+ai0RHyQLqWfxcU2U78cVVhdgnmFU/9d/+gHhTfhzpCW029NlIgNuQTgU+mAiug +27Mbrm2Q2f69SNXwWgKw2h6MfMsQxDNZI0vqbA6gvcmkwgbCrrZJr1rSl7dZaZuI +ek7l/yG/dqyzUWKcHko6jL2OM16cKkVWTRv7o7Au8RrLA2G7BA+FpHt9ZnthzX6K +LMPr6an9LMwjvnxD15YfENWphVqx7r0VYQnL3AfEinuJ9K4jyGZ1nny35jUHg1tF +XQbVIBfxoMuSLUjDep9E+iyfL5Qogh2hlZ8HuXcRXb44BucBlwruDuJm8Ft6Q84k ++pw93biUrfEm/7SXIjC5+Daf+49fCrJbMQjfGUAxRxB63qkEtNo5AbLZMlujQxFt +ByA2F5l6hq5cT97uCDPcYdW+QRr7Q+rFVy8sqxtp3K/D1LHX752yRqBl+pnf1tJA +Dud9ALqr+fQhxbd3Hw== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem new file mode 100644 index 000000000..e31505333 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249 + +ZUo4tso7YF0+ayrQpLsgM4TN2H31b5g5ryj//QqqVG/WmvYgl56Vu7fDbYXytgnb +PQoJLo+8iUI1d51nirw3RrtAx7Z9lrBu6mX+JBE7nwCVsjBVVlAx1B6d6Jwc20wj +935VaUkwT3n0zZ1dwb9HLjEGUp82TIbiZ3KjWKnfER2AhFXJl3SzswA5Fvwe0AYm +KTAEYaaxigTTPgltiEQDIvA/Pnh9ZHjh6rbM816Fa2hdk30wjU4U/KkTYbg4hdoV +vLeQpYnMT2uICCuvNXq0cXXetfbgdMFsLTxvVElUZrjyMTsw1QtjijeM+gj1dbDj +HGzR0k97Xj3q+84m+SoNW29zPLZzSaFDX4KdKKG2cHs9BTYJmzb0h7qP4pCXjGgF +8V2iUDMs7BQlgNnOa9gwT7x7DN4HM6J0MIlNIiYQZnupqqYQTDR0rd+fhdIsXHkA +qNZKI/4ep7voVIufSS8ZyoISES3f7dvs5nnM2C+QAtL+l/yaaqRdfUyn9BL1djaP +akSRPXmHrmed8s8YamuhLHyf+GPL2uYpd4i1voA2KKYSx4PnfjH/F/8fXPZr3dNh +sDtcjhgXHTNAEVVek9VOaHtlUNZEY0UcbP5uqBZta+wP2rBTC94DxIbN+k8A2SlP +cKGkaRltjnPJAXWmwKMRm1J7vXngXYq0r5VUvnGPiUhFlQwAW5TUml4+1SMEUirZ +y/Oh3AjhOus67uiAXAQoqlr9KykueXobFrhZjLCgRf7iDmP/t1eK40UyV83w85yz +cORi8FNfqvCARz05qXwfhf2NBMTRbLNzKCGjS4iY0dLNk+QYNgJGoM4nFVkHYgbM +pTThzpYgtRnxQf1mYTZFtqr8hRJqiRfexzCyk2JC3rDtEO8WUmNdvdKNN0KwCd4+ +dcVS8KzNov9fYMqiiol0dL89WBN1RN+hs7HnOJkNZZgaNVspOLCT4+SN5fLgtbJI +BzbAgTK1ILrSom5fyzZcRkYwzIqNc97YhRYnxDp7vJFlgsBqySJgtdGUkTPrrzAO +CCYyi/ukSVphPe+qRsvj9L4syZgpLRgDdZaW+BR0pbTUg2WQvZuKL5iMhfB8cbAC ++FjoKeSlxI68jukrAYHBNcco+qaAYrUaHsJFUsbf7j85DzHxnaA3M+P0i+LWJwOI +3G751QR2CrjgK+QD7XUtUjBMrsVGlJmfaQsEm7+rtuPynXq+ArJrvgha4lc0GRD6 +yNDCTTMafuBnJ72wop1UEE8zGOsqERsgvOAL10J1s5KCcPHGwrDhjhr3/x1GI6/e +H80zp/E9mPgzYQMfhl06s9SwyvsxFCIZAfrKIhq7lVqeEDiusYbe15kCLmTVNZ6C +c/BhDc76vwek05AOLaZLGbdpMRwevbOn4WvUHV0o5Yr1h1IGZKx9BQYwFS65SDCg +uxfM+dKulE6MWD2hPUP9s47+R812cBnHu5BVV+Cq52YygAiAP1+nfFw7TBKzqczo +fnIsoL69JthqtkZiwl36uMmcoWwZM621ZqYFJI53WO57uhW0uuoyidQj8HoNG/re +o3OyAgVO6sTFsw/Dwxo4WX2AKuIt9W2IJMFNC7aS7lH0iPrtiVC3FFXvuY5agipH +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem new file mode 100644 index 000000000..8bd32ace1 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CFB,2F7AF90B0C0A420FFD62214EBEFC4CD5 + +hciElffC9lqjzOx+aBT3DYY0/oZrI0Q34xfQg7IOTUPUAxrrT/UjHlToX56VIbRm +PH2M5yoF88Ji7BI2V/Y2QRAjAYRFVjZvPO9ke4IGYI8xfnKRivfxLtW/YfaiKnqc +7VyyO2UI2tYGm27+JJbGLR+GdaHmcnLmencGdS4Hn3KDQ9IK4eLLXrBPWyzGnxEZ +qA2OWdzqodjppFCjlx892YJUsq+w3BXu5lkPoooTEoxB5RywZfngUY9Y+raN60S6 +zhjkaaJTEqAfnAsdVMUvzpkYpoH5LCO1vl4+XpKdeUu3wJ5p3D9TVc4kt6/V/MeL +rHJVN8FKJKYddTlaP7xOmh4bivrJao6LzRUdnyxGL6SkVQ4ipitgWcSwFGgRQc1m +/MzFmTATtC8tocSqXMY8nblp0/sabGhUSTGG+uBGddDr16D/8J5rb8cMCfR0KLPF +3uwV89PbbqpS73IUKkolRjxslO74TPDT5ds0i+UV+J+AJM+9CnyY7WI3FgMlVvRn +KwYJuihDzFjozJfe386XWYs2Joa3Eo0vbaVvp4hbHq5Gh7S2iiBpqy2uN0xxuZA9 +QB1XpLd+rOC0y5l1usuVc9kBlGsTiFVyBoZo/pWVlTU3z8Hzgv8p1TAJN6jgqVH7 +oMVgubXsz1XPHrrjjgZEEpxqzXtKJw3DKchGDfAn4VLTSrOINwMC5sR8l30OZVtD +IdlmftUBhv2AeVUqkLsSMKGdeagfwoqOlfL4FKvSt4n8Vq+Hn9lY/S7n3cjM17YE +YAgpBjX4PJqXsp8K5KmBHPQMB08jW+NQFABOprdes5bwflrERogdLZmQH4vxqUvs +DFhHVJxo1wxeRDOftVgtxnmHzU+SaB9MgdWWhC/4pxx5uzqYi0Q2kSOZ27EXZNdh +MgVX16W6jLUw9zaR1wJIJZU7SmhJOL1fxvt85RytaD28+JvPTNs2ffDpjPu0sXh9 +n0gYiWztuBNUv1m+LMpi1SPtHvtoZLhc++9g4BXoZevtgNl+FqvHs2Ob9w3yXqkT +lyJQbqju674MaKXDoQ+3+tnXad8MRGCvIgmIUzmMZj3O7QcrBbDY/pbcxoEDOaKI +SygvYvKfrBIKq6PuGsN1KHSMrjc2A4+wuTYy75xsai9YtwwT1tyIIeCv5NXbbtJq +vW+nbSNYW+khIicBc+Ye+GFfUh2MXj+iC1lK+5i+1leKo4zLNFDmnXKgZ4jOOPMa +FMYPZkwANQ6//tyP/qzLWGyBucIC/Ym9hUvi0HlYjjU3Z+Zv92vM+2+li4mtMy7M +tdcm72bqsT3+1rtJKKRaYG/FiQizOGTDyhgV+JX9MEVwJPa+61V9jwkIPPR6iBrl +u7NoFfSp666XbD+LurRh82vlS7KYOB2zimHFxI6nOHBsypJynqtgIzLg5N1+LhVz +t+cxucW9eFvkEEXmjZwofqlxq9BDso587kKY+EpOkXrlnG/ha9XeZcyUipn+jQ0Q +64Cb7LfvcU5UEXTcMh6BKkoeNP07O1ecpD1LXMGYFn2HsfYHigwwcZ7sm9oCCC9q +vF/rjXg/oIMagmc6MZOjRE2eT9tpLRAaMynLiln7XS5u+Q8O3RexEw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem new file mode 100644 index 000000000..b6def0873 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-ECB,3E3ACDA483AAD613760CC55C7DBFE582 + +PJupElZP0QC92uiYotAm/CG6i8ypU5SXxc3zmrk7sBdxVU9JQXsIE/oIUK40AlFW +cGuHWxxYkdYNtTpuwG/CVlsrq20YfpxQrl525f4pz8ETWt/P5+aLQ0TemEKr+LVE +921o6LNstZpftQJbe3yMz0cFTjSfsxsHbadfUZUQzobr1XcbazPyhr5rrSntgIMy +rJ5M4G6QrOEAIHfVVZ1oizlFnd4vjGOKk1i6APgEEqJTIyFWoCXEzDtaMcl97GEI +EWGusd8DJrqpJKnohVoTZdOzLrnerJXEUEJ0cz+UjvljAYg2MBSJk5v6HCp8aWcc +CCoWUbJp2933n4nLBq7EXTVmJ1pwbB4cjNM1oL2BznW/pdznrSRcw8qut35ikEKW +mB97+IMVr03orl0uFjHBIch6cPLYkXKi5w7CO4vvJeqqPK+mCtckzgIlzsdTL7Pp +tp+wrMBtG2Ibh2HeJuvvlFCgoYBY482aPu/4NMei2eqfs0p5g0bf67R/BiG2Sxxr +4o8hmR14v+dzLsQeoKrr3RnMqfmrbqgdkUfgBomlsunHUu9u7jB70TuYsZk/COPn +SgMM0T1pxEuHdXfyZPSS9u2SFGEhbW4zIuVz79Lo7h3sKdYJqmwmgOk1P3IL/nra +YpcacWzmV0g/GK8O+2CSGvEh1+m0ffQac1Pd2Abjzg9jghshsBTVTpkcFI0UfkIm +gpP/hwLONl5a1KJn7u/ltFPdZkJ5CWPe0ZQ1mqjhDaPnc8j7iuFzUilsWITLRof0 +KHUDsAZSV7gZ5G/Lh6DGZdlwfkD4b+2GOPayQ44mr4p2hdOque6Z/LEXtOv+UvvF +kR9azOu2RXVTiDLL4c/ntltS6laT/nCg0goMs5NAis+3cxKd7Uk/yXBAulwR6wmy +MIZuSM4gk2pqbt6TJWIfxl4ZtPwp+jYIpMZc47XQ7w5m7YSquJzjilaj+IDVPkhF +TWTMf+Ucb4duBD39HZjBWAoLkF487M8KDtcxL60uHuhVJsKyYsb8b20ukA++c6aH +0VqU3NB8VXH7De3pA08G51P+XLurlLUUr118STaEd4r7GR8FddFmSh5x+PSuVXut +D2p2W7pfvS8OTuaMF0PZo0KkUq/TbTpvMcTax+G0DgGJqFFhqxNur6WoJyYbQE0M +nX8USnuJhS+BRNPEXc5i14dWmZEeE8i2KGm8RlL3KZfyrpBk2zwnGs+WM8xAlBSY +KnGO6bLvRaUl+8IT1nKfY30HLr2tX+F0fEM9Tn443VgsXkYnMoaPDU0aW6+J0lLE +lTeqJn8MPVRbU0Ss/0Q2PQLpayHrR+ly6yxJPOY6Nc1eLkhXoB1DwiGh5Mp7J6+V +R5UL4nRr40hZy+35sH1lf/+1mY95Rb1hAYP9r5K9dAvqkdUMSPz8rtzb/4gevLi2 +rxB5XyOHM/qZL9ySpJWjFPBwOtJ/EJioRTvnG+/8jdxXWBiGKdkGLKV8k1z7gOee +ewq2/8n4HnzMm5YKdTesy6LuaO5TaOAUe89Eo/CxPgdM5YnxSxRsxunrPR8JMLYI +V6xyNRRHLOy2ffGdJZ3nqbSOxCNiHW+Glh5I2jyrKG5Bs0S1jbt3l0hZKWSU8k5k +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem new file mode 100644 index 000000000..2986eb219 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-OFB,271025C313E6EFC0403320C73382F15B + +/L1xK2Hx7pYQBTuhHX1P/mkXqLAlbSSz58hL1E4oxsDJODiVH+ueTSKajA8+tbxG +eBK4p0s5j1fp7SJ9m4QXBwvhCnis992H9kQws6U9gGFrofrYAniRFhX6yzvm86ee +deQ2Pfcv+evGRPigkoeRSQGxSa40fJ+5cBs4G22cfrKabaEKxnLtQpqPG17JQ4/f +LdrHz64IyJTgvV6LCzJxShO7vxwIXaA82HNR6Qp09WUXxLB1/pfQ8oQfZbTUkvWi +CBdXWT42VZklPl7StNiAN9U85K/USIYkKG47CpJvWMYbWJ3Dt1EFiEFi/wmYTinv +b2K0xUrVUKxAMfmVtr1wGSJA9P9AT0/sBO2vTn5ibXVVHibtAET+vGXLtpGqf89/ +RmcqNEFYxvLzoTyR2FONtVluAC2yk10cKHY/pzZwQyVfjcgMlbnrZz9Pp1Y6ntR5 +AfXpVR/qyYOaQ8BeMCXkfR79GPyCPV6txy3KE2mbajwamvL7eR0+0R3Q0lhVcWGp +g91D1nbgVFkHGOugO+2yb8vLq9k7K84Za+TY9NCqCG6g0S46yAgZD2rqrAAO4UIf +6+nno8TS41W5wmsdEarbRoIg7iIKaPKzEmRRurSdlj/s7MKHgQFoet/OdZuAQkV6 +FumyDmqekmPAgIIJEO2NdrWo87RWKCzc61Yl52qmWsqrJIHrPORMGdjdlLVxXXIE +XZQot33Rx7/f0VZktYB5fWk08kjWQ0sKTDiHEp8Xobq/RDyMTm9TFIkeFm4rLkl6 +Zt2bzp7ssoKeYuJgpoRzUmGP83wgl+AaJZpupARdz5MlqXd5knuPTETFPaFIf98d +r/sl/V4E1nh0x83HNOBrLlpKbeWocVV4zv22q4zemALPCOQKUPWulINQWAYiTPDA +lBQhFRnJXSZYFUqFWpxjp3yIWCvTZd4wgX5IQpaJvG+ehRn0H4FR0hJukMG7Pn5y +ye0M0XlvVYWfxhLRDK23iNkRzVIbIxZfxqaInpGvatcTHyb2vnVFateSGlXIk0wU +GxgytnTGW2fZtCDOqeQxCL66nIkpqKhB2hJKaD5WIG7SUikjBblvVcN+gkj9IWML +7LB7xjE+4cyt27Rt9QHuLchdgSScPnPTZhdX0iK1LVELlJQFx8WPZpfXwpQR/xz8 +tqAKOfyhOX2XxYYOoaNN+ffQ3mEnsVFx2uQOp7PvNjL06XdYP4p/AruzVnbqsDsG +BIo+oo7PfepNw1jRxcmeoaMotIZ8Feq8H8QEARqQSnzRWAJZhV5D9ztmUtaeqyy4 +QDbgxBxdV0nLAWG7e54FMn5yJfjqq2pkBl69ZvR3N+F+L5/eWlEpalIoq2l8AffY +gDxlGgp030MAyFYSLJNYj+UUwq8k5INaC0QKjARbBMblf0HOX4U6RBqrpzn2xyvU +mlM6pTiO+mOpG9WLgQS9XTUk2te8n0vAVUTk4Camj94Vdl8JWFNsfJIgwE59hprg +a3Pz4FosIcBbj1pYtlA9Lz3kIGe9U3z9rHeQHNxJ8agW8NKGvlzY/YBdb115UhnM +WOVp5TkpF2MyE+TGWqXzwNo3GutaNVs5YO5nX3Mtx4ClRrsmQYVTMg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem new file mode 100644 index 000000000..b80686d8a --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CBC,51C73DF9487965B976234C88321E3F30 + +6yLkX7C2XTX5AE6KqWsB2Lmt+TMGsoHIH5BDl+o7Yjx7aBSzB9X9KPTsVoPmTCOg ++yhhV6am/yBImCdyuY8d9Q0A1kPIJTEkshgk5vc2KpW08blLCHSCjokEVbQ4TJDH +bMtrEBVMU1g9KBTMuBpbu6MLVaFth2GTsqExX2gu7FB5EAKvEGhkmLudo1jKkgvR +aiiyMd2CH2MTdatZtw5PrJmkhV/6RMZRKP8r9wkez8NN14ehmk5QDY2s/hj5uaEf +xK0GXY6OcwoRo85PsOYhmOeFDqHKGRo9a0pPBy5ZaV4udj0QZekE1fziOxiPf6K8 +0BL50UUzQBW+3n0dIZbzlOiJQScQkjoxi0kc088FHXHf74VBoJUo6pckAu4OwpXW +L4XLIGAr2Kv4OMiFSJOcaihyawE312B2URcAzVCO7skhTYHaC0fMYDJCGTc2D9rR ++V5tVfT1dG4xdB+p/b9TQyAu8PE10jT+tVNJqGsZRI8I3iOtyWsBcn4sQInpYFYU +R/v2tgG4hDdq1beEY5N/ZaLsoSyFYZmwbzB+BVhPg0W/9s91/nYAQgOL6XrExQjF +lZxS28ujAq1LDNzg0NDA2KsDGJF2TuST2stnxyvf23h8+KV2nZLOZXjhlVl/Nr5O +WPm3gCmuPf8F6FPqM+zI4YBBRtvLRkXafUNuvc7PYVNiaPyuMh7I7U1EUUzTpkqi +OI/YD4xv6DpDand/WEtLHaYfVYU6PAapLV0T28BoFITp/qxHYYnXVfhn4htSgiwW +R1btcxWyNjsIedjb1LJ2EwEfuXqZmzDz51uDLBq3XQ/dbvDkDzfZR3O1KGaACxAT +tAeAdnTnAVliWYQiJ7BHn4LTJZ0ERGL/R1xpQs4quki4WHtEBRRzP6BbmUYYhigO +QwvTK9darP1Ev7miF5BkRnrzWqCQHNTlDB3i/RzIfIDChQbSZtrpZH/V/quPuPlO +1353Q6D221UiChhw0+8GmIszbLwBkDq+Zr7/poUBAqHmTaA3LeiahACM55ATbg1+ +FKf0nvUL0SaEBAqFxSdQ1mnW83VCMlCE7Luh49BDl4/nufCdF+iv3cYRW2SDHPrU +HELYYLz+b4QLl+XO2SgUYEkU9s1Z+eCKcVUXGzz6vZUsA8UwvYIy8b/1cz4Y5sZ4 +MLpEXnQRMwAjArh4fvmosAG+diC18H2asLWpUS5HBBrSb8lAqKPLl+n72SlZkFjE +WP+qq3koz3EyJsjwH2qbpx5BLhTPcEVHl3DZ1eOQmCXcpSm/cqKp2MKQFubCC4rr +nphTD8uYKCP3mJXB8vqIIO9ho7+GVlCHJdZGu+3bw1L89O6ZG6WClbY56eGz2xUn +DBmikb9sppeYSs0eX+yQ9kjQRf/BGnRab2dSTGtDT7jp6cL+zWUUOawLHWS72XtN +3XYSEvvAWPygwbBuAuw17pwPPmTXduRiJosR1lRk28FGsMwzbj4byXm77IO3vD80 +cyrAQ/bmSpvlmYEHvmRn9N7QT7SFANY4a03aBK2iuqZQUz/zeo3eyrJudBXIiwUz +/ZRteBa6SQagqDsmfeuGCjgTFGVnutCokh9lajm9BZ1pZtCmHEDd7yz4Odx5CmxG +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem new file mode 100644 index 000000000..00cbae570 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CFB,58F8574921C585278A50F7A2EA529595 + +RQtPMTKDNttPq1R+DiwHrEK33FOfxK1Cst5x1jrDhXe5MObLhqbz4Ft2idjtG/vC +pemznnZqQYKsuJl/Th6Ydsthkg7HH1pYLRstc/tWQTESa0RseHDtdw3e/Wxhm6DH +pSqymOfRq8R7PQKPxboj9fjxeooWlA+RQxGdyRJ6gki6PljOD29C2hxZV4HuL2II +tUn/cdzaGu6bCvpFDvDuFja3TRtIrHSbCq01uZg6XrFui7BuwJxxR5lERsauJ6RX ++lAvhwXqN4nsEQefvZc/GeTFzklsoJ+c3HJy7pN15nyfwNzmmH5EK7C4CdBJQymv +MRwe9hY/LGXB5IFEgXvop9bh2qYk9tb/zb8aAHcLS9rwFsGOo+5+Yib3ds4GC5fx +ILKH234g+hkhutao530kmWXFf7qup8lvTlBZueAWcIFdmBCsWjm8ejxQUZaPCqEY +sZ1UMDw1HPX7/4TXdVNZWrxHisv0VWnhwJNflEcI/k/GR0/qUgkHnUPycWTtg0W2 +7ivs7D0EkIJy2OyFj5swWs+eqhsSDmd0BgGL0VduLB0voi1eU908Af3PllsTwf4D +UaLFvOkllIbul+YweImT9TinmkWIFMZuNDR/PHjpbLN/39YkvSub6oS4LOgKEu1Y +Xr779QOZHMcIP+PXoaxqOWls9hgI6M3PAH+gAjwF77OWIQIh8JZCibR6HWYcr/qo +iFTzJGNN7P06s3IOek+YoHG1c0GoPsNungPOzthNnaAUcRyvZ1Yg8cy/nhrA8Eeo +A4G/I241jr/Ex5jooykpeotV1/AMIF7qxFeTARQgObRi/fiR0r9rjaSMbOt4PlRv +Ln0ZBqedtkkRBPRGO0VViSbUAUOq0oSb98FWqPFpcFl8tXRyqe9m/W2zACczZplz +OySvRuASdKYpGk4DmMlQtS8wjzMYTesBx68OiZfw9W2nkH+Xapc4cH8hyb3+aXXb +b53nbp59+mx4UwPOcrdzVHdKhDT3BjYrJTv9kHAY8yA4Nr08ZsO5tOeI7vF+bUKx +kWu4AIEccB030iu87/xHXUEOBzsV6HzzT1TrZ5GKSh43vhRwoasYON2xlO6RuKCD +Yv6GbcPd4lv2mv4lAaDXk5IThABHUL8yhqfwru4L43av5AwdslRKIvBM7UWrlXFe +A/Hipy6jjcusGiOyH7WfWBFV2/f6NtX6lGuna03F/yMZcHI/HEK5RyhqOYOmcxfw +A1eGKSqOnq9IJ6vXnF8PuRYKB9i8Ha0z5JmWkh/dX5dhTzwH6wOz4+bLgkgXBdhY +jptSs5zsvrxGiLCbENPTjArsBbT5NISh+VTrrUtmA5BLPWx6d4NNJ5eBXTnpOIJr +rxA0halZtFYKj0mp1ZgnVylHC45QDiwzDnhXra83RVrcgQjcX4npjKOaYZRQ5cKR +2F1QdvoLvE9YqhjH0QFQWMWfvmLHGIDIDkSB6EyFsgzWdv6kIaiYsmdir5FzE8c5 +SvHvu28j1X4OL62AquOFKMXQVns1/jLp0KERx1EhrQChHUxpA/cbqNJbhjHoRQK6 +0zXWP9gNlyrSIKY4egyQmjcTDvNXVcSDu2o7EfnprNCYirFgsAbw5A== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem new file mode 100644 index 000000000..106704e94 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-ECB,A3A4C4B92548B906A635B84B3D67591E + +E4I7KvCs0qknDw8D9ISQev5oQCNiHskfB/SvuKJ/qJoJP52qk+ajN9pNMp+011R+ +MRaMlK7tANTrQ0L/Yc6QNUZW2aHyiex0aoC4ien4ojgvqHfaP12dMxFhOoLctN+N +zrAPSuQg2OEBiWxEoDqpgA7FTUbxPiJ3QdtwwOXS5kqAKIEIoNnCPCL+45uKBrP8 +encSI+nrZIXLFqGEukKZuFH9qzdF2leOKSmEW1kmwxMOfQLMVQMJyVzd19cCxU/1 +FZtPRRIzFlx4PlNYLKDpypSUavgo5V/o3UHk6vbP/Wd+Wy1ERwNliV7CTCCpOrBH +qJezvhkbktiHQQ7+5zU0jsTzTlZcxATdm2ktyfEa5GKrCNfrmUYNwNSi8DC2Dn1x +4z9r6OfKV3dKcSkgmFS3ZI97ZhrnMqpvo0h1kg8tuiboI9pPWp8OsLIvw5+jz707 +GLsl6hI0EX61YFc7bqeetnObgiaJMJxQJXHi0U+Z01GjZ+qgGb6USmQ1D8r34nuj +4l88VYW4jBhxa/IFpzUoxIioKG58xQT+OK2Fi7BF/OJLQpj+3RA3YLqry0D+AOT+ +f+nDJepwrQ/CZtoQl53ssct+mDY0D1IU6u7ah9WdIuuptV7+WxutFfDpXsmErKcZ +eILXaH5zK9iNVnVNQDmnVacjQt0x0Rm28wrjI5N7M8jGWKWi9PMLElx3BTo9EbON +pJ6x6xshjmdCR3gOLo86CZGkoUM1eNGhJuihrl6HelcZxeFnuiNYnLb5hIaqDd1v +NpFUQBRC6Q3jz85zIvVsiN2vIyak2OGDRs7r5dqb1x9QVz5tMjxuKe3t+rfX1FN1 +vCusACQQzOl6NdTgmm5Of+pMniOL/kRF78e7zva8vM1Qf31/z8wtq3gemt+pZstW +WV/kRhIvY/p2Nm41TtltlctThbYquFTEy8gxhB/Cot2k7Z494+8UBVIn7SjsdDpU +X+N24itXM9/sd1LHrXBSbBT5PzSBJFC5MS4Nt6qpvSKIRbyWINjUoTvbbUwoCo6g +soYBPJR9KeAcQ8YdBOEXtFScq7c5ZPOGCj/+3p++Pk7yMmlxNPvs6HLjdHchjAYz +jycK/uWYNLOwKS/AMxwi4R3i45pPgIRuwGdRyi17Z8kOKATdyQwScbPOShW9/066 +OA0rEORx3C9gMoKa9QYo3O9YLjA7NS1ERSY9c3X9anSgR7eSs+DLRwFiB3EHoCba +ULqd3n7qBKgkQpVF60p34yKb3K8o5s0cIE7oAm3VdoI/O/RSs87rDmUbpuYzAA24 +mXRwBvPpwEhke5PoPeFIYmcWa4wUZOJWuF78U/tZw047vcLKgr60Z1s+DlQJvFXI +tXkV3qS45f9UDaWQ15YNev9fq+x/1JDO1LjQ9AHANBjRQSzE9K6YpyIw/SZlbo1O +xuFrE077EL3hrRNh00O2rtcrK53mAOKMX9D5xifIcN4/uD9AdwU24YvC44gij47m +hSg5wz0RokMNGLKTXaJxJGs4+ZK8JWQs/Kf/V9j6j/i4iDWuy5Ra7+/dIU/Qy1ZW +cc8Uo2ji4i2z+QyzbpbR/jBqO++lcV2byEVDy8Xp/0X2G9mY0ymIbm7ATTlzE2/b +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem new file mode 100644 index 000000000..88dd91a78 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-OFB,9797077D8AC3052C37DE4D719CA8FC00 + +SU3g1XmkcVhlJpQSWXdeHcHI8IQCQBg0oenT/35NKgWnFBlysqwGwl/pwgdDBmm4 +jLsPaE5Vanm4aqWv9DNhItOQokIbIkxF6qKeV3wNSNbTsSaG2LNphwMiLs9rw4G9 +3aFV+0THPLAy3BDTsB3NPuRqlOSVcwVrfaeMXQGhCOPGmsGDeczai1xH7eq1C1no +KUqNMGdf8g1NuCmQnvswuTF9BCi6rIO0JRqLPTxoz/1emKfHhJFefpSj88zg3ucm +cz6ZOAlsmWm1MQrktXd+odzpmjHtd1vNsgr4GSYUeVxxWQX4o8pVFqWqiQXii+HS +ubtMARXAuFIGoM1RCMN8o7sJG00RbG7zNxfhHqe4wSkKgx3qEuusUDewXkDeYhHJ +HGQCD1epByGHCZkLwBntccOqbCQoSNB0/PcFU6vJrtgVFl8N4VsNMRuLj2ZJ7uuL +/EZ3qkLTk/Ek68++m2dtAdyj2KF1O4z2SFROSh7MCqWl2rYh4zZcBtGEfmQe5Pwz ++kPycc76ayzHO8Bjg6rl/16Ua5Wx7d6vy4Hg7JYb5eDmj2UGJ8p/z83KBdQnb1ku +84ZjpYgmtjZ1vY8Z5iZqfZro9JBjWM4wFZIKNXcBniC7kBV9fRC5nzpjs6qWTPRb +bd7PLMuyRZz9PO6cRuhqYlP5tYSGYYVhAMVutIqSrQVRDV8AnmblfPiOtT5lHC48 +GR/xPTIFxxVqsDmeyBzyXn9gzAJKgjTVCXNksXojM/ZMfDDvAF6m/Ntz/izp2CbI +f2lcHgsm7SwVn2fvHikAugA9B6ixMCXygO0L5OEUDJW1e1fB7FMasjrwRorDsxsj +JUNDW0KhUXWt/U8lNyfRm3oNUjQQU3x1iEymjQZV10ZO9DTn28fZOF70moUWnl0y +ffELY1vLtLNP7Y5tcGNtJARSGnMUW99P7OKpLNXkhL8zE3DGEL1N+gDS1n81kzTH +7hPjM6yR6gJQVsQrQmXrEpIlHQeGA99LYchzyVog14qMhvQItDlCsr5UIPwVwhMP +LTA2LITZOYieRAqrv3vn+yFHYG4k9/C/xHwKHE/4pDw8bLn1o8thGv5ZW4yDsHGx +n6F6vqJrkPW6vXkmwcgO5jK8JBbEpyzAPc6aSsibH3JF0ufsfs2hQ4bwb96OmU6v +mukMLjQoi3BJC70Op1bpe7wtCELJw1oFvbZDoXLYsa3c06HK1M4rmzJQTIEBjqxd +vs3g4L4CQ4RHAzlkjLrCF+wcBHt33586bDrt03qBEA7GSyAUu1NSM3UKjjM0OydG +u8echgFIz6XetqDICHdN0r3ZWyICM/FgnVQhs39fCgafVJsy9C4p5jByUuDPvebP ++gvvVqkb+DGwfkKT3RUFAcYiNHdtIob3kmp8OJKTFk/nwdUwqUTEu3VFCmWog9ps +oe/0KOL7j1Kn1xEFkOt5MdSFCcpbsYjQNi7F1gWAr1vMXDDPsSizsniGSvXZIYBt +Pk5AH4MflqbHFofWClhGczSLi0FRiVPqWyudoU7LOesQhhN74Dn5IzkeAGtDL8r6 +4vC+G61PZdFXhLXQfOEL99hgJ2mjQP4rVqwdz143YE4/CUHmpq6d8g== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem new file mode 100644 index 000000000..7b032036d --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,1876F5A50C9046D504D47B2BF8951875 + +BAPOppBjFxMrMU+NI00PbmXXutKdPAiP+If8JqX5xGQDB9bSt5Q9R2QkaMx8Z94f +trVbp82iERyPYnwcnA1Av+pcZhKi/mYFgDBPP+dDLp8qKRFAWil0zc0U2jkfo0U7 +v8cpO5+oipkJ9RtjaTg3/XmrwCUFZH4KA6G+SUFc4Oxj8/dzQ5YUDtJ5iyArRlnr +v4nsvP4OvsI5UFYwp/T97ks0KSmo6YLMpJwUBwcleX2vOhX8fd3thk9I+EbVVt/f ++JztCTwr4EsLxWe4XVmit9AKfLU0AhmcA20j2YXE1VFvRJdyr+gOGPD2SDoRgiZH +rRBhfi7cou3QmZ5d43jFYoYCBc98blEV07umH0DXMTL8XSrfWNIjZf8uQR3+ZbHt +W60jVdhOCEb40KoRTHQAMBQdgVVkrbXCFyc9NeVzzhPqyKXElGxLBjRB9u0h15DV +WCJUdc9UGuHzFpVFzpEaehdm/7vl+SZXUzAOgAQDtL+ATsvZglyMx5y2UA+5L1eZ +grA6e3tQFdBcv8w+WgYW37oAY2VkHKjoHs1TnR8z1t+OpVovnpcklawybh9Avv5J +kXyZGc+lbbb2gvUw33VeYR8yIE4zBoePuhTFM3K4NfkBbKavBBXMjQlsdRzlt48r +RqdFnpYc1XB4ZLP2VparhG+Q1UueVML8uBcd5F6X/0u9n78LfIITwRUpVoaLXRzs +94Us0pbzWFDxqxtqKPZHLAVJOYvEOwZD5Haw/bwho73EHEx38MY7mk9T5PonsBko +7Op6aEmKK1qfpJ1aPvy74UmIlVDHu5WEMkYx7nQL67gnFXHY0yKjmP6dc2y3+nfR +qNK95RTaS9VbACRS+re+P9+Z3aAsQGvj3MA+4Q+qlscUmb8uk+M7tg9ADk0VSe1u +Ts2x7UZroI61c+WzgsQzMAwm2QLPoKQcvv2b+iGD82enAtleTTHL9rkoS+KmNNU6 +hWL+AJ7HP9s/5+FJ7/4CD84pcLECXQ+f185vvE42TfdZmoq6NgSKrGVZPLxYnyjO +qa2sTRzImZrXPtsnFEL9OBflWA+ZHaAGo4HJNxZW4Z90HJlAZN3isSZnE3jPToKP +YFdHsPv5m/KpNa5luh4L3K41QWzLmPlRR0aygWM7/0fYkgxI8PnBeCp4OjoK6qHx +VYTWMKJQTLyji3YwMr4CufFAVty3InUZzm+ALMFHqEORB6JqPTR9mtnR145FHtxE +1z0LnEoDFEdGuLjtC57yR+lYS/vgMbtj4EqQ2zK93JaXvI2HxxOiZCZEDww262Bx +QZo0vBoAd5vkMKmz5eAMpRVkguF1wN1RPvao7I2auJIHp/3zoaUowpZgtbmDHZFA +Kddfc927GQRxtUH3QQVe1R6FFAa7JBHNeJsBvZu3bj3l/7BATzcne5OPhjZ/t8Sl +hMqEBZuo0svrEc0w+e8dpbPEjuj8UwBmHYZWlALby5N+YJ1NEtLYmyHe2PFNXwK0 +2fo45CCSyl7YJrHD1ONJ0M804ML4nMwmYq6fOAaV9ufQBFqQQj/hyyE93blB8f2E +I8LMN/SUKN06YU0nErN0PRdm7CkrS+kutn/Pz2H4oSbUZ67z4Ee1tpnVQjoDYdQU +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem new file mode 100644 index 000000000..a616b68fd --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CFB,37639E4753C0E4CD43EEDEEA18AA66D7 + +HKuYoKfUqTRf4sW12EzTuIFK5J1FkeJAD+ajYnKeKYneNiDbmDlQv0kIk12qBv6l +LA0oBH62QKjUDKi/sg8NAO5CqYkN2ZB0gQurTgGT/jrvMkkkkwE0x1n69bGNScCN +mkqMnAnjQqbo1xERzwqX5OWNTTb4iDLiPyjiUlQDONl14pe4x6zGpVziCVCQh8Q6 +rAPDryZBg/wQtPXNhNpk8MiTiSwe03wq10QP6W5TmUIKp3kD4OVfBxpW1N4znyIu +unJDVcRdBf6XA+aL7plAsETL6F9Tx3Mxm5GaeaJcSOWWzKMvqYhAcEYwM01lx0w8 +LMMRUogny67ZqaLywXZWH6FCJGCnJK5oaJE+jlnKZ6xhbwAxMyxWRCZC9pF22ocI +3IY602+shDOWZQDoihhddwPJejh+o3mVFEglco3YEByL7Cy6GvqxhctEEH7uKvlQ +gXGb7srmOpeHHfP76N9afF2hn0mqyToakdZqgnlgT2jm4UDHJ1vQ+onIksV56I07 +tVMEmPhXQCIHhfKdzEgI/v8CiLL3W/g8r+20/5qyKCL5vPBLAxmRudYKbGkhm5pq +GkzaSp1cKe4ipUfVc5OEUikOMCuadal0TUQZ+h658aBCxLWHNPdZCzNdY/bZLN9z +XPhAzml/H6VOZyIxb9hm+FNESvqNKdlU2NaE7HW0ILKaDif7gsZhvogP4qNDp2P9 +xPANQh9UxpA16AUTUNOqk78t9aQVpbjZfAeGmcw6AxJ77uK649JgkEnKqcuxcDSi +zn/8NGeaKow/bTW6jJJj7b4cMys32uxRjeeeClC0moQiy28OIJpRRCRJIs7Muka+ +dMBoNyftBnCONH+oqj+F5au3QPMwKH4v/4VpO3hcByXcqxegH+BPEZzzYJ1OnI3u +dh9VlpTdC/CD+Gn3ZRqYbguSaqow1ZF+nlpD0xcs0IQjNEe2BVR7CULUFVXIgF44 +pTv96/LvbG1J9b0VuBr+iIp30FG9azd2xyn4O3lW2xk1uzvo/Wf1vDGvT6AYyXNG +DQS1dGtIm3+sy975sNTlba5gWgh0YNHjeiQq19I6ZzLFhkvLKfh7zpx+R53YcqSY +lXj62N0u2s4KUygqg14oiIUoEnNr+n7Pq0es/gYs34mY/KvlqA8Prax91BaoqqLW +qHN5bEv90KdKaJlvdWsCUjA3wReeaQa+U737GMXaON9/oOJ02bWC8/OIzUPgfGRH +v/8YL7kMnTd+Col0f+XxnebWSfJsAzT7mjfly+An9EjccTeiOon8submd+L8WySK +lVvWzBD3l4HKjQkr/3/YtmpuymVZyeTzngVuSdw+iXWPmOOuXHyjyD2Htn5iNWch +Zlw37a5sHhiFtpNZtOnhpmDbX9sgt68KJMB/E9Mh3JuWCaKZZ3Cv/22KA4KQRlNB +FSvDDKJBrM1m599A6GPJisR+iC7g7asJQ8hI1OqaY69v8nP0Fo+Qk8+Ac1L/n/Vm +RjksignkKjvqgWENNn5Bf9A9+zZrLLu9wJJLae7wIiw4UgsNob68sGjWdLyg+tab +QTxd15H5VUIuD6pkeAI2qC+0sSw9V6LKm6pmEIIbp188CzApcsGBXA== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem new file mode 100644 index 000000000..f679d6dcd --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-ECB,C5DF56EE3F83A1F8C1AC805EA73D4D24 + +ac22chm8+bxXpppAKfsrFJwCY0S4VPnXmFRqlAPZRuqBH9ylFcG+F8TuHdIsLeof +q6s8yxkXa8y+/3hyqIZeMwN5Ai1Cas4P1iMwEtMUCMeaip5t0nf+yeCyx433hDSW +dVnsdeuiFCiBUPUXfp6dCGO9kOLUEwu4wM4lIJkJ4QVyauO0/DwObQ6s6xEMFvQH +GF1AFFTfW39CpZuS1rguG4hTxW6aNxjEaSKHJnzWu+kduMLJEaLUiL5+i/tUw937 +V8DhGdWU//1Q6KKLMr+5w0k9i/FhVxAGJZoZ5j79ToYORGr4jpkDPOvHaCydM6Iv +JH0epC0wfG8L/dArNGLEftTpVVlvqHMpAlc0Rgvn+LtqstfyWFXqbQ90NBxC5Fs5 +xiGxKFGpkX4stoKIaOvFVw/hoCI/oxs8Eihz8u4QjBsl/3TdYQ6AUyfBGEWImy/y +hh+QKCVOfzAmVGcffXYf7fvZETVgpo6tynxKVlSRXO9ZuzANJCC8jkUEOjc7jSKl +jyMKQMNnQxyplgaFxnWIfs/snvlLQW8DlpMPH8xSkHkUgLKMWrSLB9Cisv0N7V5t +Zl7Xxm3tOteLG73JxJKJkSZ9djlhkPvlvS///mvLQc6jse8EzY8peQMI1pYQu87U +CvHVDOYn56SFVJmo2koER8FG8a1910NqdCKpNkzjqTl1Qbz7Z2VwghTslM7sUA2L +AJP6PgdCkiGbi3oU8moPy3Nyg908j/17Bj9VyCXiegMAOxI6Kefim5Nn/sq+2/7Z +MHIucQX6ka8KjEp9jvf7jvNC5WYxJkKIl+yzwAzqRQ395Lp1sun6jPfngnPQmkXY +toeOeFvKlxaQu3QgNY7Hq9wwGbK/uo+rLK+Jbnt/75w7x5aGHQF3kf36epr3O/0l +MyZPPx6sLblYcNQhBV8rnSey1WeO6105h61xTXdKV6To/m+RDZYvt+qs4z5SNQlj +oKTezoQUh4J4QMg0EPhghyCS+/+cPMdnVnwX6Ds6nD2feX2CpN27xieGEp5ZhioG +qWi6/59B38kBW2e60eQyL5f53bhWvywBg3HeUsXCD0ujtXBqPMuNnO6FU+/5Ohg5 +BAJ/bXaWiOkobmppBeaViidGv3NytL48ZIuQ1PZsYQajFb/k1SkyLebmeC2NYdO8 +VBWxAz5glgIKP11K9DJMD3n6PVl+ZyvlYZUGXjfUhOxHKVmNDHv2o5Pv8jf3WEhs +yuWEoRECvfNlkDrmda0MxMhEYjeTysbxeX6fvwD2InzuFKhfzwh49p5LdZLurEm8 +DI8KBIXUx8g3svArJRvbVLyW0deMlXBY7h8Yc/2y7c5qBwfYrYhgazxVBfRqS3lt +EsO2sa0V0GaGhPh7LUt+n1qDDYmaOfxOdpZoSLm/surciEQIQVNXt264YuFJS+ot +vHWWVHzS1AZIgizu7NHRVeUmu4XEgT8vRsJYeogyG9o3U27L/lF1L5ysvYQjtvkd +q5idZxCnY5RctE2wa5gjxPjmgbt1sUN23KOiPyz2cmXGBh/dwqEhIV6j7+WeS4/r +SFBZBeGRHi8tACblT/6G9UB6FcycyD3hf317Zb3jXZLve17ozwRZRQ8aBkz07+iy +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem new file mode 100644 index 000000000..34ed53b55 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-OFB,E6AB8D4FECB44185E26505049A97B0D6 + +Fg8Nq9CxyVZmBNEiN9vBI+gsZL4lvWqCPaR5E+Po7acLxYGos4zIcmLCBa2X8lvM +UInn087k98OAClm+0PvhZ64/AdDE952UclD/xiNvQCH25HGQy7wk/BxuOM5/FT0S +rlV6RGMibelHpnv+yploYoHD8CSo77N4RHdEuepPwod2fGTKu5Cbbt1FBGU5LXWJ +BrDMOlSN8P/rD5ePADhDsYnh86g4cBVHTb3MkrteLa0m1Szt47E6d3s+Ued8Cg5S +7tiJOTFnXkmG87LsLZ0HDp6yML3g2gpTL/1Zhn9zS9lZc3cnkBfRJmttLBPjVCiB +mStjlXnuJTDBdgQhJPJ4+2xJiR/ucFbCnUF/VICsl0hdz2Hd0PCOdhzj6U3jbRk4 +uI2sv5TV/E+e/Ppvdh2W8LISSBdIwp9CJf3se8RFz1dUXwTMGM50LKr/dpvy3T4m +NMO/Cf/LyA7HBFJxjqf++wi5LPDXzROm1QHncvXNUjypNPND3RhP53pMeQ/Ffd04 +dw29zrmbyQKQOOac5Ss9Lj33Q/WzBgw5UxxxMxwRVDyfFpdz6JRfMrnj2c97auLI +RI3euI9A9yRNxneBKTobS0EjYyqAiU6b5MbNwrybqvavbA/+ZMEg9Ylg7vtBOXpW +YLLYFYPhWNEambOfNJi4tHcX8znGACxO/W7v3Ir+QFhw2IzSvntcMODKGaNKMGys +HJ6mqKbmYidjhtKen1qHB5u2bukaGWUj2kjkv7jjuDK3ExsvB2PjEV5d0foPEwW7 +9QQeKc5pY4tOxFVA4qCq1tTzUhWr0mBkPhnFjc7XOLbu0sHYdr6ArZ3SadaNT12w +LG2yg5r8BgmaUVTTQAzIiHhAQYZoCHAq+ohNocIikIh7lPE58DL2GPpEdXZsgzTi +T+EUSkSw4VtIMmnWw5GNE3zCOxvx5qzhKiXVcnB+2+IF3nlHkQqFXcYNGhezZjnJ +4FlR4FPzumRmMj1x0zmdbp7eTFpipUpKqJtC8iuea29pEl8opXDNhvmpmrT4/429 +7x8eJOjZhm8WL1dVpV2/Ikc9boEsYzHcBkY7kuaTqT8I9tdQ08ODo8UE5aReaFuZ +vlBY4J+A4lltQ7qQ+sAk6gUMvlY8h/9L9gZiGbLe438Ndizskuwy+jAZAEx0f0cK +YnTsZxBHPkWQXgBHMhe3BAAA+CZaXPps0SjD0yMQs7lkAgag6zBXW2vqttoJLU9R +f6uP+BLwZCFDF1NtkROLV1oROnaGvMbHWcar2tw5qNe3BAsPQqGk8XnqwILz4IwX +MN6QrjzbBC2jcL5jsxPZ/Tis9+wfI3t1Ke0EljYqA9RVWuC2KtRK+X3xOK6tWEK+ +QlagHRDI0Z0u0slCLjpB/ev9Ajqwlr0h25T5ucdsLd3FFEKZbzspdfsJuOXPM5la +Uv9gpYIcuFrKcVbvuBPzt6NX/rp9gozZv7ZOnujjor6RDorHsfbgbEfcerydvJGu +PRk788TkAB0LOE2wD2J2UO8+Ufp1qK9GWmtr0WFCazqFfeiorTh71iS7pwUt08so +0BRkqfrfP6pXEcnh4p+LKh+dnbgIBD+KH0qHsyc0ci43byoOSDDHnQ== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem new file mode 100644 index 000000000..e3f6e2443 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-CBC,E59962EBB3DD3C74 + +1FpslA4+P9E8HcUUGpkIMWeZYV2XxCgOiSgCe2NAUiutcRkVAg9nPbzwnsQTbckx +d5uOE/w53BURpxPkz3nNcike0sr3fa/MzaoRUDo0P4MU5bmAihjnZqhRllqvw4Zt +BsyxjHVn54RaqZC4RNQUqwIHYZwJmHUi7Zk3+Sw7fivMZBr/AWqa66I2hk20+obB +y5ubRjtjw6uaciPLIoMZksxoEwi5xv4KnQHAQnaihQ558RPpUwweqHXyOZPEC1Kx +gNQPrTGc4Zm+CKqR4CceACSYzcYtechZpSQqn61emmtyhowDqXpqqjG2nimNihcI +hbp5O+O3fKZFkJllB20xuaj0rK1NFF4aLiS3BK6aWeCZ6aXFawSvbQb6vGx+pQmP +eQemfllRXXkT43CHUmMTaf6gKnz5DaxDBqdVP73dBa6UoWnxTrZcUNKiPUCvB3g1 +ciJePjBnsijb2Bh6jIwr7yghIbS65AYE/0V+5Duw360Fa1OqJkMuz5pKeJIUcYEZ +3yuI22CZeorkvymKhrt1hUn5xLIKRZkWg7UbXG1WXCrGtPdJ+CxnwupHMdL8iMLi +1haNeJ3E/PeMjehQRzSEEFwDljn/b1JtoWsEwnQPTPKY3505OWIhYRwRXLEo5n1y +QEfktZ9UtIsJcIpfi7hMvbpp/7Njlu2MJKZ/1ZtvwVLoaXFTSivqcAkDdP7u5enb +OJ4EaDWrRXS3Zj31fpYTV5p0fRaejFPevRNnYvMLRiSoFobd5MUrKjxpxPRCLiW7 +24BF9QY7C2Nso9yR7gNkzLw5x/725lGxa2ZD16nJmiECOaEB8ORVlilmjX2OQi66 +hpGVtjHMaoGr5IvBrtc7Q9aM0bdoFZD5I2mOm0hniNHG9es2IMByHWRAQFzOOLGH +IFoIyW3OIuzK3cz8lMLsh/Hlbzo/3bpX0rbrn1XZULWAJ1oNzRJRi6a3Sw2YoIMh +656IJB/fGRbG9CMVMl0T7onDUhZYLA/mV+xy2CjkQdPBjFpQUTn5YHu6zMU7gejo +YSV/4esuUfhogLiqw7sPuCDqLL2UftN29xloQDTY6MlrkFb9jCciAwn02DAmsN4h +7Utus3Z2N7gJnxt1dRecqr2o/agIINm3tMh0LK3/CydmlthZQNpsxMD7IqaWFfQR +Uq7zQUfYZi0l2J6iy6FUHUokskqwgiNhMP2Z+uZ1xHUnoP7E0IZMHnVWEKBIQZ0d +ddDucux1jOBlMwLqom3jYPjPkxoeSU2E0ozVNSOqsPnoKkz2qKnEHhea2sAPg4eX +lsZ9ENQyQMZVapjic41BU/32pbrE/+JkK2Cc+dcLlrnHo+JpFeTdbleJhZ2JgXHW +8r04vZHA7tQOc0KNR522Niu7dvOW302lwmfp7D5xfon62/AxVhos1DSZuNpVClm3 +V59lqeCBDm1yJwdM/946Eq45YJiTNTzYsPPFl25KNv+3+GKkhZ20GuLiaqprel3S +MC5XbMJg4nc0LiAfDT/q1jO/EKZ5LzRRtkVvx1D8To6DAptyFoJSMKyFu79tQdfN +371+sXEX1VjpEGxO2t/DUmuERIBdc9X7rPNOXSl31QxsXy4s73zcAhI94X8xrqYZ +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem new file mode 100644 index 000000000..b3581daaf --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-CFB,A6C793D28C38F56A + +sjmmZGwl3qF65MFuXEtiTkltbaXuionUsMtzc/XzyPPaIxcdl/03iR5Fix0hTY2Y +/W9BntQGcycH7uNcoYwOUScTRr2BJncyoDXZaUx/WOQ6cDHuhRWWwpLpmitfsn1B +SRvLdKddL1GE2nfG2xhCdN4N7pVPUwIahHye1AkaSJ4gur8tU0++mJQTjDo63xKB +oTh3mZB0OCnelXtoYFKGFXNh5ouAPZgcE84breDJBoGReH6f4elkigtSx/J2QhgN +vXERboYz/HHhHSRCtMSp0qLEQo+uLcFxZcSMQE12eglOOucht877V5n5RMLFT/3c +DeZdg6D1b52UzaSjTvLm/jJCdkYqZf4SFuBgLHF/rEALQ1vBqDiKQ7QxuWz5ApPm +P0ntscETngWuJ2g2M1EoxGehwNiJJEslYE/CB0Aky1XeUmUAUm++Q3QVfUA3G3C7 +pP7whQSr1Y7gL44EmttFCX+dX8GWXuZDXa399wijphVw+6bl0gp/hWRWriTern1D ++/4S78ddrci4slA+/Kkq423wjLNGZtOoy9cXRmFdbQlMfVaeu5U7LmrTQRrgGVM6 +GQjgNanXYhkCNubQ+v2Q6FflAdri8Ac8ZvFXxSIGZ3JG14cm072vOdp0/rCNkzSb +fmtyzXUGgNgKzfp/GFvIXD04lLfeipzlUhNvDK8AKUNIctrMHZegpbfSm6HD6BiV +rUFNLvr58WDK0eLeRxg4pFTCf9QXr9Q1v4MWehkn+LOTconhJtRictdlj+G2ymOQ +LYgSRPPdXVNxlBI6u5WRtMxzZM6G3N8jkEvFfFsyeMtE+R0OsXiIwvGzdksnI/1F +deQJzav9uMBj4A0bJuMQ3Ls8ydZNFU2RDofSU84bP/g6TzU8MpT7QXQXPD2jKdLp +JouxtbRw+YY+9p0sk5PFYxti+T17jZN//pqiBrZUzvspwr5sWoa8BbA3bWE2gnXT +cmx98wREJ3wWRx+t0k44084kD5/cvVH7MsAQ75XxGa0ofVj3crMCL29c+/QaUnhR +GrdJ0sVJeIthiOQZZ5zBqG+IhJfG/jkKpweA9fkQ5gm+FoasTfDnAdSJjah7WfoO +C6LKzNBB1FaOHqy4X6LUN5wraEOP+0OI3hKPdOB47yUzPF6FGneGk4BajDHG4RyT +F2ZnG1aa+FRfakQ6l7ok4j+VPtDlCPY2jnT7muj2F78G69abNOS7ASXg5+PJzso0 +liaWo1d8TDfEazlDQvglDAKpzYw2mSbpJVmmbPSaVZxUARcIIaBqxu6xWepfdN8v +qZGrOp7vTOuGu8f2YmWKd3+lcNm2CwwGYIPpuTFjtUuF7guKEdTffyj5tpOdo942 +RAy/F3tCy5zfZrI8SkSkx+wfZAnkUnI3xQNdKKVLCXcpBtQWht2UGO1G9W84OmFy +eg21zeITIwPJZfUif9WHihdINSlfm0CiS+gDRzXukS4HgniPfS3NPo6HAepc2Gzr +QUGF/ENern3v85DCEE/AebRaQN7liM+6Z55UZ4GOT3Tj64+Nth7MNQXqBYEmCS8P +ndWvlalOs+vlj2Rl13IcSUOK8OOr6S7jeZhoutej1b4lbw8RwYBXGg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem new file mode 100644 index 000000000..bc3353eca --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-ECB,1E15270A7DD42BA2 + +zz3p7Ml80hSdlJsI5RyvOScQlsGC1GLg3AK0dC/Hh0IKPTDF7a2OITL6H/y/3txz +LJ6jAcobjRfVMWGAJUwFaSlE5QF5W1+RauV+M8oMmv+Mf2K/Urha6m63EauLEVWu +IDtxj74qfQgyd//qWHU+XmWhhNEGk5MrH163VITZqpG3Qe9dYHdalh4TB/ILJqfN +URKLjdz8L4YbL48dwK6UxargixQ3tfrvIdTr4mkMiquNlayTk9g5qXWnEXy+I1DB +HweXveJeSUHhYRXdx37y2I8Bz8HcuZF5wODEDJJuYXy7a8Q+Ar0Ll/uQ4NXE3iI0 +NA8RA0caAlc+Du/xfzKdUgIPQaLt/sjhM4gPBDLlASUmO+PJfb1VYgDIbNbXiR9x +92ePzennPnbhKsPcuZzXoc/jH2BiQwwRT2gLscZ86n9O1FNoaPAnYERlyNIVrQoC +0Ll6NnGBM9Ls5k1royQQtZU2x5Yu5Q7DGcNqX2yI14AZrI4e9/Y0nEa+17WRD6eO +fdaIC5dVrv8HZxlfzwFs33FpufovP2vlINWM3IqDjMf4FIQsoLdnmTsgoLRYm4JK +zfcyiImXPt2iUrcybZHKa0EXYjrcoIVBS8YP1UTcG8WHnj3ploMxXOw0AmpXcznf +sbLsaehbs4ugM5G358PMeWFXTv8K2YXRtArXHtkIYzA45zqWzpta5E7LiTQJfBRL +VNtLja40a0gaajvROCekEzWhezZc7bu6RQ/XZXxBYHx9m7nhzKRkDlBrrJVpWSW7 +QmS0ptXblyt2tbaUtNLsi2SP7gP9ggTlc5hCpwygT+lxrcr6j18CiPgMYOgDmFY7 +gZ3jZ+HHd2+8GnimOai+r8wh1aW06/tLfIZxpIn4T9yGh/EMW/R1RTJjN0xe6oqw +wC+TPUM2bMvDtAvdn8bYh3pVVLXnFa6LjhhgNvnx6wBoiBCJ4E9R1Ec0QA4jF/97 +B4e8TEv7PAFB+VGhIPnQqfsAqRfM88FwgZqSfZrBXKMVWA7I4fBeVD0cJQq8TwCz +TY9Fi1YnomqTfacH1hf9KiX3j8OkfrhIM3+w26nE553/wOcO42YJ55NgnNXlQL2e +e1s4uJ9lroATY2WqvgLy5Th8n5y6kVkjuODb/8hk3KXqiLqbUOmZCYLuT4ZHZ+Rk +xtWuFpmFiuWgbg6Nr2t2KYXwD39pjGBRmmwMX1mBxmUD9NK28yO4HEgiPVzfn7sU +1PWC7HpgPf797M2/N1gyUfrBbfw4OXWpycvmtJLXHEJi/p/H1bz0MuMJvPtNhzUO +CP4jq0xbu9nT5eW9rD7kgvv10W+aUf314RcWKaLkOxkk2dTENjbviASce5X3ZU4l +eGG2wtoHvCvHnNVj2ImKf0jbAL7dymVJlA1XwsLANAmk+9RGyVJgHn7ZkOfRVJmW +VMfZ6AVeFY5BeJ0LCq1uE6QMClVx8fLN2iBEqamBNekcZ62Qz3b1R7ZbN2tlPKee +JnLSouju6Mu8U9twVI2tr63OTh/a0XAjtlO0OAXuVcOmYOHT9fSjPdAAt3Rp50Sj +PDvgN8s+qSkQKpx7C2OA9Wisrr71UrBrCfBhCOmN5gyWFg24PwwRKUnc1a8mT5Zx +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem new file mode 100644 index 000000000..acbd8da99 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: BF-OFB,B9F95E282FEAA06D + +StEkcUPp3txNaJlYBP+eVabWYcEzAkX64aj8vaDX64i7bVl4ospAs2stac7uXtXG +IZLTqNNACoqC0jWWTDJca9vTEoqjDRKjN9yjXYfrovj5oKi79wfsSU29oH1dcKG8 +G4y8qNsA9TexRQDWTBxYO6EiQFVie9O3oXzjhO1hYwxldSWOV5ZRWoVmg16vAOxX +Gx2W1twtjQXG/hp0HxosPkZteUDdhMZLWonYuqEw1oBC4iDG1Tjp0p5uSnb1gaIr +pzZScikP0Z4/8CxiKV9/C1VNE70EHdAUYKjUx2PAbPaMFyO/sAXOy1INI7Wis7jh +U2wKeXgCMRxmca4OMITcjDp6OGmKf41uWyTFwjO1scMvjSJsOZxNjAjcrZW1PPRA +tvnhRpU9h1G9BOH2rM7VUI6zJ2FSNKG9R6M0WOQqxRegJzvK+YNLhw5lUzrbWOR0 +RdkKL15gfnuXqLTDTMuLX+aCDS1Mu/ZRmDqLWkJH4W1HJ4l2rBojX5fcbamueMyf +Sbd1S7QtmF/B9LaGDEPMT12kOQHZkRBUYpyolK6BoMuRPYnGS0RkUwvIuPZA8uJU +vHHuYRZsOA45YFEipyB/sek61bvqYy+8TaPxzpfj0fkh7AUSQmbk3qQRkQbltzqq +/MkFShIzS7SUkyiowOet8fVjXDJPsw2bS3uOHC4zy2QQmhVKzCYWd4yCFl+WtJnZ +eEkrZH2BpoCDEzKlex/NQlH9KBLOor221nJEVd5tkdWWZt71eGld20eFL3ewtDqV +GJX8jFmR51vQL6NZ2Ehp/5zhearuBJ8VKJfFxIKSrbPjyCbEwUgYOyVHHyvYyMR/ +6hcflrUu1IFFwFhryg2bucAkdX9AhsO1dimxSgZKEFlZbihPBysCdUw3WRea57iS +n/zqLrOm786KiWh0ndBgJ973g1x+OeuUvbNl/0yiO4Vjny6PkXcBOORu+ILEflzf +UiEKyG8+cYzoYZjeiCFBxsA2+gZMdgjxVYF/lKzTqFkfpwYV+tF2K5N8W51cL8Is +yhz5OHiENobjx3QeFCZ4LWDEXg1H8cA34i9oELbXtyG7W+hkZp0B9tRDrXcDwVWk +4oYqWLNCQXqr1lL6cCuctKLdXbc1ibLt1nYGpJrPkPCbOshsI+iCMmulT23s+jqW +TMW0RNb3wFjR5z9A1YTWfiqMKEcyzRhP6bEM/+WNmHE5LRefx+dnvZrVJzGZA/3k +JAOpsxEPKv7YNR8N9yoAopRfFEOH4HYtLbsAA2sZfD6iVAXAAeiZ2Ehn+Bvek5lV +5zIOtsXswRgzXvxXCPy0V5GWqMglbkUS2HGsWaHpxDSMbvBJuaSi2blZ16p3IICM +7YcCLolKUaWqpXjhb3UypoYRwJs+40EiXid7aJ8rKoeId1SeETOwVWkz95NMiVK9 +5K37/OMvxOAdjAUxtmz/+v+twKfrUhYqP3Qkapy6FgA+qxnzpCFZZXrMKjpr99Pc +QVNcvM/SKWB34jZGTo+Styc7d+iXDC1BUS/43Pvbka/Aa2IV/LPQA2pD44aP5l3V +/tOfQFQWI0wCqpBPV8aXqGuqZU2ES0yc9DJ974a8NvS1cNWfsMcvNg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem new file mode 100644 index 000000000..2d2233e45 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,4629ADA1FF55BE00 + +2093wYtiVZThSK/Ecf2pxfukmymwYi+yaWhMDfxz/O001tbrlC/emwfU7iprUPeD +NJyyAV4GLjUBA51tfDqia3ATKaBfUtMQoC48+q/Lkr5KhLZEU0LLVuGrfvmDXmPb +Ne9Ud8XZGnrDmvAFkguzK7cF4PFWUX3l5oYKinm8he7pA+t9RJ6QX7+BHKQHlWcR +cT9e1iN7MykRD2Hh7YjSxg1uRlJ+1H5zIJBDjQ/WIUMj4EdNJriurt7eYY2XrP9M +fyvTOBgYRHn6uQU0tdV0619j5yjEBpPTRf2M4RGOeNYGfvmk4RcyZPdnccDq5bWT +w2XhhBPZMdCHmDPTCOwgfSvqBBX6OtH2EKd1aJQmtudMATPjA49Q2v9ZrgIQQxmA +ZXIXuYH8wNPlzpm+abolucwIQhWJqr5TP5q7IKfYLD7FIjyrPBJecGoDuPB/Qp8x +D9G73DKYgu3aYEFxcjs7tWwWe93pn7glEPmuybK2HP0iD5/YhXy9OUElAUZVBHXb +WNyFdcdmyP/hcex5nI3Q27yM1auTS4Wpmvg9I5Psr1NN5ilWFNiJ0fr/YcOMpVsz +NqQPuSLqxX5sg7X6m7MkE0/k8PfFO+tpy1cC/K18nnka8WgH4SJ+R1I8WXLKFznU +X+mWcOaci2YBUHT7TWRzJ9/5bL0CEWlheabTjqbaV/4kiE5L0Wcbh/am56c2YAzi +6MzassP58vp4hHXTyda94+Kj4ymYFbRBLqh9CVspolwDhy6e7ydcspGz/RRbuWrN +Xc+lsExkvnLkYvkfmaAU/C5ME5PNjgM0kH0qXLyXPPtdKmwWrkGjElzaY2iajzpP +XEmnYu4E8AsNdNg3HVcQfoUU7jFq1NeB4uibFrq8vh6VLmqGvK6XCul0gxJsfsh+ +j/38B1+5I97I0oplDZrAQMgek3BXegw6HZVqADC2KH4Jir50rYNCFrN1un9aohHG +BdTzB1wGkjW2fJ/yrU5nkkTYcNhl9zU0D09XvFvXyeRdLzJL5eFqqZluwsPPw/TM +CSwjTZbbeS2LvvstAsoYGfQTUr/E+BOXVpFmNg+94DBxwM7lCy57nG2Y6oIy8Qcb +IfmF+wKMZEVJxy8O2uaCYUwU7qpucq1tz8l4bTo8wUctxw80Iflq7WYg/8V2ilro +F1nSJ7gF0bn33KwlLxLy7akXiol8Rg6aOg+cAiMi2Apfg+5DXWrKf9YOwebDLOX3 +LWvDuMYRVccwVWsA+X4zUezGjVNuxjnjtsDfeiScf9QyliK8kjlMP/r+chrhFFzc +LXARzcVfYCQhF6heOOY9YTHvcySV4NmgRKC/dlzvN4NMGh8VxWiEFDo7Vu8XTXpN +7OiSd/BvmOism6emrC8zRMD8c1ZgCxuY1MOMVXRir/Qy1IWZXiYmI71mmJmRhE79 +Gn5JJ3aZ9xZmr34l296CWOBY/suTRvkrfyMRoSTC8Z9K5nbd+cm0MLzWMgiT5PAg +cy6PHN9zVWInz/2z00qf+3lx45ZmMeVj2+2h1PFapXaCwvek3VgsXL2HUV/mKNcU +ZH7mV8imvIopRSS4YQXB0Ophiv6i7lJWdKrSYd/Ac+Bt2E4z7q7y4wFNlZBvsBoO +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem new file mode 100644 index 000000000..814ff8946 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CFB,07BD7DC7BB2EAC98 + +yH7T+ZIRWmzcMociF5wV3YjHWCUMs9C/GUrnBP37vvJrBDBB3x0u6aQMaOs0U1Ih +xbGOweaw7cMag1HhafjVK9ZFZlYsCfXRZk6JdOvzPchDctQrnjkDxnwpOllmp0w4 +Mg9mYLuEvN968Tx2TS26va/rPAu3xxA8mrcCuSfyt6O9HteT1axwDpZzOktmnbYy +xHQDRcpDXaXspP2sVTaZJ3oq/AMGfrFXCu2m9jFHcyZKmEm/DW2aLmfOI5I7gCLP +1KMekkauODnQZEE2Iyi1SVbTBKH5DPp7yXAXWOtugBcWNHbMF9QHqKlMs5Hd2MYg +doXtBSRRBc9pLdF1FMwHHjPFI+GZL3hurqcD+YyZJqYvzEgnI9dls2K8MzQKYKDn +6VpDCNbEf8aC0QmvCLIjqei5fH2RVYeV2M4Db1GDmpRAIRJEq0fXf5ojAD0Mhv6p +DZYsz+f/MLTGwce+HCWxZyAyfptdK2ScfvaH8mUr1OHd5IdvRudh5+9sCtch5xQL +DFIp1eBRd+2gvLBMja7gBE/xHXoFZtTR8xORCwgYXVrLLf4wG27XLdKQVQiS8dpi +E+xCtiZmZfxb/1Ly9yHP/ehWD9DmxRRr/n1QeGMjSlLSzffuLgt/0tftK5yOSZri +Xc1T83n5rLqhBglNEvwR1ewsTgeIxkgZo7q/LFajrnGh4L62cIoLkLX3lG0jaEC5 +VTa06i0b7U1nJ6kiqjHuXzkZWjTim4V7p7r/SQtAGuK3s8AmqJH53EMmiK0zFq9Q +ao1ewixzD4NplA2HY4kAAVRQMR7WWIRrV2wXRTqoKwITMbZ8Yio8PwgSjsYhuzwv +Mct1CmTc2FcCH/+AZOqc2HNS4qwQVmwLnOLmsr7L9kgf9aPIl1hkn9KzC6GAU+fZ +F+N0Ti7d+ZkNAtAUg8fi2Bf/rtPvxmyJp6QICI4Tj4MFpGIRWP5rLwU6XXNch0l1 +nAcIYFvzLNL1v0TDnDz/CFW7XSp4IaDl0OLyAt+JxnPuFOAo1wJOhUWHheGynEBP +U3K4u+761XMdqHb1n14OSgfyynIuLM6WtnBDoevKX8v0dYjO6PnvcuZoRqs1sYKr +D93XsV8uMv79Oo84xQPHpJrUIJVLDeE5GLFimD7rUPvMURg1IrFnGyfcMGTvsv9O +us/B1dNmOHjG7eZwJ/8MDNsYcpwm7CQsTOJUZkQDN7MZOKJZJr2gQK659eULJwaZ +lEkR2p6A51etvlSPZ2pjy2Mgxk/T0mX/mVprEvCkxFWGlAxys1UFWKHDOOP4rUZs +iE7nxBMyW+4zHAcco4Nly5gryqWiW0gn99/I7+qQHkb5X6ydP+GKOHmUdcb8RPIH +Ec3bV7mBtfYxDC/ouStuQdVC7jWGwU7PeQqoz4d3mhK8dfeOvpudiTD1BLw30LKE +Dt8/tob6zIHMEA5NTu6g5cbfa0lhRH1tD+O/7RejWPwOTc1LbY2igvHoh5uWTo8G +ufvYO41PElmJoujef4njSZHcMvHArinYdlWlvMIg52d7Y3lQTTztY2UeO6DKRHx8 +Qjda5g8SDiqgFktkl5r9FYfqMQFqheSgKnHaJ2oPPbwuJyuNdy2Rug== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem new file mode 100644 index 000000000..91a3f4900 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-ECB,451BC59702897B57 + +lYkflQyHR1brYuUKx2oj0+L9fRwOhpKR6NMeH2nlLEMz1yntUt9DGuBRwP4RJs8o +AHo7amQ1YzGpQCEZx3p+tMmk/hHRcRmU3ZeuP3SlGwpUmbMe3NI8I2dvh/qDL3Rb +QParp+YK2vH/u/N2VPB11NvgwoUQpfS35vOhoLk3GUcupSKfbsbl/gn398DsgfoI +d0qD5VSxNutst5I05pl4JFnL5+DBv1s9w68TdvAvBqWmsfhb4ei/mSp81e6ndxOR +VLF5hgXauJjEHvI+c/ITF0roIyyxiMMjFd8IuIHbeznIjOWn4P5YcNcSswSG2wOz +1wB0e8dlskukcUGqFS6W6mJzqb2TK1Eo+l0w2B2rNGX/MlGV9f6r7e0DQQFH0nCI +nLS76C+WB5G6RA/7OMOWtsMnYSLldvXBxxZktcD1CNjyvuCOI5NK1KmG/Kajho6S +/+A1mTs274pI6sIsCNl4ay2pfgwjZSWh95l8+YNt7o0C5lHudZ4hZHCDT8U2uCoe +7dhj+KTuIS3VPI7lzruMZBGAj+haZ/cAEdqYGXizOle4MwKM5+lS8E5gEviTABua +7jqhqbBE7CkN05Y3QmyE48yzi58hzSmiTOuAJ6jhB47A6Vsp/FpKFzfsK4BoD0Zh +0ujT2BeJhtsFmPY6+RLtGITnl1498j9FTfy8ZNdrXEMxvp8SnEzlIKytLQyNoz7a +tPCe1od1w+MUz0PHqDO/Av3YMULGLCUgnuZc0YjZv3P54FdC6si6KFEEqotIGD0j +C24TXqlBpn8Qqkht/0TmzVHq6U7jynOjD1VUeB/gudPlHGLs468c7HzEzbpE5h0G +1e5o6D5u9Nh1ItMObNrjt8NUxbi2/FX/Nkm3J1Ogno0ngzh15jZUfWFPAGkI1nho +12F8Sf7YTBizPW+sd5hDbVejJURyoj/jt6UfiVKUg9iUgOW+ZzgkbD8RvC207xis +QoF+2Lr8mPsNabUaFbsXmQ+6F0Pn05BzyBN2fyTxRt6u0CKmLE1fqkIuQywk83UD +hBJfeewGoOGvoXDSy0ggIkjaRCsk//Xvntt5HEmKwc/wy/1Nzuu9H3C6n7qLqyNJ +mPhrOGXt6C4LG1JscqS87z4VmhV7mol/Umdg00HRHs7l9qKRTePdlq52JL7oUws2 +CJs/UTaBHdbV2vh06qmymtEyNmQ+PrweEL5U/neyeYyrx6DsyUDdY1h1n+aKSEyR +eittKv/pouPSLlIiMeY/DzQwN1ifoGsfYgJRst9Ry4MdlahpCTX+K7X6ryEOoJ/H +1IEOm2aSlC3qEABUGo50IqiNF/PWugS7Qf/JzXAyjtcgQdW3cskNDCR7JVJDtATu +0817ST0QXBL8qT1C3z843LcY1HpnQ1MiQvM3maDHCxuoEoUrRILWc59mc14gmowq +g5XLMOLC/y5mX5LDqkxoKhoED9eM9/9EGSSy83dWWVZlGNLzu/JHBiWa3tVhas0U +LytNa+kN8UfTC8KPe6i8euhauunLIKkq+MUBWy6agFR+jflE0zd0Av7Ox8HPbGe5 +0fraChwokeFM44fy5cOH7zENfng0jVUUreTpDtcfp390QW5Ca59J5/5P2aUBLZHi +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem new file mode 100644 index 000000000..93766e7b8 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-OFB,62D0879F9BE636D0 + ++iyQyk6TcPldmHOJyjJjsJ4BgdDqqdQYRzQWC/WfDLJyw3CXLquWDciAw5aCof3k +b6R4PvJHzvG6j9jdlcv+yD5M3j9ZVHYkLL0fTZA/LEODUOTX74gNZfoz3FGarYIV +TabFLgwQh4YJ0+Nb5N/oISaNszC+wxf20D4N445kvuHKbak7o2j+5ZzGId9zYIPU +Jat1HygggKh9PtE4NildizyVVK5h8ws8qPWbe2/m00Hf5R2oP2YC3Afn6kqMuueJ +RrvP9l26WboAKFED91xY3gJy8r3KkkLOJq9856BlndtgkA3USqRM31W6RvLqHUDy +3l4ZY3wSTCdZIX+iHV6Qm3xYaIHNzYjHRcPQKdOVmEYiUSmAZmcavcsPC7sEfD7d +OMEbrYrztF8iO90Myey/lJxo9RaL5PfWbtXqnXKUZtbcudEQd1fXM6gzdMm8AT4F +eUSayg1/3AGEEHq2PH8kKtxnWAb7xBOgLbjTuC68f38dFw2P8iWZerG5lbLsFuwD +YZ5eItuDhL8+dbFxisBX6H0lzcm0pwK1HCHOvSCcYfpWC4QrU08WbtI7NCqIuRWv +4QOHU6SoNGW99BSnUlsqgLdIcsWsyTwiotZqusZV9AusdsGqU5ixwal4YX/8JRg+ +93EwnFnl1Y0Bj/yoAwNfvPlZhtjevsMnPEbrXbFEm0Xw1kdhOYokrx0hQWUmdt7m +cFdmFBYQGsiKucvRpmInylrS41VQNbNySqQ5iGa+vDaPBMKZusvgPgwWSchotkzT +qTQ7HNjszwR4eIjBOiBSvY5YXoa9H3irdmLn76mOyDMjaQyC9o/0tbAagLKADuF1 +Ui4Z/3WV67SuUoawqDJsYEWbOaNFX04wFby0k7oACoNxqoGFM3ITRzmxnz3ZyiPE +DV/grOZICMLfTQ81VvE8/w+w697F6EJ8rY1yOznglP4GXrtIiXAaJbxEOhosyuN7 +HikpDQ3GRnPzXeg/Yngzpp8JMVdxKdEItcXnWd9uhB2Ok1vXH8LjhVkhrL76bJe7 +bhagz+LphPaLnkE5BPHKLUwL8bQQguz7ITfxsEFpWIHG5zCtpaQwdMEj2ePVubN8 +sfZ3qhDRNG8DdwXgCbCot16SKGuOawMMC5tsoeg3DFQ4MBDrKUv3C9nF8izTs1Zr +3J7kWYrZg6+hVcJDgLS3t/lbFIhaNAULmep6wl4Vcp6nBqr395r8/uDroOpoBxoa +BNjvFaztkRy3XmNHp3TOYLg5HZPWsK3KXOs0FvdTMEEsnoj3PXz6+hw0gMV6huYp +o24r34gKiwdbrkbwLRnyh0oF6d3bPOZ9WnPgA2y2MB+slulA47+hOMcP9+WiQxE/ +eGd6TTRjMPopQXJw7/tZEf6qyVYLWfKJmI0tljsea48NocZdsek+e4ZsTW/iP0oZ +wPDYNt95V64APcDZfNtfzydp0516KY7p624TanOXsxNNiBV6Nuqmd0dGhbmcRC8Q +KNgGNvgjF3rhqrXZyFpnZNQewE7a87bgmO1O772QU6GmPUZr3nzPRwE/8+TNA9AP +hHL9HtItZ3arx7eJ42obFrxj3uzpQ8WQo/cGLgQT0lz6u91xJyWi2A== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem new file mode 100644 index 000000000..9dbe30d5c --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-CBC,A48C2683D96452DF + +dRu5UKxN6kr8aSBwZnynPwIA2y8Dgu6Xf2vCf0JswuFMJAwFGjiHoZTmIHuAjArK +GWhiMl6ak552D/Nugz2SNgC3eJo/LOP/g2NIJnG09GuWOGXkiagjDKNbPCiIBPww +STIBg5ilKV07lryS0FxQSUWsjI/2c0yxk/6MGSzQ6rrAWB4Cf843u482w6Hidr/E +euPsqXJDtlQrKQ1gaMTJiOY9Y2H81b485MBN9BnKfDH4WHp49b/akcditst59fty +FtzwyUTee9SGY6u7oKaUUe6sRzFOeeRR2TgWG5Bs5sne1AFFen2/q59Va/7/iXRd +TOKKUGR4yj9gA+9EIpDF3n8Vn3G9LnTDFK0Xh1m61C1mQmXgEOqJGLVreFq4u1xq +0J1yEZKoXreZJH95+gYAW5lmG+jNCMy0RO5PsTClx7G4XcIGFZAXi8sXfk3FYLT8 +nboMgQ8IXFjqO85FIVMt+xCpov+S8yOfPMOU63zxrynaXD2eGv7y2dTpeF3Mf4Ek +be0YrQEWpCtYUdZ9AwA4N0/vkdp84/WZ3Aw/i+KUqYKtK2agkJYtarqj6iUweUvW +GgWvZqNiTAd3sGcxffSbcdSRpuNttnBG77qAFgFiPXtvJu4wRkGlaxhwVTyUWK2E +HvCEsssbzX4tZ6GUXScXv4zg3YaDP6HXsnBENl5SGXK8Uelett6PJhwH7bfpWysG +Z1TD75uk6twThhtPURGG4GUaQ6cZ1RUsL9/y06v3ZmfUBxeVGLKwyMzlr2FTYenU ++LcvzriycweTLMO6llLVQH8XwlbAZ7JgndCjZodtFXhjhrS5Iu0sO6J2D7xFvL3q +/Ym8PhhRStcVjijX+5+9aiA8AkXK3khP14T3yhPLu7iayl836Lh1+O1BHiYgr9Z6 +DdhCmO2Esa822yxyOdiwVlF+mYQylEZQy3D3kqqJytO9pn87cSvR3WbPtFOStlcs +Htms8SdqLAamuWLGZiycPr87mSH2By2JED//80fNHdR1D7cvPU7oL/ClFMX/F3EW +UJAwSXswmUxqccBR2hOJ6K3OvSIULoUn3awM/qPNTQL7rg++dSzUDbIiUywxuU9N +nXkqfBVjoJTjafgWd39G3RdoK0ohf9QFj1nqYfaQGKy90cPVw/FdjRyszJWDUBTq +jlKXnap6ZS9PGztjEoLqmFaFT75RUR49NnNtmcKmH0i6anjwFWEYBM61jox7gH+g +W0r+0R2yijAspXHVpuibx9vdgkq/WR4A36t6DEMajOHM3SVzbPzkHTV5HyYQKnaw +SZLSdUk8VwYkGSylm3f64PJLxBl7TNtrQhFLgR/9QXkhN7U2Qc7WxRQzhLQsLbtL +qcBLGH34SGQarQZ5dfo3t+B6IIW2HvHNOiT9HQsIJTz4Er1SbLNH6bco7hud6aOA +eSifKkWLp3SXXS6wjQZzsSGZ7Mws1DRcL9gEhb4tgIvopQK773AbQ1SJDEcmBpD1 +NmxrTbb1TngaW6u/79Nng84YEUiWNDKu3ovoe/HLVZoDr3tGmy5ch0jfA6NOxEn3 +KXZCiu/PjU005SLyLql5dcGzagjnnURDi7TLue/97xtpI/ac0vL868Cqfm0+e26H +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem new file mode 100644 index 000000000..451670c08 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-CFB,36E0C8A965F07E25 + +L0GHzT9XVnA03q7rlchpiD4JCgzISj+B9GxKCrKSJJBC8bRTgjgrwySMQyhdX1nw +DiCtb9q7UCxQ/j0VvHuoA3OS1/Q95mwCsnjUXYAPiXeR0NMJkLgv1hFU8EjAJHY8 +ZenlgfC1RNoUONucq7v3F7jpsqBWrxjyDXFnWwe3edSfUzkfkG27NK6LPScjqdY6 +kJWAkHGpoGog7cYVBJ78LbYYHSBR+xfeFzhVMqB78mH8/Y/CGlKvXnPFpiJCY7Af +zpd4/PJRVubXVyANc42k+0/E2oPOSKiwiKV79BxFw8g+NxkhRzXeCDuzvExKL457 +cuPNB0CQLSVNmOWKr6mA1bIBiJXgASzijsjkyoH62D/QoBo+kBT8W3hiHooSzJ89 +flhyknT+rVuAbFdPGqriS8siN/r4Qq/gbQIFhNe9jsSQesfr7lM3oK2EPGpDxstf +eKc+EhHBlT4S9X+AilnjK5il2X5szyhOFZQ7RdAiqZ7X2KPNNqbeS2L530ZvlL+W +Yw4qco88cilN276QQWCcrp3YcWv+MzawlNvfOOAb4GfUlR+njPxRAxM3rGVXiMn+ +6UL3X1SqZfADJOn57S4cDoP/A0i3FUfoPTwQW77LOAIzLSeMi7brQkZi5J9s5Izm +OMcEi+GwBrkbPl67fKMnt3cHeFGJmOftrLZCt8HpGEdiQzP5iiC828XvLLxby5Ue +BGoBILGIHL3OqkTVjBbSODKFZTIOQdVkqrWKyXlrfoI1meATptP7/GhdQP2DTW8B +ppmNgtwIbGLg/AwNmGPdpL2mP5SZLIDJHd81BL00xPJFCR9wxXLk3hgm6auzAsZV +FYjaIQ0Qza5kBCKNqu8ad8edqgp5Rj1/ZzfCWEkPRHD/lZ7nj9vuC/dMnPphohKz +q8/L1+gbp8dwER7sEVBiWDE5u3lpSbx+1qkk2CwOjE9eBh2Mr6qLL2WIFb4YUvYI +OAWIU1ftenOEjgjvYZcdeEOYT0UF6/avfHDPvkTIwl52UUhunbnqCjQM3qr18rbV +8vB1bC64DxetUPhDymLqJCe4QVQajdO5BxQ2wwRjHlBi94nlAS/uOFV+WwqtFKZD +TakruYhw3VjGxtnjukruMzNjDSqxd8Jabp1oTHY57C+aYQcBo34XAr+j+PQTPXEj +GNL19MUMHJo/yk05NZfkyf3/+YtAV+/Gle7TlWWCV1nvEwrHPE4yCGi8j6qtCzBC +TgpXl/lxJendZgVzIGGzMDemJgyrLNV6ar8TbOz6d5GDV3S84g2S7cToMVHX4Z8M +bR53pt/KfH27Wdn68z3Zd7sT8R0g7yCVIc0BJgRrZ1aLnyKLSUk7iJULg3+B5NwK +JNucRiU6mT5SUiyS5WjD6vZVDjggAx7H74DP04rzgzcHvTB2gzx1hFzw6WW9wcCk +7+RiY0j13M/nD8UjW+pp/Ugk4Oc/bvxsA2tWQ1BeyF+KSNj/zjHMwN/sp1/of43X +D+lcWS1hCwMiy79KQudrkc2DiYKWSIiXEFlblSJGiQz7SxybtO+D0PpVmlEYWiDF +AAMz3hM+CrWcXIFNw86mHSsJHvYsSjbCB3ydG8L9OdATYsS3tZo38g== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem new file mode 100644 index 000000000..c3f285f0f --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE,8B0E5396F9D19442 + +Ym7x4lqzxkC0K7f3nTtR7/ZVi0Vj36NLORWiJig0qvSmH1rhkkmMjssQqc17kWRT +ttLj4D4s1ueQBlDFaumMrXloVp8c4zQS5jbHNmf+bUsom+HXGFHbjPC0usHm9TAl +pPBWMCON5uUxoqJhw2mvrGSlkQhkkh3+Oiag6fxNxnN8Te/yTPC1XXCqIh7zRjCN +q3wjkh8+0QP8ui2jK/2zrlbwvCyggs4q1YhVzWYiecFro1llb+CDCz0mzKEXj1MM +MLyMdcooxXTb4t5PhkW87N8PSWXeJEJTxcWYbZ7bf+Bf68iHm6JChc/HTXZRLUfo +3lACV21KTTI/614rLl44l/Ftg4HDSE4UV/J2JoenbRecljKXneeVj48Lmurc3zZa +rj46e/pXEGfeEGmkuVnriWhRBcK8Mq33XfY870RsP+4bfxd2ykJYyxFZyoTT0sAU +LJ4KIVZVc3/jB58CRBZDV4s6/cA0uHPhprtzEHSxp7vI9N4dQAWaUBMnDtPVC999 +QjVGYKRUUNp2S4XVLtMH3+jZ5ntvCTTabjuie/4TAxoUY45CwKjEFpWtDBEWBbXe +zmIQYCE+o8hSVtt8DFWdz8+PGqF9QgWZ5iQtnp5hUKA4rVeaxF7+ktumTrwguZcZ +6ZK+K3t4lcHyPZMQBoiWijmBLoRsoQ7NIFEE3sn9muV0XUz3hMCRapWsqS4fd3N0 +LRXrBmZuizqzaNBcDku7lBbembdW7EI9flzY/0Q0xRl7WjOdK6Nj4V2A2MblQoh1 +J+pvV9Tc4PANApNLcFZSPawOJVyUtmpX8QZYTe7QlXQrVIQE4HX4od1S3/ZlydfT +DL8Atfec1sabrRFs1M86lJGnYxsvismLVH0VmkigWe+4sClAl5QrtCfGQepYmsYi +jyVruF3FzbOCjcv04x4a4HyKRHeCVlsRlSq/njqCh0WSc7OMacpQJZVvsUYRCaS1 +7WhmzeiVNjgKXg5lPwta78Kh+XbQUtUGryQQrwOnbj0SDsho2hBTt/gbWDpxoQjL +LGPHVxwqm0GZ4bw+4IXwltfei7MG/ceWxLZYk8ZTkc6r+w0+5HQFKZ3JuSKB3OLm +rK0m87IybLY/Zfap/WLAmreRMUz/FbsY9Vjh3gt6NqrDhqLFYCyyUKZyKrWnVlIj +j5vohFGbq968UYVavCZ2eqmtwWywsBXLOabypgrIUQhmCxOUBM7Mi2NVrTqn8uIO +G5+mwzsy8imChv3Zk2/LafxPpajlu1MuC6CtMdZjV+zrGxJBEUxADaTJU7tTAWef +lUjlZ4l/XO3vxSvv/F3yONmgKp1t3naS0ZxxYalcMRi6xTznW24r5voOAsVqIz5y +Nl5FtPMSCBE4FONoUI4Gq1GAen2h2/Dz1Q3CMYAvJz/QfpZFu4DZ+jAUISU7URfL +7P/lXQhg3onHVy5tgXhiXDhCCxY4pUPSy57eE32F+sIGeltoXU2Okx5/ey8ijr+i +5URStFLeFp90ke/EhdOuhDoE++7G826ky3twqtSBTt4jU9IemH0agFU3PWIJffm3 ++Ezce6LusooS8Bqs9rYXHHGe2q0oUNY3ipggOzx4Th4mwg1HzBQnD6FU33M/WyCw +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem new file mode 100644 index 000000000..c34872d3a --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE-OFB,0A4E382F6060AA1B + +hIbY73AFUCWIkdT7MEKMhr7+uSoSMO9wihHjhiHn01cq6kTe66Vy/z9dmTcgbK2q +edRngIRyiTqyul1dhQ2ezVDisowHAtdiD7O2/Z+YiXc1hsuC/uELnYV1hTUg73Qb +v760pWyH5AXNpqGsx2LLw+hstiiWVO+/Hs+CqtM/RgONfvUCzbyOQknDfSTDoVXB +W4gEDKSDj+ydXm0ZmMS17DLCXgk4HBsJxyiK666l2TzB9pnzj6EDA6hDsiHfy3z4 ++MxfcnLxWw9TJPxdLYVdw8WNWsXQd1JHQz/BQ/Hum4eNoYxLGgsV/hWQmkFil1XO +GkPjF2z44fxN4FJjvQskrQox+5/gvnG+KamfvQt62qN16Z6ROZu5buPijxmXoecq +gW6SyeFbnYFn27hglllax9awEEUtcJwi6OxKAkWD3REjqCfNAwcqoFqwkxlPN3IH +00Rksn3P7cN5IqePVjSdwIhZtCfeBW2267oNxb870CDon7OlrUdK8KIjp/x5jKUs +Pjehw1Ovtvn2YUQnTPvIYQsgdq3BMb9ETcnPDneCVweSxHxpb8ao2hyBMyYtQG8f +LNqvLnjh7FUyRenf3XRbqka2w8B1CFTTErkMm9E0OPD8tMtDyakI+8fMJDkGhGI5 +jMwY2q98Z+Ef4wDifOi6qNklBlJwjvvybeqhqWOoXKbQMhnQPqFnLGjp5GQMczII +m9a0anYSvmNKjRtD1LBL0KDMUgIx35U+7GKQfjrRTURYtAK8EITKUqYoWJWXUevR +t9cikdwQ2yDuDH/C+a2eaEHJITerdW7ba/Rxzh50VdPq03uUNkN21VZEMjcU+GPB +sLQ50j+gSFRMMzMfDx0G3wHoEJNAul8x2+umCUSpzPfC5D6kjbyREm/fWEuQkvL6 +AUCheoD7ouRR66R8syjIbeCKhjZEXUOvxxNYHSySrxHyiCGE5xCSVDlTzAutvcOn +kivQqRlO1C6ZoEWbGr1SPoIoi0iMoh+TKZDgMy6/pRWVbELW5P9JnH8K+IreOIXd +IgnCsqKZBVN4qRPrW8HtEwiWW7MsoXGjhpVl8wer8cNmcfPTo3x2l2+mjV2r0xEZ +Xmv2LEtjDfIUP6yXuID4OrV6kpqSDax+wmujr8jlETKf0uEi4PZAXqhrgh/fgH2p +VE+Ey0vnDaXcEhS0ketOGmBIYaKzWbMH9iX46YSkA++5/PavhlbCqZZN+906jwEW +6MS7Nq1UBoUiql1Xa8AL0p/7QKZH2mgxpFcBeCHF4q6HhebbQbCpveJgBSR7/12H +fJOIubovV6AOx2kBRAf27bii5iwMjfzC9IBE+GLCX3CXR+BLfOWutTcqbaBRdmQv +K4yJqB/WHYcjlLKf/Q8+B6elmMc59NVUfStMszkIGlTzMFIkObLHH1NYPSC700rH +ZkrdbRGfcncT2OcyFbWZ/tIvUER/aHjh/BvZ9s8UyEVEZzsFJI8HA66sJzZ3fKaM +8P7nXXagyarILIzO90JIwkX+ip//QtpSDPkrUtii6Wj7n7RO0REe5N5+NA3A7WUs +Aret+KXgmsOi2fnTmCFjVN2QgmQvOg8PGx0yYx8gxWog/NAmLCVMjw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem new file mode 100644 index 000000000..6a632f23f --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D7B3D8B829964B1 + +mw05Vw0Y4gDohoiqd0xLN6ZKCalPCK2F0QFSyAVeoPY39y1RyKdsg8xt/qDx73jZ +rgZb/fQLKs/W6SqCAAk/7EIBNTCWf+yD5TTdG9n8viNDSNXWdyq172rEnRV1CWGe +beo+YjNDh6UlZ1FcXLj82TpZ9EokUKLabzNkY/coVPLlytqTSO5oZmbdreuUxOyJ +ktQJUmGBmBY0aHJmV2wCkOFAXbzoSfo+SNPntEUNTa8i0cSIgmZd4/QS2Xfa8qRZ +c2R2hNyVZygru5t8eckKj6uvj/Yszg6XqQby4ktK/cYfveS85CNlu03WfjfI5V78 +vY5efs3+NVJi2+ush4p4TfgT0PAKTWjXwpMEiGVlmxBoPoFGtTXY3Xp+64QICgTa +MdrxPDDBw2yxmWAOpm58eeRqAN7Jd42qBxerJFiOUZxYPyRrQvro6fkldUlbPNon +53Hzb+zHXv9xM5aUqfEjMO4HyprhKT/8aZgQiDE8fHgJhI/S2Ho6Fzqz2/uOHzBB +gx0m8fM8puQ11eRxO+oSE4OSKbEQG0Uj66cHXY6FbJUhsLkGo9HdjLSGW67vx7RY +Q3PQApOCFcXLecfkXrUaAEeRPNqZXjCkF6s8bfCOXD1cr9BulaGpiGxdspu5Tk9Q +bLtoX5VHnW9VoIoFsIWs1G0h3WILs7ynCE2ttDSnIjYZhE6pRBiDHRs3J6dH/oOh +c4dFaapkisk0BANJduvB7vLvvbJ0Xs42q+sRUCWzHNnJ3BqQZtL5f0dqu1AXafji +qwxcbrEqJc1kOQ+iRAZ83nVlVkI/UgWzTceYPR24Q0PnAux1LkoIO/FWbhm62j3u +xS669GX+GS9urX8oC3JUYT2n9dnPL8ouB77KfP6c0GVxR2hhiLYmyP2600C5q5DU +6rdNm6fb75nrAmD0cgPxbdOB8zbgVvQuPXG8QnTO5Vvhp5ETgifIXPCIWwNHg5xL +o2zrAdrNaio8FZUVPHOvMKE6Wl9QDMqnnShH+8VhLk7+LQpVDewBnWaMd8pK8qGn +robl+i4HWtn20uZIDFyI4ioSa0S3Kanvd9TkchEbDjKAVi1QXdcD+q9O0AYt/X6n +ygx2DGhkNYMrQmc+AIt7dAPa6RdZv50AAc0R3S0DBaxtd36pWugT4WIEexmuYj8S +NbRNLuyjQMYCeFs/Ff4df0gmfeyH88YSlafnLyFhvv041LAbU52e/yExCEUvKr5J +Oj2qVHJVe3eVW+FX8hsoUAte/a5foVe067dThfZDVp0TirozHAycgfKI600VF3Rh +rvQiHzmXRoMptt5g/yLsTVYiKAF1n2hU9556sJPARFrG1xXoFFwhpzCS5t8ywniN +6wwV+V0s4LSJFQJBFjLrreu9ZkYMdEOrekzqBohF5wG/BJILkN8hBmnD5gckbLIM +QUzGTGxu+BIUi8JNkso0hwZDAKnYit+FVAs+5yU0NVQU6e3fW/+m48YI5gqFI+k0 +gIGmAyU6zaUJBJJQ4wc3+dOsy8sokqRhVmA59Tv20IKHh54zWq4ouFAg4Yc0bwK0 +1ua9GJMGTXN0+Trb7MKZQVKokyNA0RVCDN9AIfwCA5hDhJTahsO8Lp4Eolz2TFaQ +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem new file mode 100644 index 000000000..129e02eef --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CFB,B99E3DD88C3A9D7B + +4Dsk+pNUGsgEqelOveMyrkoDb+khouKf83Yt4/qxX8CHs5q6i70NLViQWwqvIqQP +g3h8Gs8cYKZfkEAFKP6BRFPy8EttnBCzhAdvLKrKFCZoDmhxC5ia+FxPLtNaDEb5 +6bgSoZ07KUMvfMZdnG5Kogex4DedqENVHBi2Rl3Dck1pAgxwzMntgHsluT4ht3id +SgyUT/xAaMSwIklsjclR998N6V8Nilu8TDDf5X12RHOq/MSqGZ7yJC3Wb/dsirNs +7jsEQwg9tIg5B/5hxjN12E4Ov7orIuO/WHNVtLznx1w1t/umPjLFn100Kln8GvfN +jiGSB5TUz4t8r3deN7oDrGjoyr5OMnKWSsIwKcMsNSh9aTdkjIJBUUhIB2PStdX7 +WbeNXicNMQeteIrY+ZDDPpMbjsH1Kqcz5y9OWnvaXso5lSHLBp1IamCv/XbQcAPR +zbnbN8DCOYAMcUiwcRAt0U+BNc1edX8VmCB0d4RQq5BTFbjGKqzo6yFVUOVLhiFg +E8G3v8sTqUhJyH4Dmjn0oDMtfdplk30Ywg2wZAahnI9w+cZFvzqXshL3mGdu+rbb +h7PkiJE5vS6/4VKA7pngsVanCRQa3btL43ekShth+DXwsziQixGD9HhTb2iYeF+u +9niDPI5gzi9IfxIpb3QjR1xDJYAzKDDBA4gHhbEBSObByMsVzjS0+dwP9N6DV60v +3x7RfO094FXxlVWSh2SMvz/sB9fsD9dCp/gadqHxhk2aJf7lfSU1C7EmM9hxGZku +vR3J1QcSu2FMrvHyRzFZGKozSHq3QunOLno/KmY0ja1754NEkntGvPuB7LhGBNB6 +14NvQsl7qFw5wJxmEdY5rhVdz4PxLfjnMyvCiWlku83QIC51I5DbhRP7eG9rJSMw +b7KFSQwmp2yzDeX+Ipd0JAgd14GvtmICKJVushO352O7mVnx3Jy1ZtJsonhzySz6 +1fGIvJI8jxZOdO7q1OD0bfrXS/kwdXnxoxn4pkjw3ZN3hdFTfAerVQ+qYJ7zIez5 +0lUihHNw1C/KRsggraOl9rTUNppcNtMYwKXCJOGXI2UEn8p3JIxEHLwXyOjTDfg/ +5oK2nPAmBdGsLb5ivJLPivmaqDXf7fdn0XBQQmtYUQRotlGmfpztujt/b2pL5YSE +Uqginw65zyedjL6Aff3crvP8/CUR0JARx9vF12R+v2iAnDqVk/yqYpRqOp5elm1t +yGB/PtpoRFsNU1hDnPZDu7kZV9oSeXaBDFOnHmX09qE2r869Aye1xOVmxiG5tm/u +KGA+zlJVVpQSwnPc/qk17S0dvNAlgt6MH+vYlhKw8zk1nDCuavUK3hTFT+9w31cQ +yjPdV4/K8seK4zIqpH4LZrC306/1/7BT5JXL6ZChATHaI68xwEY2GsEl/Ze0JrQv +WpWSN/I269rUfaBDE6eFaiSDzq1xY+qyApHSTNPSPDHbFeCXz+puqv9lw0bJFnRJ +nLsK2fUAKNvyCF18IydyhiGz42LYbwwjlEWuVsfWtgvftDebZRIfQFlj7DJwXfZU +zcEOI5YyuQs+wFK/8b/bknF4xRpaXwt9Il7tcV07h96TDJV05illig== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem new file mode 100644 index 000000000..bcdc5d3f6 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3,9675E5342C359F94 + +aqJHsie4Ls1x3Tk73mbL7VyTembpkhx/a8Mc345TuZOZEkU9XYrkFMvhEB+jcVoo +9ydosCL2d8xjDusry+vn5yF3iwE9HFHQ52M0/a5IH3sTtJ18BzAOi72ykGb2r6ly +FzTq7xdXNihN19wHHnI98GKdxdQmNR9uITx8VRBbZdbRNGdJopS8zT96+AV1QAE6 +lyKKLA7qbATHR7JWQN2OYz05vGt48Vmq+da+qs5liEtx+GtNUxS5x8lAC6Llmq2s +/Xv8X6kjYmxHSYWM2JyxsznGfdXKXe9f4Xxwyhedei6JgrTHa/JN/+tvgh5NWODK +er1tLBRRA7atlSoB2AAegJC7gJRVOxRF4hiKX/19cfEpq8hF9+6EHGYm/IQRSI/J +F0RGcnSdiddYbEb667qTkbLZi/d3Ih3KwKGww6ZzkHe/qPi230/cDR8tac26jmG8 +qoCwj+XCNOe9IUJsCN6RmLcFp4Tr4UVSsswxReN+xs5Ui+S3AY8IKscLSo+bB8gq +DVBvVFUBTiF5/zO8q8H8Xv2c0aA3S9UQla+l3yoZygiUym+Q204Li+tDXiM602kr +GGDA5/cGpQuit/7O51KF2OSwnnvLdu96qz0f9X+rq4QVNAy5PXcr2pj/y88UfSXN +GAbogEXqpQzn0rmV1OWM8hsnOpN2DLcuZICCJFJc/BHO4elt65OfBjAvbxjhFU6s +nJLUcR5EopLex46WwuucR6W6wjAuO8ET3cDV5L9wQI6DT+XItotk+yJyYawNPda7 +wfmxZ0o3qdcpRp7aw0ohfshRGJMuLnGVgLczU4hwO2/1LgRMnCywldacAfo8Ot8s +WnC7d0jVOre2K67Omh4gLQTzikvFoxg5kjmFFxF+QOFakT/B3RMa9mgjtOlX0boK +HepTxOtCaS+cZnL/fUCbWdnPxqooKid2DnVTNIXXBg3S97ReediwpSn6v6gU8QXI +O0X/+syPkCRAOKLjCdgxFXRB1UA13v6iqeja9aXgzbUnk/MrT6G4ivAMsNS1cEdA +KVKVpbiKchEpiiSiPyo7buZN6t3m4JnupU+UvcJAEFgdbPvP/kFvxywpPBcAycAM +HgujJ9bE3OR1lfyHHTGF/f5lXGDzB0/ND8h7Pm+Bd0AFde79rCswhnR4oJsPLuij +Uy499ouKhoxFTn3WMF6at2QLf36rfLHl41uSN0tky8trT9SE1PjX6yQUjl48bJh3 +MWUFPYBDfDPGTddENYo7hDmwoSLbE5WFxbAeJa86wgV/P4/QcDF0IPVa/wsDTPKR +RIy7eNqxXBYhFeOBCkTKHMJ0XCawi4q2CAwo7RNuAmTrHOBN2hZOwYd6yoEQ4ALq +70cflG8+rITJHOdAjXYAlcuuB1FjDWJjO1E3P9MwMfiFZBnJBsYkDT6ablfwgpaQ +z9ngnzRqxIjqAxrRY9GdR3BEWgRIiKXljUgkk8qFSRIS1i3w+nHAipreOwizTVUw +otTU++EjpQBracFsuGP6w9vcyhHOp3K+RzGYEQoh2vJm25lzUWBHvmVpCw5BBTms +RgurNRdm1IlN+qSzriotjPuHr9Ucit7VFV/gXtmyJiNNPjTLpLQEZOUpz15eaFs+ +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem new file mode 100644 index 000000000..dad36ead7 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-OFB,C8F1482CB09D61BF + +0GfYpcSxvnnRri3s5PutcESsHTuupx6UcprKRS+B1neyPR7Ga0Z3mZ2/X0trJVpM +cxJW4g/cU4TknCZLjIJlClYQenpPRH69yw6BTi6/pgUhKeGmQK9Oob6G1RMjS9lO +MTb8DKz8P9GmDR4/3SvJwPU0aEM1EAmwGJV2beB2QWRhaPkAZBzeijYf+uYn0mgm +hZwjU8tdwnNnCdUXdaHeRkeqFcL6OjJHV+U5SZaMbaky1U9lyIJL+GUQZkRfZzJD +41Qt6yVtetTgzljtCtd4ix+RX6EYsWfZ3OVtwHGYpg28IdfJ3LVE//O9EkLZoBeg +DyU9c0gDnQ8Dxl9VHGFwQvgdSEyJLvWDv+6RXvCX4Kb2Spy847yxqcfqDpjUhzgv +C7FoBwswS0pkQzGXKgdM+WlBe9/GYOrzW08IYwrX88aihf50jXi472th6ILIkFHD +6m419YsrmOeEMXGW/VIKxk8H8MGHwdvK82xewu8Ftgfx0WihfA70EyI28VLMQTAE +MMHxxCWtdWWnmd1xiHQSX6vedPLXQKKt2AYxYmHQYfqNFMcvDc5uM5uM+mNkX0qt +VL5PeYRYtdDtT5Xj4/acZD7X7DhqcOwvNll3J7PRdadNXKfjHR7iRP62YkIiESE5 +sCHhYXmtQqK2JUJr8a9M1QPhmAIF3FYr8wSFu/eWw8ooBaTxVoGCw70lT8LNHVql +TYdW9sOnvUjz36oz6H+z55CNldor0tS/Bu5jNPOZ8F6j5r4xpTWi3d/UWLW7uBbw +VTAG25EiFvQBXpJFqgRCBdD1Gcfoc+ZefLXQ1l0RJpRf1jJMkfSWvUWDRNm87PSs +qTeDBzuLNx4A1wYcJ1H+R7ds5QK4moNlvv0hJrsqbOESpLv/XPcYrFgzms0b+Q1d +uJEWjz38AgIJQxBxmoglzDSRx9OBh9D8HQ+aJLSVcz0dBmEOEtPjZn2AmxxccwCc +NkMnAxXyNPEJhecTp2/lOOupQqMYTGe8aoiee3m01QPzfgL6m5p6IJdKzOKi0TGJ +xNW6fD486B7i8d+VOnst6vnd4xiQ03gNNA654mrXIM881X5elqmoFWyup+Ct9lw5 +lxllAJGh7w+hf8P6mIsezOkZGieGhzrFnuLVM2srRDEId+shTV/0lZi4LhfDYroN +VAbZ6bySn9fmP4Pn42zu4XjoZJffF74u8gFPo8oSFYg88tzjbPN9KAPInNxD6lBA +cwp3vc1n71CEepmfeZFR6pm1wKRSupkOZNL/PV9rqsyP1pmPE3AEU7WYjNbf2ah0 +GE9f6dtLWcDP/3SssoSnZGy5SdqcNPymG9vOR+QD12YNxn7yA87HM3+swparlSYy +Mhg1BuDXb5Q5XFVFdajFwAnXJblAIbuJAeHQ/mNCAnR3HNv/Qic2GF7X757MA+dP +z86gFzJJtb7dtZ0WDQzzEVHgnfVHP5buXnHdepFLsETw9fp4ZjqPfHjLXIOvp9/9 +G9pmSzB1JL8kK8sexWgsMRnl2j2hUDYiVJ/LQjMzk2YLF5I0D5msNTAJvb/gFBdv +ynVKUpIoJEfRaY7pxR3tufbzADNiqa8OUCGxZ8jo26j7XWDkunfGAw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem new file mode 100644 index 000000000..176334059 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-CBC,C9CEE2FFE7D795D6 + +hcUF0vilpOxap0mbziQfS/5kPdXsFb59D6myNYdLDAvBWUVAuu5g8iDDJIS8KPb2 +xvmWdXRhbsnfeQGcGWM1rMc7brutqefFp/OAJVymI0TpILMgef0abf49PEqNUa/N +rYs2dd39fsyrJ0rcEWT2lBA/+GTLATB+16/9aCwjHjQ4L7d4Soh1laMo2K2Us6Eq +pB8f6an5Y/vSIlnljl4upKOlcLItd//2ehQnkuEhI2Vafz+kX08Z3+OCLZfdNEq0 ++8b5GbOvygEZbG+amZDB/tXnR1HB+AI7lR94PmM+h24COWAelatj2uPOGov54gXc +iO7NDGoouysqfkfcMpuy5SkLVW4FoCAxfOl+LOU9p4x8+iaJt7Np+TO16dvX8MOL +4WcIz4huaT125V38Q4UiB+WbsvQXrHRM4WCyJBGBhakr+FpNFdH1UPb9Unb+8UQL +BeddEGT0l9AiSebT/JMKgFUOInQdKxOjg4NBp3asVEUeTGLeTN3o06zUoopzT0S3 +CHrpgvpZLf+4NATrFMw0HkcUK4GHZl/Q68C67qNGTc4B37eGcxzGo8QOyjXzKxL8 +Lh+Ry3eJpEXae5xDUn9yt8eqYI2vdwjA/3+XE6mRhu1sbPNJCcWo2kLZ0ibYgqdB +FLsXBT8aoeKrW2p82OpehslbmswOKZgrPRYmNh1GAPz2jwBFfCEOLQYXAjCFViiL +ipFLKLGt2dhjk5RbCraN6eYRn2XcIai/7dnaYxXkjOsNH4mmPzlzjhvRh/2E/r2Z +hbTOoa2uFUtZHWtDXUz7ZzCJErJaA00ont37BksfHDdDw1HIt4z6Ut8Jm1cR5zPO +pC7s7ohOS5j8Vr8j947bEXITC2ozcvVVZOCcHwF/PnUE1zx48HBp2m9NAZ8Bz3LS +Zn799/RrNtJLnkheG0wIrizk72M5L9PZQ4FXlupfJ9c9XniaQ23GQFszagceDN8j +z/MR4tTfdWRy/889lqZ6ccNmPAXdwwijC6Tw6V9HooN9m3++ZlbPfHpboQUp6+V0 +Wwq8gdnlYW/i++9n251xBsR7mQtFNXaYwFmLUTt9C8OobyWSsX/OaeQGbWiVnmAv +vPkr7mh6g0ha/x+1vKgEOjqItJsGdspf8ePHQ3FaTkfFwhQ4eN9w4QR3uzM/7fnj +ql3yA+G8ftpaU9omFbs+VqIVNej5tvjODQ02BbjSuRklAGxnReCS14vLwjg9BV6t +Ow74oIttwlZof21BWsCISgybkPmMhkIhUNAAkHexzY3AiqjAtEGnpmvfZAX9zN8+ ++Kg58DxudjHQwUO4cwP9p50NndrilBShkotdYIqekXn6h0frYuhspJVWwIVswNjX +BuEZE5B+Otswbt/caj9C5tfsyKmnGToG4fpDdk0ItxRq2126crKQd49zZybyR3zR +phLeduyS5h0oYNwTjq+Fg2Z+f6d/iyCAE8ynfqcAPK1WpM/02DBoLsOmve5BCSPB +YYKdrKfkGbj4J2klrptGmqgctyW5jKGddE6NO4XFYV174rsdPoErNWWcfptHEMLR +BWfopqdN/HMrpRLTkjx9rIeBJ0F+wQEEH1JehnWExSSSAhm/gzQc1kU/wihOStU4 +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem new file mode 100644 index 000000000..4284fff63 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-CFB,AEA62B1564D645C9 + +NX4iex15O1Dwp6ADN+uFIycPB1ELvBDVRGh+OZnisNU9h+8dPO1cb3j2tkwLFK4i +Pml4zz797d4I4GqdF2Y23dz2AoBrl2Lj0N0W01AlOGagh92pZ9dKjjU+S5N85OBw +buDbADh16fSPW6Y88guWFXYBlGJ6HZFK/9D4CZmEfI2Pt9AwEIZ/JvWrs/zW5eGP +YMFsLslsNu9TOIKF8iDnfcWM9MFpgwcFCIqTwyQ/+dka0hw33WsBREhFcNleLxhW +NKBIMC6jNjpW916IClH5sBu7T8ps/7JVw4DUfpl8NAOaqJSicPGpZrGIZ9N9cfLp +KD1XEy+yWc9ahV0mfiyOuzNnP2x9IEBdrk5uqJwIT9RuiFZixIH9MRuqAtrA5BIP +dc2kw50AbXRghE0JdUEFfUm9zcRKdG366SgADnteNk/77gqI0OZJDD0XL9R/N3Tn +uh3EI9joJciWDbEX0/751MfcLaa/EkI7quKMEyFGWvox9sKLLEKRUV6SfO/YX8ZM +RV7ebJdW+Mxya/beG3Yb9TAYkrG2TT2+uhRqZlZllJQFnX7k5MxyfN5I+WJP7SEs +Uy5PAkNv3h7DTV7dBFMy/gPYAooY4JzBnbq33af+w/VbhyhVid/hn9UAONahw7H/ +1Ao24IlYMza2fJ9yOn+ejLhjvwYIP5992cmElneqMdBfV+oaQTHtWUuVF6g4gJBw +9QucqxH4JbYccwA1UiKIqkmOlePm5I57RbBw1OG/Un3SiPcAwiAW/UpI5yv8kNwq +kZeWnD79kMBEW2pU1CTvf5f8aBmcgQykC0M8H25Jj2kVvj0EsRGx1LuQx3ZCSM9y +sZejgZouYA1WuZaIsz+3t4fgYFiOHDxmSvPt6VtZAMJGmLB/Xa/PVI4rsyNv99wB +UinlINhzeGKpYYHnUgN0PrRQl0LBR0TdrJ0eG1djEvflXsuAQVP7+gP+oCckkT2c +pIVm2IzplT2wzsza6+o1SA5BF7RKI3A6IxySFEBJTeaiZnYeeJHxE2DJvU1Fe29G +ML/lM02waLJNbIs0Vk/i+hyE1wtMwZetptG+En5TDzTkWlVSLSqW6LXVJ53J2E+q +wypuz4akL8CaYRm4XTmIH3Tom3qSf7rdbL9gk8llZacFNqAl7x1C9zDUzKU0DAOg +qPKAtD1s7Rtg+4p+5cIEAWD0TKX6DlXKC/EdYO1w0vmavGSvQrr+KENE4+/gIRst +qlTCiEW2U+PPyOgpZAFF0g5y5Xw0Fea/0HwBBLfCiPKRmDHQIzWIEW7RkkNfQlHC +iCTBoMRFDbwXJEI9XUu2N4RdmlP+84i6fSRWuzZGUACvzEnRJEc6H0FaaN+fX0wM +Op5O2hcdA0YTGGmTLUAeajiQnqGRobC8jQL/WQRVwOiFU9rgy1K4Cu2T6eBubvVh +gk/R12LezvD/KwLgQz1+vXa5Vgjp0xhpnLnJVzPqLG0Fmj3V4uRDc1Lvvl4uLJiR +VFjFYlqxP6w+ToRqnrfbmUCuiq6pS9FQi2Tghd02P5TnZcyS2xF2X7o45gegMplS +skPzTCON8140xpx6Flep3bHwzEI0CEwO8goVMc6x4a2Ggekjn/Nz2A== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem new file mode 100644 index 000000000..d9609d749 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-ECB,270AFD04879E8434 + +u8jYUJhoDMDNI5cHXhnJJ7Pm0lF+MrOl84maQOwfwZ5hBbjpx9s+z5SMYpWfz0yQ +WlgBuGkaY1UNBDrwH6baA9/eqUzem9ZK+mYmjKC30OaumjKVJIB7cJfJf6Itcaom +SH1W0kJYeDn7ANdmstOGxbr2TDCr0BXa+7j8cTo2TZX1rfsXcdmjQ+8Qa8zfQ3Q5 +FbrO+VNmAQwO7HeFjms38+ukJRW30EPibmbzx/YTCZ7XtCsXt6t6ggYja9Kvk/eI +khwvFFk4g6Dv9YU+x2pyrkquIiTUo+jm3Vqhz2m0cGcqfynVEYn4fNPc27Ekw3uj +CrprMgnfaX8QVx/EkpDYp7gpjcLYJObpUTcBo5iA7R3lpQ8itY1Ky7u6MMwQ2VHd +XZcsS6b06mp2EW1CO951ZaPyma4AqoLl2gZ3zH4qPygp7uxrGdFdFSqrapVkDee/ +lLtj8Z+/g1IyVSIW2FP/SCoustCHcqeDDq70GKY9qiahNFybWn49vZAPB3HPM22f +mCcw4ALiKr0S9oofxrb8PKxmDQMZAJqjc8qRMLktYh9rJLMoUG2bmQqpKmLLpx5q +3CaKi3wofc005VcILyRgjumscAcpbTEz4vcR4jTwMPNP+WI8+AHtg0OcF+7hE8qc +a9KTSsx3eJNbqq5UYxVjV/DcttNx9ENllnG+jEdttkaf+T9rJiayc0WPd+Eg0XlN +ByBG0RCPQVJ9YH1Yke9HGE0FXv7FV6x4c22ePePcyE6VUNBoxdmXw+KRhRlvtXtM +1fFMwUrY//jEpfbf193avTVVctDTLxDSmwY6eAMBm81uDTlpUm0q7l2rRuKzdgFd +bG/MTOd/j7wtKJbQpbUfUNFtF6zjssPdGhJ3l+8Rg4xZyHWHgU5FYGodp9RsxUhm +8AzoPDcVbbvu5YlPP+XvyEO1860fX6iSZKuOV+owjh2i51CPzsgX6OrOEb6/1rc3 +M5AkLVl4insmetdTqb9PHCgfD6bLYcDBj7Qnf4HEDQUGcRFe+jogOoSH40C5UgPq +F83nXv6WYBb2Y97lhb44x7d1MzE1kkzQXlyf3QuZ0ZjOvm+LuOWkbQWmLj5JhFJv +9CqY2MBL39EFamKjmmBmjrRsI9XMLHvB7VvT1hJPzxbF3UwDZ5BsA8IXSps0EjXR +rZXSwo+vqTa3NlvysgvuJJUjwyf6mN2SVrNaKnZZ1OGFY1oQ3bmOgdI+SW9cpGzY +Y8eFpaG2RAiOfBZ0JIyBUoHUH1MMMPw+Mh7KzIknP7O9htwiAWEvkcjWr7X6jpG8 +sBdBmszX3TMDTToQ6DvyjVRP7mJ39dV83bLI3EA+N8bJcTOcHijCvbzQM50WzMu1 +2UA9e6rG+ouQAgwaAHdR6bwm+Zr3e7MswZ0Q8/Snd1UdpyMyJ9nb031NSRSvkEyB +ipu85/738J/g7tAIOJwwHeVWjL4lnrLC3CwbtvWAQ9Ox8Sjv848608GzQxFwHBHJ +0NWgt/AfLYsq4bmmFWtqvqTjWeAeUsM+67UY8m6/kxhfRNNN3zZcckq2zlF7TRNU +5AL/3KbVVLQl/7fD36m8AK5eImR+Gvom8ryzNacbNCL55ks0sycbICulXbdb0Jgm +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem new file mode 100644 index 000000000..cafccf9ea --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-OFB,E5989634C878E65D + +6o45POmHfE72UAdMBQrRIm2+oZCd8GmkmrFZMXYnVWP8ciNiGVQqUxVJS9j5Rx17 +8qxpNrzvcWEGWcgs9AOqog7YXHkxo/s/RIOKjUu0WhY59UrYcbkN7Rjyn3wSSD8X +kN4Z2tz3iR8LnfljD2ApbR3yEYz2NvmifZzsac58R3LvuFg3Tsl0QetPSC7PfMUh +B7dezaycDcx8QJy+nRPcqpGzeL/VVk3F4Hppc15gfdWtVellGcYsT0Z2Iu42I5nx +HYFajRliBukH98M1d905lk1aNLDj54BBcq08JsDJN/V6DY+mUpJCFOK4DfP5WLJb +/HCQg0wqsUmRHK3dVo09ilZa4OfrrRD5qTWr5boDngAqyD1r1fiHxcv7uU/HOSvt +PU53frz38BA+w1pHtlE0TSG0oBe/+741kJtpvj/1Ts7nUeYJ/DGR4vmLpg4rnbZJ +Yky5TaDV2LVLFR4syqombb3eiK5xbnjePCQFLwxYLQKZFINiS5zDr5mdjhWbIhpA +7wg9BKNpUeXRDtntWXvEH9FmyIicbk670riEYEo/EniwrxW9f7MFhPUpOb9ktE56 +RnaU0EK9zUx1sIvcu7LVq1G2EVG8IrOKGcj4LHysBtg6PQW5mvN4AA5PZlc2Sux4 +L5Z6mJfwgBbBB4OuRXAYxHZbnfMTs75vL3d/HIcvSPcvb+7nfvNLiwlaBxaUfBFh +fyDurHkMG6tBgE6OORgWraNEINJeOYcG2WK60qC4E8YfYCmc9V+28A//bsyRWyku +xIDup68r+Os5RMRAaZrkIqaH+h4Oyd5RqcjLnAFF/wLGnNwSttYT8o7WwCf9ZCCy +NFvHDWyWMUxonaWgvuSm9YPfh9/9CEsHkKh2RqBffFcZ1ktEiYaI+dGyty12QW2Y +909pnCZkKsm1Lt3ts/xie20/gcwfsnvUC8OveKPaiCnJxDv3r9pMCNFPdcXo0GuR +oadhn9r2CqNCDo+l6JWVRka2t8+yCAskZC7bKJnSeKlEDyn7A/2SLb196G2k9cve +V2qQenhzuHmG5PEVfhLWQ7fL1BmJcRDuQlSmMGrdmOD4Zb0Truq0zpFL2qaMBQvb +58hG5YkYehE25j8PpJYovOQA2hih6v9RytR2VKlTeYNFbREf1sdLfeIphB9tlHlp +qZ7eOFAjjVzLsC4LmoCzWMaQuwNO1f3WiNdGVvulHkWqFnGS9bBBTahUUWI5SYiQ +90vhSmJ7R7461rqWwn34Om5jlgRV4+2LhUbp+XdOyklujQYviHsOs8/wlg3lKr76 +SwrU5oYqlJ7FJoDq4IPpOnJaxsRjkr9foecgdqrU4SJKyJJDbkHNfoYq9r/aZJ21 +ruPFv5t021gJmWa87199GlhBZD8dxeXo0PT298Y3pmaaSdQIWLPeDAtc1R9EJLwD +6+ydhg3ZVtSgXU0zQ2SRVMGhqoEXHDUrMtjKzuaZsYL57tqH6At6vWS+xA0CJBCw +7GkDpM/lLGjyisFEQL73F0YmJPpb5s4izzCLUMxZQZ3u4T3f9OPRvAIUf8MiFJxh +RJq2Is1gD7M8+dySkFeAbQ1STvLy29uIxKTE6BgNng5NrY03GuK/5A== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem new file mode 100644 index 000000000..5a9eecfeb --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-40-CBC,BA10EF99A1862AB2 + +/CfoFtIX0zgNckXzuODWoCYVY6NoXOvu1jt7J5/BfSZUydRWKa2lpR3SWAUAesQX +H/IK9Wkz4um0QgrHy2fmVaAS1G3ifwgQ9dhW1EMiCEAmuNwPsT2YBatSyxnzWjHa +dv4eZ0Snk4DsS/Ajwn+Oc9uZ3u5gKnfYk3tXoZ9BDPQbgIz01UI/AyGHttB43brl +e1C+zKgCSa5WB8wfxCJsKHDSEHx+qlipVvDk/pntc9m4AM0sp5wsHRw3i1iirQOw +AG6qRs3Ro3jwajlEWPmJolhbRQWyA2rUfSIajElYFlFgxPLI10m0tO5M55VYXpWe +cprQNe/TxK+YJTcBvyhFmP4Ha9NeC0Vq6aHiECpZ1uObH1brZ1bdYUsSGodRzGMC +ucOkFDpsp9We48TAHqEGArCsKexxe1dDe8b+cxdvyv33ZI7dyr7DfHek3X7B2rHv +tZYjgx0cKn8SNl9qdRync9wLqjL2R99sHgphkXUA7qLP7ZdvZEeAGs5NEuq5oyDj +4aybPFJu/xvByOEZBwEtrixVJ/2h4KYF6g2vK5CgmnYrq8SUNGobt+oLv3FywKhQ +AK/YvDt97wXNdPNqPciqCP9LIeo0B0cgxFIbOOE3mvYgPaUoTtZ48B/hpkY4flKR +U7opVqbNl/pnh1OCI1ce/K5KPw0rvYgsEQ8Q04+dipPdmvONYGhcgHflS52xju6s +RbosS+iET3a6BB8ydRS8V4oezbr7AgzoSv7Od6geru87fYpVW3WbGag4w+Xgil7u +C22epy/AX8naBOsMa2QMCZ97avi/qhMFIERzhQJcxULff0lHQBq+HMGsSI8jMEiH +d2OIERTWasAEPdoBnELO3l4oywb4NmSp09m9imihdgocDAQEXyLkjmRqkm5H3Tdm +ALFIaSwU5SE/dk3T+BTmnfl+Anx7QNWTdg+ykfH8VHbs10A/K2zt6RyJGLdStfKq +VWORUG7gYcVGIQrcJllxt3Jt4sG3t3rSKA5dukM7+D1d54ExiJN5DrnaQ4kX/v7O +nENonLRtV1KqrH32R+tIuBVA8rbmyseVequTBQpkHbG/IczTG1k6p0Qye17XlnPl +kEPE3CG8+1RMLvflA1rTimSh1WafHsDwvwmTAgdkG5btLlfTpPnoKDy2hPS4Pd0P +mF7OPVfA0Hl/oEqP7bqyUxuwFrz7pZXQrKDS02nXaqVAP02nKsiEUZNo2kprAO2v +9ceOhXP3M+ItlWeNcX5jKRaaLddQvj1ntOKqDMfRk4yWm9ro8/E56Fkrq7GpKrXL +FCJJTdrWk6EcSfI6grVjPbZGBJiA+21G4IPQWskPkr9gLuE0E9I1UAdliYKXOrPK +F1lZ1ZBpG1ZBe9H8Gr2sK42pzJoFJsOvGRjCxlHpf/gBoOADH/hcxvQqBGizEr0F +kKraZWJnlL8qhDzfJ7YLMqzFsOu7uYQRqfOcv+66FqT/by9rD7dR/M03YJReupoL +lynJfffGCG6aeM8hLZ8iizjIc/RzCY0QS4lLPkRVSRNt3Z8RNX/nFuYhYgOx38pu +6dflN059kTC5iyjsI5Ka/Xzq69kR21qCcHOoq6IQqZ7q5RM4Cj0SCXw8/4jeT2xY +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem new file mode 100644 index 000000000..7d0960811 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-64-CBC,DA39EAD05DD48A5B + +mil5OpL9dVqnEoKF7dNjIRYLgDjCBmTDZ//Bmkd4aqkPszHaCoQqgyGYOuqWXdT2 +FAluu/fHMLDTizyr2Jh00ekcR3nmnGM3B0oDiEtq84YMHPWYopWkpId1ZaoqluUe +6NP6Zew4DZ8mEQvOxIxBEZqk0ye6srtLszByw/dTy4i9S7l4oR8hx1i6Jj9lLXS1 +y24lC68igFNeIecggG8uwZBVmnHCldZGn6DBBqcC0b415+59vwGuvc+POy0Hog/4 +ADPuZcXEO2whVGyOjCF7CjhEFfo0CO2niwS9PiUIYNsUluwfS+y1qhw4VJ61sQ/q +7cNHrD4NfZHGwpIRXk4c27YHS+JsxH8Kh61e/dQPoeTf5NBQs3PthFcx+hzlTBAq +VK/4TtRRlnqTVFKRydpKo3cNGp8qm9Kvz6fr/yLb7CJvdoGDyHVO7JvT8nYL5gC0 +dvN2RySKXMrgmPS7uMAWjpnDCdNoOX4pRTRPEdBw8WsdXqnBqXM8tvrkolF9n3// +lldN3sSGLiYM1cwD4dXlYJEJNaarelHk6vpJIU4A6gYyN9MQnv061jd7sibrTAjZ +Rx06R0FrYFbfkp4yAmUbrPO5gdwZPBGS9XzkZmZr+S4u1fH7tTFxIlWNgxwSzsZJ +P9LXM8Iy408gDn1AJlbT7WbdWfcFzqIsmauRIXE66TloS+485ro9zX7O27MumF8S +hjD+cRMieUEREuAAlpNxZj5kcT3SpxfSdaAZtJv8OKeRHz796LRxlLmx3ZDAjgN5 +0H37gSCXJDP2a4YnsiI7th5fNba84t1Qt4Q36v6EZT2kscv0TB04ov1+4UX9jCQI +zn2zxzJk42kkxRSEBP3BnZf/qV5t6/+BKmg1QGCmS5AkIIlCDjTPpAom3n7YH9LV +ykAQ6Wcdo/7dGtghgaHbPGl3cXR1u7BI97GCU4vzRbW58ULh7KSC1xptDJrP7tPE +6OwwYk5YZ6lmg54cLbQcxeFwYQg1dc4pYAgBppUFUB/uWeQrbJP8/FN/GlW0HTOU +kUIz5pbI7nstb2hHrRMTtG4c0oGO1ACD2LigQo5Cl7jR0sBC3I2MB/JcBBwAHPVP +tePpIdSAZjAYI+x7LFxxXvT7eXe+BU4ZLGLcTISGJjtsbJG1oJ/e7dPP5bLL+zjJ +MrwoE6awH5GKOOxB0iUGce8jg8566qY4e2vbmVL4a2qRiKyLowr7Lcz01VzzE/RX +0Ec1I8noUmsystH/57UMBuhZNFjW3LtTaw6vuTrrmFtdmJcGwars9tBtH0LPip9X +xQbwIiTJZCyDjql7Ecgu2ncw7zHZzbHrmoEF7VEdPT4z21utXgzJ3HubvB7Agvyz +sB+EXeUqwZHnyN0GdGd6sqlHkW7TP1XxMrjewUHjXuY4SvsosJ/GqMY7uKJXK/Lt +0kqYrV/YDIVsJ2JqyxwXYYIqmZfQ2xXTLuESuesT7omKFh4cgwbYHd33YWRCsZJB +7Og8d3ciguWDutd1LOgx7da2ZA+3UVz8X601GRpFD8YoZTo8QOayXFvv7L1F3oeK +b0w11lT0npxstmeMQUkbxAyCnKrwpQagiwBzKlr9ymJvh/ot6sJ5bAFDvZBBKkQU +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/rsa/openssl_rsa_unencrypted.pem b/crypto/test/data/openssl/rsa/openssl_rsa_unencrypted.pem new file mode 100644 index 000000000..f540dccf7 --- /dev/null +++ b/crypto/test/data/openssl/rsa/openssl_rsa_unencrypted.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7Plp +gpjUg4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc +8BQcwHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTj +HE5t7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindx +OSAnAxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfD +HArDqUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABAoIBAFd6vTKVVT0O/U04 +wTtiptA/p7fkDM5PHVBxh32Wxno5pj8PerIaiduKyuRVh7PvJRMJpw903BrAK95o +847WWOVOaF7TcKGMBURJUS6maiJS7TboK1ZbUVnsg/I99ArhiVUKGDhlsl/Xd4np +YPDYztzXLzLXpm7bS6CiuvP762x9dfVu8K+afP8cjH8pfXLq55ghZOUKidRQaYz1 +mNOTQyAQlCQdLRgKlYgqcRHlj0pb28XBJaln3W7Z7GFMWFPojkxx6LaCp8+Jyx2C +tv54zIZQhMjF37tQyTnfK4Ocl3sCRb+jYV4FkrUnsQE9W2dey0Tms1XB31gfUJlx +dRZu7zkCgYEA/nWcTwzot2OIAhXoJ2fnqTcpdmj05LHhGcayKjyix7BsVH2I0KpF +9kXX066tr3+LxZTergl4UpWSl3yx/4kPBQM6np4VVRytn7+cQdEhOczZnBw6x7IZ +fv81DSNruQDBRAlTtklW4KBY74JKLhaJSvF1F3x32+H+99i1MmCNJRMCgYEAyZpF +h4c3pM9z+YlmgLdUh/G2abdoamugcQOFbzHbZowsRAxEzdEW9wj2McN6mt8Rn1tc +tY/+PcYuIK+vcmk9k23GuzxRlJlkaDicHwlAebgVIulFcrStfTlSkXjpuOuusfD9 +2DuHMcUiPx3qElNB0dZJF/axpq7BjTIFENefhZ8CgYACn+vw1M1BtwEcJGW0olm9 +YRhIZGTCRyNvRKFp1h5HuQYlCPZ0UI1QMQA86rxX5xTmANcbLHXVRD2y2lJrtFo3 +TwU3xaGqsxUHZM6TzzhshDRqa9AfZzLkIHXHoOnnip5zuTTn2HHQ91ZzggCJ4Smh +YEQ47cu+tOIQZGfaESzjiQKBgQCCfnZlDJRq/NFwA40y4fg4arANa+eNgw7+OC5F +1HrUvQTmIx7iLmZ0Dvv1KDgTSTLJ+MRgzczexYoUJEQnhZGS/Wq2xYt06XlBsOr1 +d/KhFxOvXllSrzrhJJqaiS6YQQ36JijZr2aKQ7UwL7fUlsmy/safWVKStumX8Hmw +9jFOtwKBgQDmtirdNQ8aKolokD/3bDHPcDsNcybEpiCu8BIltxZAs/LsN1IIxfcp +mGP2AFt3mbblKbsRM8hDW/X9taeG9s2KGe5wlKOE5lV8YAo4hFoJYN2/0d8Y0K9X +QAAYU3iPG1zL+a/7TFLJ0u/biqsBg9hnNbMnN/tOeSuKnH2Rx9F1rg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/openssl/test.pem b/crypto/test/data/openssl/test.pem new file mode 100644 index 000000000..c52453c61 --- /dev/null +++ b/crypto/test/data/openssl/test.pem @@ -0,0 +1,133 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,079DD7CA8A9BAA19 + +jIqIT0DIvUlwvkREv6gnCTVFdOsoVwUS9nxcVuQ8JOwg+TB42GnhgZ5x6MFczgNd +Dw9L60zono+ethYfYB91CdIcVULzvg61/DCAFDjIFPgOIYTVNmteUq75Dmt6wDTV +4A07iMwjwBk+0YHaeVwcr0AkdvXEcVySOGdGrwy10K8Eq/kSndzm1Sm6tUCJ45+v +zSUelLlT9fgRTmAbeowT1/tlt/q52bGTcXJzIWBxDuOxK5ASCTjk28kri9WeRUb/ +iCnXn+cqR3BvkDCdlhk2A6A6Q8U9vo0m1MPtwwsolz76jnxbtBNr6Sc+zcny0brP +jCPMP1qF+IIk01N3YsAZ9mbJmXYoFf9B0VwNUjPudWlSqhvmzzanatevgZ9TID8G +Mnltd2XsqIgdvu0JhhEJRC6n7hBvn+l7iwYKtBoK+rJmEWWttkoP82UGgjzjzqKa +rEtdaZPUCEiBLqHPyiIaDWm5Pe4sZZqrV8Ix8vDLKK59ZUkgmYXyCul2yL/cfO5T +gjMqh9EeQCrNsu3hJGuEEE3MlskQkCpEspm9qDGbKPkMno7CE37plVopx0o0oovE +S8MZn0v2lIzV8yZ6krtcEA== +-----END DSA PRIVATE KEY----- +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9AC3CD3B4ED42426 + +AzAvQsDkxXGdPMlFjqO0lYXSlypkfGJWIMqij00cZI1B6K7pMnBHo3wIYStlKDg2 +SMMTYwJfsbFA8+cyCyzsqVBQC63ZgEnStMrDOt/U0SGXNb/C4mFsf1ksnAI6y/3J +3lhuPAZbMKCmANslivbj9gp4hSe828btXDhvIPKKJgKHhwHveeW9JDulySAN5KYn +s4aeasvSWVBOYtefFaS+NzrXjDnPtOMX6TQDxd9CE8es1RQbU9Ze2CEa9S7l4coj +0abWVTjxu55foDCDzbukkQm+eU0aaI4OoydoOCz6bcOfADgRx3/fJ9Z9IuS5w73O +BiF8Z4S8e7GYpgsPVEqj06PuNH7t6bwzKC9U2FTiNcejZIYPqz21d9iA4hsEfFDd +0DlXqYUKMazE+TjU8goss5cEqyLNDQmWLYLKUE2p8QmSZC/UqEsZ9pu1VZz3xpFT +k2sju26HCV14XPG5oi9LpxDQaVRmXBMFxz5b+RmUwPfZuWntTzHQXuNyH2J3B9FN +el8gaskt4hxHI28hB/eF0h7pOIBUDiR9n/BB+feOrNW8y7/ThSkdI3OK0+dyOzLg +go9s7SGz5WLyy8FWevw0k2Is4IpCueTwclDrOAPixW+paHhDGIasnvvCsz5jGqQz +4F4JPmA2ZYg/Z8dYob/ZeF/3KuJqFZAm9gseGS19sT7UzVvvmSf5IXOFfpb7VdRn +ScFMRVr8PY9ANGh7zYg/8w+G3JJj4C7djA3RB/yOhK4KwbTz/2cnEDI26VREjKs0 +7/WPQXxr/oQ+XEBTnYuJZfa7o7orGL+6wA0Vk/GJqjA= +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE REQUEST----- +MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0 +ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsO4slP/KdZQsZyYn3asTWDtX +E1YN+QQbbHELK7boPQa91YHv5DV/SgucThoXXCtSA45d3dQhrEbZ2+HRBarZIylk +Nc+VmcV1qFX5KsD9wCYPMtdAYYog6jz259yCOKPDXPm787Q5t9h2zV3Ml1i0eWhC +cdRYiWHQ5g20W4Bq3GsCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw +EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAZGPA0Jyw49cHPJjG +bloqKAPNlBO200AiRFsHnkOQ1DopJff3mW+FdszAc9g6rTB4/YAiM4r0E314e0vm +XSlW2q8sp+c2XJO7PUIdJIuAUnvSmMb/uwXFP2SzLdjLcmymMsnFfjvwkht0K2it +O5HuUDuhLnxEimGlUEBrfkdrsH0= +-----END CERTIFICATE REQUEST----- +-----BEGIN NEW CERTIFICATE REQUEST----- +MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0 +ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsO4slP/KdZQsZyYn3asTWDtX +E1YN+QQbbHELK7boPQa91YHv5DV/SgucThoXXCtSA45d3dQhrEbZ2+HRBarZIylk +Nc+VmcV1qFX5KsD9wCYPMtdAYYog6jz259yCOKPDXPm787Q5t9h2zV3Ml1i0eWhC +cdRYiWHQ5g20W4Bq3GsCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw +EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAZGPA0Jyw49cHPJjG +bloqKAPNlBO200AiRFsHnkOQ1DopJff3mW+FdszAc9g6rTB4/YAiM4r0E314e0vm +XSlW2q8sp+c2XJO7PUIdJIuAUnvSmMb/uwXFP2SzLdjLcmymMsnFfjvwkht0K2it +O5HuUDuhLnxEimGlUEBrfkdrsH0= +-----END NEW CERTIFICATE REQUEST----- +-----BEGIN CERTIFICATE----- +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= +-----END CERTIFICATE----- +-----BEGIN X509 CERTIFICATE----- +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= +-----END X509 CERTIFICATE----- +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl +IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy +aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV +BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv +dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw +MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV +MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI +NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7 +eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G +odUBlSsJwPPQjZSU +-----END ATTRIBUTE CERTIFICATE----- +-----BEGIN X509 CRL----- +MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT +F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw +MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw +MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw +MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw +MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw +MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw +MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw +NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw +NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF +AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ +wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt +JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v +-----END X509 CRL----- +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,ADBCD679C6C6363E + +MmYmhTgKNKwwnA4AIskePMy+gp3Ch7Pn/UqRGjQypIyibbp/UFY+aSbQmvQNG2R9 +6Zj6cbBJGt/C2EYXk9UonUTA9Q+FVytkpR8ON6NHlSc2twrvDpqi7lpeSB9ywlH7 +WLffwNZMNsNHfcNK2slHf4RCmpqcGsXffHe45dQG0CI= +-----END EC PRIVATE KEY----- diff --git a/crypto/test/data/rfc4134/3.1.bin b/crypto/test/data/rfc4134/3.1.bin new file mode 100644 index 000000000..c4e92dd7c Binary files /dev/null and b/crypto/test/data/rfc4134/3.1.bin differ diff --git a/crypto/test/data/rfc4134/3.2.bin b/crypto/test/data/rfc4134/3.2.bin new file mode 100644 index 000000000..9c82edf72 --- /dev/null +++ b/crypto/test/data/rfc4134/3.2.bin @@ -0,0 +1 @@ +0+ *H This is some sample content. \ No newline at end of file diff --git a/crypto/test/data/rfc4134/4.1.bin b/crypto/test/data/rfc4134/4.1.bin new file mode 100644 index 000000000..d99f79d34 Binary files /dev/null and b/crypto/test/data/rfc4134/4.1.bin differ diff --git a/crypto/test/data/rfc4134/4.10.bin b/crypto/test/data/rfc4134/4.10.bin new file mode 100644 index 000000000..d3815bdfa Binary files /dev/null and b/crypto/test/data/rfc4134/4.10.bin differ diff --git a/crypto/test/data/rfc4134/4.11.bin b/crypto/test/data/rfc4134/4.11.bin new file mode 100644 index 000000000..e203651ff Binary files /dev/null and b/crypto/test/data/rfc4134/4.11.bin differ diff --git a/crypto/test/data/rfc4134/4.2.bin b/crypto/test/data/rfc4134/4.2.bin new file mode 100644 index 000000000..c1b602413 Binary files /dev/null and b/crypto/test/data/rfc4134/4.2.bin differ diff --git a/crypto/test/data/rfc4134/4.3.bin b/crypto/test/data/rfc4134/4.3.bin new file mode 100644 index 000000000..1bc6b1549 Binary files /dev/null and b/crypto/test/data/rfc4134/4.3.bin differ diff --git a/crypto/test/data/rfc4134/4.4.bin b/crypto/test/data/rfc4134/4.4.bin new file mode 100644 index 000000000..3245c115d Binary files /dev/null and b/crypto/test/data/rfc4134/4.4.bin differ diff --git a/crypto/test/data/rfc4134/4.5.bin b/crypto/test/data/rfc4134/4.5.bin new file mode 100644 index 000000000..6608d9b13 Binary files /dev/null and b/crypto/test/data/rfc4134/4.5.bin differ diff --git a/crypto/test/data/rfc4134/4.6.bin b/crypto/test/data/rfc4134/4.6.bin new file mode 100644 index 000000000..1a7eb9591 Binary files /dev/null and b/crypto/test/data/rfc4134/4.6.bin differ diff --git a/crypto/test/data/rfc4134/4.7.bin b/crypto/test/data/rfc4134/4.7.bin new file mode 100644 index 000000000..ea6b1df67 Binary files /dev/null and b/crypto/test/data/rfc4134/4.7.bin differ diff --git a/crypto/test/data/rfc4134/4.8.eml b/crypto/test/data/rfc4134/4.8.eml new file mode 100644 index 000000000..206ebf023 --- /dev/null +++ b/crypto/test/data/rfc4134/4.8.eml @@ -0,0 +1,39 @@ +MIME-Version: 1.0 +To: User2@examples.com +From: aliceDss@examples.com +Subject: Example 4.8 +Message-Id: <020906002550300.249@examples.com> +Date: Fri, 06 Sep 2002 00:25:21 -0300 +Content-Type: multipart/signed; + micalg=SHA1; + boundary="----=_NextBoundry____Fri,_06_Sep_2002_00:25:21"; + protocol="application/pkcs7-signature" + +This is a multi-part message in MIME format. + +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21 + +This is some sample content. +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21 +Content-Type: application/pkcs7-signature; name=smime.p7s +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7s + +MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGgggLgMIIC +3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDTk5MDgxNzAx +MTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2MIIBKwYHKoZIzjgE +ATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lOFzSH4M1vNESNH+n6+koYkv +4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iLVPE/sAcIR01diMPDtbPjVQh11Tl2 +EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5 ++z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3q +nMkhijt2FOnOLl2jB80jhbgvMAF8bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGB +SmA5ujY5A4GEAAKBgFzjuVp1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/ ++onyohs+JH09B41bY8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTS +ljf2YUeyxDKE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E +BAMCBsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfft +Q3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM44BAMD +MAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0NevTFjMGECAQEw +GDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjOOAQDBC4wLAIUM/mGf6gk +gp9Z0XtRdGimJeB/BxUCFGFFJqwYRt1WYcIOQoGiaowqGzVI + +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21-- diff --git a/crypto/test/data/rfc4134/4.9.eml b/crypto/test/data/rfc4134/4.9.eml new file mode 100644 index 000000000..543157589 --- /dev/null +++ b/crypto/test/data/rfc4134/4.9.eml @@ -0,0 +1,28 @@ +MIME-Version: 1.0 +To: User2@examples.com +From: aliceDss@examples.com +Subject: Example 4.9 +Message-Id: <021031164540300.304@examples.com> +Date: Thu, 31 Oct 2002 16:45:14 -0300 +Content-Type: application/pkcs7-mime; smime-type=signed-data; + name=smime.p7m +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m + +MIIDmQYJKoZIhvcNAQcCoIIDijCCA4YCAQExCTAHBgUrDgMCGjAtBgkqhkiG9w0BBwGgIAQeDQpU +aGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIIC4DCCAtwwggKboAMCAQICAgDIMAkGByqGSM44 +BAMwEjEQMA4GA1UEAxMHQ2FybERTUzAeFw05OTA4MTcwMTEwNDlaFw0zOTEyMzEyMzU5NTlaMBMx +ETAPBgNVBAMTCEFsaWNlRFNTMIIBtjCCASsGByqGSM44BAEwggEeAoGBAIGNze2D6gqeOT7CSCij +5EeT3Q7XqA7sU8WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg23j+bv7dM3F9piuR10DcMkQiV +m96nXvn89J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dhDEeL3/nbCElzfy5FEbteQJllzzflvb +AhUA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUiTKqOfs+bdlLWWpMdiM5BAI1XPLLGjDDHlBd +3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oIXks+kPht6pzJIYo7dhTpzi5dowfNI4W4LzABfG1J +iRGJNkS9+MiVSlNWteL5c+waYTYfEX/Cve3RUP+YdMLRgUpgObo2OQOBhAACgYBc47ladRSWC6l6 +3eM/qeysXty9txMRNKYWiSgRI9k0hmd1dRMSPUNbb+VRv/qJ8qIbPiR9PQeNW2PIu0WloErjhdbO +BoA/6CN+GvIkq1MauCcNHu8Iv2YUgFxirGX6FYvxuzTU0pY39mFHssQyhPB+QUD9RqdjTjPypeL0 +8oPluKOBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFHBEPoIu +b4feStN14z0gvEMrk/EfMB0GA1UdDgQWBBS+bKGz48H37UNwpM4TAeL945f+zTAfBgNVHREEGDAW +gRRBbGljZURTU0BleGFtcGxlLmNvbTAJBgcqhkjOOAQDAzAAMC0CFFUMpBkfQiuJcSIzjYNqtT1n +a79FAhUAn2FTUlQLXLLd2ud2HeIQUltDXr0xYzBhAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERTUwIC +AMgwBwYFKw4DAhowCQYHKoZIzjgEAwQuMCwCFD1cSW6LIUFzeXle3YI5SKSBer/sAhQmCq7s/CTF +HOEjgASeUjbMpx5g6A== diff --git a/crypto/test/data/rfc4134/5.1.bin b/crypto/test/data/rfc4134/5.1.bin new file mode 100644 index 000000000..9750174a0 Binary files /dev/null and b/crypto/test/data/rfc4134/5.1.bin differ diff --git a/crypto/test/data/rfc4134/5.2.bin b/crypto/test/data/rfc4134/5.2.bin new file mode 100644 index 000000000..de17b0137 Binary files /dev/null and b/crypto/test/data/rfc4134/5.2.bin differ diff --git a/crypto/test/data/rfc4134/5.3.eml b/crypto/test/data/rfc4134/5.3.eml new file mode 100644 index 000000000..55013adcf --- /dev/null +++ b/crypto/test/data/rfc4134/5.3.eml @@ -0,0 +1,19 @@ +MIME-Version: 1.0 +Message-Id: <00103112005203.00349@amyemily.ig.com> +Date: Tue, 31 Oct 2000 12:00:52 -0600 (Central Standard Time) +From: User1 +To: User2 +Subject: Example 5.3 +Content-Type: application/pkcs7-mime; + name=smime.p7m; + smime-type=enveloped-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m + +MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYXJsUlNB +AhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8k +bKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJ +tuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJKoZI +hvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4OxUk660cu1lXeCSFOSOpO +J7FuVyU= + diff --git a/crypto/test/data/rfc4134/6.0.bin b/crypto/test/data/rfc4134/6.0.bin new file mode 100644 index 000000000..dfbfaaaed Binary files /dev/null and b/crypto/test/data/rfc4134/6.0.bin differ diff --git a/crypto/test/data/rfc4134/7.1.bin b/crypto/test/data/rfc4134/7.1.bin new file mode 100644 index 000000000..9184c5852 Binary files /dev/null and b/crypto/test/data/rfc4134/7.1.bin differ diff --git a/crypto/test/data/rfc4134/7.2.bin b/crypto/test/data/rfc4134/7.2.bin new file mode 100644 index 000000000..b95b34140 Binary files /dev/null and b/crypto/test/data/rfc4134/7.2.bin differ diff --git a/crypto/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer b/crypto/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer new file mode 100644 index 000000000..7e96210fc Binary files /dev/null and b/crypto/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer differ diff --git a/crypto/test/data/rfc4134/AlicePrivDSSSign.pri b/crypto/test/data/rfc4134/AlicePrivDSSSign.pri new file mode 100644 index 000000000..e123ee72d Binary files /dev/null and b/crypto/test/data/rfc4134/AlicePrivDSSSign.pri differ diff --git a/crypto/test/data/rfc4134/AlicePrivRSASign.pri b/crypto/test/data/rfc4134/AlicePrivRSASign.pri new file mode 100644 index 000000000..c885108e7 Binary files /dev/null and b/crypto/test/data/rfc4134/AlicePrivRSASign.pri differ diff --git a/crypto/test/data/rfc4134/AliceRSASignByCarl.cer b/crypto/test/data/rfc4134/AliceRSASignByCarl.cer new file mode 100644 index 000000000..848ba8726 Binary files /dev/null and b/crypto/test/data/rfc4134/AliceRSASignByCarl.cer differ diff --git a/crypto/test/data/rfc4134/BobPrivRSAEncrypt.pri b/crypto/test/data/rfc4134/BobPrivRSAEncrypt.pri new file mode 100644 index 000000000..b0805b84a Binary files /dev/null and b/crypto/test/data/rfc4134/BobPrivRSAEncrypt.pri differ diff --git a/crypto/test/data/rfc4134/BobRSASignByCarl.cer b/crypto/test/data/rfc4134/BobRSASignByCarl.cer new file mode 100644 index 000000000..1068ab9d4 Binary files /dev/null and b/crypto/test/data/rfc4134/BobRSASignByCarl.cer differ diff --git a/crypto/test/data/rfc4134/CarlDSSCRLEmpty.crl b/crypto/test/data/rfc4134/CarlDSSCRLEmpty.crl new file mode 100644 index 000000000..42af3a09a Binary files /dev/null and b/crypto/test/data/rfc4134/CarlDSSCRLEmpty.crl differ diff --git a/crypto/test/data/rfc4134/CarlDSSCRLForAll.crl b/crypto/test/data/rfc4134/CarlDSSCRLForAll.crl new file mode 100644 index 000000000..52b818d4a Binary files /dev/null and b/crypto/test/data/rfc4134/CarlDSSCRLForAll.crl differ diff --git a/crypto/test/data/rfc4134/CarlDSSCRLForCarl.crl b/crypto/test/data/rfc4134/CarlDSSCRLForCarl.crl new file mode 100644 index 000000000..2a4e79499 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlDSSCRLForCarl.crl differ diff --git a/crypto/test/data/rfc4134/CarlDSSSelf.cer b/crypto/test/data/rfc4134/CarlDSSSelf.cer new file mode 100644 index 000000000..b47c682fd Binary files /dev/null and b/crypto/test/data/rfc4134/CarlDSSSelf.cer differ diff --git a/crypto/test/data/rfc4134/CarlPrivDSSSign.pri b/crypto/test/data/rfc4134/CarlPrivDSSSign.pri new file mode 100644 index 000000000..4b1fdc00d Binary files /dev/null and b/crypto/test/data/rfc4134/CarlPrivDSSSign.pri differ diff --git a/crypto/test/data/rfc4134/CarlPrivRSASign.pri b/crypto/test/data/rfc4134/CarlPrivRSASign.pri new file mode 100644 index 000000000..7fee220a6 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlPrivRSASign.pri differ diff --git a/crypto/test/data/rfc4134/CarlRSACRLEmpty.crl b/crypto/test/data/rfc4134/CarlRSACRLEmpty.crl new file mode 100644 index 000000000..c3eb30466 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlRSACRLEmpty.crl differ diff --git a/crypto/test/data/rfc4134/CarlRSACRLForAll.crl b/crypto/test/data/rfc4134/CarlRSACRLForAll.crl new file mode 100644 index 000000000..3708ccbf5 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlRSACRLForAll.crl differ diff --git a/crypto/test/data/rfc4134/CarlRSACRLForCarl.crl b/crypto/test/data/rfc4134/CarlRSACRLForCarl.crl new file mode 100644 index 000000000..2ce8e4db5 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlRSACRLForCarl.crl differ diff --git a/crypto/test/data/rfc4134/CarlRSASelf.cer b/crypto/test/data/rfc4134/CarlRSASelf.cer new file mode 100644 index 000000000..ce6737d90 Binary files /dev/null and b/crypto/test/data/rfc4134/CarlRSASelf.cer differ diff --git a/crypto/test/data/rfc4134/DianeDSSSignByCarlInherit.cer b/crypto/test/data/rfc4134/DianeDSSSignByCarlInherit.cer new file mode 100644 index 000000000..e0fa3ac75 Binary files /dev/null and b/crypto/test/data/rfc4134/DianeDSSSignByCarlInherit.cer differ diff --git a/crypto/test/data/rfc4134/DianePrivDSSSign.pri b/crypto/test/data/rfc4134/DianePrivDSSSign.pri new file mode 100644 index 000000000..68ddc9594 Binary files /dev/null and b/crypto/test/data/rfc4134/DianePrivDSSSign.pri differ diff --git a/crypto/test/data/rfc4134/DianePrivRSASignEncrypt.pri b/crypto/test/data/rfc4134/DianePrivRSASignEncrypt.pri new file mode 100644 index 000000000..b7bcb2953 Binary files /dev/null and b/crypto/test/data/rfc4134/DianePrivRSASignEncrypt.pri differ diff --git a/crypto/test/data/rfc4134/DianeRSASignByCarl.cer b/crypto/test/data/rfc4134/DianeRSASignByCarl.cer new file mode 100644 index 000000000..062260a9d Binary files /dev/null and b/crypto/test/data/rfc4134/DianeRSASignByCarl.cer differ diff --git a/crypto/test/data/rfc4134/ExContent.bin b/crypto/test/data/rfc4134/ExContent.bin new file mode 100644 index 000000000..22ddba65c --- /dev/null +++ b/crypto/test/data/rfc4134/ExContent.bin @@ -0,0 +1 @@ +This is some sample content. \ No newline at end of file diff --git a/crypto/test/data/rfc4134/rfc4134.txt b/crypto/test/data/rfc4134/rfc4134.txt new file mode 100644 index 000000000..a53cec5e1 --- /dev/null +++ b/crypto/test/data/rfc4134/rfc4134.txt @@ -0,0 +1,7619 @@ + + + + + + +Network Working Group P. Hoffman, Ed. +Request for Comments: 4134 Internet Mail Consortium +Category: Informational July 2005 + + + Examples of S/MIME Messages + +Status of This Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + This document gives examples of message bodies formatted using + S/MIME. Specifically, it has examples of Cryptographic Message + Syntax (CMS) objects and S/MIME messages (including the MIME + formatting). It includes examples of many common CMS formats. The + purpose of this document is to help increase interoperability for + S/MIME and other protocols that rely on CMS. + + + + + + + + + + + + + + + + + + + + + + + + + + +Hoffman, Ed. Informational [Page 1] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +Table of Contents + + 1. Introduction ................................................ 3 + 2. Constants Used in the Examples .............................. 3 + 2.1. Content of Documents .................................. 4 + 2.2. Private Keys .......................................... 4 + 2.3. Certificates .......................................... 13 + 2.4. CRLs .................................................. 33 + 3. Trivial Examples ............................................ 39 + 3.1. ContentInfo with Data Type, BER ....................... 39 + 3.2. ContentInfo with Data Type, DER ....................... 39 + 4. Signed-data ................................................. 39 + 4.1. Basic Signed Content, DSS ............................. 39 + 4.2. Basic Signed Content, RSA ............................. 44 + 4.3. Basic Signed Content, Detached Content ................ 49 + 4.4. Fancier Signed Content ................................ 53 + 4.5. All RSA Signed Message ................................ 68 + 4.6. Multiple Signers ...................................... 75 + 4.7. Signing Using SKI ..................................... 83 + 4.8. S/MIME multipart/signed Message ....................... 87 + 4.9. S/MIME application/pkcs7-mime Signed Message .......... 88 + 4.10. SignedData with Attributes ............................ 89 + 4.11. SignedData with Certificates Only ..................... 101 + 5. Enveloped-data .............................................. 109 + 5.1. Basic Encrypted Content, TripleDES and RSA ............ 109 + 5.2. Basic Encrypted Content, RC2/128 and RSA .............. 110 + 5.3. S/MIME application/pkcs7-mime Encrypted Message ....... 112 + 6. Digested-data ............................................... 112 + 7. Encrypted-data .............................................. 113 + 7.1. Simple EncryptedData .................................. 113 + 7.2. EncryptedData with Unprotected Attributes ............. 114 + 8. Security Considerations ..................................... 115 + 9. References .................................................. 115 + 9.1. Normative References .................................. 115 + 9.2. Informative References ................................ 115 + A. Binaries of the Examples .................................... 116 + A.1. How the Binaries and Extractor Works .................. 116 + A.2. Example Extraction Program ............................ 116 + B. Examples in Order of Appearance ............................. 118 + C. Acknowledgements ............................................ 135 + + + + + + + + + + + +Hoffman, Ed. Informational [Page 2] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +1. Introduction + + The examples in this document show the structure and format of CMS + message bodies, as described in [CMS]. They are useful to + implementors who use protocols that rely on CMS, such as the S/MIME + message format protocol. There are also examples of simple S/MIME + messages [SMIME-MSG] (including the MIME headers). + + Every example in this document has been checked by two different + implementors. This strongly indicates (but does not assure) that the + examples are correct. All CMS implementors must read the CMS + document carefully before implementing from it. No one should use + the examples in this document as stand-alone explanations of how to + create CMS message bodies. + + This document explicitly does not attempt to cover many PKIX [PKIX] + examples. Documents with examples of that format may be forthcoming. + Also, note that [DVCS], which covers PKIX Data Validation and + Certification Server Protocols, has examples of formats for its + protocol. + + The examples shown here were created and validated by many different + people over a long period of time. Because of this, some of the + dates used in the examples are many years in the past. This, plus + the fact that some of the certificates in the examples have very long + lifespans, may cause problems in some test situations. + +2. Constants Used in the Examples + + This section defines the data used in the rest of the document. The + names of the constants indicate their use. For example, + AlicePrivDSSSign is the private part of Alice's DSS signing key. + + - Alice is the creator of the message bodies in this document. + + - Bob is the recipient of the messages. + + - Carl is a CA. + + - Diane sometimes gets involved with these folks. + + - Erica also sometimes gets involved. + + + + + + + + + +Hoffman, Ed. Informational [Page 3] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +2.1. Content of Documents + + ExContent is the following sentence: + + This is some sample content. + + That is, it is the string of characters starting with "T" up to and + including the ".". + + The hex for ExContent is + + 5468 6973 2069 7320 736f 6d65 2073 616d 706c 6520 636f 6e74 656e 742e + + The MD5 hash of ExContent is + + 9898 cac8 fab7 691f f89d c207 24e7 4a04 + + The SHA-1 hash of ExContent is + + 406a ec08 5279 ba6e 1602 2d9e 0629 c022 9687 dd48 + +2.2. Private Keys + + The following private keys are needed to create the samples. To find + the public keys, see the certificates in the next section. + + AlicePrivDSSSign = + 0 30 331: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 299: SEQUENCE { + 11 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 20 30 286: SEQUENCE { + 24 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 156 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + + + +Hoffman, Ed. Informational [Page 4] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 179 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 310 04 23: OCTET STRING, encapsulates { + 312 02 21: INTEGER + : 00 BB 44 46 D1 A5 C9 46 07 2E D0 FE + : 7A D6 92 07 F0 9A 85 89 3F + : } + : } + + AlicePrivRSASign = + 0 30 630: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 13: SEQUENCE { + 9 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 20 05 0: NULL + : } + 22 04 608: OCTET STRING, encapsulates { + 26 30 604: SEQUENCE { + 30 02 1: INTEGER 0 + 33 02 129: INTEGER + : 00 E0 89 73 39 8D D8 F5 F5 E8 87 76 + : 39 7F 4E B0 05 BB 53 83 DE 0F B7 AB + : DC 7D C7 75 29 0D 05 2E 6D 12 DF A6 + : 86 26 D4 D2 6F AA 58 29 FC 97 EC FA + : 82 51 0F 30 80 BE B1 50 9E 46 44 F1 + : 2C BB D8 32 CF C6 68 6F 07 D9 B0 60 + : AC BE EE 34 09 6A 13 F5 F7 05 05 93 + : DF 5E BA 35 56 D9 61 FF 19 7F C9 81 + : E6 F8 6C EA 87 40 70 EF AC 6D 2C 74 + : 9F 2D FA 55 3A B9 99 77 02 A6 48 52 + : 8C 4E F3 57 38 57 74 57 5F + 165 02 3: INTEGER 65537 + 170 02 128: INTEGER + : 00 A4 03 C3 27 47 76 34 34 6C A6 86 + + + +Hoffman, Ed. Informational [Page 5] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : B5 79 49 01 4B 2E 8A D2 C8 62 B2 C7 + : D7 48 09 6A 8B 91 F7 36 F2 75 D6 E8 + : CD 15 90 60 27 31 47 35 64 4D 95 CD + : 67 63 CE B4 9F 56 AC 2F 37 6E 1C EE + : 0E BF 28 2D F4 39 90 6F 34 D8 6E 08 + : 5B D5 65 6A D8 41 F3 13 D7 2D 39 5E + : FE 33 CB FF 29 E4 03 0B 3D 05 A2 8F + : B7 F1 8E A2 76 37 B0 79 57 D3 2F 2B + : DE 87 06 22 7D 04 66 5E C9 1B AF 8B + : 1A C3 EC 91 44 AB 7F 21 + 301 02 65: INTEGER + : 00 F6 D6 E0 22 21 4C 5F 0A 70 FF 27 + : FC E5 B3 50 6A 9D E5 0F B5 85 96 C6 + : 40 FA A8 0A B4 9B 9B 0C 55 C2 01 1D + : F9 37 82 8A 14 C8 F2 93 0E 92 CD A5 + : 66 21 B9 3C D2 06 BF B4 55 31 C9 DC + : AD CA 98 2D D1 + 368 02 65: INTEGER + : 00 E8 DE B0 11 25 09 D2 02 51 01 DE + : 8A E8 98 50 F5 77 77 61 A4 45 93 6B + : 08 55 96 73 5D F4 C8 5B 12 93 22 73 + : 8B 7F D3 70 7F F5 A4 AA BB 74 FD 3C + : 22 6A DA 38 91 2A 86 5B 6C 14 E8 AE + : 4C 9E FA 8E 2F + 435 02 65: INTEGER + : 00 97 4C F0 87 9B 17 7F EE 1B 83 1B + : 14 B6 0B 6A 90 5F 86 27 51 E1 B7 A0 + : 7F F5 E4 88 E3 59 B9 F9 1E 9B D3 29 + : 77 38 22 48 D7 22 B1 25 98 BA 3D 59 + : 53 B7 FA 1E 20 B2 C8 51 16 23 75 93 + : 51 E7 AB CD F1 + 502 02 64: INTEGER + : 2C F0 24 5B FA A0 CD 85 22 EA D0 6E + : 4F FA 6C CD 21 D3 C8 E4 F1 84 44 48 + : 64 73 D7 29 8F 7E 46 8C EC 15 DE E4 + : 51 B3 94 E7 2C 99 2D 55 65 7B 24 EA + : A3 62 1F 3E 6C 4D 67 41 11 3B E1 BE + : E9 83 02 83 + 568 02 64: INTEGER + : 58 88 D9 A1 50 38 84 6A AB 03 BC BB + : DF 4B F4 9C 6F B8 B4 2A 25 FB F6 E4 + : 05 2F 6E E2 88 89 21 6F 4B 25 9E D0 + : AB 50 93 CA BF 40 71 EC 21 25 C5 7F + : FB 02 E9 21 96 B8 33 CD E2 C6 95 EE + : 6F 8D 5F 28 + : } + : } + : } + + + +Hoffman, Ed. Informational [Page 6] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + BobPrivRSAEncrypt = + 0 30 645: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 13: SEQUENCE { + 9 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 20 05 0: NULL + : } + 22 04 608: OCTET STRING, encapsulates { + 26 30 604: SEQUENCE { + 30 02 1: INTEGER 0 + 33 02 129: INTEGER + : 00 A9 E1 67 98 3F 39 D5 5F F2 A0 93 + : 41 5E A6 79 89 85 C8 35 5D 9A 91 5B + : FB 1D 01 DA 19 70 26 17 0F BD A5 22 + : D0 35 85 6D 7A 98 66 14 41 5C CF B7 + : B7 08 3B 09 C9 91 B8 19 69 37 6D F9 + : 65 1E 7B D9 A9 33 24 A3 7F 3B BB AF + : 46 01 86 36 34 32 CB 07 03 59 52 FC + : 85 8B 31 04 B8 CC 18 08 14 48 E6 4F + : 1C FB 5D 60 C4 E0 5C 1F 53 D3 7F 53 + : D8 69 01 F1 05 F8 7A 70 D1 BE 83 C6 + : 5F 38 CF 1C 2C AA 6A A7 EB + 165 02 3: INTEGER 65537 + 170 02 128: INTEGER + : 67 CD 48 4C 9A 0D 8F 98 C2 1B 65 FF + : 22 83 9C 6D F0 A6 06 1D BC ED A7 03 + : 88 94 F2 1C 6B 0F 8B 35 DE 0E 82 78 + : 30 CB E7 BA 6A 56 AD 77 C6 EB 51 79 + : 70 79 0A A0 F4 FE 45 E0 A9 B2 F4 19 + : DA 87 98 D6 30 84 74 E4 FC 59 6C C1 + : C6 77 DC A9 91 D0 7C 30 A0 A2 C5 08 + : 5E 21 71 43 FC 0D 07 3D F0 FA 6D 14 + : 9E 4E 63 F0 17 58 79 1C 4B 98 1C 3D + : 3D B0 1B DF FA 25 3B A3 C0 2C 98 05 + : F6 10 09 D8 87 DB 03 19 + 301 02 65: INTEGER + : 00 D0 C3 22 C6 DE A2 99 18 76 8F 8D + : BC A6 75 D6 66 3F D4 8D 45 52 8C 76 + : F5 72 C4 EB F0 46 9A F1 3E 5C AA 55 + : 0B 9B DA DD 6B 6D F8 FC 3B 3C 08 43 + : 93 B5 5B FE CE EA FD 68 84 23 62 AF + : F3 31 C2 B9 E5 + 368 02 65: INTEGER + : 00 D0 51 FC 1E 22 B7 5B ED B5 8E 01 + : C8 D7 AB F2 58 D4 F7 82 94 F3 53 A8 + : 19 45 CB 66 CA 28 19 5F E2 10 2B F3 + + + +Hoffman, Ed. Informational [Page 7] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 8F EC 6A 30 74 F8 4D 11 F4 A7 C4 20 + : B5 47 21 DC 49 01 F9 0A 20 29 F0 24 + : 08 84 60 7D 8F + 435 02 64: INTEGER + : 34 BA 64 C9 48 28 57 74 D7 55 50 DE + : 6A 48 EF 1B 2A 5A 1C 48 7B 1E 21 59 + : C3 60 3B 9B 97 A9 C0 EF 18 66 A9 4E + : 62 52 38 84 CE E5 09 88 48 94 69 C5 + : 20 14 99 5A 57 FE 23 6C E4 A7 23 7B + : D0 80 B7 85 + 501 02 65: INTEGER + : 00 9E 2F B3 37 9A FB 0B 06 5D 57 E1 + : 09 06 A4 5D D9 90 96 06 05 5F 24 06 + : 40 72 9C 3A 88 85 9C 87 0F 9D 62 12 + : 88 16 68 A8 35 1A 1B 43 E8 38 C0 98 + : 69 AF 03 0A 48 32 04 4E E9 0F 8F 77 + : 7D 34 30 25 07 + 568 02 64: INTEGER + : 57 18 67 D6 0A D2 B5 AB C2 BA 7A E7 + : 54 DA 9C 05 4F 81 D4 EF 01 89 1E 32 + : 3D 69 CB 31 C4 52 C8 54 55 25 00 3B + : 1C 2A 7C 26 50 D5 E9 A6 D7 77 CB CF + : 15 F5 EE 0B D5 8D EE B3 AF 4C A1 7C + : 63 46 41 F6 + : } + : } + 634 A0 13: [0] { + 636 30 11: SEQUENCE { + 638 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 643 31 4: SET { + 645 03 2: BIT STRING 0 unused bits + : '00001000'B (bit 3) + : Error: Spurious zero bits in bitstring. + : } + : } + : } + : } + + CarlPrivDSSSign = + 0 30 330: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 299: SEQUENCE { + 11 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 20 30 286: SEQUENCE { + 24 02 129: INTEGER + : 00 B6 49 18 3E 8A 44 C1 29 71 94 4C + + + +Hoffman, Ed. Informational [Page 8] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 01 C4 12 C1 7A 79 CB 54 4D AB 1E 81 + : FB C6 4C B3 0E 94 09 06 EB 01 D4 B1 + : C8 71 4B C7 45 C0 50 25 5D 9C FC DA + : E4 6D D3 E2 86 48 84 82 7D BA 15 95 + : 4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A + : 0A 8A BA 16 7B B9 50 01 48 93 8B EB + : 25 15 51 97 55 DC 8F 53 0E 10 A9 50 + : FC 70 B7 CD 30 54 FD DA DE A8 AA 22 + : B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9 + : AD E1 08 D4 6D 29 2D D6 E9 + 156 02 21: INTEGER + : 00 DD C1 2F DF 53 CE 0B 34 60 77 3E + : 02 A4 BF 8A 5D 98 B9 10 D5 + 179 02 128: INTEGER + : 0C EE 57 9B 4B BD DA B6 07 6A 74 37 + : 4F 55 7F 9D ED BC 61 0D EB 46 59 3C + : 56 0B 2B 5B 0C 91 CE A5 62 52 69 CA + : E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C + : AD CB AE 45 E3 06 AC 8C 22 9D 9C 44 + : 87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE + : AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A + : 73 AA 7F 46 51 1F A9 42 16 9C 48 EB + : 8A 79 61 B4 D5 2F 53 22 44 63 1F 86 + : B8 A3 58 06 25 F8 29 C0 EF BA E0 75 + : F0 42 C4 63 65 52 9B 0A + : } + : } + 310 04 22: OCTET STRING, encapsulates { + 312 02 20: INTEGER + : 19 B3 38 A5 21 62 31 50 E5 7F B9 3E + : 08 46 78 D1 3E B5 E5 72 + : } + : } + + CarlPrivRSASign = + 0 30 630: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 13: SEQUENCE { + 9 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 20 05 0: NULL + : } + 22 04 608: OCTET STRING, encapsulates { + 26 30 604: SEQUENCE { + 30 02 1: INTEGER 0 + 33 02 129: INTEGER + : 00 E4 4B FF 18 B8 24 57 F4 77 FF 6E + + + +Hoffman, Ed. Informational [Page 9] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 73 7B 93 71 5C BC 33 1A 92 92 72 23 + : D8 41 46 D0 CD 11 3A 04 B3 8E AF 82 + : 9D BD 51 1E 17 7A F2 76 2C 2B 86 39 + : A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC + : A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F + : 99 25 8F B8 4E AB B9 7D D5 96 65 DA + : 16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7 + : 29 CB 82 DD AC 44 E9 AA 93 94 29 0E + : F8 18 D6 C8 57 5E F2 76 C4 F2 11 60 + : 38 B9 1B 3C 1D 97 C9 6A F1 + 165 02 3: INTEGER 65537 + 170 02 129: INTEGER + : 00 AE 73 E4 5B 5F 5B 66 5A C9 D7 C6 + : EF 38 5F 53 21 2A 2F 62 FE DE 29 9A + : 7A 86 67 36 E7 7D 62 78 75 3D 73 A0 + : BC 29 0E F3 8F BD C3 C9 C9 B6 F8 BA + : D6 13 9B C3 97 7A CA 6A F0 B8 85 65 + : 4E 0F BD A7 A8 F7 54 06 41 BD EB DC + : 20 77 90 DF 61 9B 9A 6F 74 DE EA 3B + : D4 9C 87 60 ED 76 84 F1 6A 30 37 D5 + : E0 90 16 F8 80 47 C3 19 6B ED 75 77 + : BA 4A ED 39 B6 5D 02 47 3B 5F 1B C8 + : 1C AB CB E8 F5 26 3F A4 81 + 302 02 65: INTEGER + : 00 FF DF 09 A0 56 0B 42 52 9E C4 4D + : 93 B3 B0 49 BB DE E7 81 7D 28 99 D0 + : B1 48 BA 0B 39 E1 1C 7B 22 18 33 B6 + : 40 F6 BF DC AE 1D D0 A1 AD 04 71 5A + : 61 0A 6E 3B CE 30 DA 36 9F 65 25 29 + : BB A7 0E 7F 0B + 369 02 65: INTEGER + : 00 E4 69 68 18 5F F9 57 D0 7C 66 89 + : 0F BA 63 1D 72 CB 20 A4 81 76 64 89 + : CD 7D D1 C2 27 A9 2E AC 7A 56 9A 85 + : 07 D9 30 03 A3 03 AB 7F 88 92 50 24 + : 01 AA 1B 07 1F 20 4C B7 C9 7B 56 F7 + : B6 C2 7E AB 73 + 436 02 64: INTEGER + : 57 36 6C 8F 8C 04 76 6C B6 D4 EE 24 + : 44 00 F8 80 E2 AF 42 01 A9 0F 14 84 + : F8 E7 00 E0 8F 8C 27 A4 2D 5F A2 E5 + : 6D B5 63 C0 AD 44 E9 76 91 A7 19 49 + : 2E 46 F8 77 85 4B 3B 87 04 F0 AF D2 + : D8 54 26 95 + 502 02 64: INTEGER + : 64 A1 0F AC 55 74 1B BD 0D 61 7B 17 + : 03 CD B0 E6 A7 19 1D 80 AF F1 41 48 + : D8 1A B6 88 14 A0 2C 7A C5 76 D4 0F + + + +Hoffman, Ed. Informational [Page 10] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 0E 1F 7A 2A B2 6E 37 04 AB 39 45 73 + : BA 46 A8 0F 8D 82 5F 22 14 05 CF A2 + : A3 F3 7C 83 + 568 02 64: INTEGER + : 26 1E 1D 1C A1 98 2B E4 DB 38 E8 57 + : 6E 6B 73 19 88 61 3A FA 74 4A 36 8B + : 47 68 5D 50 EB 26 E3 EA 7D 9B 4E 65 + : A9 AF 7B AB 4B 2E 76 51 3D A8 D0 11 + : AB A3 D6 A8 C0 27 36 1D 54 0B AA A7 + : D1 6D 8D FA + : } + : } + : } + + DianePrivDSSSign = + 0 30 331: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 299: SEQUENCE { + 11 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 20 30 286: SEQUENCE { + 24 02 129: INTEGER + : 00 B6 49 18 3E 8A 44 C1 29 71 94 4C + : 01 C4 12 C1 7A 79 CB 54 4D AB 1E 81 + : FB C6 4C B3 0E 94 09 06 EB 01 D4 B1 + : C8 71 4B C7 45 C0 50 25 5D 9C FC DA + : E4 6D D3 E2 86 48 84 82 7D BA 15 95 + : 4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A + : 0A 8A BA 16 7B B9 50 01 48 93 8B EB + : 25 15 51 97 55 DC 8F 53 0E 10 A9 50 + : FC 70 B7 CD 30 54 FD DA DE A8 AA 22 + : B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9 + : AD E1 08 D4 6D 29 2D D6 E9 + 156 02 21: INTEGER + : 00 DD C1 2F DF 53 CE 0B 34 60 77 3E + : 02 A4 BF 8A 5D 98 B9 10 D5 + 179 02 128: INTEGER + : 0C EE 57 9B 4B BD DA B6 07 6A 74 37 + : 4F 55 7F 9D ED BC 61 0D EB 46 59 3C + : 56 0B 2B 5B 0C 91 CE A5 62 52 69 CA + : E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C + : AD CB AE 45 E3 06 AC 8C 22 9D 9C 44 + : 87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE + : AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A + : 73 AA 7F 46 51 1F A9 42 16 9C 48 EB + : 8A 79 61 B4 D5 2F 53 22 44 63 1F 86 + : B8 A3 58 06 25 F8 29 C0 EF BA E0 75 + : F0 42 C4 63 65 52 9B 0A + + + +Hoffman, Ed. Informational [Page 11] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + 310 04 23: OCTET STRING, encapsulates { + 312 02 21: INTEGER + : 00 96 95 F9 E0 C1 E0 41 2D 32 0F 8B + : 42 52 93 2A E6 1E 0E 21 29 + : } + : } + + DianePrivRSASignEncrypt = + 0 30 631: SEQUENCE { + 4 02 1: INTEGER 0 + 7 30 13: SEQUENCE { + 9 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 20 05 0: NULL + : } + 22 04 609: OCTET STRING, encapsulates { + 26 30 605: SEQUENCE { + 30 02 1: INTEGER 0 + 33 02 129: INTEGER + : 00 D6 FD B8 C0 70 C6 4C 25 EC EA CF + : EA 7C BB A2 62 FA F0 E6 32 3A 53 FF + : B1 92 5A 17 F4 20 E1 99 24 82 0A D0 + : F6 7C FB 44 CA 8B 27 06 F1 7E 26 03 + : A9 76 9D CF EC A0 2C 70 96 F2 83 42 + : F6 D4 B7 28 0A BB F8 BF 4A 4C 19 3F + : 07 DB A0 C1 60 1E B7 7E 67 F7 DE B1 + : C3 60 49 AC 45 D7 F8 C6 EF 08 37 21 + : 93 47 EE F0 73 35 72 B0 02 C4 F3 11 + : C3 5E 47 E5 0A B7 83 F1 DB 74 69 64 + : 8B 44 1D 95 5D CD 28 C0 85 + 165 02 3: INTEGER 65537 + 170 02 128: INTEGER + : 3D BD CD C2 0E 61 14 5B 4B E7 BF 60 + : 23 04 2B C5 6B 35 A5 96 45 23 FC 69 + : 7D 93 3C 0F D3 25 96 BA 62 52 42 E2 + : 96 CF FE 58 80 8F EB B1 8C BD D4 0D + : 65 D0 3A 77 45 24 9E 0C EB 86 80 C3 + : AC 21 11 71 44 E3 B2 A8 A9 2E AC 17 + : D2 A3 84 25 63 B5 BC 2F 1E DD F6 21 + : FF 15 20 24 5B F1 80 2F D5 41 0E 32 + : 24 F7 D4 4A 32 9E B9 49 D8 19 8E 3F + : 39 8D 62 BD 80 FC 0C 24 92 93 E4 C3 + : D7 05 91 53 BB 96 B6 41 + 301 02 65: INTEGER + : 00 F3 B8 3F 4A D1 94 B0 91 60 13 41 + + + +Hoffman, Ed. Informational [Page 12] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 92 0D 8D 44 3F 77 1D FF 96 23 44 08 + : D4 0B 70 C9 1A AF E9 90 94 F2 B0 D5 + : 5F 4F 19 85 50 A1 90 91 AE BD 05 76 + : 52 B3 22 D8 A8 7C 8E 54 7F 00 72 4F + : 36 75 68 73 B5 + 368 02 65: INTEGER + : 00 E1 D2 E7 11 57 06 AE 72 95 22 16 + : AA 02 B4 5A ED 4E 9D 82 11 4F 96 3C + : 86 C9 10 8D 56 7B 31 75 79 69 E7 75 + : 68 38 00 4B 2E D2 26 32 DD B1 E2 E0 + : 2C 54 80 0A 75 BA D1 66 96 1B B0 0E + : A0 7E D2 BB 91 + 435 02 65: INTEGER + : 00 AF B6 BC DB 22 73 43 41 EC B4 B5 + : 67 A9 A1 99 FC EF D2 8E FD 1D FB E5 + : 29 8B FE 0A DF D4 C8 5E 57 25 0A 5D + : 2B D4 09 A0 56 5B C5 B1 62 FC 20 BE + : 08 2D E3 07 B5 A1 E7 B3 FF C4 C0 A5 + : 5F AC 12 5C A9 + 502 02 65: INTEGER + : 00 B9 98 41 FC 08 50 1F 73 60 8A 01 + : A2 7C 52 8A 20 5A EA 2C 89 D9 A5 19 + : DD 94 C6 1B C3 25 C0 82 51 E4 EE 2B + : 9A 19 DC 73 ED E9 1D 27 D4 F8 6C 03 + : DD AB 1D 08 7B B5 AC 7F E9 82 9B F1 + : 89 8A 71 DB 61 + 569 02 64: INTEGER + : 01 07 21 97 5F 7A 60 A8 FD 5A 5C 07 + : DF A8 DE F7 E2 B1 34 7D FC EB 91 BD + : B0 73 74 C8 C4 BE 3F 58 45 30 06 90 + : B3 AC 69 CC B3 F7 3F 7C AC C7 B8 1B + : 65 A1 16 39 39 B0 E3 74 7D CF CD C5 + : AC 6C BF E5 + : } + : } + : } + +2.3. Certificates + + AliceDSSSignByCarlNoInherit = + 0 30 732: SEQUENCE { + 4 30 667: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 2: INTEGER 200 + 17 30 9: SEQUENCE { + 19 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + + + +Hoffman, Ed. Informational [Page 13] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (ANSI X9.57 algorithm) + : } + 28 30 18: SEQUENCE { + 30 31 16: SET { + 32 30 14: SEQUENCE { + 34 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 39 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 48 30 30: SEQUENCE { + 50 17 13: UTCTime '990817011049Z' + 65 17 13: UTCTime '391231235959Z' + : } + 80 30 19: SEQUENCE { + 82 31 17: SET { + 84 30 15: SEQUENCE { + 86 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 91 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 101 30 438: SEQUENCE { + 105 30 299: SEQUENCE { + 109 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 118 30 286: SEQUENCE { + 122 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 254 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 277 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + + + +Hoffman, Ed. Informational [Page 14] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 408 03 132: BIT STRING 0 unused bits, encapsulates { + 412 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 543 A3 129: [3] { + 546 30 127: SEQUENCE { + 548 30 12: SEQUENCE { + 550 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 555 01 1: BOOLEAN TRUE + 558 04 2: OCTET STRING, encapsulates { + 560 30 0: SEQUENCE {} + : } + : } + 562 30 14: SEQUENCE { + 564 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 569 01 1: BOOLEAN TRUE + 572 04 4: OCTET STRING, encapsulates { + 574 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 578 30 31: SEQUENCE { + 580 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + + + +Hoffman, Ed. Informational [Page 15] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (X.509 id-ce (2 5 29)) + 585 04 24: OCTET STRING, encapsulates { + 587 30 22: SEQUENCE { + 589 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 611 30 29: SEQUENCE { + 613 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 618 04 22: OCTET STRING, encapsulates { + 620 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 642 30 31: SEQUENCE { + 644 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 649 04 24: OCTET STRING, encapsulates { + 651 30 22: SEQUENCE { + 653 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } + 675 30 9: SEQUENCE { + 677 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 686 03 48: BIT STRING 0 unused bits, encapsulates { + 689 30 45: SEQUENCE { + 691 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 713 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + + AliceRSASignByCarl = + + + +Hoffman, Ed. Informational [Page 16] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 0 30 556: SEQUENCE { + 4 30 405: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + 31 30 13: SEQUENCE { + 33 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 44 05 0: NULL + : } + 46 30 18: SEQUENCE { + 48 31 16: SET { + 50 30 14: SEQUENCE { + 52 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 57 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 66 30 30: SEQUENCE { + 68 17 13: UTCTime '990919010847Z' + 83 17 13: UTCTime '391231235959Z' + : } + 98 30 19: SEQUENCE { + 100 31 17: SET { + 102 30 15: SEQUENCE { + 104 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 109 13 8: PrintableString 'AliceRSA' + : } + : } + : } + 119 30 159: SEQUENCE { + 122 30 13: SEQUENCE { + 124 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 135 05 0: NULL + : } + 137 03 141: BIT STRING 0 unused bits, encapsulates { + 141 30 137: SEQUENCE { + 144 02 129: INTEGER + : 00 E0 89 73 39 8D D8 F5 F5 E8 87 76 + : 39 7F 4E B0 05 BB 53 83 DE 0F B7 AB + + + +Hoffman, Ed. Informational [Page 17] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : DC 7D C7 75 29 0D 05 2E 6D 12 DF A6 + : 86 26 D4 D2 6F AA 58 29 FC 97 EC FA + : 82 51 0F 30 80 BE B1 50 9E 46 44 F1 + : 2C BB D8 32 CF C6 68 6F 07 D9 B0 60 + : AC BE EE 34 09 6A 13 F5 F7 05 05 93 + : DF 5E BA 35 56 D9 61 FF 19 7F C9 81 + : E6 F8 6C EA 87 40 70 EF AC 6D 2C 74 + : 9F 2D FA 55 3A B9 99 77 02 A6 48 52 + : 8C 4E F3 57 38 57 74 57 5F + 276 02 3: INTEGER 65537 + : } + : } + : } + 281 A3 129: [3] { + 284 30 127: SEQUENCE { + 286 30 12: SEQUENCE { + 288 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 293 01 1: BOOLEAN TRUE + 296 04 2: OCTET STRING, encapsulates { + 298 30 0: SEQUENCE {} + : } + : } + 300 30 14: SEQUENCE { + 302 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 307 01 1: BOOLEAN TRUE + 310 04 4: OCTET STRING, encapsulates { + 312 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 316 30 31: SEQUENCE { + 318 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 323 04 24: OCTET STRING, encapsulates { + 325 30 22: SEQUENCE { + 327 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 349 30 29: SEQUENCE { + 351 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + + + +Hoffman, Ed. Informational [Page 18] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (X.509 id-ce (2 5 29)) + 356 04 22: OCTET STRING, encapsulates { + 358 04 20: OCTET STRING + : 77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D + : CE EC 3C A0 3A E3 FF 50 + : } + : } + 380 30 31: SEQUENCE { + 382 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 387 04 24: OCTET STRING, encapsulates { + 389 30 22: SEQUENCE { + 391 81 20: [1] 'AliceRSA@example.com' + : } + : } + : } + : } + : } + : } + 413 30 13: SEQUENCE { + 415 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 426 05 0: NULL + : } + 428 03 129: BIT STRING 0 unused bits + : 3E 70 47 A8 48 CC 13 58 8F CA 51 71 + : 6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC + : CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C + : 59 A9 20 AA 05 81 A8 4E 25 AD A7 70 + : 14 75 2F F5 C7 9B D1 0E E9 63 D2 64 + : B7 C6 66 6E 73 21 54 DF F4 BA 25 5D + : 7D 49 D3 94 6B 22 36 74 73 B8 4A EC + : 2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A + : B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA + : F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A + : 76 AE EB 9B DB 49 B0 22 + : } + + BobRSASignByCarl = + 0 30 551: SEQUENCE { + 4 30 400: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : CD 5D 71 D0 + + + +Hoffman, Ed. Informational [Page 19] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 31 30 13: SEQUENCE { + 33 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 44 05 0: NULL + : } + 46 30 18: SEQUENCE { + 48 31 16: SET { + 50 30 14: SEQUENCE { + 52 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 57 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 66 30 30: SEQUENCE { + 68 17 13: UTCTime '990919010902Z' + 83 17 13: UTCTime '391231235959Z' + : } + 98 30 17: SEQUENCE { + 100 31 15: SET { + 102 30 13: SEQUENCE { + 104 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 109 13 6: PrintableString 'BobRSA' + : } + : } + : } + 117 30 159: SEQUENCE { + 120 30 13: SEQUENCE { + 122 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 133 05 0: NULL + : } + 135 03 141: BIT STRING 0 unused bits, encapsulates { + 139 30 137: SEQUENCE { + 142 02 129: INTEGER + : 00 A9 E1 67 98 3F 39 D5 5F F2 A0 93 + : 41 5E A6 79 89 85 C8 35 5D 9A 91 5B + : FB 1D 01 DA 19 70 26 17 0F BD A5 22 + : D0 35 85 6D 7A 98 66 14 41 5C CF B7 + : B7 08 3B 09 C9 91 B8 19 69 37 6D F9 + : 65 1E 7B D9 A9 33 24 A3 7F 3B BB AF + : 46 01 86 36 34 32 CB 07 03 59 52 FC + : 85 8B 31 04 B8 CC 18 08 14 48 E6 4F + : 1C FB 5D 60 C4 E0 5C 1F 53 D3 7F 53 + : D8 69 01 F1 05 F8 7A 70 D1 BE 83 C6 + + + +Hoffman, Ed. Informational [Page 20] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 5F 38 CF 1C 2C AA 6A A7 EB + 274 02 3: INTEGER 65537 + : } + : } + : } + 279 A3 127: [3] { + 281 30 125: SEQUENCE { + 283 30 12: SEQUENCE { + 285 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 290 01 1: BOOLEAN TRUE + 293 04 2: OCTET STRING, encapsulates { + 295 30 0: SEQUENCE {} + : } + : } + 297 30 14: SEQUENCE { + 299 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 304 01 1: BOOLEAN TRUE + 307 04 4: OCTET STRING, encapsulates { + 309 03 2: BIT STRING 5 unused bits + : '100'B (bit 2) + : } + : } + 313 30 31: SEQUENCE { + 315 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 320 04 24: OCTET STRING, encapsulates { + 322 30 22: SEQUENCE { + 324 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 346 30 29: SEQUENCE { + 348 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 353 04 22: OCTET STRING, encapsulates { + 355 04 20: OCTET STRING + : E8 F4 B8 67 D8 B3 96 A4 2A F3 11 AA + : 29 D3 95 5A 86 16 B4 24 + : } + : } + 377 30 29: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 21] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 379 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 384 04 22: OCTET STRING, encapsulates { + 386 30 20: SEQUENCE { + 388 81 18: [1] 'BobRSA@example.com' + : } + : } + : } + : } + : } + : } + 408 30 13: SEQUENCE { + 410 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 421 05 0: NULL + : } + 423 03 129: BIT STRING 0 unused bits + : 7B 8E 66 C5 F1 10 3F 10 20 4C 88 71 + : AB 7B 40 6B 21 33 FA 4A 95 DE 9D 0E + : 5B 6B 94 21 05 C0 F2 E1 7E 2A CD 9C + : 93 88 87 FB 8B B7 7E 7D 41 61 E1 E4 + : D6 6D F9 E2 04 55 61 45 BC 64 27 44 + : C0 A1 BD 59 79 D9 1D 64 3C 21 D6 45 + : B0 5D 68 33 92 EA AC F1 57 E5 81 7D + : 98 E6 35 91 A3 39 DE 77 F4 E8 1C 3B + : 29 DC 7F 51 07 97 F3 36 F0 50 0A DD + : 9B DE B6 5E 38 11 2B FB 57 EA 89 6D + : AD C9 88 D8 8F CF 2B D3 + : } + + CarlDSSSelf = + 0 30 667: SEQUENCE { + 4 30 602: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 1: INTEGER 1 + 16 30 9: SEQUENCE { + 18 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 27 30 18: SEQUENCE { + 29 31 16: SET { + 31 30 14: SEQUENCE { + 33 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 38 13 7: PrintableString 'CarlDSS' + + + +Hoffman, Ed. Informational [Page 22] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + 47 30 30: SEQUENCE { + 49 17 13: UTCTime '990816225050Z' + 64 17 13: UTCTime '391231235959Z' + : } + 79 30 18: SEQUENCE { + 81 31 16: SET { + 83 30 14: SEQUENCE { + 85 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 90 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 99 30 439: SEQUENCE { + 103 30 299: SEQUENCE { + 107 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 116 30 286: SEQUENCE { + 120 02 129: INTEGER + : 00 B6 49 18 3E 8A 44 C1 29 71 94 4C + : 01 C4 12 C1 7A 79 CB 54 4D AB 1E 81 + : FB C6 4C B3 0E 94 09 06 EB 01 D4 B1 + : C8 71 4B C7 45 C0 50 25 5D 9C FC DA + : E4 6D D3 E2 86 48 84 82 7D BA 15 95 + : 4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A + : 0A 8A BA 16 7B B9 50 01 48 93 8B EB + : 25 15 51 97 55 DC 8F 53 0E 10 A9 50 + : FC 70 B7 CD 30 54 FD DA DE A8 AA 22 + : B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9 + : AD E1 08 D4 6D 29 2D D6 E9 + 252 02 21: INTEGER + : 00 DD C1 2F DF 53 CE 0B 34 60 77 3E + : 02 A4 BF 8A 5D 98 B9 10 D5 + 275 02 128: INTEGER + : 0C EE 57 9B 4B BD DA B6 07 6A 74 37 + : 4F 55 7F 9D ED BC 61 0D EB 46 59 3C + : 56 0B 2B 5B 0C 91 CE A5 62 52 69 CA + : E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C + : AD CB AE 45 E3 06 AC 8C 22 9D 9C 44 + : 87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE + : AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A + : 73 AA 7F 46 51 1F A9 42 16 9C 48 EB + : 8A 79 61 B4 D5 2F 53 22 44 63 1F 86 + : B8 A3 58 06 25 F8 29 C0 EF BA E0 75 + : F0 42 C4 63 65 52 9B 0A + + + +Hoffman, Ed. Informational [Page 23] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + 406 03 133: BIT STRING 0 unused bits, encapsulates { + 410 02 129: INTEGER + : 00 99 87 74 27 03 66 A0 B1 C0 AD DC + : 2C 75 BB E1 6C 44 9C DA 21 6D 4D 47 + : 6D B1 62 09 E9 D8 AE 1E F2 3A B4 94 + : B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25 + : 4E B9 60 96 19 24 01 F3 62 0C FE 75 + : C0 FB CE D8 68 00 E3 FD D5 70 4F DF + : 23 96 19 06 94 F4 B1 61 8F 3A 57 B1 + : 08 11 A4 0B 26 25 F0 52 76 81 EA 0B + : 62 0D 95 2A E6 86 BA 72 B2 A7 50 83 + : 0B AA 27 CD 1B A9 4D 89 9A D7 8D 18 + : 39 84 3F 8B C5 56 4D 80 7A + : } + : } + 542 A3 66: [3] { + 544 30 64: SEQUENCE { + 546 30 15: SEQUENCE { + 548 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 553 01 1: BOOLEAN TRUE + 556 04 5: OCTET STRING, encapsulates { + 558 30 3: SEQUENCE { + 560 01 1: BOOLEAN TRUE + : } + : } + : } + 563 30 14: SEQUENCE { + 565 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 570 01 1: BOOLEAN TRUE + 573 04 4: OCTET STRING, encapsulates { + 575 03 2: BIT STRING 1 unused bits + : '1100001'B + : } + : } + 579 30 29: SEQUENCE { + 581 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 586 04 22: OCTET STRING, encapsulates { + 588 04 20: OCTET STRING + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + + + +Hoffman, Ed. Informational [Page 24] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + 610 30 9: SEQUENCE { + 612 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 621 03 48: BIT STRING 0 unused bits, encapsulates { + 624 30 45: SEQUENCE { + 626 02 20: INTEGER + : 6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B + : C9 06 37 E9 11 17 A1 13 + 648 02 21: INTEGER + : 00 8F 34 69 2A 8B B1 3C 03 79 94 32 + : 4D 12 1F CE 89 FB 46 B2 3B + : } + : } + : } + + CarlRSASelf = + 0 30 491: SEQUENCE { + 4 30 340: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : 9F F2 50 20 + 31 30 13: SEQUENCE { + 33 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 44 05 0: NULL + : } + 46 30 18: SEQUENCE { + 48 31 16: SET { + 50 30 14: SEQUENCE { + 52 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 57 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 66 30 30: SEQUENCE { + 68 17 13: UTCTime '990818070000Z' + 83 17 13: UTCTime '391231235959Z' + : } + + + +Hoffman, Ed. Informational [Page 25] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 98 30 18: SEQUENCE { + 100 31 16: SET { + 102 30 14: SEQUENCE { + 104 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 109 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 118 30 159: SEQUENCE { + 121 30 13: SEQUENCE { + 123 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 134 05 0: NULL + : } + 136 03 141: BIT STRING 0 unused bits, encapsulates { + 140 30 137: SEQUENCE { + 143 02 129: INTEGER + : 00 E4 4B FF 18 B8 24 57 F4 77 FF 6E + : 73 7B 93 71 5C BC 33 1A 92 92 72 23 + : D8 41 46 D0 CD 11 3A 04 B3 8E AF 82 + : 9D BD 51 1E 17 7A F2 76 2C 2B 86 39 + : A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC + : A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F + : 99 25 8F B8 4E AB B9 7D D5 96 65 DA + : 16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7 + : 29 CB 82 DD AC 44 E9 AA 93 94 29 0E + : F8 18 D6 C8 57 5E F2 76 C4 F2 11 60 + : 38 B9 1B 3C 1D 97 C9 6A F1 + 275 02 3: INTEGER 65537 + : } + : } + : } + 280 A3 66: [3] { + 282 30 64: SEQUENCE { + 284 30 15: SEQUENCE { + 286 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 291 01 1: BOOLEAN TRUE + 294 04 5: OCTET STRING, encapsulates { + 296 30 3: SEQUENCE { + 298 01 1: BOOLEAN TRUE + : } + : } + : } + 301 30 14: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 26] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 303 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 308 01 1: BOOLEAN TRUE + 311 04 4: OCTET STRING, encapsulates { + 313 03 2: BIT STRING 1 unused bits + : '1100001'B + : } + : } + 317 30 29: SEQUENCE { + 319 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 324 04 22: OCTET STRING, encapsulates { + 326 04 20: OCTET STRING + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + : } + : } + 348 30 13: SEQUENCE { + 350 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 361 05 0: NULL + : } + 363 03 129: BIT STRING 0 unused bits + : B7 9E D4 04 D3 ED 29 E4 FF 89 89 15 + : 2E 4C DB 0C F0 48 0F 32 61 EE C4 04 + : EC 12 5D 2D FF 0F 64 59 7E 0A C3 ED + : 18 FD E3 56 40 37 A7 07 B5 F0 38 12 + : 61 50 ED EF DD 3F E3 0B B8 61 A5 A4 + : 9B 3C E6 9E 9C 54 9A B6 95 D6 DA 6C + : 3B B5 2D 45 35 9D 49 01 76 FA B9 B9 + : 31 F9 F9 6B 12 53 A0 F5 14 60 9B 7D + : CA 3E F2 53 6B B0 37 6F AD E6 74 D7 + : DB FA 5A EA 14 41 63 5D CD BE C8 0E + : C1 DA 6A 8D 53 34 18 02 + : } + + DianeDSSSignByCarlInherit = + 0 30 440: SEQUENCE { + 4 30 375: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 2: INTEGER 210 + + + +Hoffman, Ed. Informational [Page 27] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 17 30 9: SEQUENCE { + 19 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 28 30 18: SEQUENCE { + 30 31 16: SET { + 32 30 14: SEQUENCE { + 34 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 39 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 48 30 30: SEQUENCE { + 50 17 13: UTCTime '990817020810Z' + 65 17 13: UTCTime '391231235959Z' + : } + 80 30 19: SEQUENCE { + 82 31 17: SET { + 84 30 15: SEQUENCE { + 86 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 91 13 8: PrintableString 'DianeDSS' + : } + : } + : } + 101 30 147: SEQUENCE { + 104 30 9: SEQUENCE { + 106 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + : } + 115 03 133: BIT STRING 0 unused bits, encapsulates { + 119 02 129: INTEGER + : 00 A0 00 17 78 2C EE 7E 81 53 2E 2E + : 61 08 0F A1 9B 51 52 1A DA 59 A8 73 + : 2F 12 25 B6 08 CB CA EF 2A 44 76 8A + : 52 09 EA BD 05 22 D5 0F F6 FD 46 D7 + : AF 99 38 09 0E 13 CB 4F 2C DD 1C 34 + : F7 1C BF 25 FF 23 D3 3B 59 E7 82 97 + : 37 BE 31 24 D8 18 C8 F3 49 39 5B B7 + : E2 E5 27 7E FC 8C 45 72 5B 7E 3E 8F + : 68 4D DD 46 7A 22 BE 8E FF CC DA 39 + : 29 A3 39 E5 9F 43 E9 55 C9 D7 5B A6 + : 81 67 CC C0 AA CD 2E C5 23 + : } + : } + 251 A3 129: [3] { + 254 30 127: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 28] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 256 30 12: SEQUENCE { + 258 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 263 01 1: BOOLEAN TRUE + 266 04 2: OCTET STRING, encapsulates { + 268 30 0: SEQUENCE {} + : } + : } + 270 30 14: SEQUENCE { + 272 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 277 01 1: BOOLEAN TRUE + 280 04 4: OCTET STRING, encapsulates { + 282 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 286 30 31: SEQUENCE { + 288 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 293 04 24: OCTET STRING, encapsulates { + 295 30 22: SEQUENCE { + 297 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 319 30 29: SEQUENCE { + 321 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 326 04 22: OCTET STRING, encapsulates { + 328 04 20: OCTET STRING + : 64 30 99 7D 5C DC 45 0B 99 3A 52 2F + : 16 BF 58 50 DD CE 2B 18 + : } + : } + 350 30 31: SEQUENCE { + 352 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 357 04 24: OCTET STRING, encapsulates { + 359 30 22: SEQUENCE { + 361 81 20: [1] 'DianeDSS@example.com' + : } + : } + + + +Hoffman, Ed. Informational [Page 29] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + 383 30 9: SEQUENCE { + 385 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 394 03 48: BIT STRING 0 unused bits, encapsulates { + 397 30 45: SEQUENCE { + 399 02 21: INTEGER + : 00 A1 1A F8 17 0E 3E 5D A8 8C F4 B6 + : 55 33 1E 4B E3 2C AC B9 5F + 422 02 20: INTEGER + : 28 4B 10 45 58 D2 1C 9D 55 35 14 18 + : 91 B2 3F 39 DF B5 6E D3 + : } + : } + : } + + DianeRSASignByCarl = + 0 30 556: SEQUENCE { + 4 30 405: SEQUENCE { + 8 A0 3: [0] { + 10 02 1: INTEGER 2 + : } + 13 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : D5 9A 30 90 + 31 30 13: SEQUENCE { + 33 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 44 05 0: NULL + : } + 46 30 18: SEQUENCE { + 48 31 16: SET { + 50 30 14: SEQUENCE { + 52 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 57 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 66 30 30: SEQUENCE { + 68 17 13: UTCTime '990819070000Z' + 83 17 13: UTCTime '391231235959Z' + : } + + + +Hoffman, Ed. Informational [Page 30] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 98 30 19: SEQUENCE { + 100 31 17: SET { + 102 30 15: SEQUENCE { + 104 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 109 13 8: PrintableString 'DianeRSA' + : } + : } + : } + 119 30 159: SEQUENCE { + 122 30 13: SEQUENCE { + 124 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 135 05 0: NULL + : } + 137 03 141: BIT STRING 0 unused bits, encapsulates { + 141 30 137: SEQUENCE { + 144 02 129: INTEGER + : 00 D6 FD B8 C0 70 C6 4C 25 EC EA CF + : EA 7C BB A2 62 FA F0 E6 32 3A 53 FF + : B1 92 5A 17 F4 20 E1 99 24 82 0A D0 + : F6 7C FB 44 CA 8B 27 06 F1 7E 26 03 + : A9 76 9D CF EC A0 2C 70 96 F2 83 42 + : F6 D4 B7 28 0A BB F8 BF 4A 4C 19 3F + : 07 DB A0 C1 60 1E B7 7E 67 F7 DE B1 + : C3 60 49 AC 45 D7 F8 C6 EF 08 37 21 + : 93 47 EE F0 73 35 72 B0 02 C4 F3 11 + : C3 5E 47 E5 0A B7 83 F1 DB 74 69 64 + : 8B 44 1D 95 5D CD 28 C0 85 + 276 02 3: INTEGER 65537 + : } + : } + : } + 281 A3 129: [3] { + 284 30 127: SEQUENCE { + 286 30 12: SEQUENCE { + 288 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 293 01 1: BOOLEAN TRUE + 296 04 2: OCTET STRING, encapsulates { + 298 30 0: SEQUENCE {} + : } + : } + 300 30 14: SEQUENCE { + 302 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + + + +Hoffman, Ed. Informational [Page 31] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 307 01 1: BOOLEAN TRUE + 310 04 4: OCTET STRING, encapsulates { + 312 03 2: BIT STRING 5 unused bits + : '111'B + : } + : } + 316 30 31: SEQUENCE { + 318 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 323 04 24: OCTET STRING, encapsulates { + 325 30 22: SEQUENCE { + 327 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 349 30 29: SEQUENCE { + 351 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 356 04 22: OCTET STRING, encapsulates { + 358 04 20: OCTET STRING + : 8C F3 CB 75 0E 8D 31 F6 D4 29 DA 44 + : 92 75 B8 FE ED 4F 39 0C + : } + : } + 380 30 31: SEQUENCE { + 382 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 387 04 24: OCTET STRING, encapsulates { + 389 30 22: SEQUENCE { + 391 81 20: [1] 'DianeRSA@example.com' + : } + : } + : } + : } + : } + : } + 413 30 13: SEQUENCE { + 415 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption (1 2 840 113549 1 1 5) + : (PKCS #1) + 426 05 0: NULL + : } + 428 03 129: BIT STRING 0 unused bits + : 7D A6 2C B5 78 42 D6 79 F3 31 FE F6 + + + +Hoffman, Ed. Informational [Page 32] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 42 CA 0F 13 07 92 09 1B E0 6F B0 91 + : 18 F6 BF 4A FB CC 63 79 FB 81 BF DD + : 97 C7 90 6B CB 0A 37 2B 41 6A 03 98 + : C5 1B 3E 32 C8 45 2B 86 01 9C 1C E2 + : 36 EF 16 C1 1A 92 B8 BE 62 FB 53 3E + : 49 47 0B C4 B9 E4 2B 58 A6 06 83 F0 + : B2 A7 BB 85 7E D5 C6 DA CE 9C 7B 31 + : 72 D7 A2 EA 41 AB 6A C0 DD 1F B9 14 + : 44 18 CF 84 57 66 E8 C5 E6 B8 DC 2D + : B3 1F 1B 28 43 36 75 7A + : } + +2.4. CRLs + + CarlDSSCRLForAll = + 0 30 216: SEQUENCE { + 3 30 153: SEQUENCE { + 6 30 9: SEQUENCE { + 8 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 17 30 18: SEQUENCE { + 19 31 16: SET { + 21 30 14: SEQUENCE { + 23 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 28 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 37 17 13: UTCTime '990827070000Z' + 52 30 105: SEQUENCE { + 54 30 19: SEQUENCE { + 56 02 2: INTEGER 200 + 60 17 13: UTCTime '990822070000Z' + : } + 75 30 19: SEQUENCE { + 77 02 2: INTEGER 201 + 81 17 13: UTCTime '990822070000Z' + : } + 96 30 19: SEQUENCE { + 98 02 2: INTEGER 211 + 102 17 13: UTCTime '990822070000Z' + : } + 117 30 19: SEQUENCE { + 119 02 2: INTEGER 210 + 123 17 13: UTCTime '990822070000Z' + : } + + + +Hoffman, Ed. Informational [Page 33] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 138 30 19: SEQUENCE { + 140 02 2: INTEGER 212 + 144 17 13: UTCTime '990824070000Z' + : } + : } + : } + 159 30 9: SEQUENCE { + 161 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 170 03 47: BIT STRING 0 unused bits, encapsulates { + 173 30 44: SEQUENCE { + 175 02 20: INTEGER + : 7E 65 52 76 33 FE 34 73 17 D1 F7 96 + : F9 A0 D4 D8 6D 5C 7D 3D + 197 02 20: INTEGER + : 02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E + : DA 24 F3 2A 83 9C 35 A1 + : } + : } + : } + + CarlDSSCRLForCarl = + 0 30 131: SEQUENCE { + 3 30 68: SEQUENCE { + 5 30 9: SEQUENCE { + 7 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 16 30 18: SEQUENCE { + 18 31 16: SET { + 20 30 14: SEQUENCE { + 22 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 27 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 36 17 13: UTCTime '990825070000Z' + 51 30 20: SEQUENCE { + 53 30 18: SEQUENCE { + 55 02 1: INTEGER 1 + 58 17 13: UTCTime '990822070000Z' + : } + : } + : } + 73 30 9: SEQUENCE { + 75 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + + + +Hoffman, Ed. Informational [Page 34] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (ANSI X9.57 algorithm) + : } + 84 03 48: BIT STRING 0 unused bits, encapsulates { + 87 30 45: SEQUENCE { + 89 02 21: INTEGER + : 00 B3 1F C5 4F 7A 3D EC 76 D5 60 F9 + : DE 79 22 EC 4F B0 90 FE 97 + 112 02 20: INTEGER + : 5A 8B C3 84 BC 66 87 1B BF 79 82 5B + : 0A 5D 07 F6 BA A9 05 29 + : } + : } + : } + + CarlDSSCRLEmpty = + 0 30 109: SEQUENCE { + 2 30 46: SEQUENCE { + 4 30 9: SEQUENCE { + 6 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 15 30 18: SEQUENCE { + 17 31 16: SET { + 19 30 14: SEQUENCE { + 21 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 26 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 35 17 13: UTCTime '990820070000Z' + : } + 50 30 9: SEQUENCE { + 52 06 7: OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 61 03 48: BIT STRING 0 unused bits, encapsulates { + 64 30 45: SEQUENCE { + 66 02 20: INTEGER + : 62 3F 36 17 31 58 2E 67 50 79 F5 09 + : 4B 8C AD D4 6B F4 64 9F + 88 02 21: INTEGER + : 00 B5 3B 4E A1 4C 7B FD 0F C3 8D 9B + : B6 FE C3 5D 6F DE 65 28 7D + : } + : } + : } + + + + +Hoffman, Ed. Informational [Page 35] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + CarlRSACRLForAll = + 0 30 307: SEQUENCE { + 4 30 157: SEQUENCE { + 7 30 13: SEQUENCE { + 9 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 20 05 0: NULL + : } + 22 30 18: SEQUENCE { + 24 31 16: SET { + 26 30 14: SEQUENCE { + 28 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 33 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 42 17 13: UTCTime '990827070000Z' + 57 30 105: SEQUENCE { + 59 30 33: SEQUENCE { + 61 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + 79 17 13: UTCTime '990822070000Z' + : } + 94 30 33: SEQUENCE { + 96 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : D5 9A 30 90 + 114 17 13: UTCTime '990822070000Z' + : } + 129 30 33: SEQUENCE { + 131 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : CD 5D 71 D0 + 149 17 13: UTCTime '990824070000Z' + : } + : } + : } + 164 30 13: SEQUENCE { + 166 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 177 05 0: NULL + : } + 179 03 129: BIT STRING 0 unused bits + : BF B3 97 AA 53 F0 32 21 16 2B 77 92 + + + +Hoffman, Ed. Informational [Page 36] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 7A 6B BB 97 C8 DC EA F1 FA 66 16 30 + : 0E B5 9E 5C F0 81 D4 5E B3 6E C1 88 + : 6B 8C D4 5E C5 4D FB 47 5E 66 F3 5D + : AB E5 B4 18 36 60 A8 4D 9C 3C 89 EC + : 6F 27 BF 35 50 71 81 C2 B9 44 5B 62 + : 89 19 12 31 A9 7B 9A D3 CC 66 CB 11 + : D9 0B 10 47 77 AD 4F 22 D9 E5 7F 30 + : F2 5B FC 94 51 A5 58 76 3B 1F A8 46 + : A6 1F F6 A1 DE 55 A1 ED 31 88 69 97 + : 0F 08 D3 D4 0C 60 5B 1E + : } + + CarlRSACRLForCarl = + 0 30 236: SEQUENCE { + 3 30 87: SEQUENCE { + 5 30 13: SEQUENCE { + 7 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 18 05 0: NULL + : } + 20 30 18: SEQUENCE { + 22 31 16: SET { + 24 30 14: SEQUENCE { + 26 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 31 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 40 17 13: UTCTime '990825070000Z' + 55 30 35: SEQUENCE { + 57 30 33: SEQUENCE { + 59 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : 9F F2 50 20 + 77 17 13: UTCTime '990822070000Z' + : } + : } + : } + 92 30 13: SEQUENCE { + 94 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 105 05 0: NULL + : } + 107 03 129: BIT STRING 0 unused bits + : 21 EF 21 D4 C1 1A 85 95 49 6B CA 45 + + + +Hoffman, Ed. Informational [Page 37] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 62 DC D7 09 FF A9 51 2E 8E D9 47 18 + : FA F8 E5 72 DD 4F ED 74 74 E3 F3 65 + : 32 65 28 2C 9A 1D 57 E5 D5 26 06 EA + : D5 E6 23 95 84 8D 0E 89 9E EE 9B 0C + : 2F CE 07 F7 A3 D1 6B 85 4C 0F FF E6 + : DD FC DC CD 73 2C 1E 7D DC B0 71 C5 + : 4C FC 01 6E 52 57 69 1E 39 63 DF 12 + : 22 30 C7 13 55 94 05 6E 2A 00 A9 5B + : C4 2A 66 94 62 CE 36 33 C2 2B 63 47 + : 25 9D F3 DE 70 EE 00 56 + : } + + CarlRSACRLEmpty = + 0 30 199: SEQUENCE { + 3 30 50: SEQUENCE { + 5 30 13: SEQUENCE { + 7 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 18 05 0: NULL + : } + 20 30 18: SEQUENCE { + 22 31 16: SET { + 24 30 14: SEQUENCE { + 26 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 31 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 40 17 13: UTCTime '990820070000Z' + : } + 55 30 13: SEQUENCE { + 57 06 9: OBJECT IDENTIFIER + : md5withRSAEncryption (1 2 840 113549 1 1 4) + : (PKCS #1) + 68 05 0: NULL + : } + 70 03 129: BIT STRING 0 unused bits + : A9 C5 21 B8 13 7C 74 F3 B5 11 EC 04 + : F3 20 45 86 1E 0B 6E 7F 83 6D 5F F4 + : 34 76 06 59 25 0E 04 3D 88 09 88 81 + : 37 C4 DC 20 98 FA 17 81 0B 37 94 AC + : B4 8F 7B 51 89 14 A4 CB 72 73 14 07 + : BC 22 9C 40 A1 07 FC 44 7C 85 0F 0B + : 88 D1 EE E1 0E AF F6 16 74 AD A1 AF + : C1 00 75 00 64 EA A5 9A F6 0B 08 A2 + : DB 95 19 5F A6 A7 B9 39 45 25 0A 0E + + + +Hoffman, Ed. Informational [Page 38] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : F6 5E 84 E7 F8 B9 5A C9 18 C2 0E B8 + : A0 96 BE 81 3A 80 6D C9 + : } + +3. Trivial Examples + + This section covers examples of small CMS types. + +3.1. ContentInfo with Data Type, BER + + The object is a ContentInfo containing a Data object in BER format + that is ExContent. + + 0 30 NDEF: SEQUENCE { + 2 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 13 A0 NDEF: [0] { + 15 24 NDEF: OCTET STRING { + 17 04 4: OCTET STRING 'This' + 23 04 24: OCTET STRING ' is some sample content.' + : } + : } + : } + +3.2. ContentInfo with Data Type, DER + + The object is a ContentInfo containing a Data object in DER format + that is ExContent. + + 0 30 43: SEQUENCE { + 2 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 13 A0 30: [0] { + 15 04 28: OCTET STRING 'This is some sample content.' + : } + : } + +4. Signed-data + +4.1. Basic Signed Content, DSS + + A SignedData with no attribute certificates, signed by Alice using + DSS, just her certificate (not Carl's root cert), no CRL. The + message is ExContent, and is included in the eContent. There are no + signed or unsigned attributes. + + + + + + +Hoffman, Ed. Informational [Page 39] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 0 30 919: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 904: [0] { + 19 30 900: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 43: SEQUENCE { + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 50 A0 30: [0] { + 52 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 82 A0 736: [0] { + 86 30 732: SEQUENCE { + 90 30 667: SEQUENCE { + 94 A0 3: [0] { + 96 02 1: INTEGER 2 + : } + 99 02 2: INTEGER 200 + 103 30 9: SEQUENCE { + 105 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 114 30 18: SEQUENCE { + 116 31 16: SET { + 118 30 14: SEQUENCE { + 120 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 125 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 134 30 30: SEQUENCE { + 136 17 13: UTCTime '990817011049Z' + 151 17 13: UTCTime '391231235959Z' + : } + 166 30 19: SEQUENCE { + 168 31 17: SET { + 170 30 15: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 40] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 172 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 177 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 187 30 438: SEQUENCE { + 191 30 299: SEQUENCE { + 195 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 204 30 286: SEQUENCE { + 208 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 340 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 363 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 494 03 132: BIT STRING 0 unused bits, encapsulates { + 498 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + + + +Hoffman, Ed. Informational [Page 41] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 629 A3 129: [3] { + 632 30 127: SEQUENCE { + 634 30 12: SEQUENCE { + 636 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 641 01 1: BOOLEAN TRUE + 644 04 2: OCTET STRING, encapsulates { + 646 30 0: SEQUENCE {} + : } + : } + 648 30 14: SEQUENCE { + 650 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 655 01 1: BOOLEAN TRUE + 658 04 4: OCTET STRING, encapsulates { + 660 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 664 30 31: SEQUENCE { + 666 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 671 04 24: OCTET STRING, encapsulates { + 673 30 22: SEQUENCE { + 675 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 697 30 29: SEQUENCE { + 699 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 704 04 22: OCTET STRING, encapsulates { + 706 04 20: OCTET STRING + + + +Hoffman, Ed. Informational [Page 42] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 728 30 31: SEQUENCE { + 730 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 735 04 24: OCTET STRING, encapsulates { + 737 30 22: SEQUENCE { + 739 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } + 761 30 9: SEQUENCE { + 763 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 772 03 48: BIT STRING 0 unused bits, encapsulates { + 775 30 45: SEQUENCE { + 777 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 799 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 822 31 99: SET { + 824 30 97: SEQUENCE { + 826 02 1: INTEGER 1 + 829 30 24: SEQUENCE { + 831 30 18: SEQUENCE { + 833 31 16: SET { + 835 30 14: SEQUENCE { + 837 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 842 13 7: PrintableString 'CarlDSS' + : } + : } + : } + + + +Hoffman, Ed. Informational [Page 43] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 851 02 2: INTEGER 200 + : } + 855 30 7: SEQUENCE { + 857 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 864 30 9: SEQUENCE { + 866 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 875 04 46: OCTET STRING, encapsulates { + 877 30 44: SEQUENCE { + 879 02 20: INTEGER + : 09 91 FE EB D2 69 F5 18 B7 D7 CD 55 + : F4 81 EA 2A 42 6A AD 03 + 901 02 20: INTEGER + : 3A 07 CC C3 21 BE E1 1A 4B 7F 3E B5 + : 0D DB BA 1C EA BC CD 89 + : } + : } + : } + : } + : } + : } + : } + +4.2. Basic Signed Content, RSA + + Same as 4.1, except using RSA signatures. A SignedData with no + attribute certificates, signed by Alice using RSA, just her + certificate (not Carl's root cert), no CRL. The message is + ExContent, and is included in the eContent. There are no signed or + unsigned attributes. + + 0 30 850: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 835: [0] { + 19 30 831: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 11: SET { + 28 30 9: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + 37 05 0: NULL + : } + : } + + + +Hoffman, Ed. Informational [Page 44] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 39 30 43: SEQUENCE { + 41 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 52 A0 30: [0] { + 54 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 84 A0 560: [0] { + 88 30 556: SEQUENCE { + 92 30 405: SEQUENCE { + 96 A0 3: [0] { + 98 02 1: INTEGER 2 + : } + 101 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + 119 30 13: SEQUENCE { + 121 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 132 05 0: NULL + : } + 134 30 18: SEQUENCE { + 136 31 16: SET { + 138 30 14: SEQUENCE { + 140 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 145 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 154 30 30: SEQUENCE { + 156 17 13: UTCTime '990919010847Z' + 171 17 13: UTCTime '391231235959Z' + : } + 186 30 19: SEQUENCE { + 188 31 17: SET { + 190 30 15: SEQUENCE { + 192 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 197 13 8: PrintableString 'AliceRSA' + : } + : } + : } + 207 30 159: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 45] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 210 30 13: SEQUENCE { + 212 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 223 05 0: NULL + : } + 225 03 141: BIT STRING 0 unused bits, encapsulates { + 229 30 137: SEQUENCE { + 232 02 129: INTEGER + : 00 E0 89 73 39 8D D8 F5 F5 E8 87 76 + : 39 7F 4E B0 05 BB 53 83 DE 0F B7 AB + : DC 7D C7 75 29 0D 05 2E 6D 12 DF A6 + : 86 26 D4 D2 6F AA 58 29 FC 97 EC FA + : 82 51 0F 30 80 BE B1 50 9E 46 44 F1 + : 2C BB D8 32 CF C6 68 6F 07 D9 B0 60 + : AC BE EE 34 09 6A 13 F5 F7 05 05 93 + : DF 5E BA 35 56 D9 61 FF 19 7F C9 81 + : E6 F8 6C EA 87 40 70 EF AC 6D 2C 74 + : 9F 2D FA 55 3A B9 99 77 02 A6 48 52 + : 8C 4E F3 57 38 57 74 57 5F + 364 02 3: INTEGER 65537 + : } + : } + : } + 369 A3 129: [3] { + 372 30 127: SEQUENCE { + 374 30 12: SEQUENCE { + 376 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 381 01 1: BOOLEAN TRUE + 384 04 2: OCTET STRING, encapsulates { + 386 30 0: SEQUENCE {} + : } + : } + 388 30 14: SEQUENCE { + 390 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 395 01 1: BOOLEAN TRUE + 398 04 4: OCTET STRING, encapsulates { + 400 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 404 30 31: SEQUENCE { + 406 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + + + +Hoffman, Ed. Informational [Page 46] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (X.509 id-ce (2 5 29)) + 411 04 24: OCTET STRING, encapsulates { + 413 30 22: SEQUENCE { + 415 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 437 30 29: SEQUENCE { + 439 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 444 04 22: OCTET STRING, encapsulates { + 446 04 20: OCTET STRING + : 77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D + : CE EC 3C A0 3A E3 FF 50 + : } + : } + 468 30 31: SEQUENCE { + 470 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 475 04 24: OCTET STRING, encapsulates { + 477 30 22: SEQUENCE { + 479 81 20: [1] 'AliceRSA@example.com' + : } + : } + : } + : } + : } + : } + 501 30 13: SEQUENCE { + 503 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 514 05 0: NULL + : } + 516 03 129: BIT STRING 0 unused bits + : 3E 70 47 A8 48 CC 13 58 8F CA 51 71 + : 6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC + : CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C + : 59 A9 20 AA 05 81 A8 4E 25 AD A7 70 + : 14 75 2F F5 C7 9B D1 0E E9 63 D2 64 + : B7 C6 66 6E 73 21 54 DF F4 BA 25 5D + : 7D 49 D3 94 6B 22 36 74 73 B8 4A EC + : 2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A + + + +Hoffman, Ed. Informational [Page 47] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA + : F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A + : 76 AE EB 9B DB 49 B0 22 + : } + : } + 648 31 203: SET { + 651 30 200: SEQUENCE { + 654 02 1: INTEGER 1 + 657 30 38: SEQUENCE { + 659 30 18: SEQUENCE { + 661 31 16: SET { + 663 30 14: SEQUENCE { + 665 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 670 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 679 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + : } + 697 30 9: SEQUENCE { + 699 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + 706 05 0: NULL + : } + 708 30 13: SEQUENCE { + 710 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 721 05 0: NULL + : } + 723 04 128: OCTET STRING + : 2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E + : 9D BF 89 9A 81 E5 75 C4 91 3D D3 D0 + : D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84 + : F5 CD 60 4E 27 95 F6 CF 00 86 76 75 + : 3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16 + : 04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20 + : 44 D5 9F 07 C5 53 24 FA CE 01 1D 0F + : 17 13 A7 2A 95 9D 2B E4 03 95 14 0B + : E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6 + : 55 13 D4 68 6F D0 07 D7 A2 B1 62 4C + : E3 8F AF FD E0 D5 5D C7 + : } + : } + + + +Hoffman, Ed. Informational [Page 48] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + +4.3. Basic Signed Content, Detached Content + + Same as 4.1, except with no eContent. A SignedData with no attribute + certificates, signed by Alice using DSS, just her certificate (not + Carl's root cert), no CRL. The message is ExContent, but the + eContent is not included. There are no signed or unsigned + attributes. + + 0 30 887: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 872: [0] { + 19 30 868: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 11: SEQUENCE { + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + 50 A0 736: [0] { + 54 30 732: SEQUENCE { + 58 30 667: SEQUENCE { + 62 A0 3: [0] { + 64 02 1: INTEGER 2 + : } + 67 02 2: INTEGER 200 + 71 30 9: SEQUENCE { + 73 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 82 30 18: SEQUENCE { + 84 31 16: SET { + 86 30 14: SEQUENCE { + 88 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 93 13 7: PrintableString 'CarlDSS' + : } + + + +Hoffman, Ed. Informational [Page 49] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + 102 30 30: SEQUENCE { + 104 17 13: UTCTime '990817011049Z' + 119 17 13: UTCTime '391231235959Z' + : } + 134 30 19: SEQUENCE { + 136 31 17: SET { + 138 30 15: SEQUENCE { + 140 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 145 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 155 30 438: SEQUENCE { + 159 30 299: SEQUENCE { + 163 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 172 30 286: SEQUENCE { + 176 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 308 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 331 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + + + +Hoffman, Ed. Informational [Page 50] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : D1 81 4A 60 39 BA 36 39 + : } + : } + 462 03 132: BIT STRING 0 unused bits, encapsulates { + 466 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 597 A3 129: [3] { + 600 30 127: SEQUENCE { + 602 30 12: SEQUENCE { + 604 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 609 01 1: BOOLEAN TRUE + 612 04 2: OCTET STRING, encapsulates { + 614 30 0: SEQUENCE {} + : } + : } + 616 30 14: SEQUENCE { + 618 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 623 01 1: BOOLEAN TRUE + 626 04 4: OCTET STRING, encapsulates { + 628 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 632 30 31: SEQUENCE { + 634 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 639 04 24: OCTET STRING, encapsulates { + 641 30 22: SEQUENCE { + 643 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + + + +Hoffman, Ed. Informational [Page 51] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + 665 30 29: SEQUENCE { + 667 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 672 04 22: OCTET STRING, encapsulates { + 674 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 696 30 31: SEQUENCE { + 698 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 703 04 24: OCTET STRING, encapsulates { + 705 30 22: SEQUENCE { + 707 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } + 729 30 9: SEQUENCE { + 731 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 740 03 48: BIT STRING 0 unused bits, encapsulates { + 743 30 45: SEQUENCE { + 745 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 767 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 790 31 99: SET { + 792 30 97: SEQUENCE { + 794 02 1: INTEGER 1 + 797 30 24: SEQUENCE { + 799 30 18: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 52] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 801 31 16: SET { + 803 30 14: SEQUENCE { + 805 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 810 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 819 02 2: INTEGER 200 + : } + 823 30 7: SEQUENCE { + 825 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 832 30 9: SEQUENCE { + 834 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 843 04 46: OCTET STRING, encapsulates { + 845 30 44: SEQUENCE { + 847 02 20: INTEGER + : 06 FB C7 2A 24 D5 34 89 F7 8B B5 FD + : 73 24 A5 86 C8 0F 5A 6C + 869 02 20: INTEGER + : 66 69 19 BC 68 58 D1 8D B1 9D 52 3F + : DA 14 88 0D FD C9 A1 B8 + : } + : } + : } + : } + : } + : } + : } + +4.4. Fancier Signed Content + + Same as 4.1, but includes Carl's root cert, Carl's CRL, some signed + and unsigned attributes (Countersignature by Diane). A SignedData + with no attribute certificates, signed by Alice using DSS, her + certificate and Carl's root cert, Carl's DSS CRL. The message is + ExContent, and is included in the eContent. The signed attributes + are Content Type, Message Digest and Signing Time; the unsigned + attributes are content hint and counter signature. The message + includes also Alice's RSA certificate. + + + + + +Hoffman, Ed. Informational [Page 53] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 0 30 2829: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 2814: [0] { + 19 30 2810: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 43: SEQUENCE { + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 50 A0 30: [0] { + 52 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 82 A0 1967: [0] { + 86 30 556: SEQUENCE { + 90 30 405: SEQUENCE { + 94 A0 3: [0] { + 96 02 1: INTEGER 2 + : } + 99 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + 117 30 13: SEQUENCE { + 119 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 130 05 0: NULL + : } + 132 30 18: SEQUENCE { + 134 31 16: SET { + 136 30 14: SEQUENCE { + 138 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 143 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 152 30 30: SEQUENCE { + 154 17 13: UTCTime '990919010847Z' + 169 17 13: UTCTime '391231235959Z' + + + +Hoffman, Ed. Informational [Page 54] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + 184 30 19: SEQUENCE { + 186 31 17: SET { + 188 30 15: SEQUENCE { + 190 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 195 13 8: PrintableString 'AliceRSA' + : } + : } + : } + 205 30 159: SEQUENCE { + 208 30 13: SEQUENCE { + 210 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 221 05 0: NULL + : } + 223 03 141: BIT STRING 0 unused bits, encapsulates { + 227 30 137: SEQUENCE { + 230 02 129: INTEGER + : 00 E0 89 73 39 8D D8 F5 F5 E8 87 76 + : 39 7F 4E B0 05 BB 53 83 DE 0F B7 AB + : DC 7D C7 75 29 0D 05 2E 6D 12 DF A6 + : 86 26 D4 D2 6F AA 58 29 FC 97 EC FA + : 82 51 0F 30 80 BE B1 50 9E 46 44 F1 + : 2C BB D8 32 CF C6 68 6F 07 D9 B0 60 + : AC BE EE 34 09 6A 13 F5 F7 05 05 93 + : DF 5E BA 35 56 D9 61 FF 19 7F C9 81 + : E6 F8 6C EA 87 40 70 EF AC 6D 2C 74 + : 9F 2D FA 55 3A B9 99 77 02 A6 48 52 + : 8C 4E F3 57 38 57 74 57 5F + 362 02 3: INTEGER 65537 + : } + : } + : } + 367 A3 129: [3] { + 370 30 127: SEQUENCE { + 372 30 12: SEQUENCE { + 374 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 379 01 1: BOOLEAN TRUE + 382 04 2: OCTET STRING, encapsulates { + 384 30 0: SEQUENCE {} + : } + : } + 386 30 14: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 55] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 388 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 393 01 1: BOOLEAN TRUE + 396 04 4: OCTET STRING, encapsulates { + 398 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 402 30 31: SEQUENCE { + 404 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 409 04 24: OCTET STRING, encapsulates { + 411 30 22: SEQUENCE { + 413 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 435 30 29: SEQUENCE { + 437 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 442 04 22: OCTET STRING, encapsulates { + 444 04 20: OCTET STRING + : 77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D + : CE EC 3C A0 3A E3 FF 50 + : } + : } + 466 30 31: SEQUENCE { + 468 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 473 04 24: OCTET STRING, encapsulates { + 475 30 22: SEQUENCE { + 477 81 20: [1] 'AliceRSA@example.com' + : } + : } + : } + : } + : } + : } + 499 30 13: SEQUENCE { + 501 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + + + +Hoffman, Ed. Informational [Page 56] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (PKCS #1) + 512 05 0: NULL + : } + 514 03 129: BIT STRING 0 unused bits + : 3E 70 47 A8 48 CC 13 58 8F CA 51 71 + : 6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC + : CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C + : 59 A9 20 AA 05 81 A8 4E 25 AD A7 70 + : 14 75 2F F5 C7 9B D1 0E E9 63 D2 64 + : B7 C6 66 6E 73 21 54 DF F4 BA 25 5D + : 7D 49 D3 94 6B 22 36 74 73 B8 4A EC + : 2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A + : B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA + : F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A + : 76 AE EB 9B DB 49 B0 22 + : } + 646 30 667: SEQUENCE { + 650 30 602: SEQUENCE { + 654 A0 3: [0] { + 656 02 1: INTEGER 2 + : } + 659 02 1: INTEGER 1 + 662 30 9: SEQUENCE { + 664 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 673 30 18: SEQUENCE { + 675 31 16: SET { + 677 30 14: SEQUENCE { + 679 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 684 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 693 30 30: SEQUENCE { + 695 17 13: UTCTime '990816225050Z' + 710 17 13: UTCTime '391231235959Z' + : } + 725 30 18: SEQUENCE { + 727 31 16: SET { + 729 30 14: SEQUENCE { + 731 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 736 13 7: PrintableString 'CarlDSS' + + + +Hoffman, Ed. Informational [Page 57] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + 745 30 439: SEQUENCE { + 749 30 299: SEQUENCE { + 753 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 762 30 286: SEQUENCE { + 766 02 129: INTEGER + : 00 B6 49 18 3E 8A 44 C1 29 71 94 4C + : 01 C4 12 C1 7A 79 CB 54 4D AB 1E 81 + : FB C6 4C B3 0E 94 09 06 EB 01 D4 B1 + : C8 71 4B C7 45 C0 50 25 5D 9C FC DA + : E4 6D D3 E2 86 48 84 82 7D BA 15 95 + : 4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A + : 0A 8A BA 16 7B B9 50 01 48 93 8B EB + : 25 15 51 97 55 DC 8F 53 0E 10 A9 50 + : FC 70 B7 CD 30 54 FD DA DE A8 AA 22 + : B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9 + : AD E1 08 D4 6D 29 2D D6 E9 + 898 02 21: INTEGER + : 00 DD C1 2F DF 53 CE 0B 34 60 77 3E + : 02 A4 BF 8A 5D 98 B9 10 D5 + 921 02 128: INTEGER + : 0C EE 57 9B 4B BD DA B6 07 6A 74 37 + : 4F 55 7F 9D ED BC 61 0D EB 46 59 3C + : 56 0B 2B 5B 0C 91 CE A5 62 52 69 CA + : E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C + : AD CB AE 45 E3 06 AC 8C 22 9D 9C 44 + : 87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE + : AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A + : 73 AA 7F 46 51 1F A9 42 16 9C 48 EB + : 8A 79 61 B4 D5 2F 53 22 44 63 1F 86 + : B8 A3 58 06 25 F8 29 C0 EF BA E0 75 + : F0 42 C4 63 65 52 9B 0A + : } + : } + 1052 03 133: BIT STRING 0 unused bits, encapsulates { + 1056 02 129: INTEGER + : 00 99 87 74 27 03 66 A0 B1 C0 AD DC + : 2C 75 BB E1 6C 44 9C DA 21 6D 4D 47 + : 6D B1 62 09 E9 D8 AE 1E F2 3A B4 94 + : B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25 + : 4E B9 60 96 19 24 01 F3 62 0C FE 75 + : C0 FB CE D8 68 00 E3 FD D5 70 4F DF + : 23 96 19 06 94 F4 B1 61 8F 3A 57 B1 + : 08 11 A4 0B 26 25 F0 52 76 81 EA 0B + + + +Hoffman, Ed. Informational [Page 58] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 62 0D 95 2A E6 86 BA 72 B2 A7 50 83 + : 0B AA 27 CD 1B A9 4D 89 9A D7 8D 18 + : 39 84 3F 8B C5 56 4D 80 7A + : } + : } + 1188 A3 66: [3] { + 1190 30 64: SEQUENCE { + 1192 30 15: SEQUENCE { + 1194 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 1199 01 1: BOOLEAN TRUE + 1202 04 5: OCTET STRING, encapsulates { + 1204 30 3: SEQUENCE { + 1206 01 1: BOOLEAN TRUE + : } + : } + : } + 1209 30 14: SEQUENCE { + 1211 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 1216 01 1: BOOLEAN TRUE + 1219 04 4: OCTET STRING, encapsulates { + 1221 03 2: BIT STRING 1 unused bits + : '1100001'B + : } + : } + 1225 30 29: SEQUENCE { + 1227 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 1232 04 22: OCTET STRING, encapsulates { + 1234 04 20: OCTET STRING + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + : } + : } + 1256 30 9: SEQUENCE { + 1258 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 1267 03 48: BIT STRING 0 unused bits, encapsulates { + 1270 30 45: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 59] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 1272 02 20: INTEGER + : 6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B + : C9 06 37 E9 11 17 A1 13 + 1294 02 21: INTEGER + : 00 8F 34 69 2A 8B B1 3C 03 79 94 32 + : 4D 12 1F CE 89 FB 46 B2 3B + : } + : } + : } + 1317 30 732: SEQUENCE { + 1321 30 667: SEQUENCE { + 1325 A0 3: [0] { + 1327 02 1: INTEGER 2 + : } + 1330 02 2: INTEGER 200 + 1334 30 9: SEQUENCE { + 1336 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 1345 30 18: SEQUENCE { + 1347 31 16: SET { + 1349 30 14: SEQUENCE { + 1351 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 1356 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 1365 30 30: SEQUENCE { + 1367 17 13: UTCTime '990817011049Z' + 1382 17 13: UTCTime '391231235959Z' + : } + 1397 30 19: SEQUENCE { + 1399 31 17: SET { + 1401 30 15: SEQUENCE { + 1403 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 1408 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 1418 30 438: SEQUENCE { + 1422 30 299: SEQUENCE { + 1426 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + + + +Hoffman, Ed. Informational [Page 60] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (ANSI X9.57 algorithm) + 1435 30 286: SEQUENCE { + 1439 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 1571 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 1594 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 1725 03 132: BIT STRING 0 unused bits, encapsulates { + 1729 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 1860 A3 129: [3] { + 1863 30 127: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 61] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 1865 30 12: SEQUENCE { + 1867 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 1872 01 1: BOOLEAN TRUE + 1875 04 2: OCTET STRING, encapsulates { + 1877 30 0: SEQUENCE {} + : } + : } + 1879 30 14: SEQUENCE { + 1881 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 1886 01 1: BOOLEAN TRUE + 1889 04 4: OCTET STRING, encapsulates { + 1891 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 1895 30 31: SEQUENCE { + 1897 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 1902 04 24: OCTET STRING, encapsulates { + 1904 30 22: SEQUENCE { + 1906 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 1928 30 29: SEQUENCE { + 1930 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 1935 04 22: OCTET STRING, encapsulates { + 1937 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 1959 30 31: SEQUENCE { + 1961 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 1966 04 24: OCTET STRING, encapsulates { + 1968 30 22: SEQUENCE { + 1970 81 20: [1] 'AliceDSS@example.com' + + + +Hoffman, Ed. Informational [Page 62] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + : } + : } + 1992 30 9: SEQUENCE { + 1994 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 2003 03 48: BIT STRING 0 unused bits, encapsulates { + 2006 30 45: SEQUENCE { + 2008 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 2030 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 2053 A1 219: [1] { + 2056 30 216: SEQUENCE { + 2059 30 153: SEQUENCE { + 2062 30 9: SEQUENCE { + 2064 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 2073 30 18: SEQUENCE { + 2075 31 16: SET { + 2077 30 14: SEQUENCE { + 2079 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 2084 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 2093 17 13: UTCTime '990827070000Z' + 2108 30 105: SEQUENCE { + 2110 30 19: SEQUENCE { + 2112 02 2: INTEGER 200 + 2116 17 13: UTCTime '990822070000Z' + : } + 2131 30 19: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 63] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 2133 02 2: INTEGER 201 + 2137 17 13: UTCTime '990822070000Z' + : } + 2152 30 19: SEQUENCE { + 2154 02 2: INTEGER 211 + 2158 17 13: UTCTime '990822070000Z' + : } + 2173 30 19: SEQUENCE { + 2175 02 2: INTEGER 210 + 2179 17 13: UTCTime '990822070000Z' + : } + 2194 30 19: SEQUENCE { + 2196 02 2: INTEGER 212 + 2200 17 13: UTCTime '990824070000Z' + : } + : } + : } + 2215 30 9: SEQUENCE { + 2217 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 2226 03 47: BIT STRING 0 unused bits, encapsulates { + 2229 30 44: SEQUENCE { + 2231 02 20: INTEGER + : 7E 65 52 76 33 FE 34 73 17 D1 F7 96 + : F9 A0 D4 D8 6D 5C 7D 3D + 2253 02 20: INTEGER + : 02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E + : DA 24 F3 2A 83 9C 35 A1 + : } + : } + : } + : } + 2275 31 554: SET { + 2279 30 550: SEQUENCE { + 2283 02 1: INTEGER 1 + 2286 30 24: SEQUENCE { + 2288 30 18: SEQUENCE { + 2290 31 16: SET { + 2292 30 14: SEQUENCE { + 2294 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 2299 13 7: PrintableString 'CarlDSS' + : } + : } + : } + + + +Hoffman, Ed. Informational [Page 64] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 2308 02 2: INTEGER 200 + : } + 2312 30 7: SEQUENCE { + 2314 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 2321 A0 93: [0] { + 2323 30 24: SEQUENCE { + 2325 06 9: OBJECT IDENTIFIER + : contentType (1 2 840 113549 1 9 3) + : (PKCS #9 (1 2 840 113549 1 9)) + 2336 31 11: SET { + 2338 06 9: OBJECT IDENTIFIER + : data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + : } + 2349 30 28: SEQUENCE { + 2351 06 9: OBJECT IDENTIFIER + : signingTime (1 2 840 113549 1 9 5) + : (PKCS #9 (1 2 840 113549 1 9)) + 2362 31 15: SET { + 2364 17 13: UTCTime '030514153900Z' + : } + : } + 2379 30 35: SEQUENCE { + 2381 06 9: OBJECT IDENTIFIER + : messageDigest (1 2 840 113549 1 9 4) + : (PKCS #9 (1 2 840 113549 1 9)) + 2392 31 22: SET { + 2394 04 20: OCTET STRING + : 40 6A EC 08 52 79 BA 6E 16 02 2D 9E + : 06 29 C0 22 96 87 DD 48 + : } + : } + : } + 2416 30 9: SEQUENCE { + 2418 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 2427 04 46: OCTET STRING, encapsulates { + 2429 30 44: SEQUENCE { + 2431 02 20: INTEGER + : 3B A5 E0 4A DB 6D 58 E0 19 D1 00 1C + : 4F 44 9A 57 7A 71 66 68 + 2453 02 20: INTEGER + : 1A 11 98 D6 1F 1F AF 34 81 01 DE BE + + + +Hoffman, Ed. Informational [Page 65] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 8B DC B6 A8 6A 91 69 13 + : } + : } + 2475 A1 354: [1] { + 2479 30 62: SEQUENCE { + 2481 06 11: OBJECT IDENTIFIER + : id-aa-contentHint + : (1 2 840 113549 1 9 16 2 4) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) + 2494 31 47: SET { + 2496 30 45: SEQUENCE { + 2498 0C 32: UTF8String + : 'Content Hints Description Buffer' + 2532 06 9: OBJECT IDENTIFIER + : data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + : } + : } + 2543 30 286: SEQUENCE { + 2547 06 9: OBJECT IDENTIFIER + : countersignature (1 2 840 113549 1 9 6) + : (PKCS #9 (1 2 840 113549 1 9)) + 2558 31 271: SET { + 2562 30 267: SEQUENCE { + 2566 02 1: INTEGER 1 + 2569 30 38: SEQUENCE { + 2571 30 18: SEQUENCE { + 2573 31 16: SET { + 2575 30 14: SEQUENCE { + 2577 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 2582 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 2591 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + : } + 2609 30 7: SEQUENCE { + 2611 06 5: OBJECT IDENTIFIER + : sha1 (1 3 14 3 2 26) + : (OIW) + : } + 2618 A0 67: [0] { + + + +Hoffman, Ed. Informational [Page 66] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 2620 30 28: SEQUENCE { + 2622 06 9: OBJECT IDENTIFIER + : signingTime + : (1 2 840 113549 1 9 5) + : (PKCS #9 (1 2 840 113549 1 9)) + 2633 31 15: SET { + 2635 17 13: UTCTime '030514153900Z' + : } + : } + 2650 30 35: SEQUENCE { + 2652 06 9: OBJECT IDENTIFIER + : messageDigest + : (1 2 840 113549 1 9 4) + : (PKCS #9 (1 2 840 113549 1 9)) + 2663 31 22: SET { + 2665 04 20: OCTET STRING + : 02 5F 49 4E 39 98 50 85 B3 66 D3 8A + : 1F 7B 9E 69 AA FB D8 33 + : } + : } + : } + 2687 30 13: SEQUENCE { + 2689 06 9: OBJECT IDENTIFIER + : rsaEncryption + : (1 2 840 113549 1 1 1) + : (PKCS #1) + 2700 05 0: NULL + : } + 2702 04 128: OCTET STRING + : 6D AA 20 24 ED 7A EE A5 5E 87 DD 75 + : 1F 2B 54 10 65 F4 CE 9B B1 2C 78 74 + : BC 8B 1C 60 B5 DB 8B 03 9E 49 F2 2B + : 7F 93 6E 3D 89 14 C9 E3 6B F4 F6 7D + : 76 AE 3E 58 1F 9B BB BC 7C 30 19 4E + : 10 F7 02 F1 8B 5B B4 DB 9A BB 93 B4 + : 18 D0 CC 2B C9 91 A9 AD D9 46 F8 65 + : A9 E2 71 95 D0 D4 4E 1F CD 74 6F 82 + : E8 37 6F 5A 3D CB C7 D4 5F C2 80 1B + : DA D3 84 40 68 5F 56 9A 62 F5 3B 0D + : 6C 33 C3 ED 67 3F 43 BF + : } + : } + : } + : } + : } + : } + : } + : } + + + +Hoffman, Ed. Informational [Page 67] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + +4.5. All RSA Signed Message + + Same as 4.2, but includes Carl's RSA root cert (but no CRL). A + SignedData with no attribute certificates, signed by Alice using RSA, + her certificate and Carl's root cert, no CRL. The message is + ExContent, and is included in the eContent. There are no signed or + unsigned attributes. + + 0 30 NDEF: SEQUENCE { + 2 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 13 A0 NDEF: [0] { + 15 30 NDEF: SEQUENCE { + 17 02 1: INTEGER 1 + 20 31 11: SET { + 22 30 9: SEQUENCE { + 24 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + 31 05 0: NULL + : } + : } + 33 30 NDEF: SEQUENCE { + 35 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 46 A0 NDEF: [0] { + 48 24 NDEF: OCTET STRING { + 50 04 4: OCTET STRING 'This' + 56 04 24: OCTET STRING ' is some sample content.' + : } + : } + : } + 88 A0 NDEF: [0] { + 90 30 491: SEQUENCE { + 94 30 340: SEQUENCE { + 98 A0 3: [0] { + 100 02 1: INTEGER 2 + : } + 103 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : 9F F2 50 20 + 121 30 13: SEQUENCE { + 123 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 134 05 0: NULL + + + +Hoffman, Ed. Informational [Page 68] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + 136 30 18: SEQUENCE { + 138 31 16: SET { + 140 30 14: SEQUENCE { + 142 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 147 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 156 30 30: SEQUENCE { + 158 17 13: UTCTime '990818070000Z' + 173 17 13: UTCTime '391231235959Z' + : } + 188 30 18: SEQUENCE { + 190 31 16: SET { + 192 30 14: SEQUENCE { + 194 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 199 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 208 30 159: SEQUENCE { + 211 30 13: SEQUENCE { + 213 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 224 05 0: NULL + : } + 226 03 141: BIT STRING 0 unused bits, encapsulates { + 230 30 137: SEQUENCE { + 233 02 129: INTEGER + : 00 E4 4B FF 18 B8 24 57 F4 77 FF 6E + : 73 7B 93 71 5C BC 33 1A 92 92 72 23 + : D8 41 46 D0 CD 11 3A 04 B3 8E AF 82 + : 9D BD 51 1E 17 7A F2 76 2C 2B 86 39 + : A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC + : A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F + : 99 25 8F B8 4E AB B9 7D D5 96 65 DA + : 16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7 + : 29 CB 82 DD AC 44 E9 AA 93 94 29 0E + : F8 18 D6 C8 57 5E F2 76 C4 F2 11 60 + : 38 B9 1B 3C 1D 97 C9 6A F1 + 365 02 3: INTEGER 65537 + : } + + + +Hoffman, Ed. Informational [Page 69] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + 370 A3 66: [3] { + 372 30 64: SEQUENCE { + 374 30 15: SEQUENCE { + 376 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 381 01 1: BOOLEAN TRUE + 384 04 5: OCTET STRING, encapsulates { + 386 30 3: SEQUENCE { + 388 01 1: BOOLEAN TRUE + : } + : } + : } + 391 30 14: SEQUENCE { + 393 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 398 01 1: BOOLEAN TRUE + 401 04 4: OCTET STRING, encapsulates { + 403 03 2: BIT STRING 1 unused bits + : '1100001'B + : } + : } + 407 30 29: SEQUENCE { + 409 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 414 04 22: OCTET STRING, encapsulates { + 416 04 20: OCTET STRING + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + : } + : } + 438 30 13: SEQUENCE { + 440 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 451 05 0: NULL + : } + 453 03 129: BIT STRING 0 unused bits + : B7 9E D4 04 D3 ED 29 E4 FF 89 89 15 + : 2E 4C DB 0C F0 48 0F 32 61 EE C4 04 + + + +Hoffman, Ed. Informational [Page 70] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : EC 12 5D 2D FF 0F 64 59 7E 0A C3 ED + : 18 FD E3 56 40 37 A7 07 B5 F0 38 12 + : 61 50 ED EF DD 3F E3 0B B8 61 A5 A4 + : 9B 3C E6 9E 9C 54 9A B6 95 D6 DA 6C + : 3B B5 2D 45 35 9D 49 01 76 FA B9 B9 + : 31 F9 F9 6B 12 53 A0 F5 14 60 9B 7D + : CA 3E F2 53 6B B0 37 6F AD E6 74 D7 + : DB FA 5A EA 14 41 63 5D CD BE C8 0E + : C1 DA 6A 8D 53 34 18 02 + : } + 585 30 556: SEQUENCE { + 589 30 405: SEQUENCE { + 593 A0 3: [0] { + 595 02 1: INTEGER 2 + : } + 598 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + 616 30 13: SEQUENCE { + 618 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 629 05 0: NULL + : } + 631 30 18: SEQUENCE { + 633 31 16: SET { + 635 30 14: SEQUENCE { + 637 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 642 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 651 30 30: SEQUENCE { + 653 17 13: UTCTime '990919010847Z' + 668 17 13: UTCTime '391231235959Z' + : } + 683 30 19: SEQUENCE { + 685 31 17: SET { + 687 30 15: SEQUENCE { + 689 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 694 13 8: PrintableString 'AliceRSA' + : } + : } + + + +Hoffman, Ed. Informational [Page 71] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + 704 30 159: SEQUENCE { + 707 30 13: SEQUENCE { + 709 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 720 05 0: NULL + : } + 722 03 141: BIT STRING 0 unused bits, encapsulates { + 726 30 137: SEQUENCE { + 729 02 129: INTEGER + : 00 E0 89 73 39 8D D8 F5 F5 E8 87 76 + : 39 7F 4E B0 05 BB 53 83 DE 0F B7 AB + : DC 7D C7 75 29 0D 05 2E 6D 12 DF A6 + : 86 26 D4 D2 6F AA 58 29 FC 97 EC FA + : 82 51 0F 30 80 BE B1 50 9E 46 44 F1 + : 2C BB D8 32 CF C6 68 6F 07 D9 B0 60 + : AC BE EE 34 09 6A 13 F5 F7 05 05 93 + : DF 5E BA 35 56 D9 61 FF 19 7F C9 81 + : E6 F8 6C EA 87 40 70 EF AC 6D 2C 74 + : 9F 2D FA 55 3A B9 99 77 02 A6 48 52 + : 8C 4E F3 57 38 57 74 57 5F + 861 02 3: INTEGER 65537 + : } + : } + : } + 866 A3 129: [3] { + 869 30 127: SEQUENCE { + 871 30 12: SEQUENCE { + 873 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 878 01 1: BOOLEAN TRUE + 881 04 2: OCTET STRING, encapsulates { + 883 30 0: SEQUENCE {} + : } + : } + 885 30 14: SEQUENCE { + 887 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 892 01 1: BOOLEAN TRUE + 895 04 4: OCTET STRING, encapsulates { + 897 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 901 30 31: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 72] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 903 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 908 04 24: OCTET STRING, encapsulates { + 910 30 22: SEQUENCE { + 912 80 20: [0] + : E9 E0 90 27 AC 78 20 7A 9A D3 4C F2 + : 42 37 4E 22 AE 9E 38 BB + : } + : } + : } + 934 30 29: SEQUENCE { + 936 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 941 04 22: OCTET STRING, encapsulates { + 943 04 20: OCTET STRING + : 77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D + : CE EC 3C A0 3A E3 FF 50 + : } + : } + 965 30 31: SEQUENCE { + 967 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 972 04 24: OCTET STRING, encapsulates { + 974 30 22: SEQUENCE { + 976 81 20: [1] 'AliceRSA@example.com' + : } + : } + : } + : } + : } + : } + 998 30 13: SEQUENCE { + 1000 06 9: OBJECT IDENTIFIER + : sha1withRSAEncryption + : (1 2 840 113549 1 1 5) + : (PKCS #1) + 1011 05 0: NULL + : } + 1013 03 129: BIT STRING 0 unused bits + : 3E 70 47 A8 48 CC 13 58 8F CA 51 71 + : 6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC + : CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C + : 59 A9 20 AA 05 81 A8 4E 25 AD A7 70 + : 14 75 2F F5 C7 9B D1 0E E9 63 D2 64 + : B7 C6 66 6E 73 21 54 DF F4 BA 25 5D + + + +Hoffman, Ed. Informational [Page 73] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 7D 49 D3 94 6B 22 36 74 73 B8 4A EC + : 2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A + : B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA + : F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A + : 76 AE EB 9B DB 49 B0 22 + : } + : } + 1147 31 203: SET { + 1150 30 200: SEQUENCE { + 1153 02 1: INTEGER 1 + 1156 30 38: SEQUENCE { + 1158 30 18: SEQUENCE { + 1160 31 16: SET { + 1162 30 14: SEQUENCE { + 1164 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 1169 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 1178 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : C4 10 B3 B0 + : } + 1196 30 9: SEQUENCE { + 1198 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + 1205 05 0: NULL + : } + 1207 30 13: SEQUENCE { + 1209 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 1220 05 0: NULL + : } + 1222 04 128: OCTET STRING + : 2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E + : 9D BF 89 9A 81 E5 75 C4 91 3D D3 D0 + : D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84 + : F5 CD 60 4E 27 95 F6 CF 00 86 76 75 + : 3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16 + : 04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20 + : 44 D5 9F 07 C5 53 24 FA CE 01 1D 0F + : 17 13 A7 2A 95 9D 2B E4 03 95 14 0B + : E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6 + : 55 13 D4 68 6F D0 07 D7 A2 B1 62 4C + : E3 8F AF FD E0 D5 5D C7 + + + +Hoffman, Ed. Informational [Page 74] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + : } + +4.6. Multiple Signers + + Similar to 4.1, but the message is also signed by Diane. Two + signerInfos (one for Alice, one for Diane) with no attribute + certificates, each signed using DSS, Alice's and Diane's certificate + (not Carl's root cert), no CRL. The message is ExContent, and is + included in the eContent. There are no signed or unsigned + attributes. + + 0 30 1463: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 1448: [0] { + 19 30 1444: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 43: SEQUENCE { + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 50 A0 30: [0] { + 52 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 82 A0 1180: [0] { + 86 30 440: SEQUENCE { + 90 30 375: SEQUENCE { + 94 A0 3: [0] { + 96 02 1: INTEGER 2 + : } + 99 02 2: INTEGER 210 + 103 30 9: SEQUENCE { + 105 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 114 30 18: SEQUENCE { + 116 31 16: SET { + + + +Hoffman, Ed. Informational [Page 75] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 118 30 14: SEQUENCE { + 120 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 125 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 134 30 30: SEQUENCE { + 136 17 13: UTCTime '990817020810Z' + 151 17 13: UTCTime '391231235959Z' + : } + 166 30 19: SEQUENCE { + 168 31 17: SET { + 170 30 15: SEQUENCE { + 172 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 177 13 8: PrintableString 'DianeDSS' + : } + : } + : } + 187 30 147: SEQUENCE { + 190 30 9: SEQUENCE { + 192 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + : } + 201 03 133: BIT STRING 0 unused bits, encapsulates { + 205 02 129: INTEGER + : 00 A0 00 17 78 2C EE 7E 81 53 2E 2E + : 61 08 0F A1 9B 51 52 1A DA 59 A8 73 + : 2F 12 25 B6 08 CB CA EF 2A 44 76 8A + : 52 09 EA BD 05 22 D5 0F F6 FD 46 D7 + : AF 99 38 09 0E 13 CB 4F 2C DD 1C 34 + : F7 1C BF 25 FF 23 D3 3B 59 E7 82 97 + : 37 BE 31 24 D8 18 C8 F3 49 39 5B B7 + : E2 E5 27 7E FC 8C 45 72 5B 7E 3E 8F + : 68 4D DD 46 7A 22 BE 8E FF CC DA 39 + : 29 A3 39 E5 9F 43 E9 55 C9 D7 5B A6 + : 81 67 CC C0 AA CD 2E C5 23 + : } + : } + 337 A3 129: [3] { + 340 30 127: SEQUENCE { + 342 30 12: SEQUENCE { + 344 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + + + +Hoffman, Ed. Informational [Page 76] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (X.509 id-ce (2 5 29)) + 349 01 1: BOOLEAN TRUE + 352 04 2: OCTET STRING, encapsulates { + 354 30 0: SEQUENCE {} + : } + : } + 356 30 14: SEQUENCE { + 358 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 363 01 1: BOOLEAN TRUE + 366 04 4: OCTET STRING, encapsulates { + 368 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 372 30 31: SEQUENCE { + 374 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 379 04 24: OCTET STRING, encapsulates { + 381 30 22: SEQUENCE { + 383 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 405 30 29: SEQUENCE { + 407 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 412 04 22: OCTET STRING, encapsulates { + 414 04 20: OCTET STRING + : 64 30 99 7D 5C DC 45 0B 99 3A 52 2F + : 16 BF 58 50 DD CE 2B 18 + : } + : } + 436 30 31: SEQUENCE { + 438 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 443 04 24: OCTET STRING, encapsulates { + 445 30 22: SEQUENCE { + 447 81 20: [1] 'DianeDSS@example.com' + : } + : } + : } + + + +Hoffman, Ed. Informational [Page 77] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + 469 30 9: SEQUENCE { + 471 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 480 03 48: BIT STRING 0 unused bits, encapsulates { + 483 30 45: SEQUENCE { + 485 02 21: INTEGER + : 00 A1 1A F8 17 0E 3E 5D A8 8C F4 B6 + : 55 33 1E 4B E3 2C AC B9 5F + 508 02 20: INTEGER + : 28 4B 10 45 58 D2 1C 9D 55 35 14 18 + : 91 B2 3F 39 DF B5 6E D3 + : } + : } + : } + 530 30 732: SEQUENCE { + 534 30 667: SEQUENCE { + 538 A0 3: [0] { + 540 02 1: INTEGER 2 + : } + 543 02 2: INTEGER 200 + 547 30 9: SEQUENCE { + 549 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 558 30 18: SEQUENCE { + 560 31 16: SET { + 562 30 14: SEQUENCE { + 564 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 569 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 578 30 30: SEQUENCE { + 580 17 13: UTCTime '990817011049Z' + 595 17 13: UTCTime '391231235959Z' + : } + 610 30 19: SEQUENCE { + 612 31 17: SET { + 614 30 15: SEQUENCE { + 616 06 3: OBJECT IDENTIFIER + + + +Hoffman, Ed. Informational [Page 78] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 621 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 631 30 438: SEQUENCE { + 635 30 299: SEQUENCE { + 639 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 648 30 286: SEQUENCE { + 652 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 784 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 807 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 938 03 132: BIT STRING 0 unused bits, encapsulates { + 942 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + + + +Hoffman, Ed. Informational [Page 79] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 1073 A3 129: [3] { + 1076 30 127: SEQUENCE { + 1078 30 12: SEQUENCE { + 1080 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 1085 01 1: BOOLEAN TRUE + 1088 04 2: OCTET STRING, encapsulates { + 1090 30 0: SEQUENCE {} + : } + : } + 1092 30 14: SEQUENCE { + 1094 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 1099 01 1: BOOLEAN TRUE + 1102 04 4: OCTET STRING, encapsulates { + 1104 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 1108 30 31: SEQUENCE { + 1110 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 1115 04 24: OCTET STRING, encapsulates { + 1117 30 22: SEQUENCE { + 1119 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 1141 30 29: SEQUENCE { + 1143 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 1148 04 22: OCTET STRING, encapsulates { + 1150 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + + + +Hoffman, Ed. Informational [Page 80] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 13 01 E2 FD E3 97 FE CD + : } + : } + 1172 30 31: SEQUENCE { + 1174 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 1179 04 24: OCTET STRING, encapsulates { + 1181 30 22: SEQUENCE { + 1183 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } + 1205 30 9: SEQUENCE { + 1207 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 1216 03 48: BIT STRING 0 unused bits, encapsulates { + 1219 30 45: SEQUENCE { + 1221 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 1243 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 1266 31 198: SET { + 1269 30 97: SEQUENCE { + 1271 02 1: INTEGER 1 + 1274 30 24: SEQUENCE { + 1276 30 18: SEQUENCE { + 1278 31 16: SET { + 1280 30 14: SEQUENCE { + 1282 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 1287 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 1296 02 2: INTEGER 200 + + + +Hoffman, Ed. Informational [Page 81] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + 1300 30 7: SEQUENCE { + 1302 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 1309 30 9: SEQUENCE { + 1311 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 1320 04 46: OCTET STRING, encapsulates { + 1322 30 44: SEQUENCE { + 1324 02 20: INTEGER + : 48 24 DE 8B 85 F2 16 AF EC 82 61 A9 + : 54 D0 2D 04 A1 CC 5A 4F + 1346 02 20: INTEGER + : 17 ED D5 77 02 EE 75 13 D8 10 BD 3D + : 97 17 20 88 BB FD 7B 81 + : } + : } + : } + 1368 30 97: SEQUENCE { + 1370 02 1: INTEGER 1 + 1373 30 24: SEQUENCE { + 1375 30 18: SEQUENCE { + 1377 31 16: SET { + 1379 30 14: SEQUENCE { + 1381 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 1386 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 1395 02 2: INTEGER 210 + : } + 1399 30 7: SEQUENCE { + 1401 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 1408 30 9: SEQUENCE { + 1410 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 1419 04 46: OCTET STRING, encapsulates { + 1421 30 44: SEQUENCE { + 1423 02 20: INTEGER + + + +Hoffman, Ed. Informational [Page 82] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 15 FF 81 4D 8C AD 80 4E 9B 35 58 04 + : 37 6E 63 6E E9 5B 83 FA + 1445 02 20: INTEGER + : 06 7E 58 4E 2B 31 84 41 ED 49 79 38 + : 3E 77 D2 A6 8C 75 08 21 + : } + : } + : } + : } + : } + : } + : } + +4.7. Signing Using SKI + + Same as 4.1, but the signature uses the SKI instead of the + issuer/serial number in the cert. A SignedData with no attribute + certificates, signed by Alice using DSS, just her certificate (not + Carl's root cert), identified by the SKI, no CRL. The message is + ExContent, and is included in the eContent. There are no signed or + unsigned attributes. + + 0 30 915: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 900: [0] { + 19 30 896: SEQUENCE { + 23 02 1: INTEGER 3 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 43: SEQUENCE { + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 50 A0 30: [0] { + 52 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 82 A0 736: [0] { + 86 30 732: SEQUENCE { + 90 30 667: SEQUENCE { + 94 A0 3: [0] { + 96 02 1: INTEGER 2 + : } + 99 02 2: INTEGER 200 + + + +Hoffman, Ed. Informational [Page 83] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 103 30 9: SEQUENCE { + 105 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 114 30 18: SEQUENCE { + 116 31 16: SET { + 118 30 14: SEQUENCE { + 120 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 125 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 134 30 30: SEQUENCE { + 136 17 13: UTCTime '990817011049Z' + 151 17 13: UTCTime '391231235959Z' + : } + 166 30 19: SEQUENCE { + 168 31 17: SET { + 170 30 15: SEQUENCE { + 172 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 177 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 187 30 438: SEQUENCE { + 191 30 299: SEQUENCE { + 195 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 204 30 286: SEQUENCE { + 208 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 340 02 21: INTEGER + + + +Hoffman, Ed. Informational [Page 84] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 363 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 494 03 132: BIT STRING 0 unused bits, encapsulates { + 498 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 629 A3 129: [3] { + 632 30 127: SEQUENCE { + 634 30 12: SEQUENCE { + 636 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 641 01 1: BOOLEAN TRUE + 644 04 2: OCTET STRING, encapsulates { + 646 30 0: SEQUENCE {} + : } + : } + 648 30 14: SEQUENCE { + 650 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 655 01 1: BOOLEAN TRUE + 658 04 4: OCTET STRING, encapsulates { + + + +Hoffman, Ed. Informational [Page 85] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 660 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 664 30 31: SEQUENCE { + 666 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 671 04 24: OCTET STRING, encapsulates { + 673 30 22: SEQUENCE { + 675 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 697 30 29: SEQUENCE { + 699 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 704 04 22: OCTET STRING, encapsulates { + 706 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 728 30 31: SEQUENCE { + 730 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 735 04 24: OCTET STRING, encapsulates { + 737 30 22: SEQUENCE { + 739 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } + 761 30 9: SEQUENCE { + 763 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 772 03 48: BIT STRING 0 unused bits, encapsulates { + 775 30 45: SEQUENCE { + 777 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + + + +Hoffman, Ed. Informational [Page 86] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 83 6A B5 3D 67 6B BF 45 + 799 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 822 31 95: SET { + 824 30 93: SEQUENCE { + 826 02 1: INTEGER 3 + 829 80 20: [0] + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + 851 30 7: SEQUENCE { + 853 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 860 30 9: SEQUENCE { + 862 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + : } + 871 04 46: OCTET STRING, encapsulates { + 873 30 44: SEQUENCE { + 875 02 20: INTEGER + : 6D 8E 5A CD 28 A0 1F D9 86 AD 7A E9 + : DF AC D7 BE EC BE 3F F8 + 897 02 20: INTEGER + : 7C 8A 06 1E FC A4 41 35 7E F7 24 14 + : FD 3D C0 56 B7 05 27 D5 + : } + : } + : } + : } + : } + : } + : } + +4.8. S/MIME multipart/signed Message + + A full S/MIME message, including MIME, that includes the body part + from 4.3 and the body containing the content of the message. + +MIME-Version: 1.0 +To: User2@examples.com +From: aliceDss@examples.com +Subject: Example 4.8 +Message-Id: <020906002550300.249@examples.com> + + + +Hoffman, Ed. Informational [Page 87] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +Date: Fri, 06 Sep 2002 00:25:21 -0300 +Content-Type: multipart/signed; + micalg=SHA1; + boundary="----=_NextBoundry____Fri,_06_Sep_2002_00:25:21"; + protocol="application/pkcs7-signature" + +This is a multi-part message in MIME format. + +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21 + +This is some sample content. +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21 +Content-Type: application/pkcs7-signature; name=smime.p7s +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7s + +MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGgggL +gMIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT +k5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2M +IIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lOFz +SH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iLVPE +/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRWa4E8 +baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1nizaoFP +VjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8bUmJEYk2 +RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuVp1FJYLqXr +d4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41bY8i7RaWgSu +OF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxDKE8H5BQP1Gp +2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwHwYDVR0j +BBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfftQ3CkzhMB4v3 +jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM44BAMDMAAwLQ +IUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0NevTFjMGECAQEwG +DASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjOOAQDBC4wLAIUM/mG +f6gkgp9Z0XtRdGimJeB/BxUCFGFFJqwYRt1WYcIOQoGiaowqGzVI + +------=_NextBoundry____Fri,_06_Sep_2002_00:25:21-- + +4.9. S/MIME application/pkcs7-mime Signed Message + + A full S/MIME message, including the MIME parts. + +MIME-Version: 1.0 +To: User2@examples.com +From: aliceDss@examples.com +Subject: Example 4.9 +Message-Id: <021031164540300.304@examples.com> +Date: Thu, 31 Oct 2002 16:45:14 -0300 +Content-Type: application/pkcs7-mime; smime-type=signed-data; + name=smime.p7m + + + +Hoffman, Ed. Informational [Page 88] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m + +MIIDmQYJKoZIhvcNAQcCoIIDijCCA4YCAQExCTAHBgUrDgMCGjAtBgkqhkiG9w0BBwGgIAQ +eDQpUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIIC4DCCAtwwggKboAMCAQICAgDIMA +kGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUzAeFw05OTA4MTcwMTEwNDlaFw0zOTEyM +zEyMzU5NTlaMBMxETAPBgNVBAMTCEFsaWNlRFNTMIIBtjCCASsGByqGSM44BAEwggEeAoGB +AIGNze2D6gqeOT7CSCij5EeT3Q7XqA7sU8WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg +23j+bv7dM3F9piuR10DcMkQiVm96nXvn89J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dh +DEeL3/nbCElzfy5FEbteQJllzzflvbAhUA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUi +TKqOfs+bdlLWWpMdiM5BAI1XPLLGjDDHlBd3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oI +Xks+kPht6pzJIYo7dhTpzi5dowfNI4W4LzABfG1JiRGJNkS9+MiVSlNWteL5c+waYTYfEX/ +Cve3RUP+YdMLRgUpgObo2OQOBhAACgYBc47ladRSWC6l63eM/qeysXty9txMRNKYWiSgRI9 +k0hmd1dRMSPUNbb+VRv/qJ8qIbPiR9PQeNW2PIu0WloErjhdbOBoA/6CN+GvIkq1MauCcNH +u8Iv2YUgFxirGX6FYvxuzTU0pY39mFHssQyhPB+QUD9RqdjTjPypeL08oPluKOBgTB/MAwG +A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFHBEPoIub4feStN14z0 +gvEMrk/EfMB0GA1UdDgQWBBS+bKGz48H37UNwpM4TAeL945f+zTAfBgNVHREEGDAWgRRBbG +ljZURTU0BleGFtcGxlLmNvbTAJBgcqhkjOOAQDAzAAMC0CFFUMpBkfQiuJcSIzjYNqtT1na +79FAhUAn2FTUlQLXLLd2ud2HeIQUltDXr0xYzBhAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERT +UwICAMgwBwYFKw4DAhowCQYHKoZIzjgEAwQuMCwCFD1cSW6LIUFzeXle3YI5SKSBer/sAhQ +mCq7s/CTFHOEjgASeUjbMpx5g6A== + +4.10. SignedData with Attributes + + A SignedData message with the following list of signedAttributes: + + -unknown OID + -contentHints + -smimeCapablilties + -securityLabel + -ContentReference + -smimeEncryptKeyPreference + -mlExpansionHistory + -EquivalentLabel + + 0 30 2047: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 2032: [0] { + 19 30 2028: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 9: SET { + 28 30 7: SEQUENCE { + 30 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + : } + 37 30 43: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 89] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 39 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 50 A0 30: [0] { + 52 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 82 A0 736: [0] { + 86 30 732: SEQUENCE { + 90 30 667: SEQUENCE { + 94 A0 3: [0] { + 96 02 1: INTEGER 2 + : } + 99 02 2: INTEGER 200 + 103 30 9: SEQUENCE { + 105 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 114 30 18: SEQUENCE { + 116 31 16: SET { + 118 30 14: SEQUENCE { + 120 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 125 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 134 30 30: SEQUENCE { + 136 17 13: UTCTime '990817011049Z' + 151 17 13: UTCTime '391231235959Z' + : } + 166 30 19: SEQUENCE { + 168 31 17: SET { + 170 30 15: SEQUENCE { + 172 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 177 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 187 30 438: SEQUENCE { + 191 30 299: SEQUENCE { + 195 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 204 30 286: SEQUENCE { + + + +Hoffman, Ed. Informational [Page 90] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 208 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 340 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 363 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } + 494 03 132: BIT STRING 0 unused bits, encapsulates { + 498 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } + 629 A3 129: [3] { + 632 30 127: SEQUENCE { + 634 30 12: SEQUENCE { + 636 06 3: OBJECT IDENTIFIER + + + +Hoffman, Ed. Informational [Page 91] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 641 01 1: BOOLEAN TRUE + 644 04 2: OCTET STRING, encapsulates { + 646 30 0: SEQUENCE {} + : } + : } + 648 30 14: SEQUENCE { + 650 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 655 01 1: BOOLEAN TRUE + 658 04 4: OCTET STRING, encapsulates { + 660 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } + 664 30 31: SEQUENCE { + 666 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) + 671 04 24: OCTET STRING, encapsulates { + 673 30 22: SEQUENCE { + 675 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } + 697 30 29: SEQUENCE { + 699 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 704 04 22: OCTET STRING, encapsulates { + 706 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } + 728 30 31: SEQUENCE { + 730 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) + 735 04 24: OCTET STRING, encapsulates { + 737 30 22: SEQUENCE { + 739 81 20: [1] 'AliceDSS@example.com' + : } + : } + + + +Hoffman, Ed. Informational [Page 92] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + 761 30 9: SEQUENCE { + 763 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 772 03 48: BIT STRING 0 unused bits, encapsulates { + 775 30 45: SEQUENCE { + 777 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 + 799 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } + 822 31 1225: SET { + 826 30 1221: SEQUENCE { + 830 02 1: INTEGER 1 + 833 30 24: SEQUENCE { + 835 30 18: SEQUENCE { + 837 31 16: SET { + 839 30 14: SEQUENCE { + 841 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 846 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 855 02 2: INTEGER 200 + : } + 859 30 7: SEQUENCE { + 861 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 868 A0 1119: [0] { + 872 30 24: SEQUENCE { + 874 06 9: OBJECT IDENTIFIER + : contentType (1 2 840 113549 1 9 3) + : (PKCS #9 (1 2 840 113549 1 9)) + 885 31 11: SET { + 887 06 9: OBJECT IDENTIFIER + + + +Hoffman, Ed. Informational [Page 93] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + : } + 898 30 35: SEQUENCE { + 900 06 9: OBJECT IDENTIFIER + : messageDigest (1 2 840 113549 1 9 4) + : (PKCS #9 (1 2 840 113549 1 9)) + 911 31 22: SET { + 913 04 20: OCTET STRING + : 40 6A EC 08 52 79 BA 6E 16 02 2D 9E + : 06 29 C0 22 96 87 DD 48 + : } + : } + 935 30 56: SEQUENCE { + 937 06 3: OBJECT IDENTIFIER '1 2 5555' + 942 31 49: SET { + 944 04 47: OCTET STRING + : 'This is a test General ASN Attribut' + : 'e, number 1.' + : } + : } + 993 30 62: SEQUENCE { + 995 06 11: OBJECT IDENTIFIER + : id-aa-contentHint + : (1 2 840 113549 1 9 16 2 4) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1008 31 47: SET { +1010 30 45: SEQUENCE { +1012 0C 32: UTF8String + : 'Content Hints Description Buffer' +1046 06 9: OBJECT IDENTIFIER + : data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + : } + : } +1057 30 74: SEQUENCE { +1059 06 9: OBJECT IDENTIFIER + : sMIMECapabilities + : (1 2 840 113549 1 9 15) + : (PKCS #9 + : (1 2 840 113549 1 9)) +1070 31 61: SET { +1072 30 59: SEQUENCE { +1074 30 7: SEQUENCE { +1076 06 5: OBJECT IDENTIFIER '1 2 3 4 5 6' + + + +Hoffman, Ed. Informational [Page 94] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } +1083 30 48: SEQUENCE { +1085 06 6: OBJECT IDENTIFIER '1 2 3 4 5 6 77' +1093 04 38: OCTET STRING + : 'Smime Capabilities parameters buffe' + : 'r 2' + : } + : } + : } + : } +1133 30 109: SEQUENCE { +1135 06 11: OBJECT IDENTIFIER + : id-aa-securityLabel + : (1 2 840 113549 1 9 16 2 2) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1148 31 94: SET { +1150 31 92: SET { +1152 02 1: INTEGER 1 +1155 06 7: OBJECT IDENTIFIER '1 2 3 4 5 6 7 8' +1164 13 27: PrintableString + : 'THIS IS A PRIVACY MARK TEST' +1193 31 49: SET { +1195 30 47: SEQUENCE { +1197 80 8: [0] + : 2A 03 04 05 06 07 86 78 +1207 A1 35: [1] { +1209 13 33: PrintableString + : 'THIS IS A TEST SECURITY-' + : 'CATEGORY.' + : } + : } + : } + : } + : } + : } +1244 30 111: SEQUENCE { +1246 06 11: OBJECT IDENTIFIER + : id-aa-contentReference + : (1 2 840 113549 1 9 16 2 10) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1259 31 96: SET { +1261 30 94: SEQUENCE { +1263 06 5: OBJECT IDENTIFIER '1 2 3 4 5 6' +1270 04 43: OCTET STRING + : 'Content Reference Content Identifie' + : 'r Buffer' + + + +Hoffman, Ed. Informational [Page 95] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +1315 04 40: OCTET STRING + : 'Content Reference Signature Value B' + : 'uffer' + : } + : } + : } +1357 30 115: SEQUENCE { +1359 06 11: OBJECT IDENTIFIER + : id-aa-encrypKeyPref + : (1 2 840 113549 1 9 16 2 11) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1372 31 100: SET { +1374 A0 98: [0] { +1376 30 90: SEQUENCE { +1378 31 11: SET { +1380 30 9: SEQUENCE { +1382 06 3: OBJECT IDENTIFIER + : countryName (2 5 4 6) + : (X.520 id-at (2 5 4)) +1387 13 2: PrintableString 'US' + : } + : } +1391 31 22: SET { +1393 30 20: SEQUENCE { +1395 06 3: OBJECT IDENTIFIER + : organizationName (2 5 4 10) + : (X.520 id-at (2 5 4)) +1400 13 13: PrintableString 'US Government' + : } + : } +1415 31 17: SET { +1417 30 15: SEQUENCE { +1419 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1424 13 8: PrintableString 'VDA Site' + : } + : } +1434 31 12: SET { +1436 30 10: SEQUENCE { +1438 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1443 13 3: PrintableString 'VDA' + : } + + + +Hoffman, Ed. Informational [Page 96] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } +1448 31 18: SET { +1450 30 16: SEQUENCE { +1452 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) +1457 13 9: PrintableString 'Daisy RSA' + : } + : } + : } +1468 02 4: INTEGER 173360179 + : } + : } + : } +1474 30 252: SEQUENCE { +1477 06 11: OBJECT IDENTIFIER + : id-aa-mlExpandHistory + : (1 2 840 113549 1 9 16 2 3) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1490 31 236: SET { +1493 30 233: SEQUENCE { +1496 30 230: SEQUENCE { +1499 04 7: OCTET STRING '5738299' +1508 18 15: GeneralizedTime '19990311104433Z' +1525 A1 201: [1] { +1528 30 198: SEQUENCE { +1531 A4 97: [4] { +1533 30 95: SEQUENCE { +1535 31 11: SET { +1537 30 9: SEQUENCE { +1539 06 3: OBJECT IDENTIFIER + : countryName (2 5 4 6) + : (X.520 id-at (2 5 4)) +1544 13 2: PrintableString 'US' + : } + : } +1548 31 22: SET { +1550 30 20: SEQUENCE { +1552 06 3: OBJECT IDENTIFIER + : organizationName + : (2 5 4 10) + : (X.520 id-at (2 5 4)) +1557 13 13: PrintableString + : 'US Government' + : } + : } +1572 31 17: SET { + + + +Hoffman, Ed. Informational [Page 97] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +1574 30 15: SEQUENCE { +1576 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1581 13 8: PrintableString + : 'VDA Site' + : } + : } +1591 31 12: SET { +1593 30 10: SEQUENCE { +1595 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1600 13 3: PrintableString 'VDA' + : } + : } +1605 31 23: SET { +1607 30 21: SEQUENCE { +1609 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) +1614 13 14: PrintableString + : 'Bugs Bunny DSA' + : } + : } + : } + : } +1630 A4 97: [4] { +1632 30 95: SEQUENCE { +1634 31 11: SET { +1636 30 9: SEQUENCE { +1638 06 3: OBJECT IDENTIFIER + : countryName (2 5 4 6) + : (X.520 id-at (2 5 4)) +1643 13 2: PrintableString 'US' + : } + : } +1647 31 22: SET { +1649 30 20: SEQUENCE { +1651 06 3: OBJECT IDENTIFIER + : organizationName + : (2 5 4 10) + : (X.520 id-at (2 5 4)) +1656 13 13: PrintableString + : 'US Government' + : } + + + +Hoffman, Ed. Informational [Page 98] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } +1671 31 17: SET { +1673 30 15: SEQUENCE { +1675 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1680 13 8: PrintableString + : 'VDA Site' + : } + : } +1690 31 12: SET { +1692 30 10: SEQUENCE { +1694 06 3: OBJECT IDENTIFIER + : organizationalUnitName + : (2 5 4 11) + : (X.520 id-at (2 5 4)) +1699 13 3: PrintableString 'VDA' + : } + : } +1704 31 23: SET { +1706 30 21: SEQUENCE { +1708 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) +1713 13 14: PrintableString + : 'Elmer Fudd DSA' + : } + : } + : } + : } + : } + : } + : } + : } + : } + : } +1729 30 258: SEQUENCE { +1733 06 11: OBJECT IDENTIFIER + : id-aa-equivalentLabels + : (1 2 840 113549 1 9 16 2 9) + : (S/MIME Authenticated Attributes + : (1 2 840 113549 1 9 16 2)) +1746 31 242: SET { +1749 30 239: SEQUENCE { +1752 31 114: SET { +1754 02 1: INTEGER 1 +1757 06 7: OBJECT IDENTIFIER '1 2 3 4 5 6 7 9' + + + +Hoffman, Ed. Informational [Page 99] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +1766 13 38: PrintableString + : 'EQUIVALENT THIS IS A PRIVACY MARK T' + : 'EST' +1806 31 60: SET { +1808 30 58: SEQUENCE { +1810 80 8: [0] + : 2A 03 04 05 06 07 86 78 +1820 A1 46: [1] { +1822 13 44: PrintableString + : 'EQUIVALENT THIS IS A TEST SECURITY-' + : 'CATEGORY.' + : } + : } + : } + : } +1868 31 121: SET { +1870 02 1: INTEGER 1 +1873 06 7: OBJECT IDENTIFIER + : '1 2 3 4 5 6 7 10' +1882 13 45: PrintableString + : 'EQUIVALENT THIS IS A SECOND PRIVACY' + : ' MARK TEST' +1929 31 60: SET { +1931 30 58: SEQUENCE { +1933 80 8: [0] + : 2A 03 04 05 06 07 86 78 +1943 A1 46: [1] { +1945 13 44: PrintableString + : 'EQUIVALENT THIS IS A TEST SECURITY-' + : 'CATEGORY.' + : } + : } + : } + : } + : } + : } + : } + : } +1991 30 9: SEQUENCE { +1993 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } +2002 04 47: OCTET STRING, encapsulates { +2004 30 45: SEQUENCE { +2006 02 21: INTEGER + : 00 BC 33 37 65 C4 F7 70 5C 17 49 13 + : AA 4C 85 CA BB 52 91 48 59 + + + +Hoffman, Ed. Informational [Page 100] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +2029 02 20: INTEGER + : 63 96 A2 14 8B CF 57 DE B0 48 5F 6C + : 64 DD 84 04 49 5F 1C CA + : } + : } + : } + : } + : } + : } + : } + +4.11. SignedData with Certificates Only + + CA SignedData message with no content or signature, containing only + Alices's and Carl's certificates. + + 0 30 1672: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2) + : (PKCS #7) + 15 A0 1657: [0] { + 19 30 1653: SEQUENCE { + 23 02 1: INTEGER 1 + 26 31 0: SET {} + 28 30 11: SEQUENCE { + 30 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + : } + 41 A0 1407: [0] { + 45 30 667: SEQUENCE { + 49 30 602: SEQUENCE { + 53 A0 3: [0] { + 55 02 1: INTEGER 2 + : } + 58 02 1: INTEGER 1 + 61 30 9: SEQUENCE { + 63 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 72 30 18: SEQUENCE { + 74 31 16: SET { + 76 30 14: SEQUENCE { + 78 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 83 13 7: PrintableString 'CarlDSS' + : } + : } + + + +Hoffman, Ed. Informational [Page 101] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + 92 30 30: SEQUENCE { + 94 17 13: UTCTime '990816225050Z' + 109 17 13: UTCTime '391231235959Z' + : } + 124 30 18: SEQUENCE { + 126 31 16: SET { + 128 30 14: SEQUENCE { + 130 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 135 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 144 30 439: SEQUENCE { + 148 30 299: SEQUENCE { + 152 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 161 30 286: SEQUENCE { + 165 02 129: INTEGER + : 00 B6 49 18 3E 8A 44 C1 29 71 94 4C + : 01 C4 12 C1 7A 79 CB 54 4D AB 1E 81 + : FB C6 4C B3 0E 94 09 06 EB 01 D4 B1 + : C8 71 4B C7 45 C0 50 25 5D 9C FC DA + : E4 6D D3 E2 86 48 84 82 7D BA 15 95 + : 4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A + : 0A 8A BA 16 7B B9 50 01 48 93 8B EB + : 25 15 51 97 55 DC 8F 53 0E 10 A9 50 + : FC 70 B7 CD 30 54 FD DA DE A8 AA 22 + : B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9 + : AD E1 08 D4 6D 29 2D D6 E9 + 297 02 21: INTEGER + : 00 DD C1 2F DF 53 CE 0B 34 60 77 3E + : 02 A4 BF 8A 5D 98 B9 10 D5 + 320 02 128: INTEGER + : 0C EE 57 9B 4B BD DA B6 07 6A 74 37 + : 4F 55 7F 9D ED BC 61 0D EB 46 59 3C + : 56 0B 2B 5B 0C 91 CE A5 62 52 69 CA + : E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C + : AD CB AE 45 E3 06 AC 8C 22 9D 9C 44 + : 87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE + : AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A + : 73 AA 7F 46 51 1F A9 42 16 9C 48 EB + : 8A 79 61 B4 D5 2F 53 22 44 63 1F 86 + : B8 A3 58 06 25 F8 29 C0 EF BA E0 75 + : F0 42 C4 63 65 52 9B 0A + + + +Hoffman, Ed. Informational [Page 102] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + 451 03 133: BIT STRING 0 unused bits, encapsulates { + 455 02 129: INTEGER + : 00 99 87 74 27 03 66 A0 B1 C0 AD DC + : 2C 75 BB E1 6C 44 9C DA 21 6D 4D 47 + : 6D B1 62 09 E9 D8 AE 1E F2 3A B4 94 + : B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25 + : 4E B9 60 96 19 24 01 F3 62 0C FE 75 + : C0 FB CE D8 68 00 E3 FD D5 70 4F DF + : 23 96 19 06 94 F4 B1 61 8F 3A 57 B1 + : 08 11 A4 0B 26 25 F0 52 76 81 EA 0B + : 62 0D 95 2A E6 86 BA 72 B2 A7 50 83 + : 0B AA 27 CD 1B A9 4D 89 9A D7 8D 18 + : 39 84 3F 8B C5 56 4D 80 7A + : } + : } + 587 A3 66: [3] { + 589 30 64: SEQUENCE { + 591 30 15: SEQUENCE { + 593 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) + 598 01 1: BOOLEAN TRUE + 601 04 5: OCTET STRING, encapsulates { + 603 30 3: SEQUENCE { + 605 01 1: BOOLEAN TRUE + : } + : } + : } + 608 30 14: SEQUENCE { + 610 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) + 615 01 1: BOOLEAN TRUE + 618 04 4: OCTET STRING, encapsulates { + 620 03 2: BIT STRING 1 unused bits + : '1100001'B + : } + : } + 624 30 29: SEQUENCE { + 626 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) + 631 04 22: OCTET STRING, encapsulates { + 633 04 20: OCTET STRING + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + + + +Hoffman, Ed. Informational [Page 103] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + : } + : } + : } + 655 30 9: SEQUENCE { + 657 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 666 03 48: BIT STRING 0 unused bits, encapsulates { + 669 30 45: SEQUENCE { + 671 02 20: INTEGER + : 6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B + : C9 06 37 E9 11 17 A1 13 + 693 02 21: INTEGER + : 00 8F 34 69 2A 8B B1 3C 03 79 94 32 + : 4D 12 1F CE 89 FB 46 B2 3B + : } + : } + : } + 716 30 732: SEQUENCE { + 720 30 667: SEQUENCE { + 724 A0 3: [0] { + 726 02 1: INTEGER 2 + : } + 729 02 2: INTEGER 200 + 733 30 9: SEQUENCE { + 735 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } + 744 30 18: SEQUENCE { + 746 31 16: SET { + 748 30 14: SEQUENCE { + 750 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 755 13 7: PrintableString 'CarlDSS' + : } + : } + : } + 764 30 30: SEQUENCE { + 766 17 13: UTCTime '990817011049Z' + 781 17 13: UTCTime '391231235959Z' + : } + 796 30 19: SEQUENCE { + 798 31 17: SET { + + + +Hoffman, Ed. Informational [Page 104] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 800 30 15: SEQUENCE { + 802 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 807 13 8: PrintableString 'AliceDSS' + : } + : } + : } + 817 30 438: SEQUENCE { + 821 30 299: SEQUENCE { + 825 06 7: OBJECT IDENTIFIER + : dsa (1 2 840 10040 4 1) + : (ANSI X9.57 algorithm) + 834 30 286: SEQUENCE { + 838 02 129: INTEGER + : 00 81 8D CD ED 83 EA 0A 9E 39 3E C2 + : 48 28 A3 E4 47 93 DD 0E D7 A8 0E EC + : 53 C5 AB 84 08 4F FF 94 E1 73 48 7E + : 0C D6 F3 44 48 D1 FE 9F AF A4 A1 89 + : 2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C + : DC 5F 69 8A E4 75 D0 37 0C 91 08 95 + : 9B DE A7 5E F9 FC F4 9F 2F DD 43 A8 + : 8B 54 F1 3F B0 07 08 47 4D 5D 88 C3 + : C3 B5 B3 E3 55 08 75 D5 39 76 10 C4 + : 78 BD FF 9D B0 84 97 37 F2 E4 51 1B + : B5 E4 09 96 5C F3 7E 5B DB + 970 02 21: INTEGER + : 00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F + : B8 37 21 2B 62 8B F7 93 CD + 993 02 128: INTEGER + : 26 38 D0 14 89 32 AA 39 FB 3E 6D D9 + : 4B 59 6A 4C 76 23 39 04 02 35 5C F2 + : CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD + : AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF + : 7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B + : 3E 90 F8 6D EA 9C C9 21 8A 3B 76 14 + : E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30 + : 01 7C 6D 49 89 11 89 36 44 BD F8 C8 + : 95 4A 53 56 B5 E2 F9 73 EC 1A 61 36 + : 1F 11 7F C2 BD ED D1 50 FF 98 74 C2 + : D1 81 4A 60 39 BA 36 39 + : } + : } +1124 03 132: BIT STRING 0 unused bits, encapsulates { +1128 02 128: INTEGER + : 5C E3 B9 5A 75 14 96 0B A9 7A DD E3 + : 3F A9 EC AC 5E DC BD B7 13 11 34 A6 + : 16 89 28 11 23 D9 34 86 67 75 75 13 + + + +Hoffman, Ed. Informational [Page 105] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 12 3D 43 5B 6F E5 51 BF FA 89 F2 A2 + : 1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45 + : A5 A0 4A E3 85 D6 CE 06 80 3F E8 23 + : 7E 1A F2 24 AB 53 1A B8 27 0D 1E EF + : 08 BF 66 14 80 5C 62 AC 65 FA 15 8B + : F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4 + : 32 84 F0 7E 41 40 FD 46 A7 63 4E 33 + : F2 A5 E2 F4 F2 83 E5 B8 + : } + : } +1259 A3 129: [3] { +1262 30 127: SEQUENCE { +1264 30 12: SEQUENCE { +1266 06 3: OBJECT IDENTIFIER + : basicConstraints (2 5 29 19) + : (X.509 id-ce (2 5 29)) +1271 01 1: BOOLEAN TRUE +1274 04 2: OCTET STRING, encapsulates { +1276 30 0: SEQUENCE {} + : } + : } +1278 30 14: SEQUENCE { +1280 06 3: OBJECT IDENTIFIER + : keyUsage (2 5 29 15) + : (X.509 id-ce (2 5 29)) +1285 01 1: BOOLEAN TRUE +1288 04 4: OCTET STRING, encapsulates { +1290 03 2: BIT STRING 6 unused bits + : '11'B + : } + : } +1294 30 31: SEQUENCE { +1296 06 3: OBJECT IDENTIFIER + : authorityKeyIdentifier (2 5 29 35) + : (X.509 id-ce (2 5 29)) +1301 04 24: OCTET STRING, encapsulates { +1303 30 22: SEQUENCE { +1305 80 20: [0] + : 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3 + : 3D 20 BC 43 2B 93 F1 1F + : } + : } + : } +1327 30 29: SEQUENCE { +1329 06 3: OBJECT IDENTIFIER + : subjectKeyIdentifier (2 5 29 14) + : (X.509 id-ce (2 5 29)) +1334 04 22: OCTET STRING, encapsulates { + + + +Hoffman, Ed. Informational [Page 106] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +1336 04 20: OCTET STRING + : BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE + : 13 01 E2 FD E3 97 FE CD + : } + : } +1358 30 31: SEQUENCE { +1360 06 3: OBJECT IDENTIFIER + : subjectAltName (2 5 29 17) + : (X.509 id-ce (2 5 29)) +1365 04 24: OCTET STRING, encapsulates { +1367 30 22: SEQUENCE { +1369 81 20: [1] 'AliceDSS@example.com' + : } + : } + : } + : } + : } + : } +1391 30 9: SEQUENCE { +1393 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } +1402 03 48: BIT STRING 0 unused bits, encapsulates { +1405 30 45: SEQUENCE { +1407 02 20: INTEGER + : 55 0C A4 19 1F 42 2B 89 71 22 33 8D + : 83 6A B5 3D 67 6B BF 45 +1429 02 21: INTEGER + : 00 9F 61 53 52 54 0B 5C B2 DD DA E7 + : 76 1D E2 10 52 5B 43 5E BD + : } + : } + : } + : } +1452 A1 219: [1] { +1455 30 216: SEQUENCE { +1458 30 153: SEQUENCE { +1461 30 9: SEQUENCE { +1463 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } +1472 30 18: SEQUENCE { +1474 31 16: SET { +1476 30 14: SEQUENCE { +1478 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + + + +Hoffman, Ed. Informational [Page 107] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : (X.520 id-at (2 5 4)) +1483 13 7: PrintableString 'CarlDSS' + : } + : } + : } +1492 17 13: UTCTime '990827070000Z' +1507 30 105: SEQUENCE { +1509 30 19: SEQUENCE { +1511 02 2: INTEGER 200 +1515 17 13: UTCTime '990822070000Z' + : } +1530 30 19: SEQUENCE { +1532 02 2: INTEGER 201 +1536 17 13: UTCTime '990822070000Z' + : } +1551 30 19: SEQUENCE { +1553 02 2: INTEGER 211 +1557 17 13: UTCTime '990822070000Z' + : } +1572 30 19: SEQUENCE { +1574 02 2: INTEGER 210 +1578 17 13: UTCTime '990822070000Z' + : } +1593 30 19: SEQUENCE { +1595 02 2: INTEGER 212 +1599 17 13: UTCTime '990824070000Z' + : } + : } + : } +1614 30 9: SEQUENCE { +1616 06 7: OBJECT IDENTIFIER + : dsaWithSha1 (1 2 840 10040 4 3) + : (ANSI X9.57 algorithm) + : } +1625 03 47: BIT STRING 0 unused bits, encapsulates { +1628 30 44: SEQUENCE { +1630 02 20: INTEGER + : 7E 65 52 76 33 FE 34 73 17 D1 F7 96 + : F9 A0 D4 D8 6D 5C 7D 3D +1652 02 20: INTEGER + : 02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E + : DA 24 F3 2A 83 9C 35 A1 + : } + : } + : } + : } +1674 31 0: SET {} + : } + + + +Hoffman, Ed. Informational [Page 108] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : } + : } + +5. Enveloped-data + +5.1. Basic Encrypted Content, TripleDES and RSA + + An EnvelopedData from Alice to Bob of ExContent using TripleDES for + encrypting and RSA for key management. Does not have an + OriginatorInfo. + + 0 30 286: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER + : envelopedData (1 2 840 113549 1 7 3) + : (PKCS #7) + 15 A0 271: [0] { + 19 30 267: SEQUENCE { + 23 02 1: INTEGER 0 + 26 31 192: SET { + 29 30 189: SEQUENCE { + 32 02 1: INTEGER 0 + 35 30 38: SEQUENCE { + 37 30 18: SEQUENCE { + 39 31 16: SET { + 41 30 14: SEQUENCE { + 43 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 48 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 57 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : CD 5D 71 D0 + : } + 75 30 13: SEQUENCE { + 77 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 88 05 0: NULL + : } + 90 04 128: OCTET STRING + : 0B 71 0D E6 71 88 88 98 B6 96 C1 8F + : 70 FD A2 27 DE DA E1 EF 24 6C A4 33 + : DF AC E0 E9 9D A2 D3 2C 7A CD 80 B8 + : 99 9E E6 5F B1 41 B3 72 16 83 E7 FA + : 2A 00 8B C7 73 35 78 26 D6 C7 CF 8C + + + +Hoffman, Ed. Informational [Page 109] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 0C 56 DB A5 76 9D 08 38 0E F3 F9 D4 + : 91 43 58 78 DC 49 B6 EC EE 6C 68 33 + : A3 21 1D F0 28 78 1F F7 5D F6 07 73 + : 4D DF AD 69 31 20 4B 48 A9 75 22 6E + : 36 79 15 63 8F CC EB 9D A3 28 A1 D1 + : 2C 57 F4 DA 1A 2C 75 1F + : } + : } + 221 30 67: SEQUENCE { + 223 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 234 30 20: SEQUENCE { + 236 06 8: OBJECT IDENTIFIER + : des-EDE3-CBC (1 2 840 113549 3 7) + : (RSADSI encryptionAlgorithm + : (1 2 840 113549 3)) + 246 04 8: OCTET STRING + : 2D 68 C5 E9 47 06 51 35 + : } + 256 80 32: [0] + : 0E C8 92 7F C6 7D 3F 8D CB AD 8E 0E + : C5 49 3A EB 47 2E D6 55 DE 09 21 4E + : 48 EA 4E 27 B1 6E 57 25 + : } + : } + : } + : } + +5.2. Basic Encrypted Content, RC2/128 and RSA + + Same as 5.1, except using RC2/128 for encryption and RSA for key + management. An EnvelopedData from Alice to Bob of ExContent using + RC2/40 for encrypting and RSA for key management. Does not have an + OriginatorInfo or any attributes. + + 0 30 291: SEQUENCE { + 4 06 9: OBJECT IDENTIFIER + : envelopedData (1 2 840 113549 1 7 3) + : (PKCS #7) + 15 A0 276: [0] { + 19 30 272: SEQUENCE { + 23 02 1: INTEGER 0 + 26 31 192: SET { + 29 30 189: SEQUENCE { + 32 02 1: INTEGER 0 + 35 30 38: SEQUENCE { + 37 30 18: SEQUENCE { + 39 31 16: SET { + + + +Hoffman, Ed. Informational [Page 110] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 41 30 14: SEQUENCE { + 43 06 3: OBJECT IDENTIFIER + : commonName (2 5 4 3) + : (X.520 id-at (2 5 4)) + 48 13 7: PrintableString 'CarlRSA' + : } + : } + : } + 57 02 16: INTEGER + : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E + : CD 5D 71 D0 + : } + 75 30 13: SEQUENCE { + 77 06 9: OBJECT IDENTIFIER + : rsaEncryption (1 2 840 113549 1 1 1) + : (PKCS #1) + 88 05 0: NULL + : } + 90 04 128: OCTET STRING + : 85 42 BE E3 0B 2E E5 0F 09 AA 24 CA + : DE DA C1 D3 09 B8 27 2B 25 CB D5 71 + : FB C9 9C DB F0 B2 6E A0 8A 5F 1C 9D + : 4A ED 98 9D 15 39 26 01 1A 2E 6B F0 + : 44 39 89 37 3C 6F C7 4A 61 0B 0B 27 + : 77 AA F9 D4 97 A4 D2 21 3F C2 3F 20 + : D4 DC 10 E9 D6 3F 00 DB 9C 82 47 D6 + : 7E 96 FF 12 6E 87 84 A0 BA ED 81 0F + : 56 6D A6 1D EB AB C3 B7 A1 B9 F8 5F + : 8B CC 1B 4A E5 14 36 06 61 D0 C7 64 + : 5F 69 67 91 A9 50 EE D8 + : } + : } + 221 30 72: SEQUENCE { + 223 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 234 30 25: SEQUENCE { + 236 06 8: OBJECT IDENTIFIER rc2CBC (1 2 840 113549 3 2) + : (RSADSI encryptionAlgorithm + : (1 2 840 113549 3)) + 246 30 13: SEQUENCE { + 248 02 1: INTEGER 58 + 251 04 8: OCTET STRING + : E8 70 81 E2 EF C5 15 57 + : } + : } + 261 80 32: [0] + : 06 53 0A 7B 8D 5C 16 0D CC D5 76 D6 + : 8B 59 D6 45 8C 1A 1A 0C E6 1E F3 DE + + + +Hoffman, Ed. Informational [Page 111] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + : 43 56 00 9B 40 8C 38 5D + : } + : } + : } + : } + +5.3. S/MIME application/pkcs7-mime Encrypted Message + + A full S/MIME message, including MIME, that includes the body part + from 5.1. + +MIME-Version: 1.0 +Message-Id: <00103112005203.00349@amyemily.ig.com> +Date: Tue, 31 Oct 2000 12:00:52 -0600 (Central Standard Time) +From: User1 +To: User2 +Subject: Example 5.3 +Content-Type: application/pkcs7-mime; + name=smime.p7m; + smime-type=enveloped-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m + +MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYXJ +sUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGPcP +2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadC +DgO8/nUkUNYeNxJtuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHR +LFf02hosdR8wQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43 +LrY4OxUk660cu1lXeCSFOSOpOJ7FuVyU= + +6. Digested-data + + A DigestedData from Alice to Bob of ExContent using SHA-1. + + 0 30 94: SEQUENCE { + 2 06 9: OBJECT IDENTIFIER digestedData (1 2 840 113549 1 7 5) + : (PKCS #7) + 13 A0 81: [0] { + 15 30 79: SEQUENCE { + 17 02 1: INTEGER 0 + 20 30 7: SEQUENCE { + 22 06 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + : (OIW) + : } + 29 30 43: SEQUENCE { + 31 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 42 A0 30: [0] { + + + +Hoffman, Ed. Informational [Page 112] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + 44 04 28: OCTET STRING 'This is some sample content.' + : } + : } + 74 04 20: OCTET STRING + : 40 6A EC 08 52 79 BA 6E 16 02 2D 9E + : 06 29 C0 22 96 87 DD 48 + : } + : } + : } + +7. Encrypted-data + +7.1. Simple EncryptedData + + An EncryptedData from Alice to Bob of ExContent with no attributes. + + 0 30 87: SEQUENCE { + 2 06 9: OBJECT IDENTIFIER + : encryptedData (1 2 840 113549 1 7 6) + : (PKCS #7) + 13 A0 74: [0] { + 15 30 72: SEQUENCE { + 17 02 1: INTEGER 0 + 20 30 67: SEQUENCE { + 22 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 33 30 20: SEQUENCE { + 35 06 8: OBJECT IDENTIFIER + : des-EDE3-CBC (1 2 840 113549 3 7) + : (RSADSI encryptionAlgorithm + : (1 2 840 113549 3)) + 45 04 8: OCTET STRING + : B3 6B 6B FB 62 31 08 4E + : } + 55 80 32: [0] + : FA FC ED DB 3F 18 17 1D 38 89 11 EA + : 34 D6 20 DB F4 C3 D9 58 15 EF 93 3B + : 9A F5 D7 04 F6 B5 70 E2 + : } + : } + : } + : } + + The TripleDES key is: + + 73 7c 79 1f 25 ea d0 e0 46 29 25 43 52 f7 dc 62 + 91 e5 cb 26 91 7a da 32 + + + + +Hoffman, Ed. Informational [Page 113] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +7.2. EncryptedData with Unprotected Attributes + + An EncryptedData from Alice to Bob of ExContent with unprotected + attributes. + + 0 30 149: SEQUENCE { + 3 06 9: OBJECT IDENTIFIER + : encryptedData (1 2 840 113549 1 7 6) + : (PKCS #7) + 14 A0 135: [0] { + 17 30 132: SEQUENCE { + 20 02 1: INTEGER 2 + 23 30 67: SEQUENCE { + 25 06 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) + : (PKCS #7) + 36 30 20: SEQUENCE { + 38 06 8: OBJECT IDENTIFIER + : des-EDE3-CBC (1 2 840 113549 3 7) + : (RSADSI encryptionAlgorithm + : (1 2 840 113549 3)) + 48 04 8: OCTET STRING + : 07 27 20 85 90 9E B0 7E + : } + 58 80 32: [0] + : D2 20 8F 67 48 8A CB 41 E4 22 68 5D + : BE 77 05 52 26 ED E3 01 BD 00 91 58 + : A7 35 6E BC 4B A2 07 33 + : } + 92 A1 58: [1] { + 94 30 56: SEQUENCE { + 96 06 3: OBJECT IDENTIFIER '1 2 5555' + 101 31 49: SET { + 103 04 47: OCTET STRING + : 'This is a test General ASN Attribut' + : 'e, number 1.' + : } + : } + : } + : } + : } + : } + + + + + + + + + + +Hoffman, Ed. Informational [Page 114] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +8. Security Considerations + + Because this document shows examples of S/MIME and CMS messages, this + document also inherits all of the security considerations from + [SMIME-MSG] and [CMS]. + + The Perl script in Appendix A writes to the user's local hard drive. + A malicious attacker could modify the Perl script in this document. + Be sure to read the Perl code carefully before executing it. + +9. References + +9.1. Normative References + + [CMS] Housley, R., "Cryptographic Message Syntax (CMS)", RFC + 3852, July 2004. + + [PKIX] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet + X.509 Public Key Infrastructure Certificate and + Certificate Revocation List (CRL) Profile", RFC 3280, + April 2002. + + [SMIME-MSG] Ramsdell, B., "Secure/Multipurpose Internet Mail + Extensions (S/MIME) Version 3.1 Message Specification", + RFC 3851, July 2004. + +9.2. Informative References + + [DVCS] Adams, C., Sylvester, P., Zolotarev, M., and R. + Zuccherato, "Internet X.509 Public Key Infrastructure + Data Validation and Certification Server Protocols", RFC + 3029, February 2001. + + + + + + + + + + + + + + + + + + + +Hoffman, Ed. Informational [Page 115] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +A. Binaries of the Examples + + This section contains the binaries of the examples shown in the rest + of the document. The binaries are stored in a modified Base64 + format. There is a Perl program that, when run over the contents of + this document, will extract the following binaries and write them out + to disk. The program requires Perl. + +A.1. How the Binaries and Extractor Works + + The program in the next section looks for lines that begin with a '|' + character (or some whitespace followed by a '|'), ignoring all other + lines. If the line begins with '|', the second character tells what + kind of line it is: + + A line that begins with |* is a comment + A line that begins with |> gives the name of a new file to start + A line that begins with |< tells to end the file (and checks the + file name for sanity) + A line that begins with |anythingelse is a Base64 line + + The program writes out a series of files, so you should run this in + an empty directory. The program will overwrite files (if it can), + but won't delete other files already in the directory. + + Run this program with this document as the standard input, such as: + + ./extractsample.pl " and "|<" markers, remove any page breaks, and remove + the "|" in the first column of each line. The result is a valid + Base64 blob that can be processed by any Base64 decoder. + +A.2. Example Extraction Program + +#!/usr/bin/perl + +# CMS Samples extraction program. v 1.1 + +# Get all the input as an array of lines +@AllIn = (); while () { push(@AllIn, $_) } + +$Base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr' . + 'stuvwxyz0123456789+/='; +$LineCount = 0; $CurrFile = ''; + +foreach $Line (@AllIn) { + + + +Hoffman, Ed. Informational [Page 116] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + $LineCount++; # Keep the line counter for error messages + $Line =~ s/^\s*//; # Get rid of leading whitespace + chomp($Line); # Get rid of CR or CRLF at the end of the line + if(substr($Line, 0, 1) ne '|') { next } # Not a special line + elsif(substr($Line, 1, 1) eq '*') { next } # It is a comment + elsif(substr($Line, 1, 1) eq '>') + { &StartNewFile(substr($Line, 2)) } # Start a new file + elsif(substr($Line, 1, 1) eq '<') + { &EndCurrFile(substr($Line, 2)) } # End the current file + else { &DoBase64(substr($Line, 1)) } # It is a line of Base64 +} + +sub StartNewFile { + $TheNewFile = shift(@_); + if($CurrFile ne '') { die "Was about to start a new file at " . + "line $LineCount, but the old file, $CurrFile, was open\n" } + open(OUT, ">$TheNewFile") or + die "Could not open $TheNewFile for writing: $!\n"; + binmode(OUT); # This is needed for Windows, is a noop on Unix + $CurrFile = $TheNewFile; + $LeftOver = 0; # Amount left from previous Base64 character + $NextPos = 0; # Bit position to start the next Base64 character + # (bits are numbered 01234567) + $OutString = ''; # Holds the text going out to the file +} + +sub EndCurrFile { + $FileToEnd = shift(@_); + if($CurrFile ne $FileToEnd) { die "Was about to close " . + "$FileToEnd at line $LineCount, but that name didn't match " . + "the name of the currently open file, $CurrFile\n" } + print OUT $OutString; + close(OUT); + $CurrFile = ''; +} + +sub DoBase64 { + $TheIn = shift(@_); + if($CurrFile eq '') { die "Got some Base64 at line $LineCount, " . + "but appear to not be writing to any particular file.\n" } + @Chars = split(//, $TheIn); # Make an array of the characters + foreach $ThisChar (@Chars) { + # $ThisVal is the position in the string and the Base64 value + $ThisVal = index($Base64Chars, $ThisChar); + if($ThisVal == -1) { die "At line $LineCount, found the " . + "character $ThisChar, which is not a Base64 character\n" } + if($ThisVal == 64) { last } # It is a "=", so we're done + if ($NextPos == 0 ) { + + + +Hoffman, Ed. Informational [Page 117] + +RFC 4134 Examples of S/MIME Messages July 2005 + + + # Don't output anything, just fill the left of $LeftOver + $LeftOver = $ThisVal * 4; + $NextPos = 6; + } elsif ($NextPos == 2) { + # Add $ThisVal to $LeftOver, output, and reset + $OutString .= chr($LeftOver + $ThisVal); + $LeftOver = 0; + $NextPos = 0; + } elsif ($NextPos == 4) { + # Add upper 4 bits of $ThisVal to $LeftOver and output + $Upper4 = ($ThisVal & 60); + $OutString .= chr($LeftOver + ($Upper4/4)); + $LeftOver = (($ThisVal - $Upper4) * 64); + $NextPos = 2; + } elsif ($NextPos == 6) { + # Add upper 2 bits of $ThisVal to $LeftOver and output + $Upper2 = ($ThisVal & 48); + $OutString .= chr($LeftOver + ($Upper2/16)); + $LeftOver = (($ThisVal - $Upper2) * 16); + $NextPos = 4; + } else { die "\$NextPos has an illegal value: $NextPos." } + } +} + +B. Examples in Order of Appearance + +From Section 2.1 + +***ExContent.bin*** + +|* Section 2.1 +|>ExContent.bin +|VGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50Lg== +|AlicePrivDSSSign.pri +|MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAIGNze2D6gqeOT7CSCij5EeT3Q7XqA7sU8 +|WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg23j+bv7dM3F9piuR10DcMkQiVm96nXvn8 +|9J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dhDEeL3/nbCElzfy5FEbteQJllzzflvbAh +|UA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUiTKqOfs+bdlLWWpMdiM5BAI1XPLLGjDD +|HlBd3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oIXks+kPht6pzJIYo7dhTpzi5dowfNI4 +|W4LzABfG1JiRGJNkS9+MiVSlNWteL5c+waYTYfEX/Cve3RUP+YdMLRgUpgObo2OQQXAhUA +|u0RG0aXJRgcu0P561pIH8JqFiT8= + + + +Hoffman, Ed. Informational [Page 118] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|AlicePrivRSASign.pri +|MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOCJczmN2PX16Id2OX9OsA +|W7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H +|2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE +|7zVzhXdFdfAgMBAAECgYAApAPDJ0d2NDRspoa1eUkBSy6K0shissfXSAlqi5H3NvJ11ujN +|FZBgJzFHNWRNlc1nY860n1asLzduHO4Ovygt9DmQbzTYbghb1WVq2EHzE9ctOV7+M8v/Ke +|QDCz0Foo+38Y6idjeweVfTLyvehwYifQRmXskbr4saw+yRRKt/IQJBAPbW4CIhTF8KcP8n +|/OWzUGqd5Q+1hZbGQPqoCrSbmwxVwgEd+TeCihTI8pMOks2lZiG5PNIGv7RVMcncrcqYLd +|ECQQDo3rARJQnSAlEB3oromFD1d3dhpEWTawhVlnNd9MhbEpMic4t/03B/9aSqu3T9PCJq +|2jiRKoZbbBTorkye+o4vAkEAl0zwh5sXf+4bgxsUtgtqkF+GJ1Hht6B/9eSI41m5+R6b0y +|l3OCJI1yKxJZi6PVlTt/oeILLIURYjdZNR56vN8QJALPAkW/qgzYUi6tBuT/pszSHTyOTx +|hERIZHPXKY9+RozsFd7kUbOU5yyZLVVleyTqo2IfPmxNZ0ERO+G+6YMCgwJAWIjZoVA4hG +|qrA7y730v0nG+4tCol+/bkBS9u4oiJIW9LJZ7Qq1CTyr9AcewhJcV/+wLpIZa4M83ixpXu +|b41fKA== +|BobPrivRSAEncrypt.pri +|MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf8qCTQV6meY +|mFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmRuBlpN235ZR572akzJKN/ +|O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtdYMTgXB9T039T2GkB8QX4enDRvoPGXz +|jPHCyqaqfrAgMBAAECgYBnzUhMmg2PmMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngw +|y+e6alatd8brUXlweQqg9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A +|0HPfD6bRSeTmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N +|vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiEI2Kv8zHCue +|UCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr84/sajB0+E0R9KfEILVH +|IdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5qSO8bKlocSHseIVnDYDubl6nA7xhmqU +|5iUjiEzuUJiEiUacUgFJlaV/4jbOSnI3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVf +|JAZAcpw6iIWchw+dYhKIFmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grSta +|vCunrnVNqcBU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8 +|Y0ZB9qANMAsGA1UdDzEEAwIAEA== +|CarlPrivDSSSign.pri +|MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8 +|ZMsw6UCQbrAdSxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5 +|UAFIk4vrJRVRl1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAh +|UA3cEv31POCzRgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytb + + + +Hoffman, Ed. Informational [Page 119] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|DJHOpWJSacrhbT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0 +|R5NVpzqn9GUR+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgQWAhQZ +|szilIWIxUOV/uT4IRnjRPrXlcg== +|CarlPrivRSASign.pri +|MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAORL/xi4JFf0d/9uc3uTcV +|y8MxqSknIj2EFG0M0ROgSzjq+Cnb1RHhd68nYsK4Y5p73XjRpT7OQA1ejsojax7eJQ4jIJ +|ij+fmSWPuE6ruX3VlmXaFqDFvg6uRFvvXvSnKcuC3axE6aqTlCkO+BjWyFde8nbE8hFgOL +|kbPB2XyWrxAgMBAAECgYEArnPkW19bZlrJ18bvOF9TISovYv7eKZp6hmc2531ieHU9c6C8 +|KQ7zj73Dycm2+LrWE5vDl3rKavC4hWVOD72nqPdUBkG969wgd5DfYZuab3Te6jvUnIdg7X +|aE8WowN9XgkBb4gEfDGWvtdXe6Su05tl0CRztfG8gcq8vo9SY/pIECQQD/3wmgVgtCUp7E +|TZOzsEm73ueBfSiZ0LFIugs54Rx7IhgztkD2v9yuHdChrQRxWmEKbjvOMNo2n2UlKbunDn +|8LAkEA5GloGF/5V9B8ZokPumMdcssgpIF2ZInNfdHCJ6kurHpWmoUH2TADowOrf4iSUCQB +|qhsHHyBMt8l7Vve2wn6rcwJAVzZsj4wEdmy21O4kRAD4gOKvQgGpDxSE+OcA4I+MJ6QtX6 +|LlbbVjwK1E6XaRpxlJLkb4d4VLO4cE8K/S2FQmlQJAZKEPrFV0G70NYXsXA82w5qcZHYCv +|8UFI2Bq2iBSgLHrFdtQPDh96KrJuNwSrOUVzukaoD42CXyIUBc+io/N8gwJAJh4dHKGYK+ +|TbOOhXbmtzGYhhOvp0SjaLR2hdUOsm4+p9m05lqa97q0sudlE9qNARq6PWqMAnNh1UC6qn +|0W2N+g== +|DianePrivDSSSign.pri +|MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8 +|ZMsw6UCQbrAdSxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5 +|UAFIk4vrJRVRl1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAh +|UA3cEv31POCzRgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytb +|DJHOpWJSacrhbT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0 +|R5NVpzqn9GUR+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgQXAhUA +|lpX54MHgQS0yD4tCUpMq5h4OISk= +|DianePrivRSASignEncrypt.pri +|MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANb9uMBwxkwl7OrP6ny7om +|L68OYyOlP/sZJaF/Qg4ZkkggrQ9nz7RMqLJwbxfiYDqXadz+ygLHCW8oNC9tS3KAq7+L9K +|TBk/B9ugwWAet35n996xw2BJrEXX+MbvCDchk0fu8HM1crACxPMRw15H5Qq3g/HbdGlki0 +|QdlV3NKMCFAgMBAAECgYA9vc3CDmEUW0vnv2AjBCvFazWllkUj/Gl9kzwP0yWWumJSQuKW +|z/5YgI/rsYy91A1l0Dp3RSSeDOuGgMOsIRFxROOyqKkurBfSo4QlY7W8Lx7d9iH/FSAkW/ +|GAL9VBDjIk99RKMp65SdgZjj85jWK9gPwMJJKT5MPXBZFTu5a2QQJBAPO4P0rRlLCRYBNB +|kg2NRD93Hf+WI0QI1AtwyRqv6ZCU8rDVX08ZhVChkJGuvQV2UrMi2Kh8jlR/AHJPNnVoc7 + + + +Hoffman, Ed. Informational [Page 120] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|UCQQDh0ucRVwaucpUiFqoCtFrtTp2CEU+WPIbJEI1WezF1eWnndWg4AEsu0iYy3bHi4CxU +|gAp1utFmlhuwDqB+0ruRAkEAr7a82yJzQ0HstLVnqaGZ/O/Sjv0d++Upi/4K39TIXlclCl +|0r1AmgVlvFsWL8IL4ILeMHtaHns//EwKVfrBJcqQJBALmYQfwIUB9zYIoBonxSiiBa6iyJ +|2aUZ3ZTGG8MlwIJR5O4rmhncc+3pHSfU+GwD3asdCHu1rH/pgpvxiYpx22ECQAEHIZdfem +|Co/VpcB9+o3vfisTR9/OuRvbBzdMjEvj9YRTAGkLOsacyz9z98rMe4G2WhFjk5sON0fc/N +|xaxsv+U= +|AliceDSSSignByCarlNoInherit.cer +|MIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT +|k5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2 +|MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lO +|FzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iL +|VPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRW +|a4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1ni +|zaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8bU +|mJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuVp1 +|FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41bY8 +|i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxDKE +|8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBs +|AwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfft +|Q3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM +|44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0Ne +|vQ== +|AliceRSASignByCarl.cer +|MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUFADASMRAwDg +|YDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1OVowEzERMA8G +|A1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJczmN2PX16I +|d2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvY +|Ms/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mX +|cCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG +|wDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUd9K00bdMio +|qjzkWdzuw8oDrj/1AwHwYDVR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb20wDQYJKoZI +|hvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzPbrMcWakgqg +|WBqE4lradwFHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2Tt0z3Sp0LF +|6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCI= +|BobRSASignByCarl.cer +|MIICJzCCAZCgAwIBAgIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQUFADASMRAwDg +|YDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDkwMloXDTM5MTIzMTIzNTk1OVowETEPMA0G +|A1UEAxMGQm9iUlNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp4WeYPznVX/Kgk0 +|FepnmJhcg1XZqRW/sdAdoZcCYXD72lItA1hW16mGYUQVzPt7cIOwnJkbgZaTdt+WUee9mp +|MySjfzu7r0YBhjY0MssHA1lS/IWLMQS4zBgIFEjmTxz7XWDE4FwfU9N/U9hpAfEF+Hpw0b +|6Dxl84zxwsqmqn6wIDAQABo38wfTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFIDAf +|BgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQU6PS4Z9izlqQq8x +|GqKdOVWoYWtCQwHQYDVR0RBBYwFIESQm9iUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEB +|BQUAA4GBAHuOZsXxED8QIEyIcat7QGshM/pKld6dDltrlCEFwPLhfirNnJOIh/uLt359QW +|Hh5NZt+eIEVWFFvGQnRMChvVl52R1kPCHWRbBdaDOS6qzxV+WBfZjmNZGjOd539OgcOync +|f1EHl/M28FAK3Zvetl44ESv7V+qJba3JiNiPzyvT +|CarlDSSSelf.cer +|MIICmzCCAlqgAwIBAgIBATAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOT +|kwODE2MjI1MDUwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdDYXJsRFNTMIIBtzCC +|ASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8ZMsw6UCQbrAd +|SxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5UAFIk4vrJRVR +|l1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAhUA3cEv31POCz +|Rgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytbDJHOpWJSacrh +|bT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0R5NVpzqn9GUR +|+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgOBhQACgYEAmYd0JwNm +|oLHArdwsdbvhbESc2iFtTUdtsWIJ6diuHvI6tJSxo456m3FOAJTJtCVOuWCWGSQB82IM/n +|XA+87YaADj/dVwT98jlhkGlPSxYY86V7EIEaQLJiXwUnaB6gtiDZUq5oa6crKnUIMLqifN +|G6lNiZrXjRg5hD+LxVZNgHqjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAg +|GGMB0GA1UdDgQWBBRwRD6CLm+H3krTdeM9ILxDK5PxHzAJBgcqhkjOOAQDAzAAMC0CFGup +|8E56Wnnj+b49K8kGN+kRF6ETAhUAjzRpKouxPAN5lDJNEh/OiftGsjs= +|CarlRSASelf.cer +|MIIB6zCCAVSgAwIBAgIQRjRrx4AAVrwR024un/JQIDANBgkqhkiG9w0BAQUFADASMRAwDg +|YDVQQDEwdDYXJsUlNBMB4XDTk5MDgxODA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEjEQMA4G +|A1UEAxMHQ2FybFJTQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Ev/GLgkV/R3/2 +|5ze5NxXLwzGpKSciPYQUbQzRE6BLOOr4KdvVEeF3rydiwrhjmnvdeNGlPs5ADV6OyiNrHt +|4lDiMgmKP5+ZJY+4Tqu5fdWWZdoWoMW+Dq5EW+9e9Kcpy4LdrETpqpOUKQ74GNbIV17yds +|TyEWA4uRs8HZfJavECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +|AYYwHQYDVR0OBBYEFOngkCeseCB6mtNM8kI3TiKunji7MA0GCSqGSIb3DQEBBQUAA4GBAL +|ee1ATT7Snk/4mJFS5M2wzwSA8yYe7EBOwSXS3/D2RZfgrD7Rj941ZAN6cHtfA4EmFQ7e/d + + + +Hoffman, Ed. Informational [Page 122] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|P+MLuGGlpJs85p6cVJq2ldbabDu1LUU1nUkBdvq5uTH5+WsSU6D1FGCbfco+8lNrsDdvre +|Z019v6WuoUQWNdzb7IDsHaao1TNBgC +|DianeDSSSignByCarlInherit.cer +|MIIBuDCCAXegAwIBAgICANIwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT +|k5MDgxNzAyMDgxMFoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIRGlhbmVEU1MwgZMw +|CQYHKoZIzjgEAQOBhQACgYEAoAAXeCzufoFTLi5hCA+hm1FSGtpZqHMvEiW2CMvK7ypEdo +|pSCeq9BSLVD/b9RtevmTgJDhPLTyzdHDT3HL8l/yPTO1nngpc3vjEk2BjI80k5W7fi5Sd+ +|/IxFclt+Po9oTd1GeiK+jv/M2jkpoznln0PpVcnXW6aBZ8zAqs0uxSOjgYEwfzAMBgNVHR +|MBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm+H3krTdeM9ILxD +|K5PxHzAdBgNVHQ4EFgQUZDCZfVzcRQuZOlIvFr9YUN3OKxgwHwYDVR0RBBgwFoEURGlhbm +|VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhUAoRr4Fw4+XaiM9LZVMx5L4yys +|uV8CFChLEEVY0hydVTUUGJGyPznftW7T +|DianeRSASignByCarl.cer +|MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024u1ZowkDANBgkqhkiG9w0BAQUFADASMRAwDg +|YDVQQDEwdDYXJsUlNBMB4XDTk5MDgxOTA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEzERMA8G +|A1UEAxMIRGlhbmVSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANb9uMBwxkwl7O +|rP6ny7omL68OYyOlP/sZJaF/Qg4ZkkggrQ9nz7RMqLJwbxfiYDqXadz+ygLHCW8oNC9tS3 +|KAq7+L9KTBk/B9ugwWAet35n996xw2BJrEXX+MbvCDchk0fu8HM1crACxPMRw15H5Qq3g/ +|HbdGlki0QdlV3NKMCFAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF +|4DAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUjPPLdQ6NMf +|bUKdpEknW4/u1POQwwHwYDVR0RBBgwFoEURGlhbmVSU0FAZXhhbXBsZS5jb20wDQYJKoZI +|hvcNAQEFBQADgYEAfaYstXhC1nnzMf72QsoPEweSCRvgb7CRGPa/SvvMY3n7gb/dl8eQa8 +|sKNytBagOYxRs+MshFK4YBnBziNu8WwRqSuL5i+1M+SUcLxLnkK1imBoPwsqe7hX7VxtrO +|nHsxctei6kGrasDdH7kURBjPhFdm6MXmuNwtsx8bKEM2dXo= +|CarlDSSCRLForAll.crl +|MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWj +|BpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05 +|OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMD +|BaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fv +|ftok8yqDnDWh +|CarlDSSCRLForCarl.crl +|MIGDMEQwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTFw05OTA4MjUwNzAwMDBaMB +|QwEgIBARcNOTkwODIyMDcwMDAwWjAJBgcqhkjOOAQDAzAAMC0CFQCzH8VPej3sdtVg+d55 +|IuxPsJD+lwIUWovDhLxmhxu/eYJbCl0H9rqpBSk= +|CarlDSSCRLEmpty.crl +|MG0wLjAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MXDTk5MDgyMDA3MDAwMFowCQ +|YHKoZIzjgEAwMwADAtAhRiPzYXMVguZ1B59QlLjK3Ua/RknwIVALU7TqFMe/0Pw42btv7D +|XW/eZSh9 +|CarlRSACRLForAll.crl +|MIIBMzCBnTANBgkqhkiG9w0BAQQFADASMRAwDgYDVQQDEwdDYXJsUlNBFw05OTA4MjcwNz +|AwMDBaMGkwIQIQRjRrx4AAVrwR024uxBCzsBcNOTkwODIyMDcwMDAwWjAhAhBGNGvHgABW +|vBHTbi7VmjCQFw05OTA4MjIwNzAwMDBaMCECEEY0a8eAAFa8EdNuLs1dcdAXDTk5MDgyND +|A3MDAwMFowDQYJKoZIhvcNAQEEBQADgYEAv7OXqlPwMiEWK3eSemu7l8jc6vH6ZhYwDrWe +|XPCB1F6zbsGIa4zUXsVN+0deZvNdq+W0GDZgqE2cPInsbye/NVBxgcK5RFtiiRkSMal7mt +|PMZssR2QsQR3etTyLZ5X8w8lv8lFGlWHY7H6hGph/2od5Voe0xiGmXDwjT1AxgWx4= +|CarlRSACRLForCarl.crl +|MIHsMFcwDQYJKoZIhvcNAQEEBQAwEjEQMA4GA1UEAxMHQ2FybFJTQRcNOTkwODI1MDcwMD +|AwWjAjMCECEEY0a8eAAFa8EdNuLp/yUCAXDTk5MDgyMjA3MDAwMFowDQYJKoZIhvcNAQEE +|BQADgYEAIe8h1MEahZVJa8pFYtzXCf+pUS6O2UcY+vjlct1P7XR04/NlMmUoLJodV+XVJg +|bq1eYjlYSNDome7psML84H96PRa4VMD//m3fzczXMsHn3csHHFTPwBblJXaR45Y98SIjDH +|E1WUBW4qAKlbxCpmlGLONjPCK2NHJZ3z3nDuAFY= +|CarlRSACRLEmpty.crl +|MIHHMDIwDQYJKoZIhvcNAQEEBQAwEjEQMA4GA1UEAxMHQ2FybFJTQRcNOTkwODIwMDcwMD +|AwWjANBgkqhkiG9w0BAQQFAAOBgQCpxSG4E3x087UR7ATzIEWGHgtuf4NtX/Q0dgZZJQ4E +|PYgJiIE3xNwgmPoXgQs3lKy0j3tRiRSky3JzFAe8IpxAoQf8RHyFDwuI0e7hDq/2FnStoa + + + +Hoffman, Ed. Informational [Page 124] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|/BAHUAZOqlmvYLCKLblRlfpqe5OUUlCg72XoTn+LlayRjCDriglr6BOoBtyQ== +|3.1.bin +|MIAGCSqGSIb3DQEHAaCAJIAEBFRoaXMEGCBpcyBzb21lIHNhbXBsZSBjb250ZW50LgAAAA +|AAAA== +|<3.1.bin + +***3.2.bin*** + +|* Example 3.2.bin +|>3.2.bin +|MCsGCSqGSIb3DQEHAaAeBBxUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQu +|<3.2.bin + +***4.1.bin*** + +|* Example 4.1.bin +|>4.1.bin +|MIIDlwYJKoZIhvcNAQcCoIIDiDCCA4QCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg +|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ +|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj +|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB +|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T +|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV +|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj +|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 +|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm +|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm +|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK +|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij +|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R +|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX +|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MWMwYQIBATAYMBIxEDAOBgNV +|BAMTB0NhcmxEU1MCAgDIMAcGBSsOAwIaMAkGByqGSM44BAMELjAsAhQJkf7r0mn1GLfXzV +|X0geoqQmqtAwIUOgfMwyG+4RpLfz61Ddu6HOq8zYk= +|<4.1.bin + + + + + + + + +Hoffman, Ed. Informational [Page 125] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +***4.2.bin*** + +|* Example 4.2.bin +|>4.2.bin +|MIIDUgYJKoZIhvcNAQcCoIIDQzCCAz8CAQExCzAJBgUrDgMCGgUAMCsGCSqGSIb3DQEHAa +|AeBBxUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIICMDCCAiwwggGVoAMCAQICEEY0 +|a8eAAFa8EdNuLsQQs7AwDQYJKoZIhvcNAQEFBQAwEjEQMA4GA1UEAxMHQ2FybFJTQTAeFw +|05OTA5MTkwMTA4NDdaFw0zOTEyMzEyMzU5NTlaMBMxETAPBgNVBAMTCEFsaWNlUlNBMIGf +|MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgiXM5jdj19eiHdjl/TrAFu1OD3g+3q9x9x3 +|UpDQUubRLfpoYm1NJvqlgp/Jfs+oJRDzCAvrFQnkZE8Sy72DLPxmhvB9mwYKy+7jQJahP1 +|9wUFk99eujVW2WH/GX/Jgeb4bOqHQHDvrG0sdJ8t+lU6uZl3AqZIUoxO81c4V3RXXwIDAQ +|ABo4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwHwYDVR0jBBgwFoAU6eCQ +|J6x4IHqa00zyQjdOIq6eOLswHQYDVR0OBBYEFHfStNG3TIqKo85Fnc7sPKA64/9QMB8GA1 +|UdEQQYMBaBFEFsaWNlUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4GBAD5wR6hI +|zBNYj8pRcWtONhhdBH6AsY1NzMqjj8x9Vsi8z26zHFmpIKoFgahOJa2ncBR1L/XHm9EO6W +|PSZLfGZm5zIVTf9LolXX1J05RrIjZ0c7hK7C9k7dM90qdCxeg3irTbn2fkvZ/5/nTv6vnu +|Y2rYP0slCbXYGnau65vbSbAiMYHLMIHIAgEBMCYwEjEQMA4GA1UEAxMHQ2FybFJTQQIQRj +|Rrx4AAVrwR024uxBCzsDAJBgUrDgMCGgUAMA0GCSqGSIb3DQEBAQUABIGALyOC0vMJX7gM +|WOtOnb+JmoHldcSRPdPQ1Xu21f6UoYqs48SE9c1gTieV9s8AhnZ1Pyvw59QCZ6f1x40WBK +|WztefZMvAk7+cgRNWfB8VTJPrOAR0PFxOnKpWdK+QDlRQL6TkNus5unJ4M6JjmVRPUaG/Q +|B9eisWJM44+v/eDVXcc= +|<4.2.bin + +***4.3.bin*** + +|* Example 4.3.bin +|>4.3.bin +|MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGggg +|LgMIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4X +|DTk5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1Mwgg +|G2MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE// +|lOFzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6 +|iLVPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6Ya +|RWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1 +|nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8 +|bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuV +|p1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41b +|Y8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxD +|KE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC +|BsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwf +|ftQ3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqG +|SM44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0 +|NevTFjMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjO +|OAQDBC4wLAIUBvvHKiTVNIn3i7X9cySlhsgPWmwCFGZpGbxoWNGNsZ1SP9oUiA39yaG4 +|<4.3.bin + + + + + + +Hoffman, Ed. Informational [Page 126] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +***4.4.bin*** + +|* Example 4.4.bin +|>4.4.bin +|MIILDQYJKoZIhvcNAQcCoIIK/jCCCvoCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg +|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCB68wggIsMIIBlaADAgECAhBGNGvH +|gABWvBHTbi7EELOwMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNVBAMTB0NhcmxSU0EwHhcNOT +|kwOTE5MDEwODQ3WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZVJTQTCBnzAN +|BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ +|0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcF +|BZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18CAwEAAa +|OBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFOngkCes +|eCB6mtNM8kI3TiKunji7MB0GA1UdDgQWBBR30rTRt0yKiqPORZ3O7DygOuP/UDAfBgNVHR +|EEGDAWgRRBbGljZVJTQUBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOBgQA+cEeoSMwT +|WI/KUXFrTjYYXQR+gLGNTczKo4/MfVbIvM9usxxZqSCqBYGoTiWtp3AUdS/1x5vRDulj0m +|S3xmZucyFU3/S6JV19SdOUayI2dHO4SuwvZO3TPdKnQsXoN4q0259n5L2f+f507+r57mNq +|2D9LJQm12Bp2ruub20mwIjCCApswggJaoAMCAQICAQEwCQYHKoZIzjgEAzASMRAwDgYDVQ +|QDEwdDYXJsRFNTMB4XDTk5MDgxNjIyNTA1MFoXDTM5MTIzMTIzNTk1OVowEjEQMA4GA1UE +|AxMHQ2FybERTUzCCAbcwggErBgcqhkjOOAQBMIIBHgKBgQC2SRg+ikTBKXGUTAHEEsF6ec +|tUTasegfvGTLMOlAkG6wHUschxS8dFwFAlXZz82uRt0+KGSISCfboVlUoW9kbt3faY0rt+ +|igqKuhZ7uVABSJOL6yUVUZdV3I9TDhCpUPxwt80wVP3a3qiqIrWhr4vMAojni3Bfua3hCN +|RtKS3W6QIVAN3BL99Tzgs0YHc+AqS/il2YuRDVAoGADO5Xm0u92rYHanQ3T1V/ne28YQ3r +|Rlk8VgsrWwyRzqViUmnK4W0+vb/+4be5K2E8rcuuReMGrIwinZxEhwvHzfAc2bVOXXPerw +|7JHVpR9U9EeTVac6p/RlEfqUIWnEjrinlhtNUvUyJEYx+GuKNYBiX4KcDvuuB18ELEY2VS +|mwoDgYUAAoGBAJmHdCcDZqCxwK3cLHW74WxEnNohbU1HbbFiCenYrh7yOrSUsaOOeptxTg +|CUybQlTrlglhkkAfNiDP51wPvO2GgA4/3VcE/fI5YZBpT0sWGPOlexCBGkCyYl8FJ2geoL +|Yg2VKuaGunKyp1CDC6onzRupTYma140YOYQ/i8VWTYB6o0IwQDAPBgNVHRMBAf8EBTADAQ +|H/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUcEQ+gi5vh95K03XjPSC8QyuT8R8wCQYH +|KoZIzjgEAwMwADAtAhRrqfBOelp54/m+PSvJBjfpERehEwIVAI80aSqLsTwDeZQyTRIfzo +|n7RrI7MIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNT +|MB4XDTk5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1 +|MwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauE +|CE//lOFzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny +|/dQ6iLVPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDi +|R6YaRWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF +|3dm1nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgv +|MAF8bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgF +|zjuVp1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09 +|B41bY8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YU +|eyxDKE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E +|BAMCBsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sob +|PjwfftQ3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkG +|ByqGSM44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4h +|BSW0NevaGB2zCB2DCBmTAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MXDTk5MDgy +|NzA3MDAwMFowaTATAgIAyBcNOTkwODIyMDcwMDAwWjATAgIAyRcNOTkwODIyMDcwMDAwWj +|ATAgIA0xcNOTkwODIyMDcwMDAwWjATAgIA0hcNOTkwODIyMDcwMDAwWjATAgIA1BcNOTkw +|ODI0MDcwMDAwWjAJBgcqhkjOOAQDAy8AMCwCFH5lUnYz/jRzF9H3lvmg1NhtXH09AhQCel +|u31VsYwc+H737aJPMqg5w1oTGCAiowggImAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERTUwIC + + + +Hoffman, Ed. Informational [Page 127] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|AMgwBwYFKw4DAhqgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBT +|EPFw0wMzA1MTQxNTM5MDBaMCMGCSqGSIb3DQEJBDEWBBRAauwIUnm6bhYCLZ4GKcAilofd +|SDAJBgcqhkjOOAQDBC4wLAIUO6XgStttWOAZ0QAcT0SaV3pxZmgCFBoRmNYfH680gQHevo +|vctqhqkWkToYIBYjA+BgsqhkiG9w0BCRACBDEvMC0MIENvbnRlbnQgSGludHMgRGVzY3Jp +|cHRpb24gQnVmZmVyBgkqhkiG9w0BBwEwggEeBgkqhkiG9w0BCQYxggEPMIIBCwIBATAmMB +|IxEDAOBgNVBAMTB0NhcmxSU0ECEEY0a8eAAFa8EdNuLsQQs7AwBwYFKw4DAhqgQzAcBgkq +|hkiG9w0BCQUxDxcNMDMwNTE0MTUzOTAwWjAjBgkqhkiG9w0BCQQxFgQUAl9JTjmYUIWzZt +|OKH3ueaar72DMwDQYJKoZIhvcNAQEBBQAEgYBtqiAk7XrupV6H3XUfK1QQZfTOm7EseHS8 +|ixxgtduLA55J8it/k249iRTJ42v09n12rj5YH5u7vHwwGU4Q9wLxi1u025q7k7QY0MwryZ +|GprdlG+GWp4nGV0NROH810b4LoN29aPcvH1F/CgBva04RAaF9WmmL1Ow1sM8PtZz9Dvw== +|<4.4.bin + +***4.5.bin*** + +|* Example 4.5.bin +|>4.5.bin +|MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEBF +|RoaXMEGCBpcyBzb21lIHNhbXBsZSBjb250ZW50LgAAAAAAAKCAMIIB6zCCAVSgAwIBAgIQ +|RjRrx4AAVrwR024un/JQIDANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB +|4XDTk5MDgxODA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEjEQMA4GA1UEAxMHQ2FybFJTQTCB +|nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Ev/GLgkV/R3/25ze5NxXLwzGpKSciPYQU +|bQzRE6BLOOr4KdvVEeF3rydiwrhjmnvdeNGlPs5ADV6OyiNrHt4lDiMgmKP5+ZJY+4Tqu5 +|fdWWZdoWoMW+Dq5EW+9e9Kcpy4LdrETpqpOUKQ74GNbIV17ydsTyEWA4uRs8HZfJavECAw +|EAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOng +|kCeseCB6mtNM8kI3TiKunji7MA0GCSqGSIb3DQEBBQUAA4GBALee1ATT7Snk/4mJFS5M2w +|zwSA8yYe7EBOwSXS3/D2RZfgrD7Rj941ZAN6cHtfA4EmFQ7e/dP+MLuGGlpJs85p6cVJq2 +|ldbabDu1LUU1nUkBdvq5uTH5+WsSU6D1FGCbfco+8lNrsDdvreZ019v6WuoUQWNdzb7IDs +|Haao1TNBgCMIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUF +|ADASMRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1OV +|owEzERMA8GA1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJ +|czmN2PX16Id2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sV +|CeRkTxLLvYMs/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0 +|ny36VTq5mXcCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDw +|EB/wQEAwIGwDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQU +|d9K00bdMioqjzkWdzuw8oDrj/1AwHwYDVR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb2 +|0wDQYJKoZIhvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzP +|brMcWakgqgWBqE4lradwFHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2 +|Tt0z3Sp0LF6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCIAADGByzCByAIB +|ATAmMBIxEDAOBgNVBAMTB0NhcmxSU0ECEEY0a8eAAFa8EdNuLsQQs7AwCQYFKw4DAhoFAD +|ANBgkqhkiG9w0BAQEFAASBgC8jgtLzCV+4DFjrTp2/iZqB5XXEkT3T0NV7ttX+lKGKrOPE +|hPXNYE4nlfbPAIZ2dT8r8OfUAmen9ceNFgSls7Xn2TLwJO/nIETVnwfFUyT6zgEdDxcTpy +|qVnSvkA5UUC+k5DbrObpyeDOiY5lUT1Ghv0AfXorFiTOOPr/3g1V3HAAAAAAAA +|<4.5.bin + + + + + + + + +Hoffman, Ed. Informational [Page 128] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +***4.6.bin*** + +|* Example 4.6.bin +|>4.6.bin +|MIIFtwYJKoZIhvcNAQcCoIIFqDCCBaQCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg +|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCBJwwggG4MIIBd6ADAgECAgIA0jAJ +|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDIwODEwWhcNMzkxMj +|MxMjM1OTU5WjATMREwDwYDVQQDEwhEaWFuZURTUzCBkzAJBgcqhkjOOAQBA4GFAAKBgQCg +|ABd4LO5+gVMuLmEID6GbUVIa2lmocy8SJbYIy8rvKkR2ilIJ6r0FItUP9v1G16+ZOAkOE8 +|tPLN0cNPccvyX/I9M7WeeClze+MSTYGMjzSTlbt+LlJ378jEVyW34+j2hN3UZ6Ir6O/8za +|OSmjOeWfQ+lVyddbpoFnzMCqzS7FI6OBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BA +|QDAgbAMB8GA1UdIwQYMBaAFHBEPoIub4feStN14z0gvEMrk/EfMB0GA1UdDgQWBBRkMJl9 +|XNxFC5k6Ui8Wv1hQ3c4rGDAfBgNVHREEGDAWgRREaWFuZURTU0BleGFtcGxlLmNvbTAJBg +|cqhkjOOAQDAzAAMC0CFQChGvgXDj5dqIz0tlUzHkvjLKy5XwIUKEsQRVjSHJ1VNRQYkbI/ +|Od+1btMwggLcMIICm6ADAgECAgIAyDAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1 +|MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURT +|UzCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4 +|QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2TDINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSf +|L91DqItU8T+wBwhHTV2Iw8O1s+NVCHXVOXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAO +|JHphpFZrgTxtqPuDchK2KL95PNAoGAJjjQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5Q +|Xd2bWeLNqgU9WMB7oja4bgevfYpCJaf0dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC +|8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGmE2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGA +|XOO5WnUUlgupet3jP6nsrF7cvbcTETSmFokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT +|0HjVtjyLtFpaBK44XWzgaAP+gjfhryJKtTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/Zh +|R7LEMoTwfkFA/UanY04z8qXi9PKD5bijgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/w +|QEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyh +|s+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0RBBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQ +|YHKoZIzjgEAwMwADAtAhRVDKQZH0IriXEiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3i +|EFJbQ169MYHGMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBg +|cqhkjOOAQDBC4wLAIUSCTei4XyFq/sgmGpVNAtBKHMWk8CFBft1XcC7nUT2BC9PZcXIIi7 +|/XuBMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIA0jAHBgUrDgMCGjAJBgcqhkjOOA +|QDBC4wLAIUFf+BTYytgE6bNVgEN25jbulbg/oCFAZ+WE4rMYRB7Ul5OD530qaMdQgh +|<4.6.bin + +***4.7.bin*** + +|* Example 4.7.bin +|>4.7.bin +|MIIDlAYJKoZIhvcNAQcCoIIDhTCCA4ECAQMxCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg +|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ +|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj +|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB +|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T +|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV +|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj +|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 +|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm +|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm + + + +Hoffman, Ed. Informational [Page 129] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK +|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij +|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R +|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX +|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MWAwXgIBA4AUvmyhs+PB9+1D +|cKTOEwHi/eOX/s0wBwYFKw4DAhowCQYHKoZIzjgEAwQvMC0CFQCJw2t7VvfDEgBl8Tf1xF +|gXjRFXgwIUCw9DOqrs3nphLIyc9UGZpzwgw7c= +|<4.7.bin + +***4.8.eml*** + +|* Example 4.8.eml +|>4.8.eml +|TUlNRS1WZXJzaW9uOiAxLjAKVG86IFVzZXIyQGV4YW1wbGVzLmNvbQpGcm9tOiBhbGljZU +|Rzc0BleGFtcGxlcy5jb20KU3ViamVjdDogRXhhbXBsZSA0LjgKTWVzc2FnZS1JZDogPDAy +|MDkwNjAwMjU1MDMwMC4yNDlAZXhhbXBsZXMuY29tPgpEYXRlOiBGcmksIDA2IFNlcCAyMD +|AyIDAwOjI1OjIxIC0wMzAwIApDb250ZW50LVR5cGU6IG11bHRpcGFydC9zaWduZWQ7CiAg +|ICBtaWNhbGc9U0hBMTsKICAgIGJvdW5kYXJ5PSItLS0tPV9OZXh0Qm91bmRyeV9fX19Gcm +|ksXzA2X1NlcF8yMDAyXzAwOjI1OjIxIjsKICAgIHByb3RvY29sPSJhcHBsaWNhdGlvbi9w +|a2NzNy1zaWduYXR1cmUiCgpUaGlzIGlzIGEgbXVsdGktcGFydCBtZXNzYWdlIGluIE1JTU +|UgZm9ybWF0LgoKLS0tLS0tPV9OZXh0Qm91bmRyeV9fX19GcmksXzA2X1NlcF8yMDAyXzAw +|OjI1OjIxCgpUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuCi0tLS0tLT1fTmV4dEJvdW +|5kcnlfX19fRnJpLF8wNl9TZXBfMjAwMl8wMDoyNToyMQpDb250ZW50LVR5cGU6IGFwcGxp +|Y2F0aW9uL3BrY3M3LXNpZ25hdHVyZTsgbmFtZT1zbWltZS5wN3MKQ29udGVudC1UcmFuc2 +|Zlci1FbmNvZGluZzogYmFzZTY0CkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7 +|IGZpbGVuYW1lPXNtaW1lLnA3cwoKTUlJRGR3WUpLb1pJaHZjTkFRY0NvSUlEYURDQ0EyUU +|NBUUV4Q1RBSEJnVXJEZ01DR2pBTEJna3Foa2lHOXcwQkJ3R2dnZ0xnTUlJQwozRENDQXB1 +|Z0F3SUJBZ0lDQU1nd0NRWUhLb1pJempnRUF6QVNNUkF3RGdZRFZRUURFd2REWVhKc1JGTl +|RNQjRYRFRrNU1EZ3hOekF4Ck1UQTBPVm9YRFRNNU1USXpNVEl6TlRrMU9Wb3dFekVSTUE4 +|R0ExVUVBeE1JUVd4cFkyVkVVMU13Z2dHMk1JSUJLd1lIS29aSXpqZ0UKQVRDQ0FSNENnWU +|VBZ1kzTjdZUHFDcDQ1UHNKSUtLUGtSNVBkRHRlb0R1eFR4YXVFQ0UvL2xPRnpTSDRNMXZO +|RVNOSCtuNitrb1lrdgo0ZGt3eURiZVA1dS90MHpjWDJtSzVIWFFOd3lSQ0pXYjNxZGUrZn +|owbnkvZFE2aUxWUEUvc0FjSVIwMWRpTVBEdGJQalZRaDExVGwyCkVNUjR2Zitkc0lTWE4v +|TGtVUnUxNUFtV1hQTitXOXNDRlFEaVI2WWFSV2E0RThiYWo3ZzNJU3RpaS9lVHpRS0JnQ1 +|k0MEJTSk1xbzUKK3o1dDJVdFpha3gySXprRUFqVmM4c3NhTU1NZVVGM2RtMW5pemFvRlBW +|akFlNkkydUc0SHIzMktRaVduOUhYUFNnaGVTejZRK0czcQpuTWtoaWp0MkZPbk9MbDJqQj +|gwamhiZ3ZNQUY4YlVtSkVZazJSTDM0eUpWS1UxYTE0dmx6N0JwaE5oOFJmOEs5N2RGUS81 +|aDB3dEdCClNtQTV1alk1QTRHRUFBS0JnRnpqdVZwMUZKWUxxWHJkNHorcDdLeGUzTDIzRX +|hFMHBoYUpLQkVqMlRTR1ozVjFFeEk5UTF0djVWRy8KK29ueW9ocytKSDA5QjQxYlk4aTdS +|YVdnU3VPRjFzNEdnRC9vSTM0YThpU3JVeHE0SncwZTd3aS9aaFNBWEdLc1pmb1ZpL0c3Tk +|5UUwpsamYyWVVleXhES0U4SDVCUVAxR3AyTk9NL0tsNHZUeWcrVzRvNEdCTUg4d0RBWURW +|UjBUQVFIL0JBSXdBREFPQmdOVkhROEJBZjhFCkJBTUNCc0F3SHdZRFZSMGpCQmd3Rm9BVW +|NFUStnaTV2aDk1SzAzWGpQU0M4UXl1VDhSOHdIUVlEVlIwT0JCWUVGTDVzb2JQandmZnQK +|UTNDa3poTUI0djNqbC83Tk1COEdBMVVkRVFRWU1CYUJGRUZzYVdObFJGTlRRR1Y0WVcxd2 +|JHVXVZMjl0TUFrR0J5cUdTTTQ0QkFNRApNQUF3TFFJVVZReWtHUjlDSzRseElqT05nMnEx +|UFdkcnYwVUNGUUNmWVZOU1ZBdGNzdDNhNTNZZDRoQlNXME5ldlRGak1HRUNBUUV3CkdEQV +|NNUkF3RGdZRFZRUURFd2REWVhKc1JGTlRBZ0lBeURBSEJnVXJEZ01DR2pBSkJnY3Foa2pP + + + +Hoffman, Ed. Informational [Page 130] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|T0FRREJDNHdMQUlVTS9tR2Y2Z2sKZ3A5WjBYdFJkR2ltSmVCL0J4VUNGR0ZGSnF3WVJ0MV +|dZY0lPUW9HaWFvd3FHelZJCgotLS0tLS09X05leHRCb3VuZHJ5X19fX0ZyaSxfMDZfU2Vw +|XzIwMDJfMDA6MjU6MjEtLQo= +|<4.8.eml + +***4.9.eml*** + +|* Example 4.9.eml +|>4.9.eml +|TUlNRS1WZXJzaW9uOiAxLjAKVG86IFVzZXIyQGV4YW1wbGVzLmNvbQpGcm9tOiBhbGljZU +|Rzc0BleGFtcGxlcy5jb20KU3ViamVjdDogRXhhbXBsZSA0LjkKTWVzc2FnZS1JZDogPDAy +|MTAzMTE2NDU0MDMwMC4zMDRAZXhhbXBsZXMuY29tPgpEYXRlOiBUaHUsIDMxIE9jdCAyMD +|AyIDE2OjQ1OjE0IC0wMzAwIApDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL3BrY3M3LW1p +|bWU7IHNtaW1lLXR5cGU9c2lnbmVkLWRhdGE7CiAgICBuYW1lPXNtaW1lLnA3bQpDb250ZW +|50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKQ29udGVudC1EaXNwb3NpdGlvbjogYXR0 +|YWNobWVudDsgZmlsZW5hbWU9c21pbWUucDdtCgpNSUlEbVFZSktvWklodmNOQVFjQ29JSU +|RpakNDQTRZQ0FRRXhDVEFIQmdVckRnTUNHakF0QmdrcWhraUc5dzBCQndHZ0lBUWVEUXBV +|CmFHbHpJR2x6SUhOdmJXVWdjMkZ0Y0d4bElHTnZiblJsYm5RdW9JSUM0RENDQXR3d2dnS2 +|JvQU1DQVFJQ0FnRElNQWtHQnlxR1NNNDQKQkFNd0VqRVFNQTRHQTFVRUF4TUhRMkZ5YkVS +|VFV6QWVGdzA1T1RBNE1UY3dNVEV3TkRsYUZ3MHpPVEV5TXpFeU16VTVOVGxhTUJNeApFVE +|FQQmdOVkJBTVRDRUZzYVdObFJGTlRNSUlCdGpDQ0FTc0dCeXFHU000NEJBRXdnZ0VlQW9H +|QkFJR056ZTJENmdxZU9UN0NTQ2lqCjVFZVQzUTdYcUE3c1U4V3JoQWhQLzVUaGMwaCtETm +|J6UkVqUi9wK3ZwS0dKTCtIWk1NZzIzaitidjdkTTNGOXBpdVIxMERjTWtRaVYKbTk2blh2 +|bjg5Sjh2M1VPb2kxVHhQN0FIQ0VkTlhZakR3N1d6NDFVSWRkVTVkaERFZUwzL25iQ0Vsem +|Z5NUZFYnRlUUpsbHp6Zmx2YgpBaFVBNGtlbUdrVm11QlBHMm8rNE55RXJZb3YzazgwQ2dZ +|QW1PTkFVaVRLcU9mcytiZGxMV1dwTWRpTTVCQUkxWFBMTEdqRERIbEJkCjNadFo0czJxQl +|QxWXdIdWlOcmh1QjY5OWlrSWxwL1IxejBvSVhrcytrUGh0NnB6SklZbzdkaFRwemk1ZG93 +|Zk5JNFc0THpBQmZHMUoKaVJHSk5rUzkrTWlWU2xOV3RlTDVjK3dhWVRZZkVYL0N2ZTNSVV +|ArWWRNTFJnVXBnT2JvMk9RT0JoQUFDZ1lCYzQ3bGFkUlNXQzZsNgozZU0vcWV5c1h0eTl0 +|eE1STktZV2lTZ1JJOWswaG1kMWRSTVNQVU5iYitWUnYvcUo4cUliUGlSOVBRZU5XMlBJdT +|BXbG9FcmpoZGJPCkJvQS82Q04rR3ZJa3ExTWF1Q2NOSHU4SXYyWVVnRnhpckdYNkZZdnh1 +|elRVMHBZMzltRkhzc1F5aFBCK1FVRDlScWRqVGpQeXBlTDAKOG9QbHVLT0JnVEIvTUF3R0 +|ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdiQU1COEdBMVVkSXdRWU1CYUFG +|SEJFUG9JdQpiNGZlU3ROMTR6MGd2RU1yay9FZk1CMEdBMVVkRGdRV0JCUytiS0d6NDhIMz +|dVTndwTTRUQWVMOTQ1Zit6VEFmQmdOVkhSRUVHREFXCmdSUkJiR2xqWlVSVFUwQmxlR0Z0 +|Y0d4bExtTnZiVEFKQmdjcWhrak9PQVFEQXpBQU1DMENGRlVNcEJrZlFpdUpjU0l6allOcX +|RUMW4KYTc5RkFoVUFuMkZUVWxRTFhMTGQydWQySGVJUVVsdERYcjB4WXpCaEFnRUJNQmd3 +|RWpFUU1BNEdBMVVFQXhNSFEyRnliRVJUVXdJQwpBTWd3QndZRkt3NERBaG93Q1FZSEtvWk +|l6amdFQXdRdU1Dd0NGRDFjU1c2TElVRnplWGxlM1lJNVNLU0Jlci9zQWhRbUNxN3MvQ1RG +|CkhPRWpnQVNlVWpiTXB4NWc2QT09Cg== +|<4.9.eml + +***4.10.bin*** + +|* Example 4.10.bin +|>4.10.bin +|MIIH/wYJKoZIhvcNAQcCoIIH8DCCB+wCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg +|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ + + + +Hoffman, Ed. Informational [Page 131] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj +|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB +|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T +|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV +|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj +|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 +|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm +|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm +|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK +|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij +|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R +|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX +|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MYIEyTCCBMUCAQEwGDASMRAw +|DgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGqCCBF8wGAYJKoZIhvcNAQkDMQsGCSqGSI +|b3DQEHATAjBgkqhkiG9w0BCQQxFgQUQGrsCFJ5um4WAi2eBinAIpaH3UgwOAYDKqszMTEE +|L1RoaXMgaXMgYSB0ZXN0IEdlbmVyYWwgQVNOIEF0dHJpYnV0ZSwgbnVtYmVyIDEuMD4GCy +|qGSIb3DQEJEAIEMS8wLQwgQ29udGVudCBIaW50cyBEZXNjcmlwdGlvbiBCdWZmZXIGCSqG +|SIb3DQEHATBKBgkqhkiG9w0BCQ8xPTA7MAcGBSoDBAUGMDAGBioDBAUGTQQmU21pbWUgQ2 +|FwYWJpbGl0aWVzIHBhcmFtZXRlcnMgYnVmZmVyIDIwbQYLKoZIhvcNAQkQAgIxXjFcAgEB +|BgcqAwQFBgcIExtUSElTIElTIEEgUFJJVkFDWSBNQVJLIFRFU1QxMTAvgAgqAwQFBgeGeK +|EjEyFUSElTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4wbwYLKoZIhvcNAQkQAgox +|YDBeBgUqAwQFBgQrQ29udGVudCBSZWZlcmVuY2UgQ29udGVudCBJZGVudGlmaWVyIEJ1Zm +|ZlcgQoQ29udGVudCBSZWZlcmVuY2UgU2lnbmF0dXJlIFZhbHVlIEJ1ZmZlcjBzBgsqhkiG +|9w0BCRACCzFkoGIwWjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDVVTIEdvdmVybm1lbnQxET +|APBgNVBAsTCFZEQSBTaXRlMQwwCgYDVQQLEwNWREExEjAQBgNVBAMTCURhaXN5IFJTQQIE +|ClVEMzCB/AYLKoZIhvcNAQkQAgMxgewwgekwgeYEBzU3MzgyOTkYDzE5OTkwMzExMTA0ND +|MzWqGByTCBxqRhMF8xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1VUyBHb3Zlcm5tZW50MREw +|DwYDVQQLEwhWREEgU2l0ZTEMMAoGA1UECxMDVkRBMRcwFQYDVQQDEw5CdWdzIEJ1bm55IE +|RTQaRhMF8xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1VUyBHb3Zlcm5tZW50MREwDwYDVQQL +|EwhWREEgU2l0ZTEMMAoGA1UECxMDVkRBMRcwFQYDVQQDEw5FbG1lciBGdWRkIERTQTCCAQ +|IGCyqGSIb3DQEJEAIJMYHyMIHvMXICAQEGByoDBAUGBwkTJkVRVUlWQUxFTlQgVEhJUyBJ +|UyBBIFBSSVZBQ1kgTUFSSyBURVNUMTwwOoAIKgMEBQYHhnihLhMsRVFVSVZBTEVOVCBUSE +|lTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4xeQIBAQYHKgMEBQYHChMtRVFVSVZB +|TEVOVCBUSElTIElTIEEgU0VDT05EIFBSSVZBQ1kgTUFSSyBURVNUMTwwOoAIKgMEBQYHhn +|ihLhMsRVFVSVZBTEVOVCBUSElTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4wCQYH +|KoZIzjgEAwQvMC0CFQC8MzdlxPdwXBdJE6pMhcq7UpFIWQIUY5aiFIvPV96wSF9sZN2EBE +|lfHMo= +|<4.10.bin + +***4.11.bin*** + +|* Example 4.11.bin +|>4.11.bin +|MIIGiAYJKoZIhvcNAQcCoIIGeTCCBnUCAQExADALBgkqhkiG9w0BBwGgggV/MIICmzCCAl +|qgAwIBAgIBATAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE2MjI1 +|MDUwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdDYXJsRFNTMIIBtzCCASsGByqGSM +|44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8ZMsw6UCQbrAdSxyHFLx0XA + + + +Hoffman, Ed. Informational [Page 132] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +|UCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5UAFIk4vrJRVRl1Xcj1MOEK +|lQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAhUA3cEv31POCzRgdz4CpL+K +|XZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytbDJHOpWJSacrhbT69v/7ht7 +|krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0R5NVpzqn9GUR+pQhacSOuK +|eWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgOBhQACgYEAmYd0JwNmoLHArdwsdb +|vhbESc2iFtTUdtsWIJ6diuHvI6tJSxo456m3FOAJTJtCVOuWCWGSQB82IM/nXA+87YaADj +|/dVwT98jlhkGlPSxYY86V7EIEaQLJiXwUnaB6gtiDZUq5oa6crKnUIMLqifNG6lNiZrXjR +|g5hD+LxVZNgHqjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1Ud +|DgQWBBRwRD6CLm+H3krTdeM9ILxDK5PxHzAJBgcqhkjOOAQDAzAAMC0CFGup8E56Wnnj+b +|49K8kGN+kRF6ETAhUAjzRpKouxPAN5lDJNEh/OiftGsjswggLcMIICm6ADAgECAgIAyDAJ +|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj +|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB +|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T +|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV +|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj +|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 +|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm +|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm +|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK +|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij +|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R +|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX +|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169oYHbMIHYMIGZMAkGByqGSM44 +|BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4Mj +|IwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMC +|AgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLw +|AwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWhMQA= +|<4.11.bin + +***5.1.bin*** + +|* Example 5.1.bin +|>5.1.bin +|MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYX +|JsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGP +|cP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpX +|adCDgO8/nUkUNYeNxJtuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652j +|KKHRLFf02hosdR8wQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8 +|Z9P43LrY4OxUk660cu1lXeCSFOSOpOJ7FuVyU= +|<5.1.bin + + + + + + + + + + +Hoffman, Ed. Informational [Page 133] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +***5.2.bin*** + +|* Example 5.2.bin +|>5.2.bin +|MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4GA1UEAxMHQ2 +|FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEFAASBgJQmQojGi7Z4IP+C +|VypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQt9i3YcMwcap+aiOkyqjMalT03VUC0X +|BOGv+HYI3HBZm/aFzxoq+YOXAWs5xlGerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg +|+TGrnGVNQBNw47Ewoj4CAQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGH +|cUr5MSJ/g9HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC +|AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRRyw== +|<5.2.bin + +***5.3.eml*** + +|* Example 5.3.eml +|>5.3.eml +|TUlNRS1WZXJzaW9uOiAxLjAKTWVzc2FnZS1JZDogPDAwMTAzMTEyMDA1MjAzLjAwMzQ5QG +|FteWVtaWx5LmlnLmNvbT4KRGF0ZTogVHVlLCAzMSBPY3QgMjAwMCAxMjowMDo1MiAtMDYw +|MCAoQ2VudHJhbCBTdGFuZGFyZCBUaW1lKQpGcm9tOiBVc2VyMQpUbzogVXNlcjIKU3Viam +|VjdDogRXhhbXBsZSA1LjMKQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wa2NzNy1taW1l +|OwoJbmFtZT1zbWltZS5wN207CglzbWltZS10eXBlPWVudmVsb3BlZC1kYXRhCkNvbnRlbn +|QtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NApDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRh +|Y2htZW50OyBmaWxlbmFtZT1zbWltZS5wN20KCk1JSUJIZ1lKS29aSWh2Y05BUWNEb0lJQk +|R6Q0NBUXNDQVFBeGdjQXdnYjBDQVFBd0pqQVNNUkF3RGdZRFZRUURFd2REWVhKc1VsTkIK +|QWhCR05HdkhnQUJXdkJIVGJpN05YWEhRTUEwR0NTcUdTSWIzRFFFQkFRVUFCSUdBQzNFTj +|VuR0lpSmkybHNHUGNQMmlKOTdhNGU4awpiS1F6MzZ6ZzZaMmkweXg2ellDNG1aN21YN0ZC +|czNJV2crZjZLZ0NMeDNNMWVDYld4OCtNREZiYnBYYWRDRGdPOC9uVWtVTlllTnhKCnR1en +|ViR2d6b3lFZDhDaDRIL2RkOWdkelRkK3RhVEVnUzBpcGRTSnVObmtWWTQvTTY1MmpLS0hS +|TEZmMDJob3NkUjh3UXdZSktvWkkKaHZjTkFRY0JNQlFHQ0NxR1NJYjNEUU1IQkFndGFNWH +|BSd1pSTllBZ0RzaVNmOFo5UDQzTHJZNE94VWs2NjBjdTFsWGVDU0ZPU09wTwpKN0Z1VnlV +|PQoK +|<5.3.eml + +***6.0.bin*** + +|* Example 6.0.bin +|>6.0.bin +|MF4GCSqGSIb3DQEHBaBRME8CAQAwBwYFKw4DAhowKwYJKoZIhvcNAQcBoB4EHFRoaXMgaX +|Mgc29tZSBzYW1wbGUgY29udGVudC4EFEBq7AhSebpuFgItngYpwCKWh91I +|<6.0.bin + + + + + + + + + + +Hoffman, Ed. Informational [Page 134] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +***7.1.bin*** + +|* Example 7.1.bin +|>7.1.bin +|MFcGCSqGSIb3DQEHBqBKMEgCAQAwQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiza2v7Yj +|EIToAg+vzt2z8YFx04iRHqNNYg2/TD2VgV75M7mvXXBPa1cOI= +|<7.1.bin + +***7.2.bin*** + +|* Example 7.2.bin +|>7.2.bin +|MIGVBgkqhkiG9w0BBwaggYcwgYQCAQIwQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgHJy +|CFkJ6wfoAg0iCPZ0iKy0HkImhdvncFUibt4wG9AJFYpzVuvEuiBzOhOjA4BgMqqzMxMQQv +|VGhpcyBpcyBhIHRlc3QgR2VuZXJhbCBBU04gQXR0cmlidXRlLCBudW1iZXIgMS4= +|<7.2.bin + +C. Acknowledgements + + Blake Ramsdell, Jim Schaad, and John Pawling contributed the vast + majority of the examples in this document, and/or correct examples + during the early versions of this document. Additional examples came + from many people, including Rob Colestock and Paul Hoffman. + Additional testing came from Holger Ebel and Russ Housley. + + The examples are displayed with a modified version of Peter Gutmann's + "dumpasn1" program. Peter and Jim Schaad and Blake Ramsdell have + been updating the program based on input from the process of writing + this draft. + +Editor's Address + + Paul Hoffman + Internet Mail Consortium + 127 Segre Place + Santa Cruz, CA 95060 USA + + EMail: phoffman@imc.org + + + + + + + + + + + + + +Hoffman, Ed. Informational [Page 135] + +RFC 4134 Examples of S/MIME Messages July 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Hoffman, Ed. Informational [Page 136] + diff --git a/crypto/test/data/rsa3/self-testcase-A.p12 b/crypto/test/data/rsa3/self-testcase-A.p12 new file mode 100644 index 000000000..79fe2f2fd Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-A.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-A.pem b/crypto/test/data/rsa3/self-testcase-A.pem new file mode 100644 index 000000000..3e507ba9c --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-A.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAC0dXvAI0/fhu22j15YEo +F8M3OYM8fwlvxs2/qtwELR3hVckpRIJmfGpUutb6/TBPgTS8a/fmzcrxLsL/aGSD +jH4/TmTHrRmhlT/einuudpAXPxaS27Yz7duxRPmyXeyHy3P0ulXDEzOaZdV8kxQs +J/v+z0knwdAh91omHRfJuNxDQtLfjp1Qtz+jrBCI6s864UblKXG/AwjWOLFQ1E0N +A2bDo72tr3aw01gryggFkyNrB9K5/15+jJLVLFjuJfP7m3FUjPfGQB9+eZMBWpNH +hGcSsPibqWVTDMjN0Z/mTGMzZDsEXX0Ao1K21q5vK1sfFYEahv/PCwkcW1dOeTGF +pQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-B.p12 b/crypto/test/data/rsa3/self-testcase-B.p12 new file mode 100644 index 000000000..ef5013228 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-B.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-B.pem b/crypto/test/data/rsa3/self-testcase-B.pem new file mode 100644 index 000000000..6c449109a --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-B.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAIYpxwPMRRjPuRBsWKhB0 +ACZHEaO6RtSwu28sHO2TF1o0kHONAnqR37OhMuPR70qBynd5dVDkjpxXUfxhLDPh +jdaxXuj2vMrbAvDJFsIsKDatlc632IsicSR4DVEnpJmUtLBQFC2VylHMxkGoo5eJ +dsf5ZY/QqUXf+VReLWfyQXEaSGe8nI7fP61xqTsgzcN4ziqkKSKGvsEtPU/oo23Y +xZDJpRMPdzu7TqkP3PnzRFy6HUamM2Xpyl2qeYELtGu7nuoSaF/1AX21bPtU9N9N ++wbxlGuq7NVIKdlIaoQ3FfgCVZGrVwjr7uxow7Gob+pWJJKjOS+IlSRL0MqH1t/U +yQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-C.p12 b/crypto/test/data/rsa3/self-testcase-C.p12 new file mode 100644 index 000000000..72527d634 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-C.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-C.pem b/crypto/test/data/rsa3/self-testcase-C.pem new file mode 100644 index 000000000..f844ee47f --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-C.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkWkqxLQH4vvX5e2oiydv +VN8Et+ZznJ78yifF7Tctjm9+EfEBRupHwXHlAZd2n2CsZfhVTqk/Rnffb078X3g5 +9jx9ka0/hhkYyG6XqLybS3yXVpC/mvaeQMRu0Ubi0uSOkcf6rYiaqGjcG5DRaSAz +SNNrDTEDYNxsuaPJoxZtQ+o1VaB3ksJ2UanzAHy45IJKXlSWS4l0Xsu6NZJxeMLB +0iL0j5+TcaK37dkNpDi4dhFbeOi30Q8rvC5BDorFMM8GEl+GevH6Rpk0P67WlnOY +qeDoKjzKi1w0ZDBS8XI95DLsmnHXcg2Iu8Dx1iBJMFST6mLtsMdVQAD+y2NTkbpM +xA== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-D.p12 b/crypto/test/data/rsa3/self-testcase-D.p12 new file mode 100644 index 000000000..c2fa40bb5 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-D.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-D.pem b/crypto/test/data/rsa3/self-testcase-D.pem new file mode 100644 index 000000000..6f93f1c06 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-D.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkSFw/c7vnAAs4wKzS24X +oyJrIiazcZD4A2ioqWMQD+QxFJlplJsyE5vcyVxv5Pww5Od1aPJCsSEd/C7h12eA +576kkQcbv5KQ8LUlpj6eRjzI4E97yc9Yi9C3YibniGCv5mxLpw2bOxix9l8EBj6h +vTfDMdoQVXkGyI2TCbYppkffJgxrL/wj82XbYeIHL27REf4+bNVRYD3LMXl7koPc +4vUC6lyxYUELfv6UnAzppqDl+LSUkKvQEe26syIUAE3ArGvy/aYjIYBCwQQu4r9H +WnXdIvcTdZqi3x9z/aN8Or9/IYIXpk3td6lLqI/DUwkPRS6zcthDo3x/1IFhUCB3 +KQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-E.p12 b/crypto/test/data/rsa3/self-testcase-E.p12 new file mode 100644 index 000000000..026564215 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-E.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-E.pem b/crypto/test/data/rsa3/self-testcase-E.pem new file mode 100644 index 000000000..0c30777de --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-E.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkFwewElSyXCGG2ygI3I4 +iYLtjAJAy002ES4JGHvr39dNhYoZ1poop18AU52mrx+SKX5vc/hAipisVa0rK9Jl +91GF5NQdhU0KWxNCBHZAy3dUf1M63jvTC3eiG8LVV+C77Cx936i8qO5f3qWCN40z +4W8eMwkCoVtpfzuuHk1by0VwCgU5IYuNIrwxR1bjudOctyhXNJjgr3SIsjDrqpTA +nS4AauNFVqFfSyyaw5AX+7eA/WrMOGdJBJT1bEhHqrWxLtQzwSzKBKu7FpuF3mVX +SHcSW4AzA6Yzq2Hcedo+SJt96IDr5xT17ncPMBzdq9pdoHlyJVq9+3O5JQOTx1WD +6g== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-F.p12 b/crypto/test/data/rsa3/self-testcase-F.p12 new file mode 100644 index 000000000..58410dcab Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-F.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-F.pem b/crypto/test/data/rsa3/self-testcase-F.pem new file mode 100644 index 000000000..fcc520547 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-F.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAaiR5Rnhj/vUqDgVqHaJk +0VcMuvDzkQVmUlAZlsDa3uH3CW43yAXXM6ahacYnOgpLB96aq6cI8E74hHzO6PU6 +M50LLdp+KWu5InQv7+6fgSpShRxnHBKigCuoLy6oKFkCTTnnK002Mplr8+eHZHbi +clm+k9rQejNalv+P9GSE5JcIEkTSXUDbfe81/ej9DCOcGbFPuL5hFQ8GNIuf+uv2 +OKXQtdpuayFZnD3hoWYE1LMT5W1lK1Jewx03phYeCMAY+MibRhzXWLDMBiwXpvW8 +cgCv777p+tRedunb5eLF+FT+/r617rskD9i9mJjqvoxQaXaYe++UX5mt9xpXZ9oM +1g== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-G.p12 b/crypto/test/data/rsa3/self-testcase-G.p12 new file mode 100644 index 000000000..c8184a252 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-G.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-G.pem b/crypto/test/data/rsa3/self-testcase-G.pem new file mode 100644 index 000000000..d10c2283b --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-G.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAoLujmlhRD05T4G8CQa+g +kIW/l43pazV1+iWaPnADd3/ywX7BNrVkGDaJHPci1BBq8lsiIA9nu7Gfxjl9TsZe +wwLzZ/LxI9tTR+ikYxy0MID+x45rk1dF0nnya9S3wQAXDhP8ZKN0d8ezvbQ2N2LG +74YPAtQZngMLMvYlG6MgoDNYOHHDkYZ6uL8PEwU9DtlZ+JPwxI7o7/E/T3XdDpvI +UcI15axKbD5QMqGQxZwgQYFVMDvKou1upkLQ6ymHYgEzSqNNSzTYVdhVrGgTX+xl +VZQFdJqR/gkloXbzxC/WqFTGrX1WN6kMvL+ZnVEh7DWELPmLFMfoWYCd4Q2hIjdx +MQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-H.p12 b/crypto/test/data/rsa3/self-testcase-H.p12 new file mode 100644 index 000000000..b38c9eb71 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-H.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-H.pem b/crypto/test/data/rsa3/self-testcase-H.pem new file mode 100644 index 000000000..0cab07503 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-H.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAPaezAGexMlsmptKQBlrV +iTDBKfTs555wM05d0CRzd6dq9GHYNk/BMPy0mPmpxLwuyQqjB3rw9+mlGre1jcLf +Kthaz+Vna1yIGqg5dqqdu7NUX6/8x51hKQ+8B3rmlqx3wjt+bWgo2Qgl8otrHXKY +EWrKfmTNd3z0+nklqaLFvxmQwQ33CKciw6k9A2O3DaOdf1smCfFyjF/hi4I0pJaX +vFB/CbCAF/zVmQW+uXMNooZmd+DcKsK5ZN6LzxDXC6iqqaN0WS1kmctjYQ4pOomg +5pdKfv+gUwUqUTbtL2/WeyuOcHY9XLluYk+nwtdFS25uQpmHZcQ4baeKB5N9IJy8 +jg== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-I.p12 b/crypto/test/data/rsa3/self-testcase-I.p12 new file mode 100644 index 000000000..7b97f68d6 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-I.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-I.pem b/crypto/test/data/rsa3/self-testcase-I.pem new file mode 100644 index 000000000..8717fd869 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-I.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAJanu4ytjXr/ppQEiEsJ3 +1TqGBIoASHHWZsjd4DZmigBgERJqtXK/AsTsljFrSo1lhP3Q9TFqOeikvJ5T3y4q +8yYY5qaEICsjUuySTIT3r7O00O5mtpdnpsRkBceqvBDDqfWefau00SVoBaqmt2P+ +Bq3x4l7MYqJNI8fPNVHqhSBlnWfxgYO/GZd4ZshhOZgrb96B98XpRlD5uYSlTpJt +cYvSb2s+BX4RCZIGSpoQJ0dgz3uU5H5i949fbuTbyGLVka0t8gvWN0IPoSPEp3Zj +mEw5Oz2UV0/R0qF2/yeKKNH3aFMEAzYUAmVqA5OdWiiZgLYcIm6pQvT0iAtgnT9x +rQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-J.p12 b/crypto/test/data/rsa3/self-testcase-J.p12 new file mode 100644 index 000000000..4073ea600 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-J.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-J.pem b/crypto/test/data/rsa3/self-testcase-J.pem new file mode 100644 index 000000000..c3fba7935 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-J.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEADFGQ9QEI1TU+qRg2QFLZ +OhYryOaAXNOaEBR+f0LCG5My9j0vI3/1BKHwq6kVPVDkfSPrrX1ZNUPOAI+PLrwI +RGsJw6ST8dyWXeY4LEarHOPLvSTD2u+WaPcRMJSsSTFnsscKgrAeu4VfZixOTpBp +tI3bfqTPkY9Fra8R1M9PbNsPik0WI34nPS0T9XqF+s/FhHCcL/mX/Hj5aD0qEZWd +wCSJGDyoZRQeMc7LowMGHpu1eqcqfSLt2TCPeXebVB031AioCe1iJUddb9WxHixH +GyNlzJl7YwztT9Z3yRqHKde6Dun128N2YThQ/7/Dn54hXcWQCK4gFCTz2deD5S9Z +TQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/self-testcase-L.p12 b/crypto/test/data/rsa3/self-testcase-L.p12 new file mode 100644 index 000000000..50b3b76f2 Binary files /dev/null and b/crypto/test/data/rsa3/self-testcase-L.p12 differ diff --git a/crypto/test/data/rsa3/self-testcase-L.pem b/crypto/test/data/rsa3/self-testcase-L.pem new file mode 100644 index 000000000..b9805f5b0 --- /dev/null +++ b/crypto/test/data/rsa3/self-testcase-L.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X +DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ +BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg +Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md +VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g +hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20 +69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB +9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di +PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA +AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB +jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw +EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15 +IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAoArZH56QUnasmPqCd68C +kcG6hw5S6p7wloY9jz+iwh9b2tF3k1SPCeE7rBV7cevr1ruv/wWttBFiGfJK/hlL +8C/MMPj1X5JuLY3JgNmNDSK9MLr5Ejvps0AQ+kA4CCSxxpTLWeUlqNnGk/Zcfoqa +Gyk37PDlHMQC3QWLgAX+wG/rg8WvrAP1ZjM6t25yb6hIPZgCWZbq+j8X5kS3Qxz0 +buc9HMi9oeuejeP7zWRJHhnCcDuClmpI6pk9nkjmunYtF2rMWi7f2eJ0Qjbo1wnn +rUU5sCGLZ6i3ux/HvMgynho7RVqV+bqV+G9wZem3crNbtLhUSB2SAgYZnMqrLcW9 +jQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62 +OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z +2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ +fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr +WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y +GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI +htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR +KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v +lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt +qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv +aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4 +NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP +vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz +6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT +Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4 +z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S +FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu +rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo +x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp +B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf +YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG +HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY +1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD +Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8 +5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/data/rsa3/testcases.README b/crypto/test/data/rsa3/testcases.README new file mode 100644 index 000000000..648574027 Binary files /dev/null and b/crypto/test/data/rsa3/testcases.README differ diff --git a/crypto/test/data/scrypt/TestVectors.txt b/crypto/test/data/scrypt/TestVectors.txt new file mode 100644 index 000000000..1b54dd696 --- /dev/null +++ b/crypto/test/data/scrypt/TestVectors.txt @@ -0,0 +1,20 @@ +scrypt(“”, “”, 16, 1, 1, 64) = +77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 +f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 +fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 +e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 +scrypt(“password”, “NaCl”, 1024, 8, 16, 64) = +fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe +7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 +2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da +c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 +scrypt(“pleaseletmein”, “SodiumChloride”, 16384, 8, 1, 64) = +70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb +fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 +d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 +e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 +scrypt(“pleaseletmein”, “SodiumChloride”, 1048576, 8, 1, 64) = +21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 +ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 +8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 +37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 diff --git a/crypto/test/data/tls/keystores/client_store.dsa b/crypto/test/data/tls/keystores/client_store.dsa new file mode 100644 index 000000000..77c6e47c0 Binary files /dev/null and b/crypto/test/data/tls/keystores/client_store.dsa differ diff --git a/crypto/test/data/tls/keystores/client_store.rsa b/crypto/test/data/tls/keystores/client_store.rsa new file mode 100644 index 000000000..fb4810331 Binary files /dev/null and b/crypto/test/data/tls/keystores/client_store.rsa differ diff --git a/crypto/test/data/tls/keystores/server_store.dsa b/crypto/test/data/tls/keystores/server_store.dsa new file mode 100644 index 000000000..819cecd70 Binary files /dev/null and b/crypto/test/data/tls/keystores/server_store.dsa differ diff --git a/crypto/test/data/tls/keystores/server_store.rsa b/crypto/test/data/tls/keystores/server_store.rsa new file mode 100644 index 000000000..5ade0b7b9 Binary files /dev/null and b/crypto/test/data/tls/keystores/server_store.rsa differ diff --git a/crypto/test/lib/nunit.core.dll b/crypto/test/lib/nunit.core.dll new file mode 100644 index 000000000..f58c07d42 Binary files /dev/null and b/crypto/test/lib/nunit.core.dll differ diff --git a/crypto/test/lib/nunit.core.interfaces.dll b/crypto/test/lib/nunit.core.interfaces.dll new file mode 100644 index 000000000..cdf50b687 Binary files /dev/null and b/crypto/test/lib/nunit.core.interfaces.dll differ diff --git a/crypto/test/lib/nunit.framework.dll b/crypto/test/lib/nunit.framework.dll new file mode 100644 index 000000000..c7b1c65d9 Binary files /dev/null and b/crypto/test/lib/nunit.framework.dll differ diff --git a/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs b/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs new file mode 100644 index 000000000..030da04cb --- /dev/null +++ b/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs @@ -0,0 +1,359 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class Asn1SequenceParserTest + { + private static readonly byte[] seqData = Hex.Decode("3006020100060129"); + private static readonly byte[] nestedSeqData = Hex.Decode("300b0201000601293003020101"); + private static readonly byte[] expTagSeqData = Hex.Decode("a1083006020100060129"); + private static readonly byte[] implTagSeqData = Hex.Decode("a106020100060129"); + private static readonly byte[] nestedSeqExpTagData = Hex.Decode("300d020100060129a1053003020101"); + private static readonly byte[] nestedSeqImpTagData = Hex.Decode("300b020100060129a103020101"); + + private static readonly byte[] berSeqData = Hex.Decode("30800201000601290000"); + private static readonly byte[] berDerNestedSeqData = Hex.Decode("308002010006012930030201010000"); + private static readonly byte[] berNestedSeqData = Hex.Decode("3080020100060129308002010100000000"); + private static readonly byte[] berExpTagSeqData = Hex.Decode("a180308002010006012900000000"); + private static readonly byte[] berSeqWithDERNullData = Hex.Decode("308005000201000601290000"); + + [Test] + public void TestDerWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut); + + seqGen.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen.AddObject(new DerObjectIdentifier("1.1")); + + seqGen.Close(); + + Assert.IsTrue(Arrays.AreEqual(seqData, bOut.ToArray()), "basic DER writing test failed."); + } + + [Test] + public void TestNestedDerWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut); + + seqGen1.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen1.AddObject(new DerObjectIdentifier("1.1")); + + DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream()); + + seqGen2.AddObject(new DerInteger(BigInteger.One)); + + seqGen2.Close(); + + seqGen1.Close(); + + Assert.IsTrue(Arrays.AreEqual(nestedSeqData, bOut.ToArray()), "nested DER writing test failed."); + } + + [Test] + public void TestDerExplicitTaggedSequenceWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, true); + + seqGen.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen.AddObject(new DerObjectIdentifier("1.1")); + + seqGen.Close(); + + Assert.IsTrue(Arrays.AreEqual(expTagSeqData, bOut.ToArray()), "explicit tag writing test failed."); + } + + [Test] + public void TestDerImplicitTaggedSequenceWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, false); + + seqGen.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen.AddObject(new DerObjectIdentifier("1.1")); + + seqGen.Close(); + + Assert.IsTrue(Arrays.AreEqual(implTagSeqData, bOut.ToArray()), "implicit tag writing test failed."); + } + + [Test] + public void TestNestedExplicitTagDerWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut); + + seqGen1.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen1.AddObject(new DerObjectIdentifier("1.1")); + + DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, true); + + seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1))); + + seqGen2.Close(); + + seqGen1.Close(); + + Assert.IsTrue(Arrays.AreEqual(nestedSeqExpTagData, bOut.ToArray()), "nested explicit tagged DER writing test failed."); + } + + [Test] + public void TestNestedImplicitTagDerWriting() + { + MemoryStream bOut = new MemoryStream(); + DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut); + + seqGen1.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen1.AddObject(new DerObjectIdentifier("1.1")); + + DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, false); + + seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1))); + + seqGen2.Close(); + + seqGen1.Close(); + + Assert.IsTrue(Arrays.AreEqual(nestedSeqImpTagData, bOut.ToArray()), "nested implicit tagged DER writing test failed."); + } + + [Test] + public void TestBerWriting() + { + MemoryStream bOut = new MemoryStream(); + BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut); + + seqGen.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen.AddObject(new DerObjectIdentifier("1.1")); + + seqGen.Close(); + + Assert.IsTrue(Arrays.AreEqual(berSeqData, bOut.ToArray()), "basic BER writing test failed."); + } + + [Test] + public void TestNestedBerDerWriting() + { + MemoryStream bOut = new MemoryStream(); + BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut); + + seqGen1.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen1.AddObject(new DerObjectIdentifier("1.1")); + + DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream()); + + seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1))); + + seqGen2.Close(); + + seqGen1.Close(); + + Assert.IsTrue(Arrays.AreEqual(berDerNestedSeqData, bOut.ToArray()), "nested BER/DER writing test failed."); + } + + [Test] + public void TestNestedBerWriting() + { + MemoryStream bOut = new MemoryStream(); + BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut); + + seqGen1.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen1.AddObject(new DerObjectIdentifier("1.1")); + + BerSequenceGenerator seqGen2 = new BerSequenceGenerator(seqGen1.GetRawOutputStream()); + + seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1))); + + seqGen2.Close(); + + seqGen1.Close(); + + Assert.IsTrue(Arrays.AreEqual(berNestedSeqData, bOut.ToArray()), "nested BER writing test failed."); + } + + [Test] + public void TestDerReading() + { + Asn1StreamParser aIn = new Asn1StreamParser(seqData); + + Asn1SequenceParser seq = (Asn1SequenceParser)aIn.ReadObject(); + int count = 0; + + Assert.IsNotNull(seq, "null sequence returned"); + + object o; + while ((o = seq.ReadObject()) != null) + { + switch (count) + { + case 0: + Assert.IsTrue(o is DerInteger); + break; + case 1: + Assert.IsTrue(o is DerObjectIdentifier); + break; + } + count++; + } + + Assert.AreEqual(2, count, "wrong number of objects in sequence"); + } + + private void doTestNestedReading( + byte[] data) + { + Asn1StreamParser aIn = new Asn1StreamParser(data); + + Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject(); + object o = null; + int count = 0; + + Assert.IsNotNull(seq, "null sequence returned"); + + while ((o = seq.ReadObject()) != null) + { + switch (count) + { + case 0: + Assert.IsTrue(o is DerInteger); + break; + case 1: + Assert.IsTrue(o is DerObjectIdentifier); + break; + case 2: + Assert.IsTrue(o is Asn1SequenceParser); + + Asn1SequenceParser s = (Asn1SequenceParser)o; + + // NB: Must exhaust the nested parser + while (s.ReadObject() != null) + { + // Ignore + } + + break; + } + count++; + } + + Assert.AreEqual(3, count, "wrong number of objects in sequence"); + } + + [Test] + public void TestNestedDerReading() + { + doTestNestedReading(nestedSeqData); + } + + [Test] + public void TestBerReading() + { + Asn1StreamParser aIn = new Asn1StreamParser(berSeqData); + + Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject(); + object o = null; + int count = 0; + + Assert.IsNotNull(seq, "null sequence returned"); + + while ((o = seq.ReadObject()) != null) + { + switch (count) + { + case 0: + Assert.IsTrue(o is DerInteger); + break; + case 1: + Assert.IsTrue(o is DerObjectIdentifier); + break; + } + count++; + } + + Assert.AreEqual(2, count, "wrong number of objects in sequence"); + } + + [Test] + public void TestNestedBerDerReading() + { + doTestNestedReading(berDerNestedSeqData); + } + + [Test] + public void TestNestedBerReading() + { + doTestNestedReading(berNestedSeqData); + } + + [Test] + public void TestBerExplicitTaggedSequenceWriting() + { + MemoryStream bOut = new MemoryStream(); + BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut, 1, true); + + seqGen.AddObject(new DerInteger(BigInteger.Zero)); + + seqGen.AddObject(new DerObjectIdentifier("1.1")); + + seqGen.Close(); + + Assert.IsTrue(Arrays.AreEqual(berExpTagSeqData, bOut.ToArray()), "explicit BER tag writing test failed."); + } + + [Test] + public void TestSequenceWithDerNullReading() + { + doTestParseWithNull(berSeqWithDERNullData); + } + + private void doTestParseWithNull( + byte[] data) + { + Asn1StreamParser aIn = new Asn1StreamParser(data); + Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject(); + object o; + int count = 0; + + Assert.IsNotNull(seq, "null sequence returned"); + + while ((o = seq.ReadObject()) != null) + { + switch (count) + { + case 0: + Assert.IsTrue(o is Asn1Null); + break; + case 1: + Assert.IsTrue(o is DerInteger); + break; + case 2: + Assert.IsTrue(o is DerObjectIdentifier); + break; + } + count++; + } + + Assert.AreEqual(3, count, "wrong number of objects in sequence"); + } + } +} diff --git a/crypto/test/src/asn1/test/ASN1UnitTest.cs b/crypto/test/src/asn1/test/ASN1UnitTest.cs new file mode 100644 index 000000000..88492bede --- /dev/null +++ b/crypto/test/src/asn1/test/ASN1UnitTest.cs @@ -0,0 +1,88 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + public abstract class Asn1UnitTest + : 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/crypto/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs b/crypto/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs new file mode 100644 index 000000000..ac4ff9809 --- /dev/null +++ b/crypto/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs @@ -0,0 +1,77 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class AdditionalInformationSyntaxUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "AdditionalInformationSyntax"; } + } + + public override void PerformTest() + { + 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + AdditionalInformationSyntax syntax, + DirectoryString information) + { + checkValues(syntax, information); + + syntax = AdditionalInformationSyntax.GetInstance(syntax); + + checkValues(syntax, information); + + Asn1InputStream aIn = new Asn1InputStream(syntax.ToAsn1Object().GetEncoded()); + + IAsn1String info = (IAsn1String) aIn.ReadObject(); + + syntax = AdditionalInformationSyntax.GetInstance(info); + + checkValues(syntax, information); + } + + private void checkValues( + AdditionalInformationSyntax syntax, + DirectoryString information) + { + checkMandatoryField("information", information, syntax.Information); + } + + public static void Main( + string[] args) + { + RunTest(new AdditionalInformationSyntaxUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/AdmissionSyntaxUnitTest.cs b/crypto/test/src/asn1/test/AdmissionSyntaxUnitTest.cs new file mode 100644 index 000000000..59464d212 --- /dev/null +++ b/crypto/test/src/asn1/test/AdmissionSyntaxUnitTest.cs @@ -0,0 +1,99 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class AdmissionSyntaxUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "AdmissionSyntax"; } + } + + public override void PerformTest() + { + GeneralName name = new GeneralName(new X509Name("CN=hello world")); + Asn1Sequence admissions = new DerSequence( + new Admissions(name, + new NamingAuthority(new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + AdmissionSyntax syntax, + GeneralName authority, + Asn1Sequence admissions) + { + 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.AdmissionAuthority); + + Admissions[] adm = syntax.GetContentsOfAdmissions(); + + if (adm.Length != 1 || !adm[0].Equals(admissions[0])) + { + Fail("admissions check failed"); + } + } + + public static void Main( + string[] args) + { + RunTest(new AdmissionSyntaxUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/AdmissionsUnitTest.cs b/crypto/test/src/asn1/test/AdmissionsUnitTest.cs new file mode 100644 index 000000000..edefeb830 --- /dev/null +++ b/crypto/test/src/asn1/test/AdmissionsUnitTest.cs @@ -0,0 +1,90 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class AdmissionsUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "Admissions"; } + } + + public override void PerformTest() + { + GeneralName name = new GeneralName(new X509Name("CN=hello world")); + NamingAuthority auth = new NamingAuthority(new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + Admissions admissions, + GeneralName name, + NamingAuthority auth) + { + 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.AdmissionAuthority); + checkMandatoryField("namingAuthority", auth, admissions.NamingAuthority); + } + + public static void Main( + string[] args) + { + RunTest(new AdmissionsUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/AllTests.cs b/crypto/test/src/asn1/test/AllTests.cs new file mode 100644 index 000000000..a1ae8fd48 --- /dev/null +++ b/crypto/test/src/asn1/test/AllTests.cs @@ -0,0 +1,32 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +namespace Org.BouncyCastle.Asn1.Tests +{ + public class AllTests + { + public static void Main(string[] args) + { +// junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("ASN.1 tests"); + + suite.Add(new AllTests()); + + // TODO Add these tests to RegressionTest list + suite.Add(new Asn1SequenceParserTest()); + suite.Add(new OctetStringTest()); + suite.Add(new ParseTest()); + suite.Add(new TimeTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/asn1/test/AttributeTableUnitTest.cs b/crypto/test/src/asn1/test/AttributeTableUnitTest.cs new file mode 100644 index 000000000..5dcf349cc --- /dev/null +++ b/crypto/test/src/asn1/test/AttributeTableUnitTest.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Asn1Cms = Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class AttributeTableUnitTest + : SimpleTest + { + private static readonly DerObjectIdentifier type1 = new DerObjectIdentifier("1.1.1"); + private static readonly DerObjectIdentifier type2 = new DerObjectIdentifier("1.1.2"); + private static readonly DerObjectIdentifier type3 = new DerObjectIdentifier("1.1.3"); + + public override string Name + { + get { return "AttributeTable"; } + } + + public override void PerformTest() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new Asn1Cms.Attribute(type1, new DerSet(type1)), + new Asn1Cms.Attribute(type2, new DerSet(type2))); + + Asn1Cms.AttributeTable table = new Asn1Cms.AttributeTable(v); + + Asn1Cms.Attribute a = table[type1]; + if (a == null) + { + Fail("type1 attribute not found."); + } + if (!a.AttrValues.Equals(new DerSet(type1))) + { + Fail("wrong value retrieved for type1!"); + } + + a = table[type2]; + if (a == null) + { + Fail("type2 attribute not found."); + } + if (!a.AttrValues.Equals(new DerSet(type2))) + { + Fail("wrong value retrieved for type2!"); + } + + a = table[type3]; + if (a != null) + { + Fail("type3 attribute found when none expected."); + } + + Asn1EncodableVector vec = table.GetAll(type1); + if (vec.Count != 1) + { + Fail("wrong vector size for type1."); + } + + vec = table.GetAll(type3); + if (vec.Count != 0) + { + Fail("wrong vector size for type3."); + } + + vec = table.ToAsn1EncodableVector(); + if (vec.Count != 2) + { + Fail("wrong vector size for single."); + } + + IDictionary t = table.ToDictionary(); + + if (t.Count != 2) + { + Fail("hashtable wrong size."); + } + + // multiple + + v = new Asn1EncodableVector( + new Asn1Cms.Attribute(type1, new DerSet(type1)), + new Asn1Cms.Attribute(type1, new DerSet(type2)), + new Asn1Cms.Attribute(type1, new DerSet(type3)), + new Asn1Cms.Attribute(type2, new DerSet(type2))); + + table = new Asn1Cms.AttributeTable(v); + + a = table[type1]; + if (!a.AttrValues.Equals(new DerSet(type1))) + { + Fail("wrong value retrieved for type1 multi Get!"); + } + + vec = table.GetAll(type1); + if (vec.Count != 3) + { + Fail("wrong vector size for multiple type1."); + } + + a = (Asn1Cms.Attribute)vec[0]; + if (!a.AttrValues.Equals(new DerSet(type1))) + { + Fail("wrong value retrieved for type1(0)!"); + } + + a = (Asn1Cms.Attribute)vec[1]; + if (!a.AttrValues.Equals(new DerSet(type2))) + { + Fail("wrong value retrieved for type1(1)!"); + } + + a = (Asn1Cms.Attribute)vec[2]; + if (!a.AttrValues.Equals(new DerSet(type3))) + { + Fail("wrong value retrieved for type1(2)!"); + } + + vec = table.GetAll(type2); + if (vec.Count != 1) + { + Fail("wrong vector size for multiple type2."); + } + + vec = table.ToAsn1EncodableVector(); + if (vec.Count != 4) + { + Fail("wrong vector size for multiple."); + } + } + + public static void Main( + string[] args) + { + RunTest(new AttributeTableUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/BiometricDataUnitTest.cs b/crypto/test/src/asn1/test/BiometricDataUnitTest.cs new file mode 100644 index 000000000..a542f71af --- /dev/null +++ b/crypto/test/src/asn1/test/BiometricDataUnitTest.cs @@ -0,0 +1,133 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class BiometricDataUnitTest + : SimpleTest + { + public override string Name + { + get { return "BiometricData"; } + } + + private byte[] GenerateHash() + { + Random rand = new Random(); + byte[] bytes = new byte[20]; + rand.NextBytes(bytes); + return bytes; + } + + public override void PerformTest() + { + TypeOfBiometricData dataType = new TypeOfBiometricData(TypeOfBiometricData.HandwrittenSignature); + 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 (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + BiometricData bd, + TypeOfBiometricData dataType, + AlgorithmIdentifier hashAlgorithm, + Asn1OctetString dataHash, + DerIA5String dataUri) + { + CheckValues(bd, dataType, hashAlgorithm, dataHash, dataUri); + + bd = BiometricData.GetInstance(bd); + + CheckValues(bd, dataType, hashAlgorithm, dataHash, dataUri); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(bd.ToAsn1Object().GetEncoded()); + + 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.TypeOfBiometricData.Equals(dataType)) + { + Fail("types don't match."); + } + + if (!bd.HashAlgorithm.Equals(algID)) + { + Fail("hash algorithms don't match."); + } + + if (!bd.BiometricDataHash.Equals(dataHash)) + { + Fail("hash algorithms don't match."); + } + + if (sourceDataURI != null) + { + if (!bd.SourceDataUri.Equals(sourceDataURI)) + { + Fail("data uris don't match."); + } + } + else if (bd.SourceDataUri != null) + { + Fail("data uri found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new BiometricDataUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/BitStringConstantTester.cs b/crypto/test/src/asn1/test/BitStringConstantTester.cs new file mode 100644 index 000000000..bb966d3e4 --- /dev/null +++ b/crypto/test/src/asn1/test/BitStringConstantTester.cs @@ -0,0 +1,25 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tests +{ + public class BitStringConstantTester + { + private static readonly 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 ArgumentException("bit value " + bitNo + " wrong"); + } + } + } +} diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs new file mode 100644 index 000000000..3a2dc3156 --- /dev/null +++ b/crypto/test/src/asn1/test/BitStringTest.cs @@ -0,0 +1,82 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class BitStringTest + : ITest + { + public ITestResult Perform() + { + KeyUsage k = new KeyUsage(KeyUsage.DigitalSignature); + if ((k.GetBytes()[0] != (byte)KeyUsage.DigitalSignature) || (k.PadBits != 7)) + { + return new SimpleTestResult(false, Name + ": failed digitalSignature"); + } + + k = new KeyUsage(KeyUsage.NonRepudiation); + if ((k.GetBytes()[0] != (byte)KeyUsage.NonRepudiation) || (k.PadBits != 6)) + { + return new SimpleTestResult(false, Name + ": failed nonRepudiation"); + } + + k = new KeyUsage(KeyUsage.KeyEncipherment); + if ((k.GetBytes()[0] != (byte)KeyUsage.KeyEncipherment) || (k.PadBits != 5)) + { + return new SimpleTestResult(false, Name + ": failed keyEncipherment"); + } + + k = new KeyUsage(KeyUsage.CrlSign); + if ((k.GetBytes()[0] != (byte)KeyUsage.CrlSign) || (k.PadBits != 1)) + { + return new SimpleTestResult(false, Name + ": failed cRLSign"); + } + + k = new KeyUsage(KeyUsage.DecipherOnly); + if ((k.GetBytes()[1] != (byte)(KeyUsage.DecipherOnly >> 8)) || (k.PadBits != 7)) + { + return new SimpleTestResult(false, Name + ": failed decipherOnly"); + } + + // test for zero length bit string + try + { + Asn1Object.FromByteArray(new DerBitString(new byte[0], 0).GetEncoded()); + } + catch (IOException e) + { + return new SimpleTestResult(false, Name + ": " + e); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public string Name + { + get { return "BitString"; } + } + + public static void Main( + string[] args) + { + ITest test = new BitStringTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CMSTest.cs b/crypto/test/src/asn1/test/CMSTest.cs new file mode 100644 index 000000000..1afb363af --- /dev/null +++ b/crypto/test/src/asn1/test/CMSTest.cs @@ -0,0 +1,306 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CmsTest + : ITest + { + // + // compressed data object + // + private static readonly 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 + // + private static readonly byte[] envDataKeyTrns = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1Cb3Vu" + + "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASBgC5vdGrB" + + "itQSGwifLf3KwPILjaB4WEXgT/IIO1KDzrsbItCJsMA0Smq2y0zptxT0pSRL6JRg" + + "NMxLk1ySnrIrvGiEPLMR1zjxlT8yQ6VLX+kEoK43ztd1aaLw0oBfrcXcLN7BEpZ1" + + "TIdjlBfXIOx1S88WY1MiYqJJFc3LMwRUaTEDMIAGCSqGSIb3DQEHATAdBglghkgB" + + "ZQMEARYEEAfxLMWeaBOTTZQwUq0Y5FuggAQgwOJhL04rjSZCBCSOv5i5XpFfGsOd" + + "YSHSqwntGpFqCx4AAAAAAAAAAAAA"); + + private static readonly byte[] envDataKEK = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxUqJQAgEEMAcEBQECAwQFMBAGCyqGSIb3DQEJE" + + "AMHAgE6BDC7G/HyUPilIrin2Yeajqmj795VoLWETRnZAAFcAiQdoQWyz+oCh6WY/H" + + "jHHi+0y+cwgAYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiY3eDBBbF6naCABBiNdzJb" + + "/v6+UZB3XXKipxFDUpz9GyjzB+gAAAAAAAAAAAAA"); + + private static readonly 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 + // + private static readonly 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 static void Touch(object o) + { + } + + private ITestResult CompressionTest() + { + try + { + ContentInfo info = ContentInfo.GetInstance( + Asn1Object.FromByteArray(compData)); + CompressedData data = CompressedData.GetInstance(info.Content); + + data = new CompressedData(data.CompressionAlgorithmIdentifier, data.EncapContentInfo); + info = new ContentInfo(CmsObjectIdentifiers.CompressedData, data); + + if (!Arrays.AreEqual(info.GetEncoded(), compData)) + { + return new SimpleTestResult(false, Name + ": CMS compression failed to re-encode"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": CMS compression failed - " + e.ToString(), e); + } + } + + private ITestResult EnvelopedTest() + { + try + { + // Key trans + ContentInfo info = ContentInfo.GetInstance( + Asn1Object.FromByteArray(envDataKeyTrns)); + EnvelopedData envData = EnvelopedData.GetInstance(info.Content); + Asn1Set s = envData.RecipientInfos; + + if (s.Count != 1) + { + return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped, wrong number of recipients"); + } + + RecipientInfo recip = RecipientInfo.GetInstance(s[0]); + + if (recip.Info is KeyTransRecipientInfo) + { + KeyTransRecipientInfo inf = KeyTransRecipientInfo.GetInstance(recip.Info); + + inf = new KeyTransRecipientInfo(inf.RecipientIdentifier, inf.KeyEncryptionAlgorithm, inf.EncryptedKey); + + s = new DerSet(new RecipientInfo(inf)); + } + else + { + return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped, wrong recipient type"); + } + + envData = new EnvelopedData(envData.OriginatorInfo, s, envData.EncryptedContentInfo, envData.UnprotectedAttrs); + info = new ContentInfo(CmsObjectIdentifiers.EnvelopedData, envData); + + if (!Arrays.AreEqual(info.GetEncoded(), envDataKeyTrns)) + { + return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped failed to re-encode"); + } + + + // KEK + info = ContentInfo.GetInstance( + Asn1Object.FromByteArray(envDataKEK)); + envData = EnvelopedData.GetInstance(info.Content); + s = envData.RecipientInfos; + + if (s.Count != 1) + { + return new SimpleTestResult(false, Name + ": CMS KEK enveloped, wrong number of recipients"); + } + + recip = RecipientInfo.GetInstance(s[0]); + + if (recip.Info is KekRecipientInfo) + { + KekRecipientInfo inf = KekRecipientInfo.GetInstance(recip.Info); + + inf = new KekRecipientInfo(inf.KekID, inf.KeyEncryptionAlgorithm, inf.EncryptedKey); + + s = new DerSet(new RecipientInfo(inf)); + } + else + { + return new SimpleTestResult(false, Name + ": CMS KEK enveloped, wrong recipient type"); + } + + envData = new EnvelopedData(envData.OriginatorInfo, s, envData.EncryptedContentInfo, envData.UnprotectedAttrs); + info = new ContentInfo(CmsObjectIdentifiers.EnvelopedData, envData); + + if (!Arrays.AreEqual(info.GetEncoded(), envDataKEK)) + { + return new SimpleTestResult(false, Name + ": CMS KEK enveloped failed to re-encode"); + } + + // Nested NDEF problem + Asn1StreamParser asn1In = new Asn1StreamParser(new MemoryStream(envDataNestedNDEF, false)); + ContentInfoParser ci = new ContentInfoParser((Asn1SequenceParser)asn1In.ReadObject()); + EnvelopedDataParser ed = new EnvelopedDataParser((Asn1SequenceParser)ci + .GetContent(Asn1Tags.Sequence)); + Touch(ed.Version); + ed.GetOriginatorInfo(); + ed.GetRecipientInfos().ToAsn1Object(); + EncryptedContentInfoParser eci = ed.GetEncryptedContentInfo(); + Touch(eci.ContentType); + Touch(eci.ContentEncryptionAlgorithm); + + Stream dataIn = ((Asn1OctetStringParser)eci.GetEncryptedContent(Asn1Tags.OctetString)) + .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.ToAsn1Object(); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": CMS enveloped failed - " + e.ToString(), e); + } + } + + private ITestResult SignedTest() + { + try + { + ContentInfo info = ContentInfo.GetInstance( + Asn1Object.FromByteArray(signedData)); + SignedData sData = SignedData.GetInstance(info.Content); + + sData = new SignedData(sData.DigestAlgorithms, sData.EncapContentInfo, sData.Certificates, sData.CRLs, sData.SignerInfos); + info = new ContentInfo(CmsObjectIdentifiers.SignedData, sData); + + if (!Arrays.AreEqual(info.GetEncoded(), signedData)) + { + return new SimpleTestResult(false, Name + ": CMS signed failed to re-encode"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": CMS signed failed - " + e.ToString(), e); + } + } + + public ITestResult Perform() + { + ITestResult res = CompressionTest(); + + if (!res.IsSuccessful()) + { + return res; + } + + res = EnvelopedTest(); + if (!res.IsSuccessful()) + { + return res; + } + + return SignedTest(); + } + + public string Name + { + get { return "CMS"; } + } + + public static void Main( + string[] args) + { + ITest test = new CmsTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CertHashUnitTest.cs b/crypto/test/src/asn1/test/CertHashUnitTest.cs new file mode 100644 index 000000000..1e271a9c0 --- /dev/null +++ b/crypto/test/src/asn1/test/CertHashUnitTest.cs @@ -0,0 +1,93 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.Ocsp; +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CertHashUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "CertHash"; } + } + + public override void PerformTest() + { + AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + CertHash certHash, + AlgorithmIdentifier algId, + byte[] digest) + { + 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.HashAlgorithm); + + checkMandatoryField("certificateHash", digest, certHash.CertificateHash); + } + + public static void Main( + string[] args) + { + RunTest(new CertHashUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CertificateTest.cs b/crypto/test/src/asn1/test/CertificateTest.cs new file mode 100644 index 000000000..532e81aba --- /dev/null +++ b/crypto/test/src/asn1/test/CertificateTest.cs @@ -0,0 +1,395 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CertificateTest + : SimpleTest + { + // + // server.crt + // + private static readonly 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 + // + private static readonly 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 + // + private static readonly byte[] cert3 = Base64.Decode( + "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" + + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" + + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" + + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" + + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" + + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" + + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" + + "zl9HYIMxATFyqSiD9jsx"); + + // + // v3-cert1.pem + // + private static readonly 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 + // + private static readonly 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="); + + private static readonly 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=="); + + private static readonly 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"); + + private static readonly byte[] cert8 = Base64.Decode( + "MIIB0zCCATwCAQEwbqBsMGekZTBjMQswCQYDVQQGEwJERTELMAkGA1UECBMCQlkx" + + "EzARBgNVBAcTClJlZ2Vuc2J1cmcxEDAOBgNVBAoTB0FDIFRlc3QxCzAJBgNVBAsT" + + "AkNBMRMwEQYDVQQDEwpBQyBUZXN0IENBAgEBoHYwdKRyMHAxCzAJBgNVBAYTAkRF" + + "MQswCQYDVQQIEwJCWTETMBEGA1UEBxMKUmVnZW5zYnVyZzESMBAGA1UEChMJQUMg" + + "SXNzdWVyMRowGAYDVQQLExFBQyBJc3N1ZXIgc2VjdGlvbjEPMA0GA1UEAxMGQUMg" + + "TWFuMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIwMDQxMTI2MTI1MjUxWhgPMjAwNDEy" + + "MzEyMzAwMDBaMBkwFwYDVRhIMRAwDoEMREFVMTIzNDU2Nzg5MA0GCSqGSIb3DQEB" + + "BQUAA4GBABd4Odx3yEMGL/BvItuT1RafNR2uuWuZbajg0pD6bshUsl+WCIfRiEkq" + + "lHMkpI7WqAZikdnAEQ5jQsVWEuVejWxR6gjejKxc0fb9qpIui7/GoI5Eh6dmG20e" + + "xbwJL3+6YYFrZwxR8cC5rPvWrblUR5XKJy+Zp/H5+t9iANnL1L8J"); + + private static readonly 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 override string Name + { + get { return "Certificate"; } + } + + public void CheckCertificate( + int id, + byte[] cert) + { + Asn1Object seq = Asn1Object.FromByteArray(cert); + string dump = Asn1Dump.DumpAsString(seq); + + X509CertificateStructure obj = X509CertificateStructure.GetInstance(seq); + TbsCertificateStructure tbsCert = obj.TbsCertificate; + + if (!tbsCert.Subject.ToString().Equals(subjects[id - 1])) + { + Fail("failed subject test for certificate id " + id + + " got " + tbsCert.Subject.ToString()); + } + + if (tbsCert.Version == 3) + { + X509Extensions ext = tbsCert.Extensions; + if (ext != null) + { + foreach (DerObjectIdentifier oid in ext.ExtensionOids) + { + X509Extension extVal = ext.GetExtension(oid); + Asn1Object extObj = Asn1Object.FromByteArray(extVal.Value.GetOctets()); + + if (oid.Equals(X509Extensions.SubjectKeyIdentifier)) + { + SubjectKeyIdentifier.GetInstance(extObj); + } + else if (oid.Equals(X509Extensions.KeyUsage)) + { + KeyUsage.GetInstance(extObj); + } + else if (oid.Equals(X509Extensions.ExtendedKeyUsage)) + { + ExtendedKeyUsage ku = ExtendedKeyUsage.GetInstance(extObj); + + Asn1Sequence sq = (Asn1Sequence)ku.ToAsn1Object(); + for (int i = 0; i != sq.Count; i++) + { + KeyPurposeID.GetInstance(sq[i]); + } + } + else if (oid.Equals(X509Extensions.SubjectAlternativeName)) + { + GeneralNames gn = GeneralNames.GetInstance(extObj); + + Asn1Sequence sq = (Asn1Sequence)gn.ToAsn1Object(); + for (int i = 0; i != sq.Count; i++) + { + GeneralName.GetInstance(sq[i]); + } + } + else if (oid.Equals(X509Extensions.IssuerAlternativeName)) + { + GeneralNames gn = GeneralNames.GetInstance(extObj); + + Asn1Sequence sq = (Asn1Sequence)gn.ToAsn1Object(); + for (int i = 0; i != sq.Count; i++) + { + GeneralName.GetInstance(sq[i]); + } + } + else if (oid.Equals(X509Extensions.CrlDistributionPoints)) + { + CrlDistPoint p = CrlDistPoint.GetInstance(extObj); + + DistributionPoint[] points = p.GetDistributionPoints(); + for (int i = 0; i != points.Length; i++) + { + // do nothing + } + } + else if (oid.Equals(X509Extensions.CertificatePolicies)) + { + Asn1Sequence cp = (Asn1Sequence) extObj; + + for (int i = 0; i != cp.Count; i++) + { + PolicyInformation.GetInstance(cp[i]); + } + } + else if (oid.Equals(X509Extensions.AuthorityKeyIdentifier)) + { + AuthorityKeyIdentifier.GetInstance(extObj); + } + else if (oid.Equals(X509Extensions.BasicConstraints)) + { + BasicConstraints.GetInstance(extObj); + } + else + { + //Console.WriteLine(oid.Id); + } + } + } + } + } + + public void CheckAttributeCertificate( + int id, + byte[] cert) + { + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(cert); + string dump = Asn1Dump.DumpAsString(seq); + + AttributeCertificate obj = AttributeCertificate.GetInstance(seq); + AttributeCertificateInfo acInfo = obj.ACInfo; + + // Version + if (!(acInfo.Version.Equals(new DerInteger(1))) + && (!(acInfo.Version.Equals(new DerInteger(2))))) + { + Fail("failed AC Version test for id " + id); + } + + // Holder + Holder h = acInfo.Holder; + if (h == null) + { + Fail("failed AC Holder test, it's null, for id " + id); + } + + // Issuer + AttCertIssuer aci = acInfo.Issuer; + if (aci == null) + { + Fail("failed AC Issuer test, it's null, for id " + id); + } + + // Signature + AlgorithmIdentifier sig = acInfo.Signature; + if (sig == null) + { + Fail("failed AC Signature test for id " + id); + } + + // Serial + DerInteger serial = acInfo.SerialNumber; + + // Validity + AttCertValidityPeriod validity = acInfo.AttrCertValidityPeriod; + if (validity == null) + { + Fail("failed AC AttCertValidityPeriod test for id " + id); + } + + // Attributes + Asn1Sequence attribSeq = acInfo.Attributes; + AttributeX509[] att = new AttributeX509[attribSeq.Count]; + for (int i = 0; i < attribSeq.Count; i++) + { + att[i] = AttributeX509.GetInstance(attribSeq[i]); + } + + // IssuerUniqueId + // TODO, how to best test? + + // X509 Extensions + X509Extensions ext = acInfo.Extensions; + if (ext != null) + { + foreach (DerObjectIdentifier oid in ext.ExtensionOids) + { + X509Extension extVal = ext.GetExtension(oid); + } + } + } + + public override void PerformTest() + { + CheckCertificate(1, cert1); + CheckCertificate(2, cert2); + CheckCertificate(3, cert3); + CheckCertificate(4, cert4); + CheckCertificate(5, cert5); + CheckCertificate(6, cert6); + CheckCertificate(7, cert7); + CheckAttributeCertificate(8, cert8); + } + + public static void Main( + string[] args) + { + RunTest(new CertificateTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs b/crypto/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs new file mode 100644 index 000000000..20c2d18e3 --- /dev/null +++ b/crypto/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs @@ -0,0 +1,107 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Esf; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CommitmentTypeIndicationUnitTest + : SimpleTest + { + public override string Name + { + get { return "CommitmentTypeIndication"; } + } + + public override void PerformTest() + { + CommitmentTypeIndication cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.ProofOfOrigin); + + CheckConstruction(cti, CommitmentTypeIdentifier.ProofOfOrigin, null); + + Asn1Sequence qualifier = new DerSequence(new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + CommitmentTypeIndication mv, + DerObjectIdentifier commitmenttTypeId, + Asn1Encodable qualifier) + { + CheckStatement(mv, commitmenttTypeId, qualifier); + + mv = CommitmentTypeIndication.GetInstance(mv); + + CheckStatement(mv, commitmenttTypeId, qualifier); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + mv.ToAsn1Object().GetEncoded()); + + mv = CommitmentTypeIndication.GetInstance(seq); + + CheckStatement(mv, commitmenttTypeId, qualifier); + } + + private void CheckStatement( + CommitmentTypeIndication cti, + DerObjectIdentifier commitmentTypeId, + Asn1Encodable qualifier) + { + if (!cti.CommitmentTypeID.Equals(commitmentTypeId)) + { + Fail("commitmentTypeIds don't match."); + } + + if (qualifier != null) + { + if (!cti.CommitmentTypeQualifier.Equals(qualifier)) + { + Fail("qualifiers don't match."); + } + } + else if (cti.CommitmentTypeQualifier != null) + { + Fail("qualifier found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new CommitmentTypeIndicationUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs b/crypto/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs new file mode 100644 index 000000000..192ac52f6 --- /dev/null +++ b/crypto/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs @@ -0,0 +1,107 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Esf; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CommitmentTypeQualifierUnitTest + : SimpleTest + { + public override string Name + { + get { return "CommitmentTypeQualifier"; } + } + + public override void PerformTest() + { + CommitmentTypeQualifier ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.ProofOfOrigin); + + CheckConstruction(ctq, CommitmentTypeIdentifier.ProofOfOrigin, null); + + Asn1Encodable info = new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + CommitmentTypeQualifier mv, + DerObjectIdentifier commitmenttTypeId, + Asn1Encodable qualifier) + { + CheckStatement(mv, commitmenttTypeId, qualifier); + + mv = CommitmentTypeQualifier.GetInstance(mv); + + CheckStatement(mv, commitmenttTypeId, qualifier); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + mv.ToAsn1Object().GetEncoded()); + + mv = CommitmentTypeQualifier.GetInstance(seq); + + CheckStatement(mv, commitmenttTypeId, qualifier); + } + + private void CheckStatement( + CommitmentTypeQualifier ctq, + DerObjectIdentifier commitmentTypeId, + Asn1Encodable qualifier) + { + if (!ctq.CommitmentTypeIdentifier.Equals(commitmentTypeId)) + { + Fail("commitmentTypeIds don't match."); + } + + if (qualifier != null) + { + if (!ctq.Qualifier.Equals(qualifier)) + { + Fail("qualifiers don't match."); + } + } + else if (ctq.Qualifier != null) + { + Fail("qualifier found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new CommitmentTypeQualifierUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/ContentHintsUnitTest.cs b/crypto/test/src/asn1/test/ContentHintsUnitTest.cs new file mode 100644 index 000000000..d7453c27e --- /dev/null +++ b/crypto/test/src/asn1/test/ContentHintsUnitTest.cs @@ -0,0 +1,93 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Ess; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class ContentHintsUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "ContentHints"; } + } + + public override void PerformTest() + { + DerUtf8String contentDescription = new DerUtf8String("Description"); + DerObjectIdentifier contentType = new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + ContentHints hints, + DerObjectIdentifier contentType, + DerUtf8String description) + { + checkValues(hints, contentType, description); + + hints = ContentHints.GetInstance(hints); + + checkValues(hints, contentType, description); + + Asn1InputStream aIn = new Asn1InputStream(hints.ToAsn1Object().GetEncoded()); + + Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject(); + + hints = ContentHints.GetInstance(seq); + + checkValues(hints, contentType, description); + } + + private void checkValues( + ContentHints hints, + DerObjectIdentifier contentType, + DerUtf8String description) + { + checkMandatoryField("contentType", contentType, hints.ContentType); + checkOptionalField("description", description, hints.ContentDescription); + } + + public static void Main( + string[] args) + { + RunTest(new ContentHintsUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/CscaMasterListTest.cs b/crypto/test/src/asn1/test/CscaMasterListTest.cs new file mode 100644 index 000000000..814e98b2a --- /dev/null +++ b/crypto/test/src/asn1/test/CscaMasterListTest.cs @@ -0,0 +1,57 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Icao; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class CscaMasterListTest + : SimpleTest + { + public override string Name + { + get { return "CscaMasterList"; } + } + + public override void PerformTest() + { + byte[] input = GetInput("masterlist-content.data"); + CscaMasterList parsedList = CscaMasterList.GetInstance(Asn1Object.FromByteArray(input)); + + if (parsedList.GetCertStructs().Length != 3) + { + Fail("Cert structure parsing failed: incorrect length"); + } + + byte[] output = parsedList.GetEncoded(); + if (!AreEqual(input, output)) + { + Fail("Encoding failed after parse"); + } + } + + private byte[] GetInput(string name) + { + return Streams.ReadAll(SimpleTest.GetTestDataAsStream("asn1." + name)); + } + + public static void Main( + string[] args) + { + RunTest(new CscaMasterListTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs b/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs new file mode 100644 index 000000000..a61ae87e8 --- /dev/null +++ b/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs @@ -0,0 +1,88 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class DerApplicationSpecificTest + : SimpleTest + { + private static readonly byte[] impData = Hex.Decode("430109"); + + private static readonly byte[] certData = Hex.Decode( + "7F218201897F4E8201495F290100420E44454356434145504153533030317F49" + + "81FD060A04007F00070202020202811CD7C134AA264366862A18302575D1D787" + + "B09F075797DA89F57EC8C0FF821C68A5E62CA9CE6C1C299803A6C1530B514E18" + + "2AD8B0042A59CAD29F43831C2580F63CCFE44138870713B1A92369E33E2135D2" + + "66DBB372386C400B8439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C" + + "1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D376" + + "1402CD851CD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A793" + + "9F863904393EE8E06DB6C7F528F8B4260B49AA93309824D92CDB1807E5437EE2" + + "E26E29B73A7111530FA86B350037CB9415E153704394463797139E148701015F" + + "200E44454356434145504153533030317F4C0E060904007F0007030102015301" + + "C15F25060007000400015F24060009000400015F37384CCF25C59F3612EEE188" + + "75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310" + + "7F9B0DADA16414FFA204516AEE2B"); + + public override string Name + { + get { return "DerApplicationSpecific"; } + } + + public override void PerformTest() + { + DerInteger val = new DerInteger(9); + + DerApplicationSpecific tagged = new DerApplicationSpecific(false, 3, val); + + if (!AreEqual(impData, tagged.GetEncoded())) + { + Fail("implicit encoding failed"); + } + + DerInteger recVal = (DerInteger) tagged.GetObject(Asn1Tags.Integer); + + if (!val.Equals(recVal)) + { + Fail("implicit read back failed"); + } + + DerApplicationSpecific certObj = (DerApplicationSpecific) + Asn1Object.FromByteArray(certData); + + if (!certObj.IsConstructed() || certObj.ApplicationTag != 33) + { + Fail("parsing of certificate data failed"); + } + + byte[] encoded = certObj.GetDerEncoded(); + + if (!Arrays.AreEqual(certData, encoded)) + { + Console.WriteLine(Encoding.ASCII.GetString(certData, 0, certData.Length).Substring(0, 20)); + Console.WriteLine(Encoding.ASCII.GetString(encoded, 0, encoded.Length).Substring(0, 20)); + Fail("re-encoding of certificate data failed"); + } + } + + public static void Main( + string[] args) + { + RunTest(new DerApplicationSpecificTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/DERUTF8StringTest.cs b/crypto/test/src/asn1/test/DERUTF8StringTest.cs new file mode 100644 index 000000000..be4dace79 --- /dev/null +++ b/crypto/test/src/asn1/test/DERUTF8StringTest.cs @@ -0,0 +1,113 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class DerUtf8StringTest + : ITest + { + /** + * Unicode code point U+10400 coded as surrogate in two native Java UTF-16 + * code units + */ + private readonly static char[] glyph1_utf16 = { (char)0xd801, (char)0xdc00 }; + + /** + * U+10400 coded in UTF-8 + */ + private readonly static byte[] glyph1_utf8 = { (byte)0xF0, (byte)0x90, (byte)0x90, (byte)0x80 }; + + /** + * Unicode code point U+6771 in native Java UTF-16 + */ + private readonly static char[] glyph2_utf16 = { (char)0x6771 }; + + /** + * U+6771 coded in UTF-8 + */ + private readonly static byte[] glyph2_utf8 = { (byte)0xE6, (byte)0x9D, (byte)0xB1 }; + + /** + * Unicode code point U+00DF in native Java UTF-16 + */ + private readonly static char[] glyph3_utf16 = { (char)0x00DF }; + + /** + * U+00DF coded in UTF-8 + */ + private readonly static byte[] glyph3_utf8 = { (byte)0xC3, (byte)0x9f }; + + /** + * Unicode code point U+0041 in native Java UTF-16 + */ + private readonly static char[] glyph4_utf16 = { (char)0x0041 }; + + /** + * U+0041 coded in UTF-8 + */ + private readonly static byte[] glyph4_utf8 = { 0x41 }; + + private readonly static byte[][] glyphs_utf8 = { glyph1_utf8, glyph2_utf8, glyph3_utf8, glyph4_utf8 }; + + private readonly static char[][] glyphs_utf16 = { glyph1_utf16, glyph2_utf16, glyph3_utf16, glyph4_utf16 }; + + public ITestResult 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]; + Array.Copy(b1, 2, temp, 0, b1.Length - 2); + byte[] b2 = new DerUtf8String(new DerOctetString(temp).GetOctets()).GetEncoded(); + if (!Arrays.AreEqual(b1, b2)) + { + return new SimpleTestResult(false, Name + ": failed UTF-8 encoding and decoding"); + } + if (!Arrays.AreEqual(temp, glyphs_utf8[i])) + { + return new SimpleTestResult(false, Name + ": failed UTF-8 encoding and decoding"); + } + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed with Exception " + e.Message); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public string Name + { + get + { + return "DERUTF8String"; + } + } + + public static void Main( + string[] args) + { + DerUtf8StringTest test = new DerUtf8StringTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/DataGroupHashUnitTest.cs b/crypto/test/src/asn1/test/DataGroupHashUnitTest.cs new file mode 100644 index 000000000..dcebf4670 --- /dev/null +++ b/crypto/test/src/asn1/test/DataGroupHashUnitTest.cs @@ -0,0 +1,106 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Icao; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class DataGroupHashUnitTest + : SimpleTest + { + public override string Name + { + get { return "DataGroupHash"; } + } + + private byte[] GenerateHash() + { + Random rand = new Random(); + byte[] bytes = new byte[20]; + rand.NextBytes(bytes); + return bytes; + } + + public override void PerformTest() + { + int dataGroupNumber = 1; + Asn1OctetString dataHash = new DerOctetString(GenerateHash()); + DataGroupHash dg = new DataGroupHash(dataGroupNumber, dataHash); + + CheckConstruction(dg, dataGroupNumber, dataHash); + + try + { + DataGroupHash.GetInstance(null); + } + catch (Exception) + { + Fail("GetInstance() failed to handle null."); + } + + try + { + DataGroupHash.GetInstance(new object()); + + Fail("GetInstance() failed to detect bad object."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + DataGroupHash dg, + int dataGroupNumber, + Asn1OctetString dataGroupHashValue) + { + CheckValues(dg, dataGroupNumber, dataGroupHashValue); + + dg = DataGroupHash.GetInstance(dg); + + CheckValues(dg, dataGroupNumber, dataGroupHashValue); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + dg.ToAsn1Object().GetEncoded()); + + dg = DataGroupHash.GetInstance(seq); + + CheckValues(dg, dataGroupNumber, dataGroupHashValue); + } + + private void CheckValues( + DataGroupHash dg, + int dataGroupNumber, + Asn1OctetString dataGroupHashValue) + { + if (dg.DataGroupNumber != dataGroupNumber) + { + Fail("group number don't match."); + } + + if (!dg.DataGroupHashValue.Equals(dataGroupHashValue)) + { + Fail("hash value don't match."); + } + } + + public static void Main( + string[] args) + { + RunTest(new DataGroupHashUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs b/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs new file mode 100644 index 000000000..bd1fb5a9e --- /dev/null +++ b/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs @@ -0,0 +1,97 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class DeclarationOfMajorityUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "DeclarationOfMajority"; } + } + + public override void PerformTest() + { + DerGeneralizedTime dateOfBirth = new DerGeneralizedTime("20070315173729Z"); + DeclarationOfMajority decl = new DeclarationOfMajority(dateOfBirth); + + checkConstruction(decl, DeclarationOfMajority.Choice.DateOfBirth, dateOfBirth, -1); + + decl = new DeclarationOfMajority(6); + + checkConstruction(decl, DeclarationOfMajority.Choice.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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + DeclarationOfMajority decl, + DeclarationOfMajority.Choice type, + DerGeneralizedTime dateOfBirth, + int notYoungerThan) + { + 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, + DeclarationOfMajority.Choice type, + DerGeneralizedTime dateOfBirth, + int notYoungerThan) + { + checkMandatoryField("type", (int) type, (int) decl.Type); + checkOptionalField("dateOfBirth", dateOfBirth, decl.DateOfBirth); + if (notYoungerThan != -1 && notYoungerThan != decl.NotYoungerThan) + { + Fail("notYoungerThan mismatch"); + } + } + + public static void Main( + string[] args) + { + RunTest(new DeclarationOfMajorityUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs b/crypto/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs new file mode 100644 index 000000000..a84df59cc --- /dev/null +++ b/crypto/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs @@ -0,0 +1,152 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * Test the reading and writing of EncryptedPrivateKeyInfo objects using + * the test vectors provided at + * + * RSA's Pkcs5 Page. + *
    + * The vectors are Base 64 encoded and encrypted using the password "password" + * (without quotes). They should all yield the same PrivateKeyInfo object. + */ + [TestFixture] + public class EncryptedPrivateKeyInfoTest + : ITest + { + 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 Name + { + get { return "EncryptedPrivateKeyInfoTest"; } + } + + private ITestResult DoTest( + int id, + byte[] sample) + { + EncryptedPrivateKeyInfo info; + try + { + info = EncryptedPrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(sample)); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": test " + id + " failed construction - exception " + + e.ToString()); + } + + byte[] bytes; + try + { + bytes = info.GetDerEncoded(); + } + catch (Exception e) + { + return new SimpleTestResult(false, + Name + ": test " + id + " failed writing - exception " + e.ToString()); + } + + if (!Arrays.AreEqual(bytes, sample)) + { + try + { + Asn1Object obj = Asn1Object.FromByteArray(bytes); + + return new SimpleTestResult(false, Name + ": test " + id + + " length mismatch - expected " + sample.Length + SimpleTest.NewLine + + Asn1Dump.DumpAsString(info) + " got " + bytes.Length + SimpleTest.NewLine + + Asn1Dump.DumpAsString(obj)); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": test " + id + " data mismatch - exception " + e.ToString()); + } + } + + return new SimpleTestResult(true, Name + ": test " + id + " Okay"); + } + + public ITestResult Perform() + { + ITestResult result = DoTest(0, sample1); + if (!result.IsSuccessful()) + { + return result; + } + + result = DoTest(1, sample2); + if (!result.IsSuccessful()) + { + return result; + } + + result = DoTest(2, sample3); + if (!result.IsSuccessful()) + { + return result; + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new EncryptedPrivateKeyInfoTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs new file mode 100644 index 000000000..21172f816 --- /dev/null +++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class EqualsAndHashCodeTest + : SimpleTest + { + public override void PerformTest() + { + byte[] data = { 0, 1, 0, 1, 0, 0, 1 }; + + Asn1Object[] values = + { + new BerOctetString(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"), + DerBoolean.True, + DerBoolean.False, + new DerEnumerated(100), + new DerGeneralizedTime("20070315173729Z"), + new DerGeneralString("hello world"), + new DerIA5String("hello"), + new DerInteger(1000), + DerNull.Instance, + new DerNumericString("123456"), + new DerObjectIdentifier("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 DerUnknownTag(true, 500, data), + new DerUtcTime(new DateTime()), + new DerUtf8String("hello world"), + new DerVisibleString("hello world") + }; + + MemoryStream bOut = new MemoryStream(); + Asn1OutputStream aOut = new Asn1OutputStream(bOut); + + for (int i = 0; i != values.Length; i++) + { + aOut.WriteObject(values[i]); + } + + Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray()); + + for (int i = 0; i != values.Length; i++) + { + Asn1Object o = aIn.ReadObject(); + if (!o.Equals(values[i])) + { + Fail("Failed equality test for " + o.GetType().Name); + } + + if (o.GetHashCode() != values[i].GetHashCode()) + { + Fail("Failed hashCode test for " + o.GetType().Name); + } + } + } + + public override string Name + { + get { return "EqualsAndHashCode"; } + } + + public static void Main( + string[] args) + { + RunTest(new EqualsAndHashCodeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/EssCertIDv2UnitTest.cs b/crypto/test/src/asn1/test/EssCertIDv2UnitTest.cs new file mode 100644 index 000000000..9aac777e1 --- /dev/null +++ b/crypto/test/src/asn1/test/EssCertIDv2UnitTest.cs @@ -0,0 +1,46 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ess; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class EssCertIDv2UnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "ESSCertIDv2"; } + } + + public override void PerformTest() + { + // check GetInstance on default algorithm. + byte[] digest = new byte[32]; + EssCertIDv2 essCertIdv2 = new EssCertIDv2( + new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256), digest); + Asn1Object asn1Object = essCertIdv2.ToAsn1Object(); + + EssCertIDv2.GetInstance(asn1Object); + } + + public static void Main( + string[] args) + { + RunTest(new EssCertIDv2UnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/GeneralNameTest.cs b/crypto/test/src/asn1/test/GeneralNameTest.cs new file mode 100644 index 000000000..e9c3b5861 --- /dev/null +++ b/crypto/test/src/asn1/test/GeneralNameTest.cs @@ -0,0 +1,116 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class GeneralNameTest + : SimpleTest + { + private static readonly byte[] ipv4 = Hex.Decode("87040a090800"); + private static readonly byte[] ipv4WithMask = Hex.Decode("87080a090800ffffff00"); + + private static readonly byte[] ipv6a = Hex.Decode("871020010db885a308d313198a2e03707334"); + private static readonly byte[] ipv6b = Hex.Decode("871020010db885a3000013198a2e03707334"); + private static readonly byte[] ipv6c = Hex.Decode("871000000000000000000000000000000001"); + private static readonly byte[] ipv6d = Hex.Decode("871020010db885a3000000008a2e03707334"); + private static readonly byte[] ipv6e = Hex.Decode("871020010db885a3000000008a2e0a090800"); + private static readonly byte[] ipv6f = Hex.Decode("872020010db885a3000000008a2e0a090800ffffffffffff00000000000000000000"); + private static readonly byte[] ipv6g = Hex.Decode("872020010db885a3000000008a2e0a090800ffffffffffffffffffffffffffffffff"); + private static readonly byte[] ipv6h = Hex.Decode("872020010db885a300000000000000000000ffffffffffff00000000000000000000"); + + public override string Name + { + get { return "GeneralName"; } + } + + public override void PerformTest() + { + 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(), ipv4WithMask)) + { + Fail("ipv4 with netmask 1 encoding failed"); + } + + nm = new GeneralName(GeneralName.IPAddress, "10.9.8.0/24"); + if (!Arrays.AreEqual(nm.GetEncoded(), ipv4WithMask)) + { + Fail("ipv4 with netmask 2 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"); + } + } + + public static void Main( + string[] args) + { + RunTest(new GeneralNameTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(resultText, Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/GeneralizedTimeTest.cs b/crypto/test/src/asn1/test/GeneralizedTimeTest.cs new file mode 100644 index 000000000..b169cfea8 --- /dev/null +++ b/crypto/test/src/asn1/test/GeneralizedTimeTest.cs @@ -0,0 +1,193 @@ +using System; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * X.690 test example + */ + public class GeneralizedTimeTest + : SimpleTest + { + private static readonly 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" + }; + + private static readonly 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" + }; + + private static readonly string[] zOutput = + { + "20020122122220Z", + "20020122122220Z", + "20020122222220Z", + "20020122122220Z", + "20020122122220Z", + "20020122122220Z", + "20020122222220Z", + "20020122122220Z", + "20020122122220Z", + "20020122122220Z", + "20020122222220Z", + "20020122122220Z", + "20020122122220Z", + "20020122122220Z", + "20020122222220Z", + "20020122122220Z", + "20020122122220Z", + "20020122122220Z", + "20020122222220Z", + "20020122122220Z", + "20020122022220Z" + }; + + private static readonly 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 override string Name + { + get { return "GeneralizedTime"; } + } + + public override void PerformTest() + { + 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 (!t.ToDateTime().ToString(@"yyyyMMddHHmmss\Z").Equals(zOutput[i])) + { + Fail("failed date conversion test"); + } + } + else + { + string offset = CalculateGmtOffset(t.ToDateTime()); + if (!t.GetTime().Equals(output[i] + offset)) + { + Fail("failed conversion test"); + } + } + } + + for (int i = 0; i != input.Length; i++) + { + DerGeneralizedTime t = new DerGeneralizedTime(input[i]); + + if (!t.ToDateTime().ToString(@"yyyyMMddHHmmss.fff\Z").Equals(mzOutput[i])) + { + Console.WriteLine("{0} != {1}", t.ToDateTime().ToString(@"yyyyMMddHHmmss.SSS\Z"), mzOutput[i]); + + Fail("failed long date conversion test"); + } + } + } + + private string CalculateGmtOffset( + DateTime date) + { + char sign = '+'; + + // Note: GetUtcOffset incorporates Daylight Savings offset + TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(date); + if (offset.CompareTo(TimeSpan.Zero) < 0) + { + sign = '-'; + offset = offset.Duration(); + } + int hours = offset.Hours; + int minutes = offset.Minutes; + + return "GMT" + sign + Convert(hours) + ":" + Convert(minutes); + } + + private string Convert(int time) + { + if (time < 10) + { + return "0" + time; + } + + return time.ToString(); + } + + public static void Main( + string[] args) + { + RunTest(new GeneralizedTimeTest()); + } + } +} diff --git a/crypto/test/src/asn1/test/GenerationTest.cs b/crypto/test/src/asn1/test/GenerationTest.cs new file mode 100644 index 000000000..5acf8e149 --- /dev/null +++ b/crypto/test/src/asn1/test/GenerationTest.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class GenerationTest + : SimpleTest + { + private static readonly byte[] v1Cert = Base64.Decode( + "MIGtAgEBMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYDVQQKDA1Cb" + + "3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAxMlowNjELMA" + + "kGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3Q" + + "gMTAaMA0GCSqGSIb3DQEBAQUAAwkAMAYCAQECAQI="); + + private static readonly byte[] v3Cert = Base64.Decode( + "MIIBSKADAgECAgECMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD" + + "VQQKDA1Cb3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAw" + + "MlowNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNV" + + "BAsMBlRlc3QgMjAYMBAGBisOBwIBATAGAgEBAgECAwQAAgEDo4GVMIGSMGEGA1Ud" + + "IwEB/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJB" + + "VTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMCAG" + + "A1UdDgEB/wQWBBQ2T3aRz8you6PBCaJJEFNrqgh0UTALBgNVHQ8EBAMCBBA="); + + private static readonly byte[] v3CertNullSubject = Base64.Decode( + "MIHGoAMCAQICAQIwDQYJKoZIhvcNAQEEBQAwJTELMAkGA1UEAwwCQVUxFjAUBgNVB" + + "AoMDUJvdW5jeSBDYXN0bGUwHhcNNzAwMTAxMDAwMDAxWhcNNzAwMTAxMDAwMDAyWj" + + "AAMBgwEAYGKw4HAgEBMAYCAQECAQIDBAACAQOjSjBIMEYGA1UdEQEB/wQ8MDqkODA" + + "2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwG" + + "VGVzdCAy"); + + private static readonly byte[] v2CertList = Base64.Decode( + "MIIBRQIBATANBgkqhkiG9w0BAQUFADAlMQswCQYDVQQDDAJBVTEWMBQGA1UECgwN" + + "Qm91bmN5IENhc3RsZRcNNzAwMTAxMDAwMDAwWhcNNzAwMTAxMDAwMDAyWjAkMCIC" + + "AQEXDTcwMDEwMTAwMDAwMVowDjAMBgNVHRUEBQoDAIAAoIHFMIHCMGEGA1UdIwEB" + + "/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJBVTEW" + + "MBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMEMGA1Ud" + + "EgQ8MDqkODA2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEP" + + "MA0GA1UECwwGVGVzdCAzMAoGA1UdFAQDAgEBMAwGA1UdHAEB/wQCMAA="); + + private void TbsV1CertGenerate() + { + V1TbsCertificateGenerator gen = new V1TbsCertificateGenerator(); + DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1); + DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 12); + + gen.SetSerialNumber(new DerInteger(1)); + + gen.SetStartDate(new Time(startDate)); + gen.SetEndDate(new Time(endDate)); + + gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle")); + gen.SetSubject(new X509Name("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.One, BigInteger.Two)); + + gen.SetSubjectPublicKeyInfo(info); + + TbsCertificateStructure tbs = gen.GenerateTbsCertificate(); + + if (!Arrays.AreEqual(tbs.GetEncoded(), v1Cert)) + { + Fail("failed v1 cert generation"); + } + + // + // read back test + // + Asn1InputStream aIn = new Asn1InputStream(v1Cert); + Asn1Object o = aIn.ReadObject(); + + if (!Arrays.AreEqual(o.GetEncoded(), v1Cert)) + { + Fail("failed v1 cert read back test"); + } + } + + private AuthorityKeyIdentifier CreateAuthorityKeyId( + SubjectPublicKeyInfo info, + X509Name name, + int sNumber) + { + GeneralName genName = new GeneralName(name); + + return new AuthorityKeyIdentifier( + info, + GeneralNames.GetInstance(new DerSequence(genName)), + BigInteger.ValueOf(sNumber)); + } + + private void TbsV3CertGenerate() + { + V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator(); + DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1); + DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2); + + gen.SetSerialNumber(new DerInteger(2)); + + gen.SetStartDate(new Time(startDate)); + gen.SetEndDate(new Time(endDate)); + + gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle")); + gen.SetSubject(new X509Name("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.One, BigInteger.Two)), + new DerInteger(3)); + + gen.SetSubjectPublicKeyInfo(info); + + // + // add extensions + // + IList order = new ArrayList(); + IDictionary extensions = new Hashtable(); + + order.Add(X509Extensions.AuthorityKeyIdentifier); + order.Add(X509Extensions.SubjectKeyIdentifier); + order.Add(X509Extensions.KeyUsage); + + extensions.Add(X509Extensions.AuthorityKeyIdentifier, new X509Extension(true, new DerOctetString(CreateAuthorityKeyId(info, new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2)))); + extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(true, new DerOctetString(new SubjectKeyIdentifier(info)))); + extensions.Add(X509Extensions.KeyUsage, new X509Extension(false, new DerOctetString(new KeyUsage(KeyUsage.DataEncipherment)))); + + X509Extensions ex = new X509Extensions(order, extensions); + + gen.SetExtensions(ex); + + TbsCertificateStructure tbs = gen.GenerateTbsCertificate(); + + if (!Arrays.AreEqual(tbs.GetEncoded(), v3Cert)) + { + Fail("failed v3 cert generation"); + } + + // + // read back test + // + Asn1Object o = Asn1Object.FromByteArray(v3Cert); + + if (!Arrays.AreEqual(o.GetEncoded(), v3Cert)) + { + Fail("failed v3 cert read back test"); + } + } + + private void TbsV3CertGenWithNullSubject() + { + V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator(); + DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1); + DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2); + + gen.SetSerialNumber(new DerInteger(2)); + + gen.SetStartDate(new Time(startDate)); + gen.SetEndDate(new Time(endDate)); + + gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle")); + + gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance)); + + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( + new AlgorithmIdentifier(OiwObjectIdentifiers.ElGamalAlgorithm, + new ElGamalParameter(BigInteger.One, BigInteger.Two)), + new DerInteger(3)); + + gen.SetSubjectPublicKeyInfo(info); + + try + { + gen.GenerateTbsCertificate(); + Fail("null subject not caught!"); + } + catch (InvalidOperationException e) + { + if (!e.Message.Equals("not all mandatory fields set in V3 TBScertificate generator")) + { + Fail("unexpected exception", e); + } + } + + // + // add extensions + // + IList order = new ArrayList(); + IDictionary extensions = new Hashtable(); + + order.Add(X509Extensions.SubjectAlternativeName); + + extensions.Add( + X509Extensions.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); + + TbsCertificateStructure tbs = gen.GenerateTbsCertificate(); + + if (!Arrays.AreEqual(tbs.GetEncoded(), v3CertNullSubject)) + { + Fail("failed v3 null sub cert generation"); + } + + // + // read back test + // + Asn1Object o = Asn1Object.FromByteArray(v3CertNullSubject); + + if (!Arrays.AreEqual(o.GetEncoded(), v3CertNullSubject)) + { + Fail("failed v3 null sub cert read back test"); + } + } + + private void TbsV2CertListGenerate() + { + V2TbsCertListGenerator gen = new V2TbsCertListGenerator(); + + gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle")); + + gen.AddCrlEntry(new DerInteger(1), new Time(new DateTime(1970, 1, 1, 0, 0, 1)), ReasonFlags.AACompromise); + + gen.SetNextUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 2))); + + gen.SetThisUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 0, 500))); + + gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.Sha1WithRsaEncryption, DerNull.Instance)); + + // + // extensions + // + IList order = new ArrayList(); + IDictionary extensions = new Hashtable(); + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( + new AlgorithmIdentifier( + OiwObjectIdentifiers.ElGamalAlgorithm, + new ElGamalParameter(BigInteger.One, BigInteger.Two)), + new DerInteger(3)); + + order.Add(X509Extensions.AuthorityKeyIdentifier); + order.Add(X509Extensions.IssuerAlternativeName); + order.Add(X509Extensions.CrlNumber); + order.Add(X509Extensions.IssuingDistributionPoint); + + extensions.Add(X509Extensions.AuthorityKeyIdentifier, new X509Extension(true, new DerOctetString(CreateAuthorityKeyId(info, new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2)))); + extensions.Add(X509Extensions.IssuerAlternativeName, new X509Extension(false, new DerOctetString(GeneralNames.GetInstance(new DerSequence(new GeneralName(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 3"))))))); + extensions.Add(X509Extensions.CrlNumber, new X509Extension(false, new DerOctetString(new DerInteger(1)))); + extensions.Add(X509Extensions.IssuingDistributionPoint, new X509Extension(true, new DerOctetString(IssuingDistributionPoint.GetInstance(DerSequence.Empty)))); + + X509Extensions ex = new X509Extensions(order, extensions); + + gen.SetExtensions(ex); + + TbsCertificateList tbs = gen.GenerateTbsCertList(); + + if (!Arrays.AreEqual(tbs.GetEncoded(), v2CertList)) + { + Fail("failed v2 cert list generation"); + } + + // + // read back test + // + Asn1InputStream aIn = new Asn1InputStream(v2CertList); + Asn1Object o = aIn.ReadObject(); + + if (!Arrays.AreEqual(o.GetEncoded(), v2CertList)) + { + Fail("failed v2 cert list read back test"); + } + } + + public override void PerformTest() + { + TbsV1CertGenerate(); + TbsV3CertGenerate(); + TbsV3CertGenWithNullSubject(); + TbsV2CertListGenerate(); + } + + public override string Name + { + get { return "Generation"; } + } + + public static void Main( + string[] args) + { + RunTest(new GenerationTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(resultText, Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/InputStreamTest.cs b/crypto/test/src/asn1/test/InputStreamTest.cs new file mode 100644 index 000000000..1d92759e0 --- /dev/null +++ b/crypto/test/src/asn1/test/InputStreamTest.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class InputStreamTest + : SimpleTest + { + private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; + private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; + private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff }; + + public override string Name + { + get { return "InputStream"; } + } + + public override void PerformTest() + { + Asn1InputStream aIn = new Asn1InputStream(outOfBoundsLength); + + try + { + aIn.ReadObject(); + Fail("out of bounds length not detected."); + } + catch (IOException e) + { + if (!e.Message.StartsWith("DER length more than 4 bytes")) + { + Fail("wrong exception: " + e.Message); + } + } + + aIn = new Asn1InputStream(negativeLength); + + try + { + aIn.ReadObject(); + Fail("negative length not detected."); + } + catch (IOException e) + { + if (!e.Message.Equals("Corrupted stream - negative length found")) + { + Fail("wrong exception: " + e.Message); + } + } + + aIn = new Asn1InputStream(outsideLimitLength); + + try + { + aIn.ReadObject(); + Fail("outside limit length not detected."); + } + catch (IOException e) + { + if (!e.Message.Equals("Corrupted stream - out of bounds length found")) + { + Fail("wrong exception: " + e.Message); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new InputStreamTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs b/crypto/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs new file mode 100644 index 000000000..bb6076a93 --- /dev/null +++ b/crypto/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs @@ -0,0 +1,156 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class Iso4217CurrencyCodeUnitTest + : SimpleTest + { + private const string AlphabeticCurrencyCode = "AUD"; + private const int NUMERIC_CurrencyCode = 1; + + public override string Name + { + get { return "Iso4217CurrencyCode"; } + } + + public override void PerformTest() + { + // + // alphabetic + // + Iso4217CurrencyCode cc = new Iso4217CurrencyCode(AlphabeticCurrencyCode); + + CheckNumeric(cc, AlphabeticCurrencyCode); + + cc = Iso4217CurrencyCode.GetInstance(cc); + + CheckNumeric(cc, AlphabeticCurrencyCode); + + Asn1Object obj = cc.ToAsn1Object(); + + cc = Iso4217CurrencyCode.GetInstance(obj); + + CheckNumeric(cc, AlphabeticCurrencyCode); + + // + // numeric + // + cc = new Iso4217CurrencyCode(NUMERIC_CurrencyCode); + + CheckNumeric(cc, NUMERIC_CurrencyCode); + + cc = Iso4217CurrencyCode.GetInstance(cc); + + CheckNumeric(cc, NUMERIC_CurrencyCode); + + obj = cc.ToAsn1Object(); + + cc = Iso4217CurrencyCode.GetInstance(obj); + + CheckNumeric(cc, NUMERIC_CurrencyCode); + + cc = Iso4217CurrencyCode.GetInstance(null); + + if (cc != null) + { + Fail("null GetInstance() failed."); + } + + try + { + Iso4217CurrencyCode.GetInstance(new object()); + + Fail("GetInstance() failed to detect bad object."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new Iso4217CurrencyCode("ABCD"); + + Fail("constructor failed to detect out of range currencycode."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new Iso4217CurrencyCode(0); + + Fail("constructor failed to detect out of range small numeric code."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new Iso4217CurrencyCode(1000); + + Fail("constructor failed to detect out of range large numeric code."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckNumeric( + Iso4217CurrencyCode cc, + string code) + { + if (!cc.IsAlphabetic) + { + Fail("non-alphabetic code found when one expected."); + } + + if (!cc.Alphabetic.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.Numeric != code) + { + Fail("numeric codes don't match."); + } + } + + public static void Main( + string[] args) + { + RunTest(new Iso4217CurrencyCodeUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/IssuingDistributionPointTest.cs b/crypto/test/src/asn1/test/IssuingDistributionPointTest.cs new file mode 100644 index 000000000..b5f5c88bb --- /dev/null +++ b/crypto/test/src/asn1/test/IssuingDistributionPointTest.cs @@ -0,0 +1,133 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class IssuingDistributionPointUnitTest + : SimpleTest + { + public override string Name + { + get { return "IssuingDistributionPoint"; } + } + + public override void PerformTest() + { + 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 (ArgumentException) + { + // expected + } + } + + private void checkPoint( + int size, + DistributionPointName distributionPoint, + bool onlyContainsUserCerts, + bool onlyContainsCACerts, + ReasonFlags onlySomeReasons, + bool indirectCRL, + bool onlyContainsAttributeCerts) + { + IssuingDistributionPoint point = new IssuingDistributionPoint(distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts); + + checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts); + + Asn1Sequence seq = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(point.GetEncoded())); + + if (seq.Count != size) + { + Fail("size mismatch"); + } + + point = IssuingDistributionPoint.GetInstance(seq); + + checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts); + } + + private void checkValues( + IssuingDistributionPoint point, + DistributionPointName distributionPoint, + bool onlyContainsUserCerts, + bool onlyContainsCACerts, + ReasonFlags onlySomeReasons, + bool indirectCRL, + bool 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.OnlySomeReasons)) + { + Fail("mismatch on onlySomeReasons"); + } + + if (!isEquiv(distributionPoint, point.DistributionPoint)) + { + Fail("mismatch on distributionPoint"); + } + } + + private bool isEquiv(object o1, object o2) + { + if (o1 == null) + { + return o2 == null; + } + + return o1.Equals(o2); + } + + public static void Main( + string[] args) + { + RunTest(new IssuingDistributionPointUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/KeyUsageTest.cs b/crypto/test/src/asn1/test/KeyUsageTest.cs new file mode 100644 index 000000000..d7ed3655d --- /dev/null +++ b/crypto/test/src/asn1/test/KeyUsageTest.cs @@ -0,0 +1,49 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class KeyUsageTest + : SimpleTest + { + public override string Name + { + get + { + return "KeyUsage"; + } + } + + public override void PerformTest() + { + 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); + } + + public static void Main( + string[] args) + { + RunTest(new KeyUsageTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs b/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs new file mode 100644 index 000000000..042781632 --- /dev/null +++ b/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs @@ -0,0 +1,208 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Icao; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class LDSSecurityObjectUnitTest + : SimpleTest + { + public override string Name + { + get { return "LDSSecurityObject"; } + } + + private byte[] GenerateHash() + { + Random rand = new Random(); + byte[] bytes = new byte[20]; + rand.NextBytes(bytes); + return bytes; + } + + public override void PerformTest() + { + 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) + { + Fail("GetInstance() failed to handle null."); + } + + try + { + LdsSecurityObject.GetInstance(new object()); + + Fail("GetInstance() failed to detect bad object."); + } + catch (ArgumentException) + { + // expected + } + + try + { + LdsSecurityObject.GetInstance(DerSequence.Empty); + + Fail("constructor failed to detect empty sequence."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new LdsSecurityObject(algoId, new DataGroupHash[1]); + + Fail("constructor failed to detect small DataGroupHash array."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new LdsSecurityObject(algoId, new DataGroupHash[LdsSecurityObject.UBDataGroups + 1]); + + Fail("constructor failed to out of bounds DataGroupHash array."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + LdsSecurityObject so, + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash) + { + CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null); + + so = LdsSecurityObject.GetInstance(so); + + CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + so.ToAsn1Object().GetEncoded()); + + so = LdsSecurityObject.GetInstance(seq); + + CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null); + } + + private void CheckConstruction( + LdsSecurityObject so, + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash, + LdsVersionInfo versionInfo) + { + if (!so.Version.Equals(BigInteger.One)) + { + Fail("version number not 1"); + } + + CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo); + + so = LdsSecurityObject.GetInstance(so); + + CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + so.ToAsn1Object().GetEncoded()); + + 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.DigestAlgorithmIdentifier.Equals(digestAlgorithmIdentifier)) + { + Fail("ids don't match."); + } + } + else if (so.DigestAlgorithmIdentifier != 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.VersionInfo)) + { + Fail("versionInfo doesn't match"); + } + } + else if (so.VersionInfo != null) + { + Fail("version info found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new LDSSecurityObjectUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/MiscTest.cs b/crypto/test/src/asn1/test/MiscTest.cs new file mode 100644 index 000000000..44213c71d --- /dev/null +++ b/crypto/test/src/asn1/test/MiscTest.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Misc; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class MiscTest + : ITest + { + public ITestResult 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")), +#if INCLUDE_IDEA + new IdeaCbcPar(testIv), +#endif + new NetscapeRevocationUrl(new DerIA5String("http://test")) + }; + +#if INCLUDE_IDEA + byte[] data = Base64.Decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA=="); +#else + byte[] data = Base64.Decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvFgtodHRwOi8vdGVzdA=="); +#endif + + try + { + MemoryStream bOut = new MemoryStream(); + Asn1OutputStream aOut = new Asn1OutputStream(bOut); + + for (int i = 0; i != values.Length; i++) + { + aOut.WriteObject(values[i]); + } + + if (!Arrays.AreEqual(bOut.ToArray(), data)) + { + return new SimpleTestResult(false, Name + ": Failed data check"); + } + + Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray()); + + for (int i = 0; i != values.Length; i++) + { + Asn1Object o = aIn.ReadObject(); + + if (!values[i].Equals(o)) + { + return new SimpleTestResult(false, Name + ": Failed equality test for " + o); + } + + if (o.GetHashCode() != values[i].GetHashCode()) + { + return new SimpleTestResult(false, Name + ": Failed hashCode test for " + o); + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": Failed - exception " + e.ToString(), e); + } + } + + public string Name + { + get { return "Misc"; } + } + + public static void Main( + string[] args) + { + ITest test = new MiscTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/MonetaryLimitUnitTest.cs b/crypto/test/src/asn1/test/MonetaryLimitUnitTest.cs new file mode 100644 index 000000000..cdeb2eca5 --- /dev/null +++ b/crypto/test/src/asn1/test/MonetaryLimitUnitTest.cs @@ -0,0 +1,93 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class MonetaryLimitUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "MonetaryLimit"; } + } + + public override void PerformTest() + { + 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + MonetaryLimit limit, + string currency, + int amount, + int exponent) + { + 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.Currency); + checkMandatoryField("amount", amount, limit.Amount.IntValue); + checkMandatoryField("exponent", exponent, limit.Exponent.IntValue); + } + + public static void Main( + string[] args) + { + RunTest(new MonetaryLimitUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/MonetaryValueUnitTest.cs b/crypto/test/src/asn1/test/MonetaryValueUnitTest.cs new file mode 100644 index 000000000..c75d74505 --- /dev/null +++ b/crypto/test/src/asn1/test/MonetaryValueUnitTest.cs @@ -0,0 +1,99 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class MonetaryValueUnitTest + : SimpleTest + { + private const int TestAmount = 100; + private const int ZeroExponent = 0; + + private const string CurrencyCode = "AUD"; + + public override string Name + { + get { return "MonetaryValue"; } + } + + public override void PerformTest() + { + MonetaryValue mv = new MonetaryValue(new Iso4217CurrencyCode(CurrencyCode), TestAmount, ZeroExponent); + + CheckValues(mv, TestAmount, ZeroExponent); + + mv = MonetaryValue.GetInstance(mv); + + CheckValues(mv, TestAmount, ZeroExponent); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + mv.ToAsn1Object().GetEncoded()); + + mv = MonetaryValue.GetInstance(seq); + + CheckValues(mv, TestAmount, ZeroExponent); + + mv = MonetaryValue.GetInstance(null); + + if (mv != null) + { + Fail("null GetInstance() failed."); + } + + try + { + MonetaryValue.GetInstance(new object()); + + Fail("GetInstance() failed to detect bad object."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckValues( + MonetaryValue mv, + int amount, + int exponent) + { + if (mv.Amount.IntValue != amount) + { + Fail("amounts don't match."); + } + + if (mv.Exponent.IntValue != exponent) + { + Fail("exponents don't match."); + } + + Iso4217CurrencyCode cc = mv.Currency; + + if (!cc.Alphabetic.Equals(CurrencyCode)) + { + Fail("currency code wrong"); + } + } + + public static void Main( + string[] args) + { + RunTest(new MonetaryValueUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/NameOrPseudonymUnitTest.cs b/crypto/test/src/asn1/test/NameOrPseudonymUnitTest.cs new file mode 100644 index 000000000..45f66613b --- /dev/null +++ b/crypto/test/src/asn1/test/NameOrPseudonymUnitTest.cs @@ -0,0 +1,114 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509.SigI; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class NameOrPseudonymUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "NameOrPseudonym"; } + } + + public override void PerformTest() + { + 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + NameOrPseudonym id, + string pseudonym, + DirectoryString surname, + Asn1Sequence givenName) + { + 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 + { + IAsn1String s = (IAsn1String) 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.Surname); + checkMandatoryField("givenName", givenName, new DerSequence(id.GetGivenName()[0])); + } + else + { + checkOptionalField("pseudonym", new DirectoryString(pseudonym), id.Pseudonym); + } + } + + public static void Main( + string[] args) + { + RunTest(new NameOrPseudonymUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/NamingAuthorityUnitTest.cs b/crypto/test/src/asn1/test/NamingAuthorityUnitTest.cs new file mode 100644 index 000000000..787b2c32d --- /dev/null +++ b/crypto/test/src/asn1/test/NamingAuthorityUnitTest.cs @@ -0,0 +1,106 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class NamingAuthorityUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "NamingAuthority"; } + } + + public override void PerformTest() + { + DerObjectIdentifier namingAuthorityID = new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + NamingAuthority auth, + DerObjectIdentifier namingAuthorityID, + string namingAuthorityURL, + DirectoryString namingAuthorityText) + { + 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, + DerObjectIdentifier namingAuthorityId, + string namingAuthorityURL, + DirectoryString namingAuthorityText) + { + checkOptionalField("namingAuthorityId", namingAuthorityId, auth.NamingAuthorityID); + checkOptionalField("namingAuthorityURL", namingAuthorityURL, auth.NamingAuthorityUrl); + checkOptionalField("namingAuthorityText", namingAuthorityText, auth.NamingAuthorityText); + } + + public static void Main( + string[] args) + { + RunTest(new NamingAuthorityUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/NetscapeCertTypeTest.cs b/crypto/test/src/asn1/test/NetscapeCertTypeTest.cs new file mode 100644 index 000000000..8db5d990c --- /dev/null +++ b/crypto/test/src/asn1/test/NetscapeCertTypeTest.cs @@ -0,0 +1,45 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Misc; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class NetscapeCertTypeTest + : SimpleTest + { + public override string Name + { + get { return "NetscapeCertType"; } + } + + public override void PerformTest() + { + 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/OCSPTest.cs b/crypto/test/src/asn1/test/OCSPTest.cs new file mode 100644 index 000000000..13f59d3d1 --- /dev/null +++ b/crypto/test/src/asn1/test/OCSPTest.cs @@ -0,0 +1,183 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class OcspTest + : ITest + { + private static byte[] unsignedReq = Base64.Decode( + "MEIwQDA+MDwwOjAJBgUrDgMCGgUABBRDb9GODnq7lRhSkEqw4XX24huERwQUkY4j" + + "a6eKuDlkVP9hRgkEvIWqHPECAQE="); + + private static 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 static 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 ITestResult unSignedRequest() + { + try + { + OcspRequest req = OcspRequest.GetInstance( + Asn1Object.FromByteArray(unsignedReq)); + + if (!Arrays.AreEqual(req.GetEncoded(), unsignedReq)) + { + return new SimpleTestResult(false, Name + ": Ocsp unsigned request failed to re-encode"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed unsigned exception - " + e.ToString(), e); + } + } + + private ITestResult SignedRequest() + { + try + { + OcspRequest req = OcspRequest.GetInstance( + Asn1Object.FromByteArray(signedReq)); + + if (!Arrays.AreEqual(req.GetEncoded(), signedReq)) + { + return new SimpleTestResult(false, Name + ": Ocsp signed request failed to re-encode"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed signed exception - " + e.ToString(), e); + } + } + + private ITestResult Response() + { + try + { + OcspResponse resp = OcspResponse.GetInstance( + Asn1Object.FromByteArray(_response)); + ResponseBytes rBytes = ResponseBytes.GetInstance(resp.ResponseBytes); + + BasicOcspResponse bResp = BasicOcspResponse.GetInstance( + Asn1Object.FromByteArray(rBytes.Response.GetOctets())); + + resp = new OcspResponse( + resp.ResponseStatus, + new ResponseBytes( + rBytes.ResponseType, + new DerOctetString(bResp.GetEncoded()))); + + if (!Arrays.AreEqual(resp.GetEncoded(), _response)) + { + return new SimpleTestResult(false, Name + ": Ocsp response failed to re-encode"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed response exception - " + e.ToString(), e); + } + } + + public ITestResult Perform() + { + ITestResult res = unSignedRequest(); + + if (!res.IsSuccessful()) + { + return res; + } + + res = SignedRequest(); + if (!res.IsSuccessful()) + { + return res; + } + + return Response(); + } + + public string Name + { + get { return "Ocsp"; } + } + + public static void Main( + string[] args) + { + ITest test = new OcspTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/OIDTest.cs b/crypto/test/src/asn1/test/OIDTest.cs new file mode 100644 index 000000000..b0782db04 --- /dev/null +++ b/crypto/test/src/asn1/test/OIDTest.cs @@ -0,0 +1,149 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * X.690 test example + */ + [TestFixture] + public class OidTest + : SimpleTest + { + byte[] req1 = Hex.Decode("0603813403"); + byte[] req2 = Hex.Decode("06082A36FFFFFFDD6311"); + + public override string Name + { + get { return "OID"; } + } + + private void recodeCheck( + string oid, + byte[] enc) + { + DerObjectIdentifier o = new DerObjectIdentifier(oid); + DerObjectIdentifier encO = (DerObjectIdentifier) Asn1Object.FromByteArray(enc); + + if (!o.Equals(encO)) + { + Fail("oid ID didn't match", o, encO); + } + + byte[] bytes = o.GetDerEncoded(); + + if (!Arrays.AreEqual(bytes, enc)) + { + Fail("failed comparison test", Hex.ToHexString(enc), Hex.ToHexString(bytes)); + } + } + + private void validOidCheck( + string oid) + { + DerObjectIdentifier o = new DerObjectIdentifier(oid); + o = (DerObjectIdentifier) Asn1Object.FromByteArray(o.GetEncoded()); + + if (!o.Id.Equals(oid)) + { + Fail("failed oid check: " + oid); + } + } + + private void invalidOidCheck( + string oid) + { + try + { + new DerObjectIdentifier(oid); + Fail("failed to catch bad oid: " + oid); + } + catch (FormatException) + { + // expected + } + } + + private void branchCheck(string stem, string branch) + { + string expected = stem + "." + branch; + string actual = new DerObjectIdentifier(stem).Branch(branch).Id; + + if (expected != actual) + { + Fail("failed 'branch' check for " + stem + "/" + branch); + } + } + + private void onCheck(String stem, String test, bool expected) + { + if (expected != new DerObjectIdentifier(test).On(new DerObjectIdentifier(stem))) + { + Fail("failed 'on' check for " + stem + "/" + test); + } + } + + public override void PerformTest() + { + recodeCheck("2.100.3", req1); + recodeCheck("1.2.54.34359733987.17", req2); + + validOidCheck(PkcsObjectIdentifiers.Pkcs9AtContentType.Id); + 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) + { + ITest test = new OidTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/OctetStringTest.cs b/crypto/test/src/asn1/test/OctetStringTest.cs new file mode 100644 index 000000000..8bae1b057 --- /dev/null +++ b/crypto/test/src/asn1/test/OctetStringTest.cs @@ -0,0 +1,186 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cms; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class OctetStringTest + { + [Test] + public void TestReadingWriting() + { + MemoryStream bOut = new MemoryStream(); + BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut); + + Stream outStream = octGen.GetOctetOutputStream(); + + outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4); + outStream.Write(new byte[4], 0, 4); + + outStream.Close(); + + Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray()); + + BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject(); + + Stream inStream = s.GetOctetStream(); + int count = 0; + + while (inStream.ReadByte() >= 0) + { + count++; + } + + Assert.AreEqual(8, count); + } + + [Test] + public void TestReadingWritingZeroInLength() + { + MemoryStream bOut = new MemoryStream(); + BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut); + + Stream outStream = octGen.GetOctetOutputStream(); + + outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4); + outStream.Write(new byte[512], 0, 512); // forces a zero to appear in length + + outStream.Close(); + + Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray()); + + BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject(); + + Stream inStream = s.GetOctetStream(); + int count = 0; + + while (inStream.ReadByte() >= 0) + { + count++; + } + + Assert.AreEqual(516, count); + } + + [Test] + public void TestReadingWritingNested() + { + MemoryStream bOut = new MemoryStream(); + BerSequenceGenerator sGen = new BerSequenceGenerator(bOut); + BerOctetStringGenerator octGen = new BerOctetStringGenerator(sGen.GetRawOutputStream()); + + Stream outStream = octGen.GetOctetOutputStream(); + + BerSequenceGenerator inSGen = new BerSequenceGenerator(outStream); + + BerOctetStringGenerator inOctGen = new BerOctetStringGenerator(inSGen.GetRawOutputStream()); + + Stream inOut = inOctGen.GetOctetOutputStream(); + + inOut.Write(new byte[] { 1, 2, 3, 4 }, 0, 4); + inOut.Write(new byte[10], 0, 10); + + inOut.Close(); + + inSGen.Close(); + + outStream.Close(); + + sGen.Close(); + + Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray()); + + BerSequenceParser sq = (BerSequenceParser)aIn.ReadObject(); + + BerOctetStringParser s = (BerOctetStringParser)sq.ReadObject(); + + Asn1StreamParser aIn2 = new Asn1StreamParser(s.GetOctetStream()); + + BerSequenceParser sq2 = (BerSequenceParser)aIn2.ReadObject(); + + BerOctetStringParser inS = (BerOctetStringParser)sq2.ReadObject(); + + Stream inStream = inS.GetOctetStream(); + int count = 0; + + while (inStream.ReadByte() >= 0) + { + count++; + } + + Assert.AreEqual(14, count); + } + + [Test] + public void TestNestedStructure() + { + MemoryStream bOut = new MemoryStream(); + + BerSequenceGenerator sGen = new BerSequenceGenerator(bOut); + + sGen.AddObject(new DerObjectIdentifier(CmsObjectIdentifiers.CompressedData.Id)); + + BerSequenceGenerator cGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true); + + cGen.AddObject(new DerInteger(0)); + + // + // AlgorithmIdentifier + // + DerSequenceGenerator algGen = new DerSequenceGenerator(cGen.GetRawOutputStream()); + + algGen.AddObject(new DerObjectIdentifier("1.2")); + + algGen.Close(); + + // + // Encapsulated ContentInfo + // + BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream()); + + eiGen.AddObject(new DerObjectIdentifier("1.1")); + + BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true); + + // + // output containing zeroes + // + Stream outStream = octGen.GetOctetOutputStream(); + + outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4); + outStream.Write(new byte[4], 0, 4); + outStream.Write(new byte[20], 0, 20); + + outStream.Close(); + eiGen.Close(); + cGen.Close(); + sGen.Close(); + + // + // reading back + // + Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray()); + + ContentInfoParser cp = new ContentInfoParser((Asn1SequenceParser)aIn.ReadObject()); + + CompressedDataParser comData = new CompressedDataParser((Asn1SequenceParser)cp.GetContent(Asn1Tags.Sequence)); + ContentInfoParser content = comData.GetEncapContentInfo(); + + Asn1OctetStringParser bytes = (Asn1OctetStringParser)content.GetContent(Asn1Tags.OctetString); + + Stream inStream = bytes.GetOctetStream(); + int count = 0; + + while (inStream.ReadByte() >= 0) + { + count++; + } + + Assert.AreEqual(28, count); + } + } +} diff --git a/crypto/test/src/asn1/test/OtherCertIDUnitTest.cs b/crypto/test/src/asn1/test/OtherCertIDUnitTest.cs new file mode 100644 index 000000000..a09c18e8a --- /dev/null +++ b/crypto/test/src/asn1/test/OtherCertIDUnitTest.cs @@ -0,0 +1,100 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Esf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class OtherCertIDUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "OtherCertID"; } + } + + public override void PerformTest() + { + AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("1.2.2.3")); + byte[] digest = new byte[20]; + OtherHash otherHash = new OtherHash(new OtherHashAlgAndValue(algId, digest)); + IssuerSerial issuerSerial = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new DerInteger(1)); + + OtherCertID certID = new OtherCertID(otherHash); + + checkConstruction(certID, algId, digest, null); + + certID = new OtherCertID(otherHash, 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + OtherCertID certID, + AlgorithmIdentifier algId, + byte[] digest, + IssuerSerial issuerSerial) + { + 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("hashAlgorithm", algId, certID.OtherCertHash.HashAlgorithm); + checkMandatoryField("hashValue", digest, certID.OtherCertHash.GetHashValue()); + + checkOptionalField("issuerSerial", issuerSerial, certID.IssuerSerial); + } + + public static void Main( + string[] args) + { + RunTest(new OtherCertIDUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/OtherSigningCertificateUnitTest.cs b/crypto/test/src/asn1/test/OtherSigningCertificateUnitTest.cs new file mode 100644 index 000000000..4410d8e4c --- /dev/null +++ b/crypto/test/src/asn1/test/OtherSigningCertificateUnitTest.cs @@ -0,0 +1,94 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Esf; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class OtherSigningCertificateUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "OtherSigningCertificate"; } + } + + public override void PerformTest() + { + AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("1.2.2.3")); + byte[] digest = new byte[20]; + OtherHash otherHash = new OtherHash( + new OtherHashAlgAndValue(algId, digest)); + OtherCertID otherCertID = new OtherCertID(otherHash); + + 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + OtherSigningCertificate otherCert, + OtherCertID otherCertID) + { + 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/PKCS10Test.cs b/crypto/test/src/asn1/test/PKCS10Test.cs new file mode 100644 index 000000000..28736b816 --- /dev/null +++ b/crypto/test/src/asn1/test/PKCS10Test.cs @@ -0,0 +1,95 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class Pkcs10Test + : ITest + { + 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 Name + { + get + { + return "Pkcs10"; + } + } + + public ITestResult BasicPkcs10Test( + string testName, + byte[] req) + { + try + { + CertificationRequest r = new CertificationRequest( + (Asn1Sequence)Asn1Object.FromByteArray(req)); + byte[] bytes = r.GetDerEncoded(); + + if (!Arrays.AreEqual(bytes, req)) + { + return new SimpleTestResult(false, Name + ": " + testName + " failed comparison test"); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": Exception - " + testName + " " + e.ToString()); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public ITestResult Perform() + { + ITestResult res = BasicPkcs10Test("basic CR", req1); + + if (!res.IsSuccessful()) + { + return res; + } + + return BasicPkcs10Test("Universal CR", req2); + } + + public static void Main( + string[] args) + { + ITest test = new Pkcs10Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/PKCS12Test.cs b/crypto/test/src/asn1/test/PKCS12Test.cs new file mode 100644 index 000000000..c20fa8cc6 --- /dev/null +++ b/crypto/test/src/asn1/test/PKCS12Test.cs @@ -0,0 +1,210 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class Pkcs12Test + : SimpleTest + { + private static 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 override void PerformTest() + { + Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromByteArray(pkcs12); + + Pfx bag = new Pfx(obj); + ContentInfo info = bag.AuthSafe; + MacData mData = bag.MacData; + DigestInfo dInfo = mData.Mac; + AlgorithmIdentifier algId = dInfo.AlgorithmID; + byte[] salt = mData.GetSalt(); + int itCount = mData.IterationCount.IntValue; + + byte[] octets = ((Asn1OctetString) info.Content).GetOctets(); + AuthenticatedSafe authSafe = new AuthenticatedSafe( + (Asn1Sequence) Asn1Object.FromByteArray(octets)); + ContentInfo[] c = authSafe.GetContentInfo(); + + // + // private key section + // + if (!c[0].ContentType.Equals(PkcsObjectIdentifiers.Data)) + { + Fail("Failed comparison data test"); + } + + octets = ((Asn1OctetString)c[0].Content).GetOctets(); + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); + + SafeBag b = new SafeBag((Asn1Sequence)seq[0]); + if (!b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) + { + Fail("Failed comparison shroudedKeyBag test"); + } + + EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(b.BagValue); + + encInfo = new EncryptedPrivateKeyInfo(encInfo.EncryptionAlgorithm, encInfo.GetEncryptedData()); + + b = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, encInfo.ToAsn1Object(), b.BagAttributes); + + byte[] encodedBytes = new DerSequence(b).GetEncoded(); + + c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encodedBytes)); + + // + // certificates + // + if (!c[1].ContentType.Equals(PkcsObjectIdentifiers.EncryptedData)) + { + Fail("Failed comparison encryptedData test"); + } + + EncryptedData eData = EncryptedData.GetInstance(c[1].Content); + + c[1] = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, eData); + + // + // create an octet stream to represent the BER encoding of authSafe + // + authSafe = new AuthenticatedSafe(c); + + info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(authSafe.GetEncoded())); + + mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount); + + bag = new Pfx(info, mData); + + // + // comparison test + // + if (!Arrays.AreEqual(bag.GetEncoded(), pkcs12)) + { + Fail("Failed comparison test"); + } + } + + public override string Name + { + get { return "Pkcs12"; } + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs12Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/PKIFailureInfoTest.cs b/crypto/test/src/asn1/test/PKIFailureInfoTest.cs new file mode 100644 index 000000000..734dbbc14 --- /dev/null +++ b/crypto/test/src/asn1/test/PKIFailureInfoTest.cs @@ -0,0 +1,76 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * PKIFailureInfoTest + */ + [TestFixture] + public class PkiFailureInfoTest + : SimpleTest + { + // A correct hex encoded BAD_DATA_FORMAT PkiFailureInfo + private static readonly byte[] CORRECT_FAILURE_INFO = Base64.Decode("AwIANQ=="); + + public override string Name + { + get { return "PkiFailureInfo"; } + } + + private void doTestEncoding() + { + DerBitString bitString = (DerBitString) Asn1Object.FromByteArray(CORRECT_FAILURE_INFO); + PkiFailureInfo correct = new PkiFailureInfo(bitString); + + PkiFailureInfo bug = new PkiFailureInfo(PkiFailureInfo.BadRequest | PkiFailureInfo.BadTime | PkiFailureInfo.BadDataFormat | PkiFailureInfo.IncorrectData); + + if (!Arrays.AreEqual(correct.GetDerEncoded(), bug.GetDerEncoded())) + { + Fail("encoding doesn't match"); + } + } + + public override void PerformTest() + { + 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); + + doTestEncoding(); + } + + public static void Main( + string[] args) + { + RunTest(new PkiFailureInfoTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/ParseTest.cs b/crypto/test/src/asn1/test/ParseTest.cs new file mode 100644 index 000000000..c649fdb8d --- /dev/null +++ b/crypto/test/src/asn1/test/ParseTest.cs @@ -0,0 +1,303 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class ParseTest + { + private static readonly 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 readonly 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="); + + private static readonly byte[] longTagged = Hex.Decode("9f1f023330"); + + [Test] + public void TestClassCast() + { + ParseEnveloped(classCastTest); + } + + [Test] + public void TestDerExp() + { + ParseEnveloped(derExpTest); + } + + [Test] + public void TestLongTag() + { + Asn1StreamParser aIn = new Asn1StreamParser(longTagged); + Asn1TaggedObjectParser tagged = (Asn1TaggedObjectParser)aIn.ReadObject(); + + Assert.AreEqual(31, tagged.TagNo); + } + + private void ParseEnveloped( + byte[] data) + { + Asn1StreamParser aIn = new Asn1StreamParser(data); + + ContentInfoParser cP = new ContentInfoParser((Asn1SequenceParser)aIn.ReadObject()); + + EnvelopedDataParser eP = new EnvelopedDataParser((Asn1SequenceParser)cP.GetContent(Asn1Tags.Sequence)); + + eP.GetRecipientInfos().ToAsn1Object(); // Must drain the parser! + + EncryptedContentInfoParser ecP = eP.GetEncryptedContentInfo(); + + Asn1OctetStringParser content = (Asn1OctetStringParser)ecP.GetEncryptedContent(Asn1Tags.OctetString); + + Streams.Drain(content.GetOctetStream()); + } + } +} diff --git a/crypto/test/src/asn1/test/ParsingTest.cs b/crypto/test/src/asn1/test/ParsingTest.cs new file mode 100644 index 000000000..bb219e2fc --- /dev/null +++ b/crypto/test/src/asn1/test/ParsingTest.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + public class ParsingTest + : SimpleTest + { + private static readonly 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 override string Name + { + get { return "ParsingTest"; } + } + + public override void PerformTest() + { + inputStreamTest(); + parserTest(); + } + + private void parserTest() + { + foreach (string stream in streams) + { + Asn1StreamParser aIn = new Asn1StreamParser(Base64.Decode(stream)); + + try + { + Object obj; + while ((obj = aIn.ReadObject()) != null) + { + } + + Fail("bad stream parsed successfully!"); + } + catch (IOException) + { + // ignore + } + // Note: C# may throw these instead, since no InMemoryRepresentable support + catch (Asn1ParsingException) + { + // ignore + } + } + } + + private void inputStreamTest() + { + foreach (string stream in streams) + { + Asn1InputStream aIn = new Asn1InputStream(Base64.Decode(stream)); + + try + { + Object obj; + while ((obj = aIn.ReadObject()) != null) + { + } + + Fail("bad stream parsed successfully!"); + } + catch (IOException) + { + // ignore + } + // Note: C# may throw these instead, since no InMemoryRepresentable support + catch (Asn1ParsingException) + { + // ignore + } + } + } + + public static void Main( + string[] args) + { + RunTest(new ParsingTest()); + } + } +} diff --git a/crypto/test/src/asn1/test/PersonalDataUnitTest.cs b/crypto/test/src/asn1/test/PersonalDataUnitTest.cs new file mode 100644 index 000000000..f92e619cf --- /dev/null +++ b/crypto/test/src/asn1/test/PersonalDataUnitTest.cs @@ -0,0 +1,127 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509.SigI; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class PersonalDataUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "PersonalData"; } + } + + public override void PerformTest() + { + NameOrPseudonym nameOrPseudonym = new NameOrPseudonym("pseudonym"); + BigInteger nameDistinguisher = BigInteger.ValueOf(10); + DerGeneralizedTime dateOfBirth= new DerGeneralizedTime("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + PersonalData data, + NameOrPseudonym nameOrPseudonym, + BigInteger nameDistinguisher, + DerGeneralizedTime dateOfBirth, + DirectoryString placeOfBirth, + string gender, + DirectoryString postalAddress) + { + 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, + DerGeneralizedTime dateOfBirth, + DirectoryString placeOfBirth, + string gender, + DirectoryString postalAddress) + { + checkMandatoryField("nameOrPseudonym", nameOrPseudonym, data.NameOrPseudonym); + checkOptionalField("nameDistinguisher", nameDistinguisher, data.NameDistinguisher); + checkOptionalField("dateOfBirth", dateOfBirth, data.DateOfBirth); + checkOptionalField("placeOfBirth", placeOfBirth, data.PlaceOfBirth); + checkOptionalField("gender", gender, data.Gender); + checkOptionalField("postalAddress", postalAddress, data.PostalAddress); + } + + public static void Main( + string[] args) + { + RunTest(new PersonalDataUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/ProcurationSyntaxUnitTest.cs b/crypto/test/src/asn1/test/ProcurationSyntaxUnitTest.cs new file mode 100644 index 000000000..97d0e3eee --- /dev/null +++ b/crypto/test/src/asn1/test/ProcurationSyntaxUnitTest.cs @@ -0,0 +1,111 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class ProcurationSyntaxUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "ProcurationSyntax"; } + } + + public override void PerformTest() + { + 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 DerInteger(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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + ProcurationSyntax procuration, + string country, + DirectoryString typeOfSubstitution, + GeneralName thirdPerson, + IssuerSerial certRef) + { + 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.Country); + checkOptionalField("typeOfSubstitution", typeOfSubstitution, procuration.TypeOfSubstitution); + checkOptionalField("thirdPerson", thirdPerson, procuration.ThirdPerson); + checkOptionalField("certRef", certRef, procuration.CertRef); + } + + public static void Main( + string[] args) + { + RunTest(new ProcurationSyntaxUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/ProfessionInfoUnitTest.cs b/crypto/test/src/asn1/test/ProfessionInfoUnitTest.cs new file mode 100644 index 000000000..6af2658ef --- /dev/null +++ b/crypto/test/src/asn1/test/ProfessionInfoUnitTest.cs @@ -0,0 +1,121 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class ProfessionInfoUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "ProfessionInfo"; } + } + + public override void PerformTest() + { + NamingAuthority auth = new NamingAuthority(new DerObjectIdentifier("1.2.3"), "url", new DirectoryString("fred")); + DirectoryString[] professionItems = { new DirectoryString("substitution") }; + DerObjectIdentifier[] professionOids = { new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + ProfessionInfo profInfo, + NamingAuthority auth, + DirectoryString[] professionItems, + DerObjectIdentifier[] professionOids, + string registrationNumber, + DerOctetString addProfInfo) + { + 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, + DerObjectIdentifier[] professionOids, + string registrationNumber, + DerOctetString addProfInfo) + { + checkOptionalField("auth", auth, profInfo.NamingAuthority); + checkMandatoryField("professionItems", professionItems[0], profInfo.GetProfessionItems()[0]); + if (professionOids != null) + { + checkOptionalField("professionOids", professionOids[0], profInfo.GetProfessionOids()[0]); + } + checkOptionalField("registrationNumber", registrationNumber, profInfo.RegistrationNumber); + checkOptionalField("addProfessionInfo", addProfInfo, profInfo.AddProfessionInfo); + } + + public static void Main( + string[] args) + { + RunTest(new ProfessionInfoUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/QCStatementUnitTest.cs b/crypto/test/src/asn1/test/QCStatementUnitTest.cs new file mode 100644 index 000000000..8d8ec9ec7 --- /dev/null +++ b/crypto/test/src/asn1/test/QCStatementUnitTest.cs @@ -0,0 +1,108 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class QCStatementUnitTest + : SimpleTest + { + public override string Name + { + get { return "QCStatement"; } + } + + public override void PerformTest() + { + QCStatement mv = new QCStatement(Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1); + + CheckConstruction(mv, Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, null); + + Asn1Encodable info = new SemanticsInformation(new DerObjectIdentifier("1.2")); + + mv = new QCStatement(Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, info); + + CheckConstruction(mv, Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, 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 (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + QCStatement mv, + DerObjectIdentifier statementId, + Asn1Encodable statementInfo) + { + CheckStatement(mv, statementId, statementInfo); + + mv = QCStatement.GetInstance(mv); + + CheckStatement(mv, statementId, statementInfo); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + mv.ToAsn1Object().GetEncoded()); + + mv = QCStatement.GetInstance(seq); + + CheckStatement(mv, statementId, statementInfo); + } + + private void CheckStatement( + QCStatement qcs, + DerObjectIdentifier statementId, + Asn1Encodable statementInfo) + { + if (!qcs.StatementId.Equals(statementId)) + { + Fail("statementIds don't match."); + } + + if (statementInfo != null) + { + if (!qcs.StatementInfo.Equals(statementInfo)) + { + Fail("statementInfos don't match."); + } + } + else if (qcs.StatementInfo != null) + { + Fail("statementInfo found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new QCStatementUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/ReasonFlagsTest.cs b/crypto/test/src/asn1/test/ReasonFlagsTest.cs new file mode 100644 index 000000000..ef404b3e1 --- /dev/null +++ b/crypto/test/src/asn1/test/ReasonFlagsTest.cs @@ -0,0 +1,46 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class ReasonFlagsTest + : SimpleTest + { + public override string Name + { + get { return "ReasonFlags"; } + } + + public override void PerformTest() + { + 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/RegressionTest.cs b/crypto/test/src/asn1/test/RegressionTest.cs new file mode 100644 index 000000000..873ab4396 --- /dev/null +++ b/crypto/test/src/asn1/test/RegressionTest.cs @@ -0,0 +1,85 @@ +using System; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + public class RegressionTest + { + public static readonly ITest[] tests = + { + new AdditionalInformationSyntaxUnitTest(), + new AdmissionSyntaxUnitTest(), + new AdmissionsUnitTest(), + new AttributeTableUnitTest(), + new BiometricDataUnitTest(), + new BitStringTest(), + new CertHashUnitTest(), + new CertificateTest(), + new CmsTest(), + new CommitmentTypeIndicationUnitTest(), + new CommitmentTypeQualifierUnitTest(), + new ContentHintsUnitTest(), + new CscaMasterListTest(), + new DataGroupHashUnitTest(), + new DeclarationOfMajorityUnitTest(), + new DerApplicationSpecificTest(), + new DerUtf8StringTest(), + new EncryptedPrivateKeyInfoTest(), + new EqualsAndHashCodeTest(), + new EssCertIDv2UnitTest(), + new GeneralizedTimeTest(), + new GeneralNameTest(), + new GenerationTest(), + new InputStreamTest(), + new Iso4217CurrencyCodeUnitTest(), + new IssuingDistributionPointUnitTest(), + new KeyUsageTest(), + new LDSSecurityObjectUnitTest(), + new MiscTest(), + new MonetaryLimitUnitTest(), + new MonetaryValueUnitTest(), + new NameOrPseudonymUnitTest(), + new NamingAuthorityUnitTest(), + new NetscapeCertTypeTest(), + new OcspTest(), + new OidTest(), + new OtherCertIDUnitTest(), + new OtherSigningCertificateUnitTest(), + new ParsingTest(), + new PersonalDataUnitTest(), + new Pkcs10Test(), + new Pkcs12Test(), + new PkiFailureInfoTest(), + new ProcurationSyntaxUnitTest(), + new ProfessionInfoUnitTest(), + new QCStatementUnitTest(), + new ReasonFlagsTest(), + new RequestedCertificateUnitTest(), + new RestrictionUnitTest(), + new SemanticsInformationUnitTest(), + new SetTest(), + new SignerLocationUnitTest(), + new SmimeTest(), + new StringTest(), + new SubjectKeyIdentifierTest(), + new TagTest(), + new TargetInformationTest(), + new TypeOfBiometricDataUnitTest(), + new UtcTimeTest(), + new X509ExtensionsTest(), + new X509NameTest(), + new X9Test(), + }; + + public static void Main( + string[] args) + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult result = tests[i].Perform(); + Console.WriteLine(result); + } + } + } +} diff --git a/crypto/test/src/asn1/test/RequestedCertificateUnitTest.cs b/crypto/test/src/asn1/test/RequestedCertificateUnitTest.cs new file mode 100644 index 000000000..767504173 --- /dev/null +++ b/crypto/test/src/asn1/test/RequestedCertificateUnitTest.cs @@ -0,0 +1,117 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class RequestedCertificateUnitTest + : Asn1UnitTest + { + private static readonly byte[] certBytes = Base64.Decode( + "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" + + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" + + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" + + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" + + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" + + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" + + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" + + "zl9HYIMxATFyqSiD9jsx"); + + public override string Name + { + get { return "RequestedCertificate"; } + } + + public override void PerformTest() + { + RequestedCertificate.Choice type = RequestedCertificate.Choice.AttributeCertificate; + X509CertificateStructure cert = X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(certBytes)); + + byte[] certOctets = new byte[20]; + RequestedCertificate requested = new RequestedCertificate(type, certOctets); + + checkConstruction(requested, type, certOctets, null); + + requested = new RequestedCertificate(cert); + + checkConstruction(requested, RequestedCertificate.Choice.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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + RequestedCertificate requested, + RequestedCertificate.Choice type, + byte[] certOctets, + X509CertificateStructure cert) + { + 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, + RequestedCertificate.Choice type, + byte[] certOctets, + X509CertificateStructure cert) + { + checkMandatoryField("certType", (int) type, (int) requested.Type); + + if (requested.Type == RequestedCertificate.Choice.Certificate) + { + checkMandatoryField("certificate", cert.GetEncoded(), requested.GetCertificateBytes()); + } + else + { + checkMandatoryField("certificateOctets", certOctets, requested.GetCertificateBytes()); + } + } + + public static void Main( + string[] args) + { + RunTest(new RequestedCertificateUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/RestrictionUnitTest.cs b/crypto/test/src/asn1/test/RestrictionUnitTest.cs new file mode 100644 index 000000000..5dd6438cb --- /dev/null +++ b/crypto/test/src/asn1/test/RestrictionUnitTest.cs @@ -0,0 +1,78 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.IsisMtt.X509; +using Org.BouncyCastle.Asn1.X500; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class RestrictionUnitTest + : Asn1UnitTest + { + public override string Name + { + get { return "Restriction"; } + } + + public override void PerformTest() + { + 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 (ArgumentException) + { + // expected + } + } + + private void checkConstruction( + Restriction restriction, + DirectoryString res) + { + checkValues(restriction, res); + + restriction = Restriction.GetInstance(restriction); + + checkValues(restriction, res); + + Asn1InputStream aIn = new Asn1InputStream(restriction.ToAsn1Object().GetEncoded()); + + IAsn1String str = (IAsn1String) aIn.ReadObject(); + + restriction = Restriction.GetInstance(str); + + checkValues(restriction, res); + } + + private void checkValues( + Restriction restriction, + DirectoryString res) + { + checkMandatoryField("restriction", res, restriction.RestrictionString); + } + + public static void Main( + string[] args) + { + RunTest(new RestrictionUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/SMIMETest.cs b/crypto/test/src/asn1/test/SMIMETest.cs new file mode 100644 index 000000000..adb90e093 --- /dev/null +++ b/crypto/test/src/asn1/test/SMIMETest.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Smime; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class SmimeTest + : ITest + { + private static byte[] attrBytes = Base64.Decode("MDQGCSqGSIb3DQEJDzEnMCUwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMAcGBSsOAwIH"); + private static byte[] prefBytes = Base64.Decode("MCwGCyqGSIb3DQEJEAILMR2hGwQIAAAAAAAAAAAYDzIwMDcwMzE1MTczNzI5Wg=="); + + public ITestResult Perform() + { + SmimeCapabilityVector caps = new SmimeCapabilityVector(); + + caps.AddCapability(SmimeCapability.DesEde3Cbc); + caps.AddCapability(SmimeCapability.RC2Cbc, 128); + caps.AddCapability(SmimeCapability.DesCbc); + + SmimeCapabilitiesAttribute attr = new SmimeCapabilitiesAttribute(caps); + + SmimeEncryptionKeyPreferenceAttribute pref = new SmimeEncryptionKeyPreferenceAttribute( + new RecipientKeyIdentifier(new DerOctetString(new byte[8]), + new DerGeneralizedTime("20070315173729Z"), + null)); + + try + { + if (!Arrays.AreEqual(attr.GetEncoded(), attrBytes)) + { + return new SimpleTestResult(false, Name + ": Failed attr data check"); + } + + Asn1Object o = Asn1Object.FromByteArray(attrBytes); + if (!attr.Equals(o)) + { + return new SimpleTestResult(false, Name + ": Failed equality test for attr"); + } + + if (!Arrays.AreEqual(pref.GetEncoded(), prefBytes)) + { + return new SimpleTestResult(false, Name + ": Failed attr data check"); + } + + o = Asn1Object.FromByteArray(prefBytes); + if (!pref.Equals(o)) + { + return new SimpleTestResult(false, Name + ": Failed equality test for pref"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": Failed - exception " + e.ToString(), e); + } + } + + public string Name + { + get { return "SMIME"; } + } + + public static void Main( + string[] args) + { + ITest test = new SmimeTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/SemanticsInformationUnitTest.cs b/crypto/test/src/asn1/test/SemanticsInformationUnitTest.cs new file mode 100644 index 000000000..8f1f85f19 --- /dev/null +++ b/crypto/test/src/asn1/test/SemanticsInformationUnitTest.cs @@ -0,0 +1,138 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class SemanticsInformationUnitTest + : SimpleTest + { + public override string Name + { + get { return "SemanticsInformation"; } + } + + public override void PerformTest() + { + DerObjectIdentifier statementId = new DerObjectIdentifier("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 (ArgumentException) + { + // expected + } + + try + { + new SemanticsInformation(DerSequence.Empty); + + Fail("constructor failed to detect empty sequence."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + SemanticsInformation mv, + DerObjectIdentifier semanticsIdentifier, + GeneralName[] names) + { + CheckStatement(mv, semanticsIdentifier, names); + + mv = SemanticsInformation.GetInstance(mv); + + CheckStatement(mv, semanticsIdentifier, names); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(mv.ToAsn1Object().GetEncoded()); + + mv = SemanticsInformation.GetInstance(seq); + + CheckStatement(mv, semanticsIdentifier, names); + } + + private void CheckStatement( + SemanticsInformation si, + DerObjectIdentifier id, + GeneralName[] names) + { + if (id != null) + { + if (!si.SemanticsIdentifier.Equals(id)) + { + Fail("ids don't match."); + } + } + else if (si.SemanticsIdentifier != 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/SetTest.cs b/crypto/test/src/asn1/test/SetTest.cs new file mode 100644 index 000000000..57c46603d --- /dev/null +++ b/crypto/test/src/asn1/test/SetTest.cs @@ -0,0 +1,117 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /// Set sorting test example. + [TestFixture] + public class SetTest + : SimpleTest + { + public override string Name + { + get { return "Set"; } + } + + private void checkSortedSet( + int attempt, + Asn1Set s) + { + if (s[0] is DerBoolean + && s[1] is DerInteger + && s[2] is DerBitString + && s[3] is DerOctetString) + { + return; + } + + Fail("sorting failed on attempt: " + attempt); + } + + public override void PerformTest() + { + Asn1EncodableVector v = new Asn1EncodableVector(); + byte[] data = new byte[10]; + + v.Add(new DerOctetString(data)); + v.Add(new DerBitString(data)); + v.Add(new DerInteger(100)); + v.Add(DerBoolean.True); + + checkSortedSet(0, new DerSet(v)); + + v = new Asn1EncodableVector(); + v.Add(new DerInteger(100)); + v.Add(DerBoolean.True); + v.Add(new DerOctetString(data)); + v.Add(new DerBitString(data)); + + checkSortedSet(1, new DerSet(v)); + + v = new Asn1EncodableVector(); + v.Add(DerBoolean.True); + v.Add(new DerOctetString(data)); + v.Add(new DerBitString(data)); + v.Add(new DerInteger(100)); + + + checkSortedSet(2, new DerSet(v)); + + v = new Asn1EncodableVector(); + v.Add(new DerBitString(data)); + v.Add(new DerOctetString(data)); + v.Add(new DerInteger(100)); + v.Add(DerBoolean.True); + + checkSortedSet(3, new DerSet(v)); + + v = new Asn1EncodableVector(); + v.Add(new DerOctetString(data)); + v.Add(new DerBitString(data)); + v.Add(new DerInteger(100)); + v.Add(DerBoolean.True); + + Asn1Set s = new BerSet(v); + + if (!(s[0] is 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[0] is DerBoolean) + { + Fail("sorted when shouldn't be."); + } + + // equality test + v = new Asn1EncodableVector(); + + v.Add(DerBoolean.True); + v.Add(DerBoolean.True); + v.Add(DerBoolean.True); + + s = new DerSet(v); + } + + public static void Main( + string[] args) + { + RunTest(new SetTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/SignerLocationUnitTest.cs b/crypto/test/src/asn1/test/SignerLocationUnitTest.cs new file mode 100644 index 000000000..bf20f1fda --- /dev/null +++ b/crypto/test/src/asn1/test/SignerLocationUnitTest.cs @@ -0,0 +1,195 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Esf; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class SignerLocationUnitTest + : SimpleTest + { + public override string Name + { + get { return "SignerLocation"; } + } + + public override void PerformTest() + { + 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); + + Asn1Sequence postalAddress = new DerSequence( + new DerUtf8String("line 1"), + new DerUtf8String("line 2")); + + 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 (ArgumentException) + { + // expected + } + + // + // out of range postal address + // + postalAddress = new DerSequence( + new DerUtf8String("line 1"), + new DerUtf8String("line 2"), + new DerUtf8String("line 3"), + new DerUtf8String("line 4"), + new DerUtf8String("line 5"), + new DerUtf8String("line 6"), + new DerUtf8String("line 7")); + + try + { + new SignerLocation(null, null, postalAddress); + + Fail("constructor failed to detect bad postalAddress."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new SignerLocation(new DerSequence(new DerTaggedObject(2, postalAddress))); + + Fail("sequence constructor failed to detect bad postalAddress."); + } + catch (ArgumentException) + { + // expected + } + + try + { + new SignerLocation(new DerSequence(new DerTaggedObject(5, postalAddress))); + + Fail("sequence constructor failed to detect bad tag."); + } + catch (ArgumentException) + { + // expected + } + } + + private void CheckConstruction( + SignerLocation sl, + DerUtf8String countryName, + DerUtf8String localityName, + Asn1Sequence postalAddress) + { + CheckValues(sl, countryName, localityName, postalAddress); + + sl = SignerLocation.GetInstance(sl); + + CheckValues(sl, countryName, localityName, postalAddress); + + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray( + sl.ToAsn1Object().GetEncoded()); + + 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.CountryName)) + { + Fail("countryNames don't match."); + } + } + else if (sl.CountryName != null) + { + Fail("countryName found when none expected."); + } + + if (localityName != null) + { + if (!localityName.Equals(sl.LocalityName)) + { + Fail("localityNames don't match."); + } + } + else if (sl.LocalityName != null) + { + Fail("localityName found when none expected."); + } + + if (postalAddress != null) + { + if (!postalAddress.Equals(sl.PostalAddress)) + { + Fail("postalAddresses don't match."); + } + } + else if (sl.PostalAddress != null) + { + Fail("postalAddress found when none expected."); + } + } + + public static void Main( + string[] args) + { + RunTest(new SignerLocationUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/StringTest.cs b/crypto/test/src/asn1/test/StringTest.cs new file mode 100644 index 000000000..acfd380b2 --- /dev/null +++ b/crypto/test/src/asn1/test/StringTest.cs @@ -0,0 +1,105 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * X.690 test example + */ + [TestFixture] + public class StringTest + : SimpleTest + { + public override string Name + { + get { return "String"; } + } + + public override void PerformTest() + { + 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[] { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8 }; + string t61String = Encoding.GetEncoding("iso-8859-1").GetString(t61Bytes, 0, t61Bytes.Length); + DerT61String t61 = new DerT61String(t61Bytes); + + if (!t61.GetString().Equals(t61String)) + { + Fail("DerT61String.GetString() result incorrect"); + } + + if (!t61.ToString().Equals(t61String)) + { + Fail("DerT61String.ToString() result incorrect"); + } + } + + public static void Main( + string[] args) + { + RunTest(new StringTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/SubjectKeyIdentifierTest.cs b/crypto/test/src/asn1/test/SubjectKeyIdentifierTest.cs new file mode 100644 index 000000000..127c47a3a --- /dev/null +++ b/crypto/test/src/asn1/test/SubjectKeyIdentifierTest.cs @@ -0,0 +1,61 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class SubjectKeyIdentifierTest + : 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 override string Name + { + get { return "SubjectKeyIdentifier"; } + } + + public override void PerformTest() + { + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.GetInstance( + Asn1Object.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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/TagTest.cs b/crypto/test/src/asn1/test/TagTest.cs new file mode 100644 index 000000000..c5fce6dbc --- /dev/null +++ b/crypto/test/src/asn1/test/TagTest.cs @@ -0,0 +1,115 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * X.690 test example + */ + [TestFixture] + public class TagTest + : SimpleTest + { + private static readonly byte[] longTagged = Base64.Decode( + "ZSRzIp8gEEZFRENCQTk4NzY1NDMyMTCfIQwyMDA2MDQwMTEyMzSUCCAFERVz" + + "A4kCAHEXGBkalAggBRcYGRqUCCAFZS6QAkRFkQlURUNITklLRVKSBQECAwQF" + + "kxAREhMUFRYXGBkalAggBREVcwOJAgBxFxgZGpQIIAUXGBkalAggBWUukAJE" + + "RZEJVEVDSE5JS0VSkgUBAgMEBZMQERITFBUWFxgZGpQIIAURFXMDiQIAcRcY" + + "GRqUCCAFFxgZGpQIIAVlLpACREWRCVRFQ0hOSUtFUpIFAQIDBAWTEBESExQV" + + "FhcYGRqUCCAFERVzA4kCAHEXGBkalAggBRcYGRqUCCAFFxgZGpQIIAUXGBka" + + "lAg="); + + private static readonly byte[] longAppSpecificTag = Hex.Decode("5F610101"); + + public override string Name + { + get { return "Tag"; } + } + + public override void PerformTest() + { + DerApplicationSpecific app = (DerApplicationSpecific) + Asn1Object.FromByteArray(longTagged); + + app = (DerApplicationSpecific) Asn1Object.FromByteArray(app.GetContents()); + + Asn1InputStream aIn = new Asn1InputStream(app.GetContents()); + + Asn1TaggedObject tagged = (Asn1TaggedObject) aIn.ReadObject(); + + if (tagged.TagNo != 32) + { + Fail("unexpected tag value found - not 32"); + } + + tagged = (Asn1TaggedObject) Asn1Object.FromByteArray(tagged.GetEncoded()); + + if (tagged.TagNo != 32) + { + Fail("unexpected tag value found on recode - not 32"); + } + + tagged = (Asn1TaggedObject) aIn.ReadObject(); + + if (tagged.TagNo != 33) + { + Fail("unexpected tag value found - not 33"); + } + + tagged = (Asn1TaggedObject) Asn1Object.FromByteArray(tagged.GetEncoded()); + + if (tagged.TagNo != 33) + { + Fail("unexpected tag value found on recode - not 33"); + } + + aIn = new Asn1InputStream(longAppSpecificTag); + + app = (DerApplicationSpecific)aIn.ReadObject(); + + if (app.ApplicationTag != 97) + { + Fail("incorrect tag number read"); + } + + app = (DerApplicationSpecific)Asn1Object.FromByteArray(app.GetEncoded()); + + if (app.ApplicationTag != 97) + { + Fail("incorrect tag number read on recode"); + } + + SecureRandom sr = new SecureRandom(); + for (int i = 0; i < 100; ++i) + { + int testTag = (sr.NextInt() & int.MaxValue) >> sr.Next(26); + app = new DerApplicationSpecific(testTag, new byte[]{ 1 }); + app = (DerApplicationSpecific)Asn1Object.FromByteArray(app.GetEncoded()); + + if (app.ApplicationTag != testTag) + { + Fail("incorrect tag number read on recode (random test value: " + testTag + ")"); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new TagTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/TargetInformationTest.cs b/crypto/test/src/asn1/test/TargetInformationTest.cs new file mode 100644 index 000000000..7fa04cd01 --- /dev/null +++ b/crypto/test/src/asn1/test/TargetInformationTest.cs @@ -0,0 +1,58 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class TargetInformationTest + : SimpleTest + { + public override string Name + { + get { return "TargetInformation"; } + } + + public override void PerformTest() + { + Target[] targets = new Target[2]; + Target targetName = new Target(Target.Choice.Name, new GeneralName(GeneralName.DnsName, "www.test.com")); + Target targetGroup = new Target(Target.Choice.Group, 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.ToAsn1Object()); + TargetInformation targetInformation4 = TargetInformation.GetInstance(targetInformation2.ToAsn1Object()); + if (!targetInformation3.Equals(targetInformation4)) + { + Fail("targetInformation3 and targetInformation4 should have the same encoding."); + } + } + + public static void Main( + string[] args) + { + RunTest(new TargetInformationTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/TimeTest.cs b/crypto/test/src/asn1/test/TimeTest.cs new file mode 100644 index 000000000..6f6bd6f2c --- /dev/null +++ b/crypto/test/src/asn1/test/TimeTest.cs @@ -0,0 +1,28 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class TimeTest + { + [Test] + public void CheckCmsTimeVsX509Time() + { + DateTime now = DateTime.UtcNow; + + // Time classes only have a resolution of seconds + now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); + + Org.BouncyCastle.Asn1.Cms.Time cmsTime = new Org.BouncyCastle.Asn1.Cms.Time(now); + Org.BouncyCastle.Asn1.X509.Time x509Time = new Org.BouncyCastle.Asn1.X509.Time(now); + +// Assert.AreEqual(cmsTime.Date, x509Time.ToDateTime()); + Assert.AreEqual(now, cmsTime.Date); + Assert.AreEqual(now, x509Time.ToDateTime()); + } + } +} diff --git a/crypto/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs b/crypto/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs new file mode 100644 index 000000000..a59415c31 --- /dev/null +++ b/crypto/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs @@ -0,0 +1,152 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509.Qualified; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class TypeOfBiometricDataUnitTest + : SimpleTest + { + public override string Name + { + get { return "TypeOfBiometricData"; } + } + + public override void PerformTest() + { + // + // predefined + // + CheckPredefinedType(TypeOfBiometricData.Picture); + + CheckPredefinedType(TypeOfBiometricData.HandwrittenSignature); + + // + // non-predefined + // + DerObjectIdentifier localType = new DerObjectIdentifier("1.1"); + + TypeOfBiometricData type = new TypeOfBiometricData(localType); + + CheckNonPredefined(type, localType); + + type = TypeOfBiometricData.GetInstance(type); + + CheckNonPredefined(type, localType); + + Asn1Object obj = type.ToAsn1Object(); + + 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 (ArgumentException) + { + // expected + } + + try + { + new TypeOfBiometricData(100); + + Fail("constructor failed to detect bad predefined type."); + } + catch (ArgumentException) + { + // expected + } + + // Call Equals to avoid unreachable code warning + if (!Equals(TypeOfBiometricData.Picture, 0)) + { + Fail("predefined picture should be 0"); + } + + // Call Equals to avoid unreachable code warning + if (!Equals(TypeOfBiometricData.HandwrittenSignature, 1)) + { + Fail("predefined handwritten signature should be 1"); + } + } + + private void CheckPredefinedType( + int predefinedType) + { + TypeOfBiometricData type = new TypeOfBiometricData(predefinedType); + + CheckPredefined(type, predefinedType); + + type = TypeOfBiometricData.GetInstance(type); + + CheckPredefined(type, predefinedType); + + Asn1Object obj = Asn1Object.FromByteArray(type.ToAsn1Object().GetEncoded()); + + type = TypeOfBiometricData.GetInstance(obj); + + CheckPredefined(type, predefinedType); + } + + private void CheckPredefined( + TypeOfBiometricData type, + int val) + { + if (!type.IsPredefined) + { + Fail("predefined type expected but not found."); + } + + if (type.PredefinedBiometricType != val) + { + Fail("predefined type does not match."); + } + } + + private void CheckNonPredefined( + TypeOfBiometricData type, + DerObjectIdentifier val) + { + if (type.IsPredefined) + { + Fail("predefined type found when not expected."); + } + + if (!type.BiometricDataOid.Equals(val)) + { + Fail("data oid does not match."); + } + } + + public static void Main( + string[] args) + { + RunTest(new TypeOfBiometricDataUnitTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/UTCTimeTest.cs b/crypto/test/src/asn1/test/UTCTimeTest.cs new file mode 100644 index 000000000..07abbc911 --- /dev/null +++ b/crypto/test/src/asn1/test/UTCTimeTest.cs @@ -0,0 +1,122 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + /** + * X.690 test example + */ + [TestFixture] + public class UtcTimeTest + : SimpleTest + { + private static readonly string[] input = + { + "020122122220Z", + "020122122220-1000", + "020122122220+1000", + "020122122220+00", + "0201221222Z", + "0201221222-1000", + "0201221222+1000", + "0201221222+00", + "550122122220Z", + "5501221222Z" + }; + + private static readonly 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" + }; + + private static readonly string[] zOutput1 = + { + "20020122122220Z", + "20020122222220Z", + "20020122022220Z", + "20020122122220Z", + "20020122122200Z", + "20020122222200Z", + "20020122022200Z", + "20020122122200Z", + "19550122122220Z", + "19550122122200Z" + }; + + private static readonly string[] zOutput2 = + { + "20020122122220Z", + "20020122222220Z", + "20020122022220Z", + "20020122122220Z", + "20020122122200Z", + "20020122222200Z", + "20020122022200Z", + "20020122122200Z", + "19550122122220Z", + "19550122122200Z" + }; + + public override string Name + { + get { return "UTCTime"; } + } + + public override void PerformTest() + { +// 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.AdjustedTimeString.Equals(output[i])) + { + Fail("failed conversion test " + i); + } + +// if (!yyyyF.format(t.getAdjustedDate()).Equals(zOutput1[i])) + if (!t.ToAdjustedDateTime().ToString(@"yyyyMMddHHmmss\Z").Equals(zOutput1[i])) + { + Fail("failed date conversion test " + i); + } + +// if (!yyF.format(t.getDate()).Equals(zOutput2[i])) + if (!t.ToDateTime().ToString(@"yyyyMMddHHmmss\Z").Equals(zOutput2[i])) + { + Fail("failed date shortened conversion test " + i); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new UtcTimeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/X509ExtensionsTest.cs b/crypto/test/src/asn1/test/X509ExtensionsTest.cs new file mode 100644 index 000000000..f1efd3a9b --- /dev/null +++ b/crypto/test/src/asn1/test/X509ExtensionsTest.cs @@ -0,0 +1,117 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class X509ExtensionsTest + : SimpleTest + { + private static readonly DerObjectIdentifier Oid1 = new DerObjectIdentifier("1.2.1"); + private static readonly DerObjectIdentifier Oid2 = new DerObjectIdentifier("1.2.2"); + private static readonly DerObjectIdentifier Oid3 = new DerObjectIdentifier("1.2.3"); + + public override string Name + { + get { return "X509Extensions"; } + } + + public override void PerformTest() + { + X509ExtensionsGenerator gen = new X509ExtensionsGenerator(); + + gen.AddExtension(Oid1, true, new byte[20]); + gen.AddExtension(Oid2, true, new byte[20]); + + X509Extensions ext1 = gen.Generate(); + X509Extensions ext2 = gen.Generate(); + + if (!ext1.Equals(ext2)) + { + Fail("Equals test failed"); + } + + gen.Reset(); + + gen.AddExtension(Oid2, true, new byte[20]); + gen.AddExtension(Oid1, 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(Oid1, true, new byte[22]); + gen.AddExtension(Oid2, 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(Oid3, true, new byte[20]); + gen.AddExtension(Oid2, 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(Oid2, true, new byte[20]); + Fail("repeated oid"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("extension 1.2.2 already added")) + { + Fail("wrong exception on repeated oid: " + e.Message); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new X509ExtensionsTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/X509NameTest.cs b/crypto/test/src/asn1/test/X509NameTest.cs new file mode 100644 index 000000000..7a0832c3e --- /dev/null +++ b/crypto/test/src/asn1/test/X509NameTest.cs @@ -0,0 +1,674 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class X509NameTest + : SimpleTest + { + private static readonly 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 override string Name + { + get { return "X509Name"; } + } + + private static X509Name FromBytes( + byte[] bytes) + { + return X509Name.GetInstance(Asn1Object.FromByteArray(bytes)); + } + + private IAsn1Convertible createEntryValue( + DerObjectIdentifier oid, + string value) + { + IDictionary attrs = new Hashtable(); + attrs.Add(oid, value); + + IList ord = new ArrayList(); + ord.Add(oid); + + X509Name name = new X509Name(ord, attrs); + + Asn1Sequence seq = (Asn1Sequence)name.ToAsn1Object(); + Asn1Set set = (Asn1Set)seq[0]; + seq = (Asn1Sequence)set[0]; + + return seq[1]; + } + + private IAsn1Convertible createEntryValueFromString( + DerObjectIdentifier oid, + string val) + { + IDictionary attrs = new Hashtable(); + attrs.Add(oid, val); + + IList ord = new ArrayList(attrs.Keys); + + X509Name name = new X509Name(new X509Name(ord, attrs).ToString()); + + Asn1Sequence seq = (Asn1Sequence) name.ToAsn1Object(); + Asn1Set asn1Set = (Asn1Set) seq[0]; + seq = (Asn1Sequence) asn1Set[0]; + + return seq[1]; + } + + private void doTestEncodingPrintableString( + DerObjectIdentifier oid, + string value) + { + IAsn1Convertible converted = createEntryValue(oid, value); + if (!(converted is DerPrintableString)) + { + Fail("encoding for " + oid + " not printable string"); + } + } + + private void doTestEncodingIA5String( + DerObjectIdentifier oid, + string value) + { + IAsn1Convertible converted = createEntryValue(oid, value); + if (!(converted is DerIA5String)) + { + Fail("encoding for " + oid + " not IA5String"); + } + } + + private void doTestEncodingGeneralizedTime( + DerObjectIdentifier oid, + string val) + { + IAsn1Convertible converted = createEntryValue(oid, val); + if (!(converted is DerGeneralizedTime)) + { + Fail("encoding for " + oid + " not GeneralizedTime"); + } + converted = createEntryValueFromString(oid, val); + if (!(converted is DerGeneralizedTime)) + { + Fail("encoding for " + oid + " not GeneralizedTime"); + } + } + + public override void PerformTest() + { + doTestEncodingPrintableString(X509Name.C, "AU"); + doTestEncodingPrintableString(X509Name.SerialNumber, "123456"); + doTestEncodingPrintableString(X509Name.DnQualifier, "123456"); + doTestEncodingIA5String(X509Name.EmailAddress, "test@test.com"); + doTestEncodingIA5String(X509Name.DC, "test"); + // correct encoding + doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "#180F32303032303132323132323232305A"); + // compatability encoding + doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "20020122122220Z"); + + // + // composite + // + IDictionary attrs = new Hashtable(); + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.E, "feedback-crypto@bouncycastle.org"); + + IList order = new ArrayList(); + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.E); + + X509Name name1 = new X509Name(order, attrs); + + if (!name1.Equivalent(name1)) + { + Fail("Failed same object test"); + } + + if (!name1.Equivalent(name1, true)) + { + Fail("Failed same object test - in Order"); + } + + X509Name name2 = new X509Name(order, attrs); + + if (!name1.Equivalent(name2)) + { + Fail("Failed same name test"); + } + + if (!name1.Equivalent(name2, true)) + { + Fail("Failed same name test - in Order"); + } + + if (name1.GetHashCode() != name2.GetHashCode()) + { + Fail("Failed same name test - in Order"); + } + + IList ord1 = new ArrayList(); + + ord1.Add(X509Name.C); + ord1.Add(X509Name.O); + ord1.Add(X509Name.L); + ord1.Add(X509Name.ST); + ord1.Add(X509Name.E); + + IList ord2 = new ArrayList(); + + ord2.Add(X509Name.E); + ord2.Add(X509Name.ST); + ord2.Add(X509Name.L); + ord2.Add(X509Name.O); + ord2.Add(X509Name.C); + + name1 = new X509Name(ord1, attrs); + name2 = new X509Name(ord2, attrs); + + if (!name1.Equivalent(name2)) + { + Fail("Failed reverse name test"); + } + + // FIXME Sort out X509Name hashcode problem +// if (name1.GetHashCode() != name2.GetHashCode()) +// { +// Fail("Failed reverse name test GetHashCode"); +// } + + if (name1.Equivalent(name2, true)) + { + Fail("Failed reverse name test - in Order"); + } + + if (!name1.Equivalent(name2, false)) + { + Fail("Failed reverse name test - in Order false"); + } + + IList oids = name1.GetOidList(); + if (!CompareVectors(oids, ord1)) + { + Fail("oid comparison test"); + } + + IList val1 = new ArrayList(); + + val1.Add("AU"); + val1.Add("The Legion of the Bouncy Castle"); + val1.Add("Melbourne"); + val1.Add("Victoria"); + val1.Add("feedback-crypto@bouncycastle.org"); + + name1 = new X509Name(ord1, val1); + + IList values = name1.GetValueList(); + if (!CompareVectors(values, val1)) + { + Fail("value comparison test"); + } + + ord2 = new ArrayList(); + + ord2.Add(X509Name.ST); + ord2.Add(X509Name.ST); + ord2.Add(X509Name.L); + ord2.Add(X509Name.O); + ord2.Add(X509Name.C); + + name1 = new X509Name(ord1, attrs); + name2 = new X509Name(ord2, attrs); + + if (name1.Equivalent(name2)) + { + Fail("Failed different name test"); + } + + ord2 = new ArrayList(); + + ord2.Add(X509Name.ST); + ord2.Add(X509Name.L); + ord2.Add(X509Name.O); + ord2.Add(X509Name.C); + + name1 = new X509Name(ord1, attrs); + name2 = new X509Name(ord2, attrs); + + if (name1.Equivalent(name2)) + { + Fail("Failed subset name test"); + } + + + compositeTest(); + + + // + // getValues test + // + ArrayList v1 = name1.GetValues(X509Name.O); + + if (v1.Count != 1 || !v1[0].Equals("The Legion of the Bouncy Castle")) + { + Fail("O test failed"); + } + + ArrayList v2 = name1.GetValues(X509Name.L); + + if (v2.Count != 1 || !v2[0].Equals("Melbourne")) + { + Fail("L test failed"); + } + + // + // general subjects test + // + for (int i = 0; i != subjects.Length; i++) + { + X509Name name = new X509Name(subjects[i]); + byte[] encodedName = name.GetEncoded(); + name = X509Name.GetInstance(Asn1Object.FromByteArray(encodedName)); + + if (!name.ToString().Equals(subjects[i])) + { + Fail("Failed regeneration test " + i); + } + } + + // + // 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(Asn1Object.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.Equivalent(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(DerSequence.Empty)) + { + Fail("inequality test with sequence"); + } + + if (name1.Equals(new DerSequence(DerSet.Empty))) + { + Fail("inequality test with sequence and set"); + } + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerObjectIdentifier("1.1"), + new DerObjectIdentifier("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"); +// } + try + { + X509Name.GetInstance(new DerSequence(new DerSet(new DerSet(v)))); + Fail("GetInstance should reject bad sequence"); + } + catch (ArgumentException) + { + //expected + } + + if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty)))) + { + Fail("inequality test with sequence and short sequence"); + } + +// if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty)), true)) +// { +// Fail("inequality test with sequence and short sequence"); +// } + try + { + X509Name.GetInstance(new DerSequence(new DerSet(DerSequence.Empty))); + Fail("GetInstance should reject short sequence"); + } + catch (ArgumentException) + { + //expected + } + + v = new Asn1EncodableVector( + new DerObjectIdentifier("1.1"), + DerSequence.Empty); + + if (name1.Equals(new DerSequence(new DerSet(new DerSequence(v))))) + { + Fail("inequality test with sequence and bad sequence"); + } + + if (name1.Equivalent(null)) + { + Fail("inequality test with null"); + } + + if (name1.Equivalent(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(); + string hexEncodedString = "#" + Hex.ToHexString(encodedBytes); + + 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."); + } + + ArrayList vls = n.GetValues(X509Name.CN); + if (vls.Count != 1 || !vls[0].Equals("#nothex#string")) + { + Fail("Escaped # not reduced properly"); + } + + n = new X509Name("CN=\"a+b\""); + + vls = n.GetValues(X509Name.CN); + if (vls.Count != 1 || !vls[0].Equals("a+b")) + { + Fail("Escaped + not reduced properly"); + } + + n = new X509Name("CN=a\\+b"); + + vls = n.GetValues(X509Name.CN); + if (vls.Count != 1 || !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 X509Name("CN=a\\=b"); + + vls = n.GetValues(X509Name.CN); + if (vls.Count != 1 || !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 X509Name("TELEPHONENUMBER=\"+61999999999\""); + + vls = n.GetValues(X509Name.TelephoneNumber); + if (vls.Count != 1 || !vls[0].Equals("+61999999999")) + { + Fail("telephonenumber escaped + not reduced properly"); + } + + n = new X509Name("TELEPHONENUMBER=\\+61999999999"); + + vls = n.GetValues(X509Name.TelephoneNumber); + if (vls.Count != 1 || !vls[0].Equals("+61999999999")) + { + Fail("telephonenumber escaped + not reduced properly"); + } + + n = new X509Name(@"TELEPHONENUMBER=\+61999999999"); + + vls = n.GetValues(X509Name.TelephoneNumber); + if (vls.Count != 1 || !vls[0].Equals("+61999999999")) + { + Fail("telephonenumber escaped + not reduced properly"); + } + } + + private void compositeTest() + { + // + // composite test + // + byte[] enc = Hex.Decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65"); + X509Name n = X509Name.GetInstance(Asn1Object.FromByteArray(enc)); + + 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()); + } + + IDictionary symbols = X509Name.DefaultSymbols; + if (!n.ToString(true, symbols).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, symbols)); + } + + 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"); + + MemoryStream bOut = new MemoryStream(); + Asn1OutputStream aOut = new Asn1OutputStream(bOut); + + aOut.WriteObject(n); + + byte[] enc2 = bOut.ToArray(); + + 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(Asn1Object.FromByteArray(n.GetEncoded())); + } + + private void equalityTest( + X509Name x509Name, + X509Name x509Name1) + { + if (!x509Name.Equivalent(x509Name1)) + { + Fail("equality test failed for " + x509Name + " : " + x509Name1); + } + + // FIXME Sort out X509Name hashcode problem +// if (x509Name.GetHashCode() != x509Name1.GetHashCode()) +// { +// Fail("GetHashCode test failed for " + x509Name + " : " + x509Name1); +// } + + if (!x509Name.Equivalent(x509Name1, true)) + { + Fail("equality test failed for " + x509Name + " : " + x509Name1); + } + } + + private bool CompareVectors( + IList one, + IList two) + { + if (one.Count != two.Count) + return false; + + for (int i = 0; i < one.Count; ++i) + { + if (!one[i].Equals(two[i])) + return false; + } + + return true; + } + + public static void Main( + string[] args) + { + ITest test = new X509NameTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/X9Test.cs b/crypto/test/src/asn1/test/X9Test.cs new file mode 100644 index 000000000..540cddb47 --- /dev/null +++ b/crypto/test/src/asn1/test/X9Test.cs @@ -0,0 +1,181 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class X9Test + : SimpleTest + { + private static readonly byte[] namedPub = Base64.Decode("MBowEwYHKoZIzj0CAQYIKoZIzj0DAQEDAwADAQ=="); + private static readonly byte[] expPub = Base64.Decode( + "MIHfMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAA" + + "AAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL" + + "A9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks/PAF" + + "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED" + + "AwADAQ=="); + + private static readonly byte[] namedPriv = Base64.Decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK"); + private static readonly byte[] expPriv = Base64.Decode( + "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4" + + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU" + + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks" + + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC" + + "AQEECDAGAgEBBAEU"); + + private void EncodePublicKey() + { + X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3); + + if (X9IntegerConverter.GetByteLength(ecP.Curve) != 30) + { + Fail("wrong byte length reported for curve"); + } + + if (ecP.Curve.FieldSize != 239) + { + Fail("wrong field size reported for curve"); + } + + // + // named curve + // + X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1); + + X9ECPoint pPoint = new X9ECPoint( + new FpPoint(ecP.Curve, new FpFieldElement(BigInteger.Two, BigInteger.One), + new FpFieldElement(BigInteger.ValueOf(4), BigInteger.ValueOf(3)), + true)); + + Asn1OctetString p = (Asn1OctetString) pPoint.ToAsn1Object(); + + if (p == null) + { + Fail("failed to convert to ASN.1"); + } + + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), p.GetOctets()); + + if (!Arrays.AreEqual(info.GetEncoded(), namedPub)) + { + Fail("failed public named generation"); + } + + Asn1Object o = Asn1Object.FromByteArray(namedPub); + + if (!info.Equals(o)) + { + Fail("failed public named equality"); + } + + // + // explicit curve parameters + // + _params = new X962Parameters(ecP); + + info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), p.GetOctets()); + + if (!Arrays.AreEqual(info.GetEncoded(), expPub)) + { + Fail("failed public explicit generation"); + } + + o = Asn1Object.FromByteArray(expPub); + + if (!info.Equals(o)) + { + Fail("failed public explicit equality"); + } + } + + private void EncodePrivateKey() + { + X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3); + + // + // named curve + // + X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1); + + X9ECPoint pPoint = new X9ECPoint( + new FpPoint(ecP.Curve, new FpFieldElement(BigInteger.Two, BigInteger.One), + new FpFieldElement(BigInteger.ValueOf(4), BigInteger.ValueOf(3)), + true)); + + Asn1OctetString p = (Asn1OctetString) pPoint.ToAsn1Object(); + + if (p == null) + Fail("failed to convert to ASN.1"); + + PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.Ten).ToAsn1Object()); + + if (!Arrays.AreEqual(info.GetEncoded(), namedPriv)) + { + Fail("failed private named generation"); + } + + Asn1Object o = Asn1Object.FromByteArray(namedPriv); + + if (!info.Equals(o)) + { + Fail("failed private named equality"); + } + + // + // explicit curve parameters + // + _params = new X962Parameters(ecP); + + info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.ValueOf(20)).ToAsn1Object()); + + if (!Arrays.AreEqual(info.GetEncoded(), expPriv)) + { + Fail("failed private explicit generation"); + } + + o = Asn1Object.FromByteArray(expPriv); + + if (!info.Equals(o)) + { + Fail("failed private explicit equality"); + } + } + + public override void PerformTest() + { + EncodePublicKey(); + EncodePrivateKey(); + } + + public override string Name + { + get { return "X9"; } + } + + public static void Main( + string[] args) + { + RunTest(new X9Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/cms/test/AllTests.cs b/crypto/test/src/cms/test/AllTests.cs new file mode 100644 index 000000000..1ce3b7c8d --- /dev/null +++ b/crypto/test/src/cms/test/AllTests.cs @@ -0,0 +1,35 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Cms.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("CMS Tests"); + + suite.Add(new CompressedDataTest()); + suite.Add(new CompressedDataStreamTest()); + suite.Add(new EnvelopedDataTest()); + suite.Add(new EnvelopedDataStreamTest()); + suite.Add(new Rfc4134Test()); + suite.Add(new SignedDataTest()); + suite.Add(new SignedDataStreamTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/cms/test/AuthenticatedDataStreamTest.cs b/crypto/test/src/cms/test/AuthenticatedDataStreamTest.cs new file mode 100644 index 000000000..89a2174b7 --- /dev/null +++ b/crypto/test/src/cms/test/AuthenticatedDataStreamTest.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class AuthenticatedDataStreamTest + { + private const string SignDN = "O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair signKP; +// private static X509Certificate signCert; + //signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN); + +// private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + +// private static AsymmetricCipherKeyPair origKP; + //origKP = CmsTestUtil.MakeKeyPair(); +// private static X509Certificate origCert; + //origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN); + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair reciKP; + private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origECKP; + private static AsymmetricCipherKeyPair reciECKP; + private static X509Certificate reciECCert; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair ReciKP + { + get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } + } + + private static X509Certificate ReciCert + { + get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } + } + + private static AsymmetricCipherKeyPair OrigECKP + { + get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; } + } + + private static AsymmetricCipherKeyPair ReciECKP + { + get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; } + } + + private static X509Certificate ReciECCert + { + get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; } + } + + [Test] + public void TestKeyTransDESede() + { + tryKeyTrans(CmsAuthenticatedDataGenerator.DesEde3Cbc); + } + + private void tryKeyTrans( + string macAlg) + { + byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna"); + + CmsAuthenticatedDataStreamGenerator adGen = new CmsAuthenticatedDataStreamGenerator(); + + adGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + Stream aOut = adGen.Open(bOut, macAlg); + aOut.Write(data, 0, data.Length); + aOut.Close(); + + CmsAuthenticatedDataParser ad = new CmsAuthenticatedDataParser(bOut.ToArray()); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(ad.MacAlgOid, macAlg); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + } +} \ No newline at end of file diff --git a/crypto/test/src/cms/test/AuthenticatedDataTest.cs b/crypto/test/src/cms/test/AuthenticatedDataTest.cs new file mode 100644 index 000000000..0ad34a95b --- /dev/null +++ b/crypto/test/src/cms/test/AuthenticatedDataTest.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class AuthenticatedDataTest + { + private const string SignDN = "O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair signKP; +// private static X509Certificate signCert; + //signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN); + +// private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + +// private static AsymmetricCipherKeyPair origKP; + //origKP = CmsTestUtil.MakeKeyPair(); +// private static X509Certificate origCert; + //origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN); + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair reciKP; + private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origECKP; + private static AsymmetricCipherKeyPair reciECKP; + private static X509Certificate reciECCert; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair ReciKP + { + get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } + } + + private static X509Certificate ReciCert + { + get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } + } + + private static AsymmetricCipherKeyPair OrigECKP + { + get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; } + } + + private static AsymmetricCipherKeyPair ReciECKP + { + get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; } + } + + private static X509Certificate ReciECCert + { + get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; } + } + +// private static string _signDN; +// private static KeyPair _signKP; +// private static X509Certificate _signCert; +// +// private static string _origDN; +// private static KeyPair _origKP; +// private static X509Certificate _origCert; +// +// private static string _reciDN; +// private static KeyPair _reciKP; +// private static X509Certificate _reciCert; +// +// private static KeyPair _origEcKP; +// private static KeyPair _reciEcKP; +// private static X509Certificate _reciEcCert; +// +// private static bool _initialised = false; +// +// public bool DEBUG = true; +// +// private static void init() +// { +// if (!_initialised) +// { +// _initialised = true; +// +// _signDN = "O=Bouncy Castle, C=AU"; +// _signKP = CmsTestUtil.makeKeyPair(); +// _signCert = CmsTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); +// +// _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; +// _origKP = CmsTestUtil.makeKeyPair(); +// _origCert = CmsTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); +// +// _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; +// _reciKP = CmsTestUtil.makeKeyPair(); +// _reciCert = CmsTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); +// +// _origEcKP = CmsTestUtil.makeEcDsaKeyPair(); +// _reciEcKP = CmsTestUtil.makeEcDsaKeyPair(); +// _reciEcCert = CmsTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); +// } +// } +// +// public void setUp() +// { +// init(); +// } +// +// public AuthenticatedDataTest(string name) +// { +// super(name); +// } +// +// public static void main(string args[]) +// { +// junit.textui.TestRunner.run(AuthenticatedDataTest.class); +// } +// +// public static Test suite() +// throws Exception +// { +// init(); +// +// return new CMSTestSetup(new TestSuite(AuthenticatedDataTest.class)); +// } + + [Test] + public void TestKeyTransDESede() + { + tryKeyTrans(CmsAuthenticatedDataGenerator.DesEde3Cbc); + } + + [Test] + public void TestKEKDESede() + { + tryKekAlgorithm(CmsTestUtil.MakeDesEde192Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6")); + } + + [Test] + public void TestPasswordAES256() + { + passwordTest(CmsAuthenticatedDataGenerator.Aes256Cbc); + } + + [Test] + public void TestECKeyAgree() + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator(); + + adGen.AddKeyAgreementRecipient(CmsAuthenticatedDataGenerator.ECDHSha1Kdf, OrigECKP.Private, OrigECKP.Public, ReciECCert, CmsAuthenticatedDataGenerator.Aes128Wrap); + + CmsAuthenticatedData ad = adGen.Generate( + new CmsProcessableByteArray(data), + CmsAuthenticatedDataGenerator.DesEde3Cbc); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciECKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + + [Test] + public void TestEncoding() + { + byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna"); + + CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator(); + + adGen.AddKeyTransRecipient(ReciCert); + + CmsAuthenticatedData ad = adGen.Generate( + new CmsProcessableByteArray(data), + CmsAuthenticatedDataGenerator.DesEde3Cbc); + + ad = new CmsAuthenticatedData(ad.GetEncoded()); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + + private void tryKeyTrans(string macAlg) + { + byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna"); + + CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator(); + + adGen.AddKeyTransRecipient(ReciCert); + + CmsAuthenticatedData ad = adGen.Generate( + new CmsProcessableByteArray(data), + macAlg); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(ad.MacAlgOid, macAlg); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + + private void tryKekAlgorithm(KeyParameter kek, DerObjectIdentifier algOid) + { + byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna"); + + CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + // FIXME Will this work for macs? + string keyAlgorithm = ParameterUtilities.GetCanonicalAlgorithmName(algOid.Id); + + adGen.AddKekRecipient(keyAlgorithm, kek, kekId); + + CmsAuthenticatedData ad = adGen.Generate( + new CmsProcessableByteArray(data), + CmsAuthenticatedDataGenerator.DesEde3Cbc); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, algOid.Id); + + byte[] recData = recipient.GetContent(kek); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + + private void passwordTest(string algorithm) + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator(); + + adGen.AddPasswordRecipient(new Pkcs5Scheme2PbeKey("password".ToCharArray(), new byte[20], 5), algorithm); + + CmsAuthenticatedData ad = adGen.Generate( + new CmsProcessableByteArray(data), + CmsAuthenticatedDataGenerator.DesEde3Cbc); + + RecipientInformationStore recipients = ad.GetRecipientInfos(); + + Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (PasswordRecipientInformation recipient in c) + { + CmsPbeKey key = new Pkcs5Scheme2PbeKey("password".ToCharArray(), recipient.KeyDerivationAlgorithm); + + byte[] recData = recipient.GetContent(key); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac())); + } + } + } +} diff --git a/crypto/test/src/cms/test/CMSSampleMessages.cs b/crypto/test/src/cms/test/CMSSampleMessages.cs new file mode 100644 index 000000000..ae4f60fd1 --- /dev/null +++ b/crypto/test/src/cms/test/CMSSampleMessages.cs @@ -0,0 +1,147 @@ +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Cms.Tests +{ + internal class CmsSampleMessages + { + internal static readonly byte[] originatorMessage = Base64.Decode( + "MIIYGgYJKoZIhvcNAQcDoIIYCzCCGAcCAQKgggRJoIIERTCCBEEwggIpAgkA" + + "xS/+IvjTL8YwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCVVMxGDAWBgNV" + + "BAoTD1UuUy4gR292ZXJubWVudDESMBAGA1UECxMJSFNQRDEyTGFiMQ8wDQYD" + + "VQQLEwZBZ2VudHMxGzAZBgNVBAMTEkhTUEQxMiBMYWIgQ0EgUm9vdDAeFw0w" + + "NzA1MTQxNzEzMzRaFw0wODA1MTMxNzEzMzRaMFwxCzAJBgNVBAYTAlVTMRgw" + + "FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxEjAQBgNVBAsTCUhTUEQxMkxhYjEP" + + "MA0GA1UECxMGQWdlbnRzMQ4wDAYDVQQDEwV1c2VyMTCCASIwDQYJKoZIhvcN" + + "AQEBBQADggEPADCCAQoCggEBALC54HvfpSE3yq/EkpNCkUEV6a6Df3q4k8EM" + + "dlg0nQSf2FgYh1GMiztw8SVjrF80l4+Hg5/FW2XN2kpVQBap/H5ziPYXenbi" + + "VLJHCF9LVyYDOS7xGfRtQ+ZhFUcECtaCLJsR7HIiFyKZWGg0c3bFZvFkdZqT" + + "8MMwjhcIVE1BptMqcGriqqMQAUKYmOguAOzMCTGAOxqBXYFmR68WtggVNMMc" + + "5qU6S/4OxeCmaNSPG5p7pA1o4Cnv4aJF1mAPedVPQpAS4Lu2K9nNhRkug0yd" + + "6nPaxgQudk5YxlreNOPKiAHApk9RhGVepGchJCFP2aIPu9tkIiSe3omezSZu" + + "Sy/3F5UCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAGDxqVI4aR4XNfbk2MtXF" + + "agNYZOswn85X84um9gG323qjYhroW0QDuy3CwtUwhH866mpnJyhJvKx3b8UE" + + "7pZInoNEz1UVn+wgJVXMmaG5mfp3X6z0xDAEaKmDMJXl66wlFGG1iveGgcEi" + + "oMkrxFJKvu/FXywzPvz2pXD9LQapogOQpVsvg/hed//wijDG94UBkhbHTZ53" + + "6ODKuHGmooO6bgqJxKcVyLwQAq/lXGtLqODK9BDicfUzuhLWA0si7Y1daehj" + + "fjgAqFGirqRtPDdk1jywoMJdDCQqocNqNGuu/+9ZoRNtY7XFbiN7h4s4KTkw" + + "YqCph8g+RZYJVZJDw/+qc5ymYZiufbImA08D7x7IzqX9eeuAqKCebkxcK0Dz" + + "eh/wT7Ff8csw0xqkkEbi5sTORogPexKGo9T1P4j/UbOyCHaIwFQVE67kYJqZ" + + "U3BB7mGNE/dKru7jC7Aadorpj7P/EQ8sfoq5wC9r3wfFB1f5znN9ZfXd3zSU" + + "Gxne2PGl3Ry4DhrhWGy/HqB+StPSkLPJL1RNtKkywtaJG1QBnrMnLNsV7T0R" + + "mIDn69NkDkc59LAuB7yxwBmhYA7c7cHckdX3bE7zgN6yYdiyLyXr+ZQl+3J8" + + "bBPN/IVSs5Wr1kK9RDrFX8MdP95LZxHlgMATwAqoEPe5r2tvvGBoajoIA2Tw" + + "71QxggGSMIIBjgIBADB2MGkxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu" + + "IEdvdmVybm1lbnQxEjAQBgNVBAsTCUhTUEQxMkxhYjEPMA0GA1UECxMGQWdl" + + "bnRzMRswGQYDVQQDExJIU1BEMTIgTGFiIENBIFJvb3QCCQDFL/4i+NMvyTAN" + + "BgkqhkiG9w0BAQEFAASCAQCGpoi8DBLf6I2fwqVp9MPA5M0QNRnC34AMoc7N" + + "/JGKM5dWcGNpN83yL9QmOfjgyxzwJ3L3e3hYdoXp9MNelzG5ssyyKw4NxRgM" + + "C1aRPWx1R1aKee/NAgvBjN3FyDN3Pl4ACz2EMrDMmilR0zmSJkDBVbGjxNzs" + + "ZPxtsBlHeLRky/K/ZrTy5jIheFcKt/0dNJiMsFh+677OlRhDihdLzYeV4RK1" + + "5Iy1j18ls5rJMYh1fmZOx9T6wvlpw84IjFHzUcIxIBg8t1cUkncXbg1r+rxm" + + "zIaalAKdYp58oMpjy9wV6E1mxgAM/lvE/jwiYP4/a6TsXTLDPNIxe9RZVdhA" + + "GCPvMIISHQYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgQBLQIaeQQMYCCEfgv" + + "FBzVKLnlRNCjs2JE/G8jBI8aduv6YQTYTt0ePh9JEHTmSi7ISbCDdAf5baKN" + + "mzVGQJj87Srz3YyEmUcozxscWnWgVWpUbx0GJkjz6LqyGLQ3VnqUDG80xnXo" + + "nQY5q4ko6avyMIDZ+zzI2fs9ChAlBjZ41Qb0FnwDPZBH3N43q+puVWesE4wj" + + "LGftt63T4k2D/qMdg7fVfHkAsXPJIxkvR4vUrGEvxTl9e24146wYgCXe+66T" + + "UcAMViNCMr8UiFQFQYSmuPcSTHgQHqEaBwYys6X+fe61yE16mUazs32yVH2v" + + "Cyf1mG4/GAaSmqR/BIU7y7trGd+g/KaT1Kp76e+Rys9G/oakoeIH3Hkgdhmc" + + "pFBPklIlgA57EocK5n84tFRv9n9cmsbOfy0EjEa6vU4ImMPZQS4iyhLCWD1u" + + "tQziu5FyHSb9COveUPuGY2iTrOWG34rHIagNndXi1OuAIGQrLjbntHmogqxb" + + "zkB+yojr+WBwY1efb8X+WQ2L+us9v31qNGA0wyfg4AC5FZur90rBxBq59UPz" + + "JAVRD6NP5FRPdxuvHclDoGBoiMr9NXO3Uv0tJuYADHlWMQnUGoPEL7UxzuPJ" + + "VAWuHpGiywzOcWMiFEiDSIZrv4RViIVIRhEtm2bO7Ta/AGTfvJcyb6ySexc1" + + "aR5TWYOjqv1NaGAVQ1vPyqazH+g17y5wnBRj2c3nSMwksn/nC60e4ax+/yaE" + + "Ls9Qou9a0L2IyQgDlvhBA4CcRGcHklhlzAovGBX2gWG31CK05doZhH7bRIrj" + + "8h1XOF2izffrfWb6LcDcZptw5BQWT5XeyoKD4eNZfJ4ww+dMw4+0MkXPZEn6" + + "Fqg+jam9ZioqXiw5Y6bdzxawefe6gvxeca3f53KDXEm4qFaVuDgyjNZhEmyB" + + "gmsWRKokQ5DDlj1PfVlO4g2Uee4zbvmr7Yx6tGnnxm6o5i/COwvvRSXp8Oj7" + + "Zej0ZA+1zenNRAGXwuTKrbQ9ZZYRi4LCXluuVmy8vocGm8bnuqulMyz5hsUi" + + "QMAl1knunhaT+/kQOLRwEdJUgfq8ME14XsTNiVq26W8n+9AsYHoFzJhFoCfe" + + "i2wngAs1MMnw1erfnhWibkFZDlG9/5OPBZ3ZzJfgMEdT5Fs+hJxrw7UqNMkb" + + "EoH+3HpzEXfcGqCL6RfdbS0hu85v1CrZv0veK8qI+rQnoqXp+xmBRiSCyWNR" + + "ITepXcJsi6vWYX0nvNNbBjTsFqi78BSVRpg/zOFRvw1gX1TtTXQLcEdalKgf" + + "tEo+An3f3GugB3CFw38IM4JwCB06vXTRQAoK4PM4uNYVXEgSPq4vg9UuHZ3n" + + "V5l96emGLK55N5FO6FvlHFft/7elEFglbnSzSQnzVyj36Z6P7x/Q3td5SY4J" + + "VAJWvR/X4Fe2G6ebIZdNSJef9UyuNPee0Fi1iJUL8L4qO61ijkjYdE3bBcGm" + + "61eWj8NgxtELVgRyXq1vNgMOFlVAwkf2ZNDgNRUM49UnIFTNKnTaeAVB9pW2" + + "DGrZER8LA8ABctAdElECceoMVRUG1uFdAicrEbBHcWJkTdjBPjumE4bE6HUm" + + "vbpNBC4wyoPS6CSvNut/re7I4wgZwho6C6GRUuwraxJZlS+jwEvC+F4Bzlf5" + + "aPygECgVaNmSGP1E/vyN2aF8CLo4NL/5o9GG8DWg9O5GdNSislr4r6ciEjCr" + + "0a6rk47QDn4rDQy8iu/YkZz9u8/GJCAinWQzAvV8byhZxc81CfKj9xYTclDX" + + "AB75blJvUQIP4U7gpWxLB/1sdN2V5f9jw+xTLSpoJ7r/tIeBygF6rFe402Sd" + + "840SLi8ZSufAVeHUoNNDYkA/c1b6k5FaxDtN22tYQi4y3Hs7k03mGhvvLC0l" + + "05fMmvtasFaW5Bupqw8E2a7wHSLmRAXrPvnrblSL/wajptKPJWDJ+oH/9d9k" + + "NkC4EFBpcMEfIDky4PoCtfKQBFa5LT1WDQGfcCnrC9SDfUfhfRLBOpoFmUaT" + + "O0xc0vI/jmDRsoBy9d42ebyGMg5uD6tTOIvszEirpMy5SYPPa64zhHcN+Pzs" + + "db+J6fthc3aVIoob9jdv/aRUH3gDwltSnaLUIc7CWcuHSCGyM/zQPiAzkw0z" + + "x6ii5fdKXsmnQn88E+YqiJTPH0fG+kkhokAGU76bQMn7fJyBeVHhF2hqSr/0" + + "4zCIjgq1Zb+d9sEuRZWF+/XsGl2gwk4vgHTwM+XfU7edQssUR6kyD6wkw7EU" + + "6HaRrflymAHTEvdAB+PaREQbyej7/2lY41qmA9df2I5Izb60NxmMFj9F4M4V" + + "bLJOVNX5fuc8vaIhPG82hIiqe05cnBfRhtmcUUb1WDHVH3klRkti+fHrnbAW" + + "TpWd5m6Wi3VssopaUozWgYVgW9M+Zr5ZUAN9H0Kb4CatxG5YFkD0MCZShGl/" + + "lSc1SUxho6YakBB+5HxCI853/sQ3RMgSrMk+8ftalM2+BrT+V9wMK2O+wM5W" + + "ujrAcM85sQ4OqSZfJ7MmKT8+pcIsRRocmlM/cxUf5hKXfXrmCR5mkf9jxF8B" + + "J1JOwhkD8zQP7sPUcOWEcT8ctOKPygtz6tWWQDW8ciiYULYyJA6ydGrrn6T+" + + "fQj8M2VsM1y4YK9dMfJUeaiP+m4BeoOjs0vqz6pBI6J3lrNz31DaNO6SApUL" + + "4cOx8EZMg498TG0zmQ87yVw4mGmL3JpWBZH89HiNEY5eJ0zEIS3lMaOADRMf" + + "kX8B5YHadeTuAEjXsGtFIlSf1xo45kwCxIfUcikdfu2rb+Bh251Im0oq/XTj" + + "XPeviXasfas6VsMHsmTrqynFdP8THnrmHLCoeAMvgpjirXfIdR7tULJcFJtr" + + "0lZLZfdZgbTsbn9GMQKwMkAAjJLfJq42usvzf4ShC7IRtvOEVAMrebaaK1YF" + + "rtV5z1WNo3VRFonakKj85nXLOAdCNe6T3zESebexJKFn8e/6+shp9IDIRmWr" + + "hiWut6KPFiSgAgfqpeIt9fuHiYeIK8DqISA7QUdAZrgPe8GlctvKkQLvjNW0" + + "srglx9CQuDqZC6C1BLaIs3sE//yLvEd06vDFjDa0WGKWjM/Uo29af/tlL1kC" + + "vDQtDPi8OPIebK8OwI2uNDZ+cnHhv3gZXCdbKkRZc1W+mrU7rUk1Fa0ViVmc" + + "zhVGX22fDXbIrs9zJ+sA+3Towrx2XmMZ+PDkVBxHFE2bk+GABM62BW9YZoX4" + + "R4U+n7E8Ec0sI8srcxEZYX8LWHh1XSU0yEHYjkIWDQUUSGpsbgqnjXJcnTdk" + + "KK5PLk4sthLYwT4o1Gg4lRpc4dn26bIQcpGdY5PEknItDt6IBSc6bYYYoQrl" + + "PIufY67haoc//d5y1LpCi5vc0wTcvbdoVepLrxVAn4MPsejbfIFJ01N0qKgv" + + "fGWVxmRGtGXHe3iNLsMrvSE2FkORSc4sgjC42hfxHTEVmhTnzOplxTsN/MzE" + + "S7ESv/c0rIen+zwXgtiFnTg1VPHcaT4z0DtLBMNjqYNoyDrIHUrWguFeV7/i" + + "RSP7SiztMmlfKhrxlQpaNNm/XvKa1OpKbVStHMgOdpMaaCp8WaX++wb9lG6V" + + "3PqBeVSCuFm1xq6KAERLUdF4XsdXNM/uUhYZX7cGIqRS3vSDJB1EfrZTpUY5" + + "xGllybE/P2gufnG5EMpC2FHx4iW4pWMkYhIpzKv1Tkxe3K6ISs4wEs4n/AtL" + + "hupMGZE9hDJ0LV0nRvRbY8YCRXoBaj6/qF1QED7CG4hx16yrkLAR7Th5rbH7" + + "GFEzNSq1HI0IssDIimD2ZN9Cf++uH6ZpP2JZeJ/gEqGi17ovtnuklx6dtu0l" + + "KL0pQjCyAoQFEFSaVJ1m4oOQJyb58lsG4gOPaPvOw1ruiJ2obt4228VR1pA8" + + "Vm9A41E4pk/vA+VFJ/tSmkB5s2gmBBVcA8mU8iIyzMmliTNHeg53EYAytF5M" + + "X2rA7Ct8ApqbrYSSBTUPC+MEBV7UajamWB6UaSUj575MhEnzm0xl/lFqU6ZF" + + "6w0rdey/KvTiotErOS1q8RcY2dcs9Mz8Dm/8IMBcGfny0i/KLtz0OUOLFg3P" + + "/VrPBt7f+YfDqLVc8AujhrxAH/hwYauJ+Q6HSVTSJI7aXB9xtdsijzMZCmnE" + + "1oKRBkACSWD9BGvS3hpv/VqaHWU4B2dnv2oyrIkdkgQu2OtlFxpcOkqwexIj" + + "ssxxOCmT6dpB8JNehjLDU8WXhtFJVFuR84V7KlyeG/s8TaZgCW6uLLVmpteE" + + "J15bnM9jRTW/FZiHwsjy9kVbvaAT+bbIjn5u7qdGsgAQHdeKy191ONvHIttZ" + + "l/qnvrygLImaTOcuMMzU/0ECNlk0QiU0YbfS/RGH2LtRzk8x3FLFVXRiNtrD" + + "uJuwzlP4RufuoZfJsi0rFOuxNFQ/cZEq1q7TCzqP+saRoSLFK1iRE/Ei06pS" + + "JH+cwHMxk3u7k4+HxF72uK9XHIgY6G6WfZTklH2w2VrsLLZLmJ9SO6Zpyt48" + + "KcwvEcxYoZxp1gfPYDCMHeb7oi/gRj9FjnBaNf2dW3a1RqVo5y0QeSfSH4k8" + + "YWX6k+Yh803ZmoIb//TEbfkbXe8XOIffbMSUuIozCQY/Rt9wAHesMWfgTuB5" + + "LSoa8R+mR5lIS/P1ANHdgNrh+XRFrNFeD0dCw6bdYWUXMVaZbCE8Z8pXQ0LO" + + "ItiPuI+w/izD/lXdKXWJJmN/bq2RJRo4WFEDe6sJH9G2Poe/T4xwTm4kX2uA" + + "IZkYy7bZcez8a0bFJzcsJxUbBPRq93J0fXzpvQsszbVZh94VSc9nkH4FnAxT" + + "Kk2bLcsXANJlw3cFO9jOygrXh6R2fyHX0E8WExb2Q7lG68wU1BJVupT8rZ0Y" + + "oRY6WBYG0LuZb+4VAQuI0/Are3BznsgkqudCjf+JUhu1Yefh2hblWuMPNEWb" + + "mOorerNiIzkrt5tjXyBj0g8w/pL//BIlkW5JerMtKTPMfZSroHw9wuAuqHqF" + + "2sMjsW/Lbr5b8SIdIgo3vrS6EM9MGkATfSZz4z+ZWG3EB6QqcMXCZ4N2/WWl" + + "EPKsIqY/509NZRzqOavcMXkOryRJ7GQpmotNbbalI6r6swRoEQ2IzK5XPCC1" + + "iv52YpcRaV9BDpNNByk4l3ddOiEc4dsOkHjaLNvj6Vo1pG/C1Z8VXRRY909D" + + "nH2+PfUL684WZ6kIPeLfqr7N3ZbNxZAVozVG+WXwBlLFT7L+axeGHOhHdH/g" + + "SVMSmWdRX4eNuofmpsU8f3A9aCnPGDxPnB4WKnAGw34TYZrtZ9mHcjYPsq1q" + + "zY6brfZD4T7tktjAlRL2PYZ15MfWVXVH1xoyjeWImTi0o4nyuy/M0HukDfwY" + + "l6nW77TMRiH54wdQqIZUxa32dNNhjcNslRlpOf6td3FbELqhTiaptRSuKjs9" + + "8evbDFK7rb7n6RSSzAwb3oU8pwr4dM8ArTVc0EqnvdSCs1tx46ckIK3AFgcd" + + "opmNq+Qa7qhN5Zgds3cLPIQiyDThhYGPaIgyn4j/dZb1Qwa2U7urijJrBqeS" + + "/kJ2rEXV9v+OX9yTYKypM05A2gOK/ESPbx24C/HmmGm/yBXBx3pABvKt41Dh" + + "b0syB4hYrsq0RriovGemBrNgy4tiJB5BDI9VpWFC/7LR0quFFOrxxm7YvH2h" + + "GkR0oUc/socA80WZx9TegdiBg9TVPbe0gZmoeQc6XLfscBol0QdZWSmLqFxf" + + "TFN7ksaVAUPXA9phBg/k51YmrwNvx4D/A1bBQRtQmq2N4R0j3uMkynubBEfb" + + "9qvQNXpdygouzKUyrN/w+7clilaq2P+R9i7rriZ1waHyjfvAdeBzQQ/pVmgh" + + "o8EiL/TZpIZ71sTYv28scY+V7yYgBA5S/Y4bdmvzSSoMoK8yH/LcBFJOZLQd" + + "YPt7uKWSwQN8iVDA6ZcsYoKuAUw3ziiRaf+GN58ihLB/y/sGmAmX2XwLsPSZ" + + "uQIF/gT8yXjxoyWDLXl3MUgfx+pGg5vBwAtk9a2elEQR9C3a8PPsOy3N9Jh3" + + "xY/A1gJ/rjuubwrb0Sd2LinzPg5uVuKR1jeMSCEebgoyBj8/t8HvknBqJkpl" + + "tjZ6AxGiQ8+v5jRBzYSyiTQfPMxWzdBKqUePdJcLPITf/XitegQnikgAN6bh" + + "kYMS2G9kXJH2CgDm9z3svmu/0Oz2XWEpVHlOjknghPlTaLRqgWoQbK5dkuiV" + + "k9HhGwwsgiR+"); + } +} diff --git a/crypto/test/src/cms/test/CMSTestUtil.cs b/crypto/test/src/cms/test/CMSTestUtil.cs new file mode 100644 index 000000000..ef7f9169f --- /dev/null +++ b/crypto/test/src/cms/test/CMSTestUtil.cs @@ -0,0 +1,480 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Cms.Tests +{ + public class CmsTestUtil + { + public static SecureRandom rand; + private static IAsymmetricCipherKeyPairGenerator kpg; + private static IAsymmetricCipherKeyPairGenerator gostKpg; + private static IAsymmetricCipherKeyPairGenerator dsaKpg; + private static IAsymmetricCipherKeyPairGenerator ecGostKpg; + private static IAsymmetricCipherKeyPairGenerator ecDsaKpg; + public static CipherKeyGenerator aes192kg; + public static CipherKeyGenerator desede128kg; + public static CipherKeyGenerator desede192kg; + public static CipherKeyGenerator rc240kg; + public static CipherKeyGenerator rc264kg; + public static CipherKeyGenerator rc2128kg; + public static CipherKeyGenerator aesKg; + public static CipherKeyGenerator seedKg; + public static CipherKeyGenerator camelliaKg; + public static BigInteger serialNumber; + + private static readonly 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"); + + private static IAsymmetricCipherKeyPairGenerator Kpg + { + get + { + if (kpg == null) + { + kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpg.Init(new RsaKeyGenerationParameters( + BigInteger.ValueOf(17), rand, 1024, 25)); + } + + return kpg; + } + } + + private static IAsymmetricCipherKeyPairGenerator GostKpg + { + get + { + if (gostKpg == null) + { + gostKpg = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + gostKpg.Init( + new Gost3410KeyGenerationParameters( + rand, + CryptoProObjectIdentifiers.GostR3410x94CryptoProA)); + } + + return gostKpg; + } + } + + private static IAsymmetricCipherKeyPairGenerator DsaKpg + { + get + { + if (dsaKpg == null) + { + DsaParameters dsaSpec = new DsaParameters( + new BigInteger("7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673"), + new BigInteger("1138656671590261728308283492178581223478058193247"), + new BigInteger("4182906737723181805517018315469082619513954319976782448649747742951189003482834321192692620856488639629011570381138542789803819092529658402611668375788410")); + dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + dsaKpg.Init(new DsaKeyGenerationParameters(rand, dsaSpec)); + } + + return dsaKpg; + } + } + + private static IAsymmetricCipherKeyPairGenerator ECGostKpg + { + get + { + if (ecGostKpg == null) + { + ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410"); + ecGostKpg.Init( + new ECKeyGenerationParameters( + CryptoProObjectIdentifiers.GostR3410x2001CryptoProA, + new SecureRandom())); + } + + return ecGostKpg; + } + } + + private static IAsymmetricCipherKeyPairGenerator ECDsaKpg + { + get + { + if (ecDsaKpg == null) + { + ecDsaKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + ecDsaKpg.Init(new KeyGenerationParameters(rand, 239)); + } + + return ecDsaKpg; + } + } + + static CmsTestUtil() + { + try + { + rand = new SecureRandom(); + + aes192kg = GeneratorUtilities.GetKeyGenerator("AES"); + aes192kg.Init(new KeyGenerationParameters(rand, 192)); + + desede128kg = GeneratorUtilities.GetKeyGenerator("DESEDE"); + desede128kg.Init(new KeyGenerationParameters(rand, 112)); + + desede192kg = GeneratorUtilities.GetKeyGenerator("DESEDE"); + desede192kg.Init(new KeyGenerationParameters(rand, 168)); + + rc240kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc240kg.Init(new KeyGenerationParameters(rand, 40)); + + rc264kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc264kg.Init(new KeyGenerationParameters(rand, 64)); + + rc2128kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc2128kg.Init(new KeyGenerationParameters(rand, 128)); + + aesKg = GeneratorUtilities.GetKeyGenerator("AES"); + + seedKg = GeneratorUtilities.GetKeyGenerator("SEED"); + + camelliaKg = GeneratorUtilities.GetKeyGenerator("Camellia"); + + serialNumber = BigInteger.One; + } + catch (Exception ex) + { + throw new Exception(ex.ToString()); + } + } + + public static string DumpBase64( + byte[] data) + { + StringBuilder buf = new StringBuilder(); + + data = Base64.Encode(data); + + for (int i = 0; i < data.Length; i += 64) + { + if (i + 64 < data.Length) + { + buf.Append(Encoding.Default.GetString(data, i, 64)); + } + else + { + buf.Append(Encoding.Default.GetString(data, i, data.Length - i)); + } + buf.Append('\n'); + } + + return buf.ToString(); + } + + public static IX509AttributeCertificate GetAttributeCertificate() + { +// X509StreamParser parser = X509StreamParser.GetInstance("AttributeCertificate"); +// parser.Init(CmsTestUtil.attrCert); +// return (X509AttributeCertificate) parser.Read(); + + return new X509AttrCertParser().ReadAttrCert(attrCert); + } + + public static AsymmetricCipherKeyPair MakeKeyPair() + { + return Kpg.GenerateKeyPair(); + } + + public static AsymmetricCipherKeyPair MakeGostKeyPair() + { + return GostKpg.GenerateKeyPair(); + } + + public static AsymmetricCipherKeyPair MakeDsaKeyPair() + { + return DsaKpg.GenerateKeyPair(); + } + + public static AsymmetricCipherKeyPair MakeECGostKeyPair() + { + return ECGostKpg.GenerateKeyPair(); + } + + public static AsymmetricCipherKeyPair MakeECDsaKeyPair() + { + return ECDsaKpg.GenerateKeyPair(); + } + + public static KeyParameter MakeDesEde128Key() + { + return ParameterUtilities.CreateKeyParameter("DESEDE", desede128kg.GenerateKey()); + } + + public static KeyParameter MakeAes192Key() + { + return ParameterUtilities.CreateKeyParameter("AES", aes192kg.GenerateKey()); + } + + public static KeyParameter MakeDesEde192Key() + { + return ParameterUtilities.CreateKeyParameter("DESEDE", desede192kg.GenerateKey()); + } + + public static KeyParameter MakeRC240Key() + { + return ParameterUtilities.CreateKeyParameter("RC2", rc240kg.GenerateKey()); + } + + public static KeyParameter MakeRC264Key() + { + return ParameterUtilities.CreateKeyParameter("RC2", rc264kg.GenerateKey()); + } + + public static KeyParameter MakeRC2128Key() + { + return ParameterUtilities.CreateKeyParameter("RC2", rc2128kg.GenerateKey()); + } + + public static KeyParameter MakeSeedKey() + { + return ParameterUtilities.CreateKeyParameter("SEED", seedKg.GenerateKey()); + } + + public static KeyParameter MakeAesKey( + int keySize) + { + aesKg.Init(new KeyGenerationParameters(rand, keySize)); + + return ParameterUtilities.CreateKeyParameter("AES", aesKg.GenerateKey()); + } + + public static KeyParameter MakeCamelliaKey( + int keySize) + { + camelliaKg.Init(new KeyGenerationParameters(rand, keySize)); + + return ParameterUtilities.CreateKeyParameter("CAMELLIA", camelliaKg.GenerateKey()); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true); + } + + public static X509Certificate MakeV1Certificate(AsymmetricCipherKeyPair subKP, + string _subDN, AsymmetricCipherKeyPair issKP, string _issDN) + { + AsymmetricKeyParameter subPub = subKP.Public; + AsymmetricKeyParameter issPriv = issKP.Private; + AsymmetricKeyParameter issPub = issKP.Public; + + X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator(); + + v1CertGen.Reset(); + v1CertGen.SetSerialNumber(AllocateSerialNumber()); + v1CertGen.SetIssuerDN(new X509Name(_issDN)); + v1CertGen.SetNotBefore(DateTime.UtcNow); + v1CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100)); + v1CertGen.SetSubjectDN(new X509Name(_subDN)); + v1CertGen.SetPublicKey(subPub); + + if (issPub is RsaKeyParameters) + { + v1CertGen.SetSignatureAlgorithm("SHA1WithRSA"); + } + else if (issPub is DsaPublicKeyParameters) + { + v1CertGen.SetSignatureAlgorithm("SHA1withDSA"); + } + else if (issPub is ECPublicKeyParameters) + { + ECPublicKeyParameters ecPub = (ECPublicKeyParameters)issPub; + if (ecPub.AlgorithmName == "ECGOST3410") + { + v1CertGen.SetSignatureAlgorithm("GOST3411withECGOST3410"); + } + else + { + v1CertGen.SetSignatureAlgorithm("SHA1withECDSA"); + } + } + else + { + v1CertGen.SetSignatureAlgorithm("GOST3411WithGOST3410"); + } + + X509Certificate _cert = v1CertGen.Generate(issPriv); + + _cert.CheckValidity(DateTime.UtcNow); + _cert.Verify(issPub); + + return _cert; + } + + public static X509Certificate MakeCertificate( + AsymmetricCipherKeyPair subKP, string _subDN, + AsymmetricCipherKeyPair issKP, string _issDN, bool _ca) + { + AsymmetricKeyParameter subPub = subKP.Public; + AsymmetricKeyParameter issPriv = issKP.Private; + AsymmetricKeyParameter issPub = issKP.Public; + + X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + v3CertGen.Reset(); + v3CertGen.SetSerialNumber(AllocateSerialNumber()); + v3CertGen.SetIssuerDN(new X509Name(_issDN)); + v3CertGen.SetNotBefore(DateTime.UtcNow); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100)); + v3CertGen.SetSubjectDN(new X509Name(_subDN)); + v3CertGen.SetPublicKey(subPub); + + if (issPub is RsaKeyParameters) + { + v3CertGen.SetSignatureAlgorithm("SHA1WithRSA"); + } + else if (issPub is ECPublicKeyParameters) + { + ECPublicKeyParameters ecPub = (ECPublicKeyParameters) issPub; + if (ecPub.AlgorithmName == "ECGOST3410") + { + v3CertGen.SetSignatureAlgorithm("GOST3411withECGOST3410"); + } + else + { + v3CertGen.SetSignatureAlgorithm("SHA1withECDSA"); + } + } + else + { + v3CertGen.SetSignatureAlgorithm("GOST3411WithGOST3410"); + } + + v3CertGen.AddExtension( + X509Extensions.SubjectKeyIdentifier, + false, + CreateSubjectKeyId(subPub)); + + v3CertGen.AddExtension( + X509Extensions.AuthorityKeyIdentifier, + false, + CreateAuthorityKeyId(issPub)); + + v3CertGen.AddExtension( + X509Extensions.BasicConstraints, + false, + new BasicConstraints(_ca)); + + X509Certificate _cert = v3CertGen.Generate(issPriv); + + _cert.CheckValidity(); + _cert.Verify(issPub); + + return _cert; + } + + public static X509Crl MakeCrl( + AsymmetricCipherKeyPair pair) + { + X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); + DateTime now = DateTime.UtcNow; + + crlGen.SetIssuerDN(new X509Name("CN=Test CA")); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + crlGen.AddCrlEntry(BigInteger.One, now, CrlReason.PrivilegeWithdrawn); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public)); + + return crlGen.Generate(pair.Private); + } + + /* + * + * INTERNAL METHODS + * + */ + private static AuthorityKeyIdentifier CreateAuthorityKeyId( + AsymmetricKeyParameter _pubKey) + { + SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey); + return new AuthorityKeyIdentifier(_info); + } + + internal static SubjectKeyIdentifier CreateSubjectKeyId( + AsymmetricKeyParameter _pubKey) + { + SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey); + return new SubjectKeyIdentifier(_info); + } + + private static BigInteger AllocateSerialNumber() + { + BigInteger _tmp = serialNumber; + serialNumber = serialNumber.Add(BigInteger.One); + return _tmp; + } + + public static byte[] StreamToByteArray( + Stream inStream) + { + return Streams.ReadAll(inStream); + } + } +} diff --git a/crypto/test/src/cms/test/CompressedDataStreamTest.cs b/crypto/test/src/cms/test/CompressedDataStreamTest.cs new file mode 100644 index 000000000..48a6c56ee --- /dev/null +++ b/crypto/test/src/cms/test/CompressedDataStreamTest.cs @@ -0,0 +1,116 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class CompressedDataStreamTest + { + private static readonly 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"); + + private static readonly byte[] uncompData = Base64.Decode( + "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl" + + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l" + + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW" + + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj" + + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA" + + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0" + + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU" + + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz" + + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI" + + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD" + + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR" + + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk" + + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA" + + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq" + + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN" + + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD" + + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio" + + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx" + + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM" + + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi" + + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ" + + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq" + + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK" + + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj" + + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF" + + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB" + + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN" + + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU" + + "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0="); + + [Test] + public void TestWorkingData() + { + CmsCompressedDataParser ed = new CmsCompressedDataParser(compData); + + Assert.IsTrue(Arrays.AreEqual(uncompData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream))); + } + + [Test] + public void TestEach() + { + byte[] testData = Encoding.ASCII.GetBytes("Hello world!"); + + CmsCompressedDataStreamGenerator gen = new CmsCompressedDataStreamGenerator(); + MemoryStream bOut = new MemoryStream(); + + Stream cOut = gen.Open(bOut, CmsCompressedDataStreamGenerator.ZLib); + + cOut.Write(testData, 0, testData.Length); + + cOut.Close(); + + CmsCompressedDataParser ed = new CmsCompressedDataParser(bOut.ToArray()); + + Assert.IsTrue(Arrays.AreEqual(testData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream))); + } + + [Test] + public void Test1000() + { + byte[] testData = new byte[10000]; + SecureRandom rand = new SecureRandom(); + + rand.SetSeed(0); + + for (int i = 0; i != 10; i++) + { + CmsCompressedDataStreamGenerator gen = new CmsCompressedDataStreamGenerator(); + MemoryStream bOut = new MemoryStream(); + + Stream cOut = gen.Open(bOut, CmsCompressedDataStreamGenerator.ZLib); + + rand.NextBytes(testData); + + cOut.Write(testData, 0, testData.Length); + + cOut.Close(); + + CmsCompressedDataParser ed = new CmsCompressedDataParser(bOut.ToArray()); + + Assert.IsTrue(Arrays.AreEqual(testData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream))); + } + } + } +} diff --git a/crypto/test/src/cms/test/CompressedDataTest.cs b/crypto/test/src/cms/test/CompressedDataTest.cs new file mode 100644 index 000000000..6df85d9fd --- /dev/null +++ b/crypto/test/src/cms/test/CompressedDataTest.cs @@ -0,0 +1,117 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class CompressedDataTest + { + private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("Hello world!"); + + private static readonly 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"); + + private static readonly byte[] uncompData = Base64.Decode( + "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl" + + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l" + + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW" + + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj" + + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA" + + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0" + + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU" + + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz" + + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI" + + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD" + + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR" + + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk" + + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA" + + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq" + + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN" + + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD" + + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio" + + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx" + + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM" + + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi" + + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ" + + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq" + + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK" + + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj" + + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF" + + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB" + + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN" + + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU" + + "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0="); + + [Test] + public void TestWorkingData() + { + CmsCompressedData ed = new CmsCompressedData(compData); + + Assert.IsTrue(Arrays.AreEqual(uncompData, ed.GetContent())); + } + + [Test] + public void TestEach() + { + CmsCompressedData cd = GetStdData(); + + Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent())); + } + + [Test] + public void TestLimitUnder() + { + CmsCompressedData cd = GetStdData(); + + try + { + cd.GetContent(TEST_DATA.Length / 2); + } + catch (CmsException e) + { + Assert.IsTrue(e.InnerException is StreamOverflowException); + } + } + + [Test] + public void TestLimitOver() + { + CmsCompressedData cd = GetStdData(); + + Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent(TEST_DATA.Length * 2))); + } + + [Test] + public void TestLimitEqual() + { + CmsCompressedData cd = GetStdData(); + + Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent(TEST_DATA.Length))); + } + + private CmsCompressedData GetStdData() + { + CmsProcessableByteArray testData = new CmsProcessableByteArray(TEST_DATA); + CmsCompressedDataGenerator gen = new CmsCompressedDataGenerator(); + return gen.Generate(testData, CmsCompressedDataGenerator.ZLib); + } + } +} diff --git a/crypto/test/src/cms/test/EnvelopedDataStreamTest.cs b/crypto/test/src/cms/test/EnvelopedDataStreamTest.cs new file mode 100644 index 000000000..8512f6622 --- /dev/null +++ b/crypto/test/src/cms/test/EnvelopedDataStreamTest.cs @@ -0,0 +1,537 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class EnvelopedDataStreamTest + { + private const int BufferSize = 4000; + + private const string SignDN = "O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair signKP; +// private static X509Certificate signCert; + //signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN); + +// private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; +// private static AsymmetricCipherKeyPair origKP; + //origKP = CmsTestUtil.MakeKeyPair(); +// private static X509Certificate origCert; + //origCert = CmsTestUtil.MakeCertificate(origKP, OrigDN, _signKP, SignDN); + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair reciKP; + private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origECKP; + private static AsymmetricCipherKeyPair reciECKP; + private static X509Certificate reciECCert; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair ReciKP + { + get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } + } + + private static X509Certificate ReciCert + { + get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert;} + } + + private static AsymmetricCipherKeyPair OrigECKP + { + get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; } + } + + private static AsymmetricCipherKeyPair ReciECKP + { + get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; } + } + + private static X509Certificate ReciECCert + { + get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert;} + } + + [Test] + public void TestWorkingData() + { + byte[] keyData = Base64.Decode( + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" + + "nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" + + "Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" + + "64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" + + "WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" + + "bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" + + "HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" + + "VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" + + "GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" + + "ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" + + "uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" + + "eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" + + "YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" + + "MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" + + "+sxLBw=="); + + byte[] envData = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" + + "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" + + "gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" + + "0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" + + "T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" + + "1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA"); + + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(envData); + + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + +// PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData); +// KeyFactory keyFact = KeyFactory.GetInstance("RSA"); +// Key priKey = keyFact.generatePrivate(keySpec); + AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(keyData); + byte[] data = Hex.Decode("57616c6c6157616c6c6157617368696e67746f6e"); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + CmsTypedStream recData = recipient.GetContentStream(priKey); + + byte[] compare = CmsTestUtil.StreamToByteArray(recData.ContentStream); + Assert.IsTrue(Arrays.AreEqual(data, compare)); + } + } + + private void VerifyData( + byte[] encodedBytes, + string expectedOid, + byte[] expectedData) + { + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(encodedBytes); + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, expectedOid); + + ICollection c = recipients.GetRecipients(); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(expectedData, CmsTestUtil.StreamToByteArray( + recData.ContentStream))); + } + } + + [Test] + public void TestKeyTransAes128BufferedStream() + { + byte[] data = new byte[2000]; + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // unbuffered + // + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + for (int i = 0; i != 2000; i++) + { + outStream.WriteByte(data[i]); + } + + outStream.Close(); + + VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data); + + int unbufferedLength = bOut.ToArray().Length; + + // + // Using buffered output - should be == to unbuffered + // + edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + bOut.SetLength(0); + + outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + Streams.PipeAll(new MemoryStream(data, false), outStream); + outStream.Close(); + + VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data); + + Assert.AreEqual(unbufferedLength, bOut.ToArray().Length); + } + + [Test] + public void TestKeyTransAes128Buffered() + { + byte[] data = new byte[2000]; + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // unbuffered + // + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + for (int i = 0; i != 2000; i++) + { + outStream.WriteByte(data[i]); + } + + outStream.Close(); + + VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data); + + int unbufferedLength = bOut.ToArray().Length; + + // + // buffered - less than default of 1000 + // + edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.SetBufferSize(300); + + edGen.AddKeyTransRecipient(ReciCert); + + bOut.SetLength(0); + + outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + for (int i = 0; i != 2000; i++) + { + outStream.WriteByte(data[i]); + } + + outStream.Close(); + + VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data); + + Assert.IsTrue(unbufferedLength < bOut.ToArray().Length); + } + + [Test] + public void TestKeyTransAes128Der() + { + byte[] data = new byte[2000]; + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + for (int i = 0; i != 2000; i++) + { + outStream.WriteByte(data[i]); + } + + outStream.Close(); + + // convert to DER + byte[] derEncodedBytes = Asn1Object.FromByteArray(bOut.ToArray()).GetDerEncoded(); + + VerifyData(derEncodedBytes, CmsEnvelopedDataGenerator.Aes128Cbc, data); + } + + [Test] + public void TestKeyTransAes128Throughput() + { + byte[] data = new byte[40001]; + for (int i = 0; i != data.Length; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // buffered + // + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.SetBufferSize(BufferSize); + + edGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + for (int i = 0; i != data.Length; i++) + { + outStream.WriteByte(data[i]); + } + + outStream.Close(); + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray()); + RecipientInformationStore recipients = ep.GetRecipientInfos(); + ICollection c = recipients.GetRecipients(); + + IEnumerator e = c.GetEnumerator(); + + if (e.MoveNext()) + { + RecipientInformation recipient = (RecipientInformation) e.Current; + + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private); + + Stream dataStream = recData.ContentStream; + MemoryStream dataOut = new MemoryStream(); + int len; + byte[] buf = new byte[BufferSize]; + int count = 0; + + while (count != 10 && (len = dataStream.Read(buf, 0, buf.Length)) > 0) + { + Assert.AreEqual(buf.Length, len); + + dataOut.Write(buf, 0, buf.Length); + count++; + } + + len = dataStream.Read(buf, 0, buf.Length); + dataOut.Write(buf, 0, len); + + Assert.IsTrue(Arrays.AreEqual(data, dataOut.ToArray())); + } + else + { + Assert.Fail("recipient not found."); + } + } + + [Test] + public void TestKeyTransAes128() + { + byte[] data = Encoding.Default.GetBytes("WallaWallaWashington"); + + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + + outStream.Write(data, 0, data.Length); + + outStream.Close(); + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray()); + + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream))); + } + + ep.Close(); + } + + [Test] + public void TestAesKek() + { + byte[] data = Encoding.Default.GetBytes("WallaWallaWashington"); + KeyParameter kek = CmsTestUtil.MakeAes192Key(); + + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + edGen.AddKekRecipient("AES192", kek, kekId); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, + CmsEnvelopedDataGenerator.DesEde3Cbc); + outStream.Write(data, 0, data.Length); + + outStream.Close(); + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray()); + + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc); + + ICollection c = recipients.GetRecipients(); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25"); + + CmsTypedStream recData = recipient.GetContentStream(kek); + + Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream))); + } + + ep.Close(); + } + + [Test] + public void TestTwoAesKek() + { + byte[] data = Encoding.Default.GetBytes("WallaWallaWashington"); + KeyParameter kek1 = CmsTestUtil.MakeAes192Key(); + KeyParameter kek2 = CmsTestUtil.MakeAes192Key(); + + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + byte[] kekId1 = new byte[] { 1, 2, 3, 4, 5 }; + byte[] kekId2 = new byte[] { 5, 4, 3, 2, 1 }; + + edGen.AddKekRecipient("AES192", kek1, kekId1); + edGen.AddKekRecipient("AES192", kek2, kekId2); + + MemoryStream bOut = new MemoryStream(); + + Stream outStream = edGen.Open( + bOut, + CmsEnvelopedDataGenerator.DesEde3Cbc); + outStream.Write(data, 0, data.Length); + + outStream.Close(); + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray()); + + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc); + + RecipientID recSel = new RecipientID(); + + recSel.KeyIdentifier = kekId2; + + RecipientInformation recipient = recipients.GetFirstRecipient(recSel); + + Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25"); + + CmsTypedStream recData = recipient.GetContentStream(kek2); + + Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream))); + + ep.Close(); + } + + [Test] + public void TestECKeyAgree() + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator(); + + edGen.AddKeyAgreementRecipient( + CmsEnvelopedDataGenerator.ECDHSha1Kdf, + OrigECKP.Private, + OrigECKP.Public, + ReciECCert, + CmsEnvelopedDataGenerator.Aes128Wrap); + + MemoryStream bOut = new MemoryStream(); + + Stream outStr = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc); + outStr.Write(data, 0, data.Length); + + outStr.Close(); + + CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray()); + + RecipientInformationStore recipients = ep.GetRecipientInfos(); + + Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientID recSel = new RecipientID(); + +// recSel.SetIssuer(PrincipalUtilities.GetIssuerX509Principal(ReciECCert).GetEncoded()); + recSel.Issuer = PrincipalUtilities.GetIssuerX509Principal(ReciECCert); + recSel.SerialNumber = ReciECCert.SerialNumber; + + RecipientInformation recipient = recipients.GetFirstRecipient(recSel); + + CmsTypedStream recData = recipient.GetContentStream(ReciECKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream))); + + ep.Close(); + } + + [Test] + public void TestOriginatorInfo() + { + CmsEnvelopedDataParser env = new CmsEnvelopedDataParser(CmsSampleMessages.originatorMessage); + + env.GetRecipientInfos(); + + Assert.AreEqual(CmsEnvelopedDataGenerator.DesEde3Cbc, env.EncryptionAlgOid); + } + } +} diff --git a/crypto/test/src/cms/test/EnvelopedDataTest.cs b/crypto/test/src/cms/test/EnvelopedDataTest.cs new file mode 100644 index 000000000..be588ef42 --- /dev/null +++ b/crypto/test/src/cms/test/EnvelopedDataTest.cs @@ -0,0 +1,866 @@ +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class EnvelopedDataTest + { + private const string SignDN = "O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair signKP; +// private static X509Certificate signCert; + //signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN); + +// private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + +// private static AsymmetricCipherKeyPair origKP; + //origKP = CmsTestUtil.MakeKeyPair(); +// private static X509Certificate origCert; + //origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN); + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + private const string ReciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU"; + + private static AsymmetricCipherKeyPair reciKP; + private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origECKP; + private static AsymmetricCipherKeyPair reciECKP; + private static X509Certificate reciECCert; + private static AsymmetricCipherKeyPair reciECKP2; + private static X509Certificate reciECCert2; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair ReciKP + { + get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } + } + + private static X509Certificate ReciCert + { + get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } + } + + private static AsymmetricCipherKeyPair OrigECKP + { + get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; } + } + + private static AsymmetricCipherKeyPair ReciECKP + { + get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; } + } + + private static X509Certificate ReciECCert + { + get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; } + } + + private static AsymmetricCipherKeyPair ReciECKP2 + { + get { return reciECKP2 == null ? (reciECKP2 = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP2; } + } + + private static X509Certificate ReciECCert2 + { + get { return reciECCert2 == null ? (reciECCert2 = CmsTestUtil.MakeCertificate(ReciECKP2, ReciDN2, SignKP, SignDN)) : reciECCert2; } + } + + private static readonly byte[] oldKEK = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxQaI/MD0CAQQwBwQFAQIDBAUwDQYJYIZIAWUDBAEFBQAEI" + + "Fi2eHTPM4bQSjP4DUeDzJZLpfemW2gF1SPq7ZPHJi1mMIAGCSqGSIb3DQEHATAUBggqhkiG9w" + + "0DBwQImtdGyUdGGt6ggAQYk9X9z01YFBkU7IlS3wmsKpm/zpZClTceAAAAAAAAAAAAAA=="); + + private static readonly byte[] ecKeyAgreeMsgAES256 = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcShgcECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPdXlSTpub+qqno9hUGkUDl+S3/ABhPziIB5yGU4678tgOgU5CiKG9Z" + + "kfnabIJ3nZYwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBLQUAMFswWTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBCi/" + + "rJRLbFwEVW6PcLLmojjW9lI/xGD7CfZzXrqXFw8iHaf3hTRau1gYMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEASoEEMtCnKKPwccmyrbgeSIlA3qggAQQDLw8" + + "pNJR97bPpj6baG99bQQQwhEDsoj5Xg1oOxojHVcYzAAAAAAAAAAAAAA="); + + private static readonly byte[] ecKeyAgreeMsgAES128 = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgbShgbECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAL01JLEgKvKh5rbxI/hOxs/9WEezMIsAbUaZM4l5tn3CzXAN505nr5d" + + "LhrcurMK+tAwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBBQUAMEswSTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBBhi" + + "FLjc5g6aqDT3f8LomljOwl1WTrplUT8wgAYJKoZIhvcNAQcBMB0GCWCGSAFl" + + "AwQBAgQQzXjms16Y69S/rB0EbHqRMaCABBAFmc/QdVW6LTKdEy97kaZzBBBa" + + "fQuviUS03NycpojELx0bAAAAAAAAAAAAAA=="); + + private static readonly byte[] ecKeyAgreeMsgDESEDE = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcahgcMCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAALIici6Nx1WN5f0ThH2A8ht9ovm0thpC5JK54t73E1RDzCifePaoQo0" + + "xd6sUqoyGaYwHAYJK4EFEIZIPwACMA8GCyqGSIb3DQEJEAMGBQAwWzBZMC0w" + + "KDETMBEGA1UEAxMKQWRtaW4tTURTRTERMA8GA1UEChMINEJDVC0ySUQCAQEE" + + "KJuqZQ1NB1vXrKPOnb4TCpYOsdm6GscWdwAAZlm2EHMp444j0s55J9wwgAYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAjwnsDMsafCrKCABBjyPvqFOVMKxxut" + + "VfTx4fQlNGJN8S2ATRgECMcTQ/dsmeViAAAAAAAAAAAAAA=="); + + private static readonly byte[] ecMqvKeyAgreeMsgAes128 = Base64.Decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgf2hgfoCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPDKU+0H58tsjpoYmYCInMr/FayvCCkupebgsnpaGEB7qS9vzcNVUj6" + + "mrnmiC2grpmhRwRFMEMwQTALBgcqhkjOPQIBBQADMgACZpD13z9c7DzRWx6S" + + "0xdbq3S+EJ7vWO+YcHVjTD8NcQDcZcWASW899l1PkL936zsuMBoGCSuBBRCG" + + "SD8AEDANBglghkgBZQMEAQUFADBLMEkwLTAoMRMwEQYDVQQDEwpBZG1pbi1N" + + "RFNFMREwDwYDVQQKEwg0QkNULTJJRAIBAQQYFq58L71nyMK/70w3nc6zkkRy" + + "RL7DHmpZMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEDzRUpreBsZXWHBe" + + "onxOtSmggAQQ7csAZXwT1lHUqoazoy8bhAQQq+9Zjj8iGdOWgyebbfj67QAA" + + "AAAAAAAAAAA="); + + private static readonly byte[] ecKeyAgreeKey = Base64.Decode( + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC8vp7xVTbKSgYVU5Wc" + + "hGkWbzaj+yUFETIWP1Dt7+WSpq3ikSPdl7PpHPqnPVZfoIWhZANiAgSYHTgxf+Dd" + + "Tt84dUvuSKkFy3RhjxJmjwIscK6zbEUzKhcPQG2GHzXhWK5x1kov0I74XpGhVkya" + + "ElH5K6SaOXiXAzcyNGggTOk4+ZFnz5Xl0pBje3zKxPhYu0SnCw7Pcqw="); + + private static readonly byte[] bobPrivRsaEncrypt = Base64.Decode( + "MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf" + + "8qCTQV6meYmFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmR" + + "uBlpN235ZR572akzJKN/O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtd" + + "YMTgXB9T039T2GkB8QX4enDRvoPGXzjPHCyqaqfrAgMBAAECgYBnzUhMmg2P" + + "mMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngwy+e6alatd8brUXlweQqg" + + "9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A0HPfD6bRSe" + + "TmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N" + + "vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiE" + + "I2Kv8zHCueUCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr" + + "84/sajB0+E0R9KfEILVHIdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5q" + + "SO8bKlocSHseIVnDYDubl6nA7xhmqU5iUjiEzuUJiEiUacUgFJlaV/4jbOSn" + + "I3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVfJAZAcpw6iIWchw+dYhKI" + + "FmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grStavCunrnVNqc" + + "BU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8" + + "Y0ZB9qANMAsGA1UdDzEEAwIAEA=="); + + private static readonly byte[] rfc4134ex5_1 = Base64.Decode( + "MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYD" + + "VQQDEwdDYXJsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUA" + + "BIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FB" + + "s3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJtuzubGgzoyEd" + + "8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4O" + + "xUk660cu1lXeCSFOSOpOJ7FuVyU="); + + private static readonly byte[] rfc4134ex5_2 = Base64.Decode( + "MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4G" + + "A1UEAxMHQ2FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEF" + + "AASBgJQmQojGi7Z4IP+CVypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQ" + + "t9i3YcMwcap+aiOkyqjMalT03VUC0XBOGv+HYI3HBZm/aFzxoq+YOXAWs5xl" + + "GerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg+TGrnGVNQBNw47Ewoj4C" + + "AQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGHcUr5MSJ/g9" + + "HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC" + + "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR" + + "yw=="); + + [Test] + public void TestKeyTrans() + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.DesEde3Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransRC4() + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + "1.2.840.113549.3.4"); // RC4 OID + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, "1.2.840.113549.3.4"); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTrans128RC4() + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + "1.2.840.113549.3.4", 128); // RC4 OID + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, "1.2.840.113549.3.4"); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransOdes() + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + OiwObjectIdentifiers.DesCbc.Id); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, OiwObjectIdentifiers.DesCbc.Id); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransSmallAes() + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, + CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(ReciKP.Private); + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestKeyTransCast5() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Cast5Cbc, + new DerObjectIdentifier(CmsEnvelopedDataGenerator.Cast5Cbc), + typeof(Asn1Sequence)); + } + + [Test] + public void TestKeyTransAes128() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Aes128Cbc, + NistObjectIdentifiers.IdAes128Cbc, + typeof(DerOctetString)); + } + + [Test] + public void TestKeyTransAes192() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Aes192Cbc, + NistObjectIdentifiers.IdAes192Cbc, + typeof(DerOctetString)); + } + + [Test] + public void TestKeyTransAes256() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Aes256Cbc, + NistObjectIdentifiers.IdAes256Cbc, + typeof(DerOctetString)); + } + + [Test] + public void TestKeyTransSeed() + { + TryKeyTrans(CmsEnvelopedDataGenerator.SeedCbc, + KisaObjectIdentifiers.IdSeedCbc, + typeof(DerOctetString)); + } + + public void TestKeyTransCamellia128() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Camellia128Cbc, + NttObjectIdentifiers.IdCamellia128Cbc, + typeof(DerOctetString)); + } + + public void TestKeyTransCamellia192() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Camellia192Cbc, + NttObjectIdentifiers.IdCamellia192Cbc, + typeof(DerOctetString)); + } + + public void TestKeyTransCamellia256() + { + TryKeyTrans(CmsEnvelopedDataGenerator.Camellia256Cbc, + NttObjectIdentifiers.IdCamellia256Cbc, + typeof(DerOctetString)); + } + + private void TryKeyTrans( + string generatorOID, + DerObjectIdentifier checkOID, + Type asn1Params) + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyTransRecipient(ReciCert); + + CmsEnvelopedData ed = edGen.Generate(new CmsProcessableByteArray(data), generatorOID); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(checkOID.Id, ed.EncryptionAlgOid); + + if (asn1Params != null) + { + Assert.IsTrue(asn1Params.IsInstanceOfType(ed.EncryptionAlgorithmID.Parameters)); + } + + ArrayList c = new ArrayList(recipients.GetRecipients()); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(ReciKP.Private); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestErroneousKek() + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington"); + KeyParameter kek = ParameterUtilities.CreateKeyParameter( + "AES", + new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }); + + CmsEnvelopedData ed = new CmsEnvelopedData(oldKEK); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(recipient.KeyEncryptionAlgOid, NistObjectIdentifiers.IdAes128Wrap.Id); + + byte[] recData = recipient.GetContent(kek); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestDesKek() + { + TryKekAlgorithm(CmsTestUtil.MakeDesEde192Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6")); + } + + [Test] + public void TestRC2128Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeRC2128Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7")); + } + + [Test] + public void TestAes128Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeAesKey(128), NistObjectIdentifiers.IdAes128Wrap); + } + + [Test] + public void TestAes192Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeAesKey(192), NistObjectIdentifiers.IdAes192Wrap); + } + + [Test] + public void TestAes256Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeAesKey(256), NistObjectIdentifiers.IdAes256Wrap); + } + + [Test] + public void TestSeed128Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeSeedKey(), KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap); + } + + [Test] + public void TestCamellia128Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(128), NttObjectIdentifiers.IdCamellia128Wrap); + } + + [Test] + public void TestCamellia192Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(192), NttObjectIdentifiers.IdCamellia192Wrap); + } + + [Test] + public void TestCamellia256Kek() + { + TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(256), NttObjectIdentifiers.IdCamellia256Wrap); + } + + private void TryKekAlgorithm( + KeyParameter kek, + DerObjectIdentifier algOid) + { + byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington"); + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + string keyAlgorithm = ParameterUtilities.GetCanonicalAlgorithmName(algOid.Id); + + edGen.AddKekRecipient(keyAlgorithm, kek, kekId); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.DesEde3Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc); + + ArrayList c = new ArrayList(recipients.GetRecipients()); + + Assert.IsTrue(c.Count > 0); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual(algOid.Id, recipient.KeyEncryptionAlgOid); + + byte[] recData = recipient.GetContent(kek); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestECKeyAgree() + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyAgreementRecipient( + CmsEnvelopedDataGenerator.ECDHSha1Kdf, + OrigECKP.Private, + OrigECKP.Public, + ReciECCert, + CmsEnvelopedDataGenerator.Aes128Wrap); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private); + ConfirmNumberRecipients(recipients, 1); + } + + [Test] + public void TestECMqvKeyAgree() + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddKeyAgreementRecipient( + CmsEnvelopedDataGenerator.ECMqvSha1Kdf, + OrigECKP.Private, + OrigECKP.Public, + ReciECCert, + CmsEnvelopedDataGenerator.Aes128Wrap); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private); + ConfirmNumberRecipients(recipients, 1); + } + + [Test] + public void TestECMqvKeyAgreeMultiple() + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + ArrayList recipientCerts = new ArrayList(); + recipientCerts.Add(ReciECCert); + recipientCerts.Add(ReciECCert2); + + edGen.AddKeyAgreementRecipients( + CmsEnvelopedDataGenerator.ECMqvSha1Kdf, + OrigECKP.Private, + OrigECKP.Public, + recipientCerts, + CmsEnvelopedDataGenerator.Aes128Wrap); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private); + ConfirmDataReceived(recipients, data, ReciECCert2, ReciECKP2.Private); + ConfirmNumberRecipients(recipients, 2); + } + + private static void ConfirmDataReceived(RecipientInformationStore recipients, + byte[] expectedData, X509Certificate reciCert, AsymmetricKeyParameter reciPrivKey) + { + RecipientID rid = new RecipientID(); + rid.Issuer = PrincipalUtilities.GetIssuerX509Principal(reciCert); + rid.SerialNumber = reciCert.SerialNumber; + + RecipientInformation recipient = recipients[rid]; + Assert.IsNotNull(recipient); + + byte[] actualData = recipient.GetContent(reciPrivKey); + Assert.IsTrue(Arrays.AreEqual(expectedData, actualData)); + } + + private static void ConfirmNumberRecipients(RecipientInformationStore recipients, int count) + { + Assert.AreEqual(count, recipients.GetRecipients().Count); + } + + [Test] + public void TestECKeyAgreeVectors() + { + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(ecKeyAgreeKey); + + VerifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.42", ecKeyAgreeMsgAES256); + VerifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecKeyAgreeMsgAES128); + VerifyECKeyAgreeVectors(privKey, "1.2.840.113549.3.7", ecKeyAgreeMsgDESEDE); + } + + [Test] + public void TestECMqvKeyAgreeVectors() + { + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(ecKeyAgreeKey); + + VerifyECMqvKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecMqvKeyAgreeMsgAes128); + } + + [Test] + public void TestPasswordAes256() + { + PasswordTest(CmsEnvelopedDataGenerator.Aes256Cbc); + PasswordUtf8Test(CmsEnvelopedDataGenerator.Aes256Cbc); + } + + [Test] + public void TestPasswordDesEde() + { + PasswordTest(CmsEnvelopedDataGenerator.DesEde3Cbc); + PasswordUtf8Test(CmsEnvelopedDataGenerator.DesEde3Cbc); + } + + [Test] + public void TestRfc4134Ex5_1() + { + byte[] data = Hex.Decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + +// KeyFactory kFact = KeyFactory.GetInstance("RSA"); +// Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(bobPrivRsaEncrypt); + + CmsEnvelopedData ed = new CmsEnvelopedData(rfc4134ex5_1); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual("1.2.840.113549.3.7", ed.EncryptionAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + byte[] recData = recipient.GetContent(key); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + [Test] + public void TestRfc4134Ex5_2() + { + byte[] data = Hex.Decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + +// KeyFactory kFact = KeyFactory.GetInstance("RSA"); +// Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(bobPrivRsaEncrypt); + + CmsEnvelopedData ed = new CmsEnvelopedData(rfc4134ex5_2); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual("1.2.840.113549.3.2", ed.EncryptionAlgOid); + + ICollection c = recipients.GetRecipients(); + IEnumerator e = c.GetEnumerator(); + + if (e.MoveNext()) + { + do + { + RecipientInformation recipient = (RecipientInformation) e.Current; + + if (recipient is KeyTransRecipientInformation) + { + byte[] recData = recipient.GetContent(key); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + while (e.MoveNext()); + } + else + { + Assert.Fail("no recipient found"); + } + } + + [Test] + public void TestOriginatorInfo() + { + CmsEnvelopedData env = new CmsEnvelopedData(CmsSampleMessages.originatorMessage); + + RecipientInformationStore recipients = env.GetRecipientInfos(); + + Assert.AreEqual(CmsEnvelopedDataGenerator.DesEde3Cbc, env.EncryptionAlgOid); + } + + private void PasswordTest( + string algorithm) + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddPasswordRecipient(new Pkcs5Scheme2PbeKey("password".ToCharArray(), new byte[20], 5), algorithm); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (PasswordRecipientInformation recipient in c) + { + CmsPbeKey key = new Pkcs5Scheme2PbeKey("password".ToCharArray(), recipient.KeyDerivationAlgorithm); + + byte[] recData = recipient.GetContent(key); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + private void PasswordUtf8Test( + string algorithm) + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator(); + + edGen.AddPasswordRecipient( + new Pkcs5Scheme2Utf8PbeKey("abc\u5639\u563b".ToCharArray(), new byte[20], 5), + algorithm); + + CmsEnvelopedData ed = edGen.Generate( + new CmsProcessableByteArray(data), + CmsEnvelopedDataGenerator.Aes128Cbc); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (PasswordRecipientInformation recipient in c) + { + CmsPbeKey key = new Pkcs5Scheme2Utf8PbeKey( + "abc\u5639\u563b".ToCharArray(), recipient.KeyDerivationAlgorithm); + + byte[] recData = recipient.GetContent(key); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + private void VerifyECKeyAgreeVectors( + AsymmetricKeyParameter privKey, + string wrapAlg, + byte[] message) + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedData ed = new CmsEnvelopedData(message); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + Assert.AreEqual(wrapAlg, ed.EncryptionAlgOid); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual("1.3.133.16.840.63.0.2", recipient.KeyEncryptionAlgOid); + + byte[] recData = recipient.GetContent(privKey); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + + private void VerifyECMqvKeyAgreeVectors( + AsymmetricKeyParameter privKey, + string wrapAlg, + byte[] message) + { + byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CmsEnvelopedData ed = new CmsEnvelopedData(message); + + RecipientInformationStore recipients = ed.GetRecipientInfos(); + + ICollection c = recipients.GetRecipients(); + + Assert.AreEqual(wrapAlg, ed.EncryptionAlgOid); + Assert.AreEqual(1, c.Count); + + foreach (RecipientInformation recipient in c) + { + Assert.AreEqual("1.3.133.16.840.63.0.16", recipient.KeyEncryptionAlgOid); + + byte[] recData = recipient.GetContent(privKey); + + Assert.IsTrue(Arrays.AreEqual(data, recData)); + } + } + } +} diff --git a/crypto/test/src/cms/test/MiscDataStreamTest.cs b/crypto/test/src/cms/test/MiscDataStreamTest.cs new file mode 100644 index 000000000..f958d058f --- /dev/null +++ b/crypto/test/src/cms/test/MiscDataStreamTest.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class MiscDataStreamTest + { + private const string TestMessage = "Hello World!"; + private const string SignDN = "O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair signKP; + private static X509Certificate signCert; + + private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair origKP; + private static X509Certificate origCert; + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + // private static AsymmetricCipherKeyPair reciKP; + // private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origDsaKP; + private static X509Certificate origDsaCert; + + private static X509Crl signCrl; + private static X509Crl origCrl; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair OrigKP + { + get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; } + } + + // private static AsymmetricCipherKeyPair ReciKP + // { + // get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } + // } + + private static AsymmetricCipherKeyPair OrigDsaKP + { + get { return origDsaKP == null ? (origDsaKP = CmsTestUtil.MakeDsaKeyPair()) : origDsaKP; } + } + + private static X509Certificate SignCert + { + get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, SignKP, SignDN)) : signCert; } + } + + private static X509Certificate OrigCert + { + get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, SignKP, SignDN)) : origCert; } + } + + // private static X509Certificate ReciCert + // { + // get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } + // } + + private static X509Certificate OrigDsaCert + { + get { return origDsaCert == null ? (origDsaCert = CmsTestUtil.MakeCertificate(OrigDsaKP, OrigDN, SignKP, SignDN)) : origDsaCert; } + } + + private static X509Crl SignCrl + { + get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; } + } + + private static X509Crl OrigCrl + { + get { return origCrl == null ? (origCrl = CmsTestUtil.MakeCrl(OrigKP)) : origCrl; } + } + + private void VerifySignatures( + CmsSignedDataParser sp, + byte[] contentDigest) + { + IX509Store certStore = sp.GetCertificates("Collection"); + SignerInformationStore signers = sp.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = certStore.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + + if (contentDigest != null) + { + Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest())); + } + } + } + + private void VerifySignatures( + CmsSignedDataParser sp) + { + VerifySignatures(sp, null); + } + + private void VerifyEncodedData( + MemoryStream bOut) + { + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + sp.Close(); + } + + private void CheckSigParseable(byte[] sig) + { + CmsSignedDataParser sp = new CmsSignedDataParser(sig); + sp.Version.ToString(); + CmsTypedStream sc = sp.GetSignedContent(); + if (sc != null) + { + sc.Drain(); + } + sp.GetAttributeCertificates("Collection"); + sp.GetCertificates("Collection"); + sp.GetCrls("Collection"); + sp.GetSignerInfos(); + sp.Close(); + } + + [Test] + public void TestSha1WithRsa() + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + crlList.Add(SignCrl); + crlList.Add(OrigCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + Stream sigOut = gen.Open(bOut); + + CmsCompressedDataStreamGenerator cGen = new CmsCompressedDataStreamGenerator(); + + Stream cOut = cGen.Open(sigOut, CmsCompressedDataStreamGenerator.ZLib); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + cOut.Write(testBytes, 0, testBytes.Length); + + cOut.Close(); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + // generate compressed stream + MemoryStream cDataOut = new MemoryStream(); + + cOut = cGen.Open(cDataOut, CmsCompressedDataStreamGenerator.ZLib); + + cOut.Write(testBytes, 0, testBytes.Length); + + cOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser( + new CmsTypedStream(new MemoryStream(cDataOut.ToArray(), false)), bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + // + // compute expected content digest + // + IDigest md = DigestUtilities.GetDigest("SHA1"); + byte[] cDataOutBytes = cDataOut.ToArray(); + md.BlockUpdate(cDataOutBytes, 0, cDataOutBytes.Length); + byte[] hash = DigestUtilities.DoFinal(md); + + VerifySignatures(sp, hash); + } + } +} diff --git a/crypto/test/src/cms/test/Rfc4134Test.cs b/crypto/test/src/cms/test/Rfc4134Test.cs new file mode 100644 index 000000000..3bfbd1358 --- /dev/null +++ b/crypto/test/src/cms/test/Rfc4134Test.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class Rfc4134Test + { + private static readonly byte[] exContent = GetRfc4134Data("ExContent.bin"); + private static readonly byte[] sha1 = Hex.Decode("406aec085279ba6e16022d9e0629c0229687dd48"); + + [Test] + public void Test4_1() + { + byte[] data = GetRfc4134Data("4.1.bin"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + } + + [Test] + public void Test4_2() + { + byte[] data = GetRfc4134Data("4.2.bin"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + } + + [Test] + public void Test4_3() + { + CmsProcessableByteArray unencap = new CmsProcessableByteArray(exContent); + byte[] data = GetRfc4134Data("4.3.bin"); + CmsSignedData signedData = new CmsSignedData(unencap, data); + + VerifySignatures(signedData, sha1); + + CmsSignedDataParser parser = new CmsSignedDataParser( + new CmsTypedStream(unencap.GetInputStream()), data); + + VerifySignatures(parser); + } + + [Test] + public void Test4_4() + { + byte[] data = GetRfc4134Data("4.4.bin"); + byte[] counterSigCert = GetRfc4134Data("AliceRSASignByCarl.cer"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData, sha1); + + VerifySignerInfo4_4(GetFirstSignerInfo(signedData.GetSignerInfos()), counterSigCert); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + + VerifySignerInfo4_4(GetFirstSignerInfo(parser.GetSignerInfos()), counterSigCert); + } + + [Test] + public void Test4_5() + { + byte[] data = GetRfc4134Data("4.5.bin"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + } + + [Test] + public void Test4_6() + { + byte[] data = GetRfc4134Data("4.6.bin"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + } + + [Test] + public void Test4_7() + { + byte[] data = GetRfc4134Data("4.7.bin"); + CmsSignedData signedData = new CmsSignedData(data); + + VerifySignatures(signedData); + + CmsSignedDataParser parser = new CmsSignedDataParser(data); + + VerifySignatures(parser); + } + + [Test] + public void Test5_1() + { + byte[] data = GetRfc4134Data("5.1.bin"); + CmsEnvelopedData envelopedData = new CmsEnvelopedData(data); + + VerifyEnvelopedData(envelopedData, CmsEnvelopedDataGenerator.DesEde3Cbc); + + CmsEnvelopedDataParser envelopedParser = new CmsEnvelopedDataParser(data); + + VerifyEnvelopedData(envelopedParser, CmsEnvelopedDataGenerator.DesEde3Cbc); + } + + [Test] + public void Test5_2() + { + byte[] data = GetRfc4134Data("5.2.bin"); + CmsEnvelopedData envelopedData = new CmsEnvelopedData(data); + + VerifyEnvelopedData(envelopedData, CmsEnvelopedDataGenerator.RC2Cbc); + + CmsEnvelopedDataParser envelopedParser = new CmsEnvelopedDataParser(data); + + VerifyEnvelopedData(envelopedParser, CmsEnvelopedDataGenerator.RC2Cbc); + } + + private void VerifyEnvelopedData(CmsEnvelopedData envelopedData, string symAlgorithmOID) + { + byte[] privKeyData = GetRfc4134Data("BobPrivRSAEncrypt.pri"); + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyData); + Assert.IsTrue(privKey.IsPrivate); + Assert.IsTrue(privKey is RsaKeyParameters); + + RecipientInformationStore recipients = envelopedData.GetRecipientInfos(); + + Assert.AreEqual(envelopedData.EncryptionAlgOid, symAlgorithmOID); + + ArrayList c = new ArrayList(recipients.GetRecipients()); + Assert.LessOrEqual(1, c.Count); + Assert.GreaterOrEqual(2, c.Count); + + VerifyRecipient((RecipientInformation)c[0], privKey); + + if (c.Count == 2) + { + RecipientInformation recInfo = (RecipientInformation)c[1]; + + Assert.AreEqual(PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id, recInfo.KeyEncryptionAlgOid); + } + } + + private void VerifyEnvelopedData(CmsEnvelopedDataParser envelopedParser, string symAlgorithmOID) + { + byte[] privKeyData = GetRfc4134Data("BobPrivRSAEncrypt.pri"); + AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyData); + Assert.IsTrue(privKey.IsPrivate); + Assert.IsTrue(privKey is RsaKeyParameters); + + RecipientInformationStore recipients = envelopedParser.GetRecipientInfos(); + + Assert.AreEqual(envelopedParser.EncryptionAlgOid, symAlgorithmOID); + + ArrayList c = new ArrayList(recipients.GetRecipients()); + Assert.LessOrEqual(1, c.Count); + Assert.GreaterOrEqual(2, c.Count); + + VerifyRecipient((RecipientInformation)c[0], privKey); + + if (c.Count == 2) + { + RecipientInformation recInfo = (RecipientInformation)c[1]; + + Assert.AreEqual(PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id, recInfo.KeyEncryptionAlgOid); + } + } + + private void VerifyRecipient(RecipientInformation recipient, AsymmetricKeyParameter privKey) + { + Assert.IsTrue(privKey.IsPrivate); + + Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id); + + byte[] recData = recipient.GetContent(privKey); + + Assert.IsTrue(Arrays.AreEqual(exContent, recData)); + } + + private void VerifySignerInfo4_4(SignerInformation signerInfo, byte[] counterSigCert) + { + VerifyCounterSignature(signerInfo, counterSigCert); + + VerifyContentHint(signerInfo); + } + + private SignerInformation GetFirstSignerInfo(SignerInformationStore store) + { + IEnumerator e = store.GetSigners().GetEnumerator(); + e.MoveNext(); + return (SignerInformation)e.Current; + } + + private void VerifyCounterSignature(SignerInformation signInfo, byte[] certificate) + { + SignerInformation csi = GetFirstSignerInfo(signInfo.GetCounterSignatures()); + + X509Certificate cert = new X509CertificateParser().ReadCertificate(certificate); + + Assert.IsTrue(csi.Verify(cert)); + } + + private void VerifyContentHint(SignerInformation signInfo) + { + Asn1.Cms.AttributeTable attrTable = signInfo.UnsignedAttributes; + + Asn1.Cms.Attribute attr = attrTable[CmsAttributes.ContentHint]; + + Assert.AreEqual(1, attr.AttrValues.Count); + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerUtf8String("Content Hints Description Buffer"), + CmsObjectIdentifiers.Data); + + Assert.IsTrue(attr.AttrValues[0].Equals(new DerSequence(v))); + } + + private void VerifySignatures(CmsSignedData s, byte[] contentDigest) + { + IX509Store x509Certs = s.GetCertificates("Collection"); + IX509Store x509Crls = s.GetCrls("Collection"); + SignerInformationStore signers = s.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + VerifySigner(signer, cert); + + if (contentDigest != null) + { + Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest())); + } + } + + ICollection certColl = x509Certs.GetMatches(null); + ICollection crlColl = x509Crls.GetMatches(null); + + Assert.AreEqual(certColl.Count, s.GetCertificates("Collection").GetMatches(null).Count); + Assert.AreEqual(crlColl.Count, s.GetCrls("Collection").GetMatches(null).Count); + } + + private void VerifySignatures(CmsSignedData s) + { + VerifySignatures(s, null); + } + + private void VerifySignatures(CmsSignedDataParser sp) + { + CmsTypedStream sc = sp.GetSignedContent(); + if (sc != null) + { + sc.Drain(); + } + + IX509Store x509Certs = sp.GetCertificates("Collection"); + SignerInformationStore signers = sp.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate)certEnum.Current; + + VerifySigner(signer, cert); + } + } + + private void VerifySigner(SignerInformation signer, X509Certificate cert) + { + if (cert.GetPublicKey() is DsaPublicKeyParameters) + { + DsaPublicKeyParameters key = (DsaPublicKeyParameters)cert.GetPublicKey(); + + if (key.Parameters == null) + { + Assert.IsTrue(signer.Verify(GetInheritedKey(key))); + } + else + { + Assert.IsTrue(signer.Verify(cert)); + } + } + else + { + Assert.IsTrue(signer.Verify(cert)); + } + } + + private DsaPublicKeyParameters GetInheritedKey(DsaPublicKeyParameters dsaPubKey) + { + X509Certificate cert = new X509CertificateParser().ReadCertificate( + GetRfc4134Data("CarlDSSSelf.cer")); + + DsaParameters dsaParams = ((DsaPublicKeyParameters)cert.GetPublicKey()).Parameters; + + return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams); + } + + private static byte[] GetRfc4134Data(string name) + { + return Streams.ReadAll(SimpleTest.GetTestDataAsStream("rfc4134." + name)); + } + } +} diff --git a/crypto/test/src/cms/test/SignedDataStreamTest.cs b/crypto/test/src/cms/test/SignedDataStreamTest.cs new file mode 100644 index 000000000..29b0db8f4 --- /dev/null +++ b/crypto/test/src/cms/test/SignedDataStreamTest.cs @@ -0,0 +1,1215 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class SignedDataStreamTest + { + private const string TestMessage = "Hello World!"; + private const string SignDN = "O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair signKP; + private static X509Certificate signCert; + + private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair origKP; + private static X509Certificate origCert; + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; +// private static AsymmetricCipherKeyPair reciKP; +// private static X509Certificate reciCert; + + private static AsymmetricCipherKeyPair origDsaKP; + private static X509Certificate origDsaCert; + + private static X509Crl signCrl; + private static X509Crl origCrl; + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + + private static AsymmetricCipherKeyPair OrigKP + { + get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; } + } + +// private static AsymmetricCipherKeyPair ReciKP +// { +// get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } +// } + + private static AsymmetricCipherKeyPair OrigDsaKP + { + get { return origDsaKP == null ? (origDsaKP = CmsTestUtil.MakeDsaKeyPair()) : origDsaKP; } + } + + private static X509Certificate SignCert + { + get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, SignKP, SignDN)) : signCert; } + } + + private static X509Certificate OrigCert + { + get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, SignKP, SignDN)) : origCert; } + } + +// private static X509Certificate ReciCert +// { +// get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } +// } + + private static X509Certificate OrigDsaCert + { + get { return origDsaCert == null ? (origDsaCert = CmsTestUtil.MakeCertificate(OrigDsaKP, OrigDN, SignKP, SignDN)) : origDsaCert; } + } + + private static X509Crl SignCrl + { + get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; } + } + + private static X509Crl OrigCrl + { + get { return origCrl == null ? (origCrl = CmsTestUtil.MakeCrl(OrigKP)) : origCrl; } + } + + private void VerifySignatures( + CmsSignedDataParser sp, + byte[] contentDigest) + { + IX509Store certStore = sp.GetCertificates("Collection"); + SignerInformationStore signers = sp.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = certStore.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + + if (contentDigest != null) + { + Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest())); + } + } + } + + private void VerifySignatures( + CmsSignedDataParser sp) + { + VerifySignatures(sp, null); + } + + private void VerifyEncodedData( + MemoryStream bOut) + { + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + sp.Close(); + } + + private void CheckSigParseable(byte[] sig) + { + CmsSignedDataParser sp = new CmsSignedDataParser(sig); + sp.Version.ToString(); + CmsTypedStream sc = sp.GetSignedContent(); + if (sc != null) + { + sc.Drain(); + } + sp.GetAttributeCertificates("Collection"); + sp.GetCertificates("Collection"); + sp.GetCrls("Collection"); + sp.GetSignerInfos(); + sp.Close(); + } + + [Test] + public void TestEarlyInvalidKeyException() + { + try + { + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + gen.AddSigner(OrigKP.Private, OrigCert, + "DSA", // DOESN'T MATCH KEY ALG + CmsSignedDataStreamGenerator.DigestSha1); + + Assert.Fail("Expected InvalidKeyException in AddSigner"); + } + catch (InvalidKeyException) + { + // Ignore + } + } + + [Test] + public void TestEarlyNoSuchAlgorithmException() + { + try + { + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + gen.AddSigner(OrigKP.Private, OrigCert, + CmsSignedDataStreamGenerator.DigestSha1, // BAD OID! + CmsSignedDataStreamGenerator.DigestSha1); + + Assert.Fail("Expected NoSuchAlgorithmException in AddSigner"); + } + catch (SecurityUtilityException) + { + // Ignore + } + } + + [Test] + public void TestSha1EncapsulatedSignature() + { + byte[] encapSigData = Base64.Decode( + "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEH" + + "AaCAJIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEF" + + "MA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJ" + + "BgNVBAYTAkFVMB4XDTA1MDgwNzA2MjU1OVoXDTA1MTExNTA2MjU1OVowJTEW" + + "MBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI" + + "hvcNAQEBBQADgY0AMIGJAoGBAI1fZGgH9wgC3QiK6yluH6DlLDkXkxYYL+Qf" + + "nVRszJVYl0LIxZdpb7WEbVpO8fwtEgFtoDsOdxyqh3dTBv+L7NVD/v46kdPt" + + "xVkSNHRbutJVY8Xn4/TC/CDngqtbpbniMO8n0GiB6vs94gBT20M34j96O2IF" + + "73feNHP+x8PkJ+dNAgMBAAGjTTBLMB0GA1UdDgQWBBQ3XUfEE6+D+t+LIJgK" + + "ESSUE58eyzAfBgNVHSMEGDAWgBQ3XUfEE6+D+t+LIJgKESSUE58eyzAJBgNV" + + "HRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFK3r1stYOeXYJOlOyNGDTWEhZ+a" + + "OYdFeFaS6c+InjotHuFLAy+QsS8PslE48zYNFEqYygGfLhZDLlSnJ/LAUTqF" + + "01vlp+Bgn/JYiJazwi5WiiOTf7Th6eNjHFKXS3hfSGPNPIOjvicAp3ce3ehs" + + "uK0MxgLAaxievzhFfJcGSUMDMIICTTCCAbagAwIBAgIBBzANBgkqhkiG9w0B" + + "AQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAe" + + "Fw0wNTA4MDcwNjI1NTlaFw0wNTExMTUwNjI1NTlaMGUxGDAWBgNVBAMTD0Vy" + + "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0" + + "bGUub3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCB" + + "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgHCJyfwV6/V3kqSu2SOU2E/K" + + "I+N0XohCMUaxPLLNtNBZ3ijxwaV6JGFz7siTgZD/OGfzir/eZimkt+L1iXQn" + + "OAB+ZChivKvHtX+dFFC7Vq+E4Uy0Ftqc/wrGxE6DHb5BR0hprKH8wlDS8wSP" + + "zxovgk4nH0ffUZOoDSuUgjh3gG8CAwEAAaNNMEswHQYDVR0OBBYEFLfY/4EG" + + "mYrvJa7Cky+K9BJ7YmERMB8GA1UdIwQYMBaAFDddR8QTr4P634sgmAoRJJQT" + + "nx7LMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEEBQADgYEADIOmpMd6UHdMjkyc" + + "mIE1yiwfClCsGhCK9FigTg6U1G2FmkBwJIMWBlkeH15uvepsAncsgK+Cn3Zr" + + "dZMb022mwtTJDtcaOM+SNeuCnjdowZ4i71Hf68siPm6sMlZkhz49rA0Yidoo" + + "WuzYOO+dggzwDsMldSsvsDo/ARyCGOulDOAxggEvMIIBKwIBATAqMCUxFjAU" + + "BgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFVAgEHMAkGBSsOAwIa" + + "BQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP" + + "Fw0wNTA4MDcwNjI1NTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5UBOl9XwQv" + + "lfifHCMocTANBgkqhkiG9w0BAQEFAASBgGxnBl2qozYKLgZ0ygqSFgWcRGl1" + + "LgNuE587LtO+EKkgoc3aFqEdjXlAyP8K7naRsvWnFrsB6pUpnrgI9Z8ZSKv8" + + "98IlpsSSJ0jBlEb4gzzavwcBpYbr2ryOtDcF+kYmKIpScglyyoLzm+KPXOoT" + + "n7MsJMoKN3Kd2Vzh6s10PFgeAAAAAAAA"); + + CmsSignedDataParser sp = new CmsSignedDataParser(encapSigData); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + +// [Test] +// public void TestSha1WithRsaNoAttributes() +// { +// IList certList = new ArrayList(); +// CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage)); +// +// certList.Add(OrigCert); +// certList.Add(SignCert); +// +// IX509Store x509Certs = X509StoreFactory.Create( +// "Certificate/Collection", +// new X509CollectionStoreParameters(certList)); +// +// CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); +// +// gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); +// +// gen.AddCertificates(x509Certs); +// +// CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false); +// +// CmsSignedDataParser sp = new CmsSignedDataParser( +// new CmsTypedStream(new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)), s.GetEncoded()); +// +// sp.GetSignedContent().Drain(); +// +// // +// // compute expected content digest +// // +// IDigest md = DigestUtilities.GetDigest("SHA1"); +// +// byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); +// md.BlockUpdate(testBytes, 0, testBytes.Length); +// byte[] hash = DigestUtilities.DoFinal(md); +// +// VerifySignatures(sp, hash); +// } + +// [Test] +// public void TestDsaNoAttributes() +// { +// IList certList = new ArrayList(); +// CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage)); +// +// certList.Add(OrigDsaCert); +// certList.Add(SignCert); +// +// IX509Store x509Certs = X509StoreFactory.Create( +// "Certificate/Collection", +// new X509CollectionStoreParameters(certList)); +// +// CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); +// +// gen.AddSigner(OrigDsaKP.Private, OrigDsaCert, CmsSignedDataGenerator.DigestSha1); +// +// gen.AddCertificates(x509Certs); +// +// CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false); +// +// CmsSignedDataParser sp = new CmsSignedDataParser( +// new CmsTypedStream( +// new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)), +// s.GetEncoded()); +// +// sp.GetSignedContent().Drain(); +// +// // +// // compute expected content digest +// // +// IDigest md = DigestUtilities.GetDigest("SHA1"); +// +// byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); +// md.BlockUpdate(testBytes, 0, testBytes.Length); +// byte[] hash = DigestUtilities.DoFinal(md); +// +// VerifySignatures(sp, hash); +// } + + [Test] + public void TestSha1WithRsa() + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + crlList.Add(SignCrl); + crlList.Add(OrigCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + Stream sigOut = gen.Open(bOut); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + CmsSignedDataParser sp = new CmsSignedDataParser( + new CmsTypedStream(new MemoryStream(testBytes, false)), bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + // + // compute expected content digest + // + IDigest md = DigestUtilities.GetDigest("SHA1"); + md.BlockUpdate(testBytes, 0, testBytes.Length); + byte[] hash = DigestUtilities.DoFinal(md); + + VerifySignatures(sp, hash); + + // + // try using existing signer + // + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigners(sp.GetSignerInfos()); + + gen.AddCertificates(sp.GetCertificates("Collection")); + gen.AddCrls(sp.GetCrls("Collection")); + + bOut.SetLength(0); + + sigOut = gen.Open(bOut, true); + + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + VerifyEncodedData(bOut); + + // + // look for the CRLs + // + ArrayList col = new ArrayList(x509Crls.GetMatches(null)); + + Assert.AreEqual(2, col.Count); + Assert.IsTrue(col.Contains(SignCrl)); + Assert.IsTrue(col.Contains(OrigCrl)); + } + + [Test] + public void TestSha1WithRsaNonData() + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + crlList.Add(SignCrl); + crlList.Add(OrigCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + Stream sigOut = gen.Open(bOut, "1.2.3.4", true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + CmsTypedStream stream = sp.GetSignedContent(); + + Assert.AreEqual("1.2.3.4", stream.ContentType); + + stream.Drain(); + + // + // compute expected content digest + // + IDigest md = DigestUtilities.GetDigest("SHA1"); + md.BlockUpdate(testBytes, 0, testBytes.Length); + byte[] hash = DigestUtilities.DoFinal(md); + + VerifySignatures(sp, hash); + } + + [Test] + public void TestSha1AndMD5WithRsa() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddDigests(CmsSignedDataStreamGenerator.DigestSha1, + CmsSignedDataStreamGenerator.DigestMD5); + + Stream sigOut = gen.Open(bOut); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + gen.AddCertificates(x509Certs); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestMD5); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + CmsSignedDataParser sp = new CmsSignedDataParser( + new CmsTypedStream(new MemoryStream(testBytes, false)), bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestSha1WithRsaEncapsulatedBufferedStream() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // find unbuffered length + // + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.WriteByte((byte)(i & 0xff)); + } + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + int unbufferedLength = bOut.ToArray().Length; + + // + // find buffered length with buffered stream - should be equal + // + bOut.SetLength(0); + + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + sigOut = gen.Open(bOut, true); + + byte[] data = new byte[2000]; + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + Streams.PipeAll(new MemoryStream(data, false), sigOut); + sigOut.Close(); + + VerifyEncodedData(bOut); + + Assert.AreEqual(unbufferedLength, bOut.ToArray().Length); + } + + [Test] + public void TestSha1WithRsaEncapsulatedBuffered() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // find unbuffered length + // + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.WriteByte((byte)(i & 0xff)); + } + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + int unbufferedLength = bOut.ToArray().Length; + + // + // find buffered length - buffer size less than default + // + bOut.SetLength(0); + + gen = new CmsSignedDataStreamGenerator(); + + gen.SetBufferSize(300); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + sigOut = gen.Open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.WriteByte((byte)(i & 0xff)); + } + + sigOut.Close(); + + VerifyEncodedData(bOut); + + Assert.IsTrue(unbufferedLength < bOut.ToArray().Length); + } + + [Test] + public void TestSha1WithRsaEncapsulated() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1]; + + ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners()); + + AttributeTable table = ((SignerInformation) signers[0]).SignedAttributes; + Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest]; + + Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets())); + + // + // try using existing signer + // + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigners(sp.GetSignerInfos()); + + gen.AddCertificates(sp.GetCertificates("Collection")); + gen.AddCrls(sp.GetCrls("Collection")); + + bOut.SetLength(0); + + sigOut = gen.Open(bOut, true); + + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedData sd = new CmsSignedData( + new CmsProcessableByteArray(testBytes), bOut.ToArray()); + + Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count); + + VerifyEncodedData(bOut); + } + + private static readonly DerObjectIdentifier dummyOid1 = new DerObjectIdentifier("1.2.3"); + private static readonly DerObjectIdentifier dummyOid2 = new DerObjectIdentifier("1.2.3.4"); + + private class SignedGenAttributeTableGenerator + : DefaultSignedAttributeTableGenerator + { + public override AttributeTable GetAttributes( + IDictionary parameters) + { + IDictionary table = createStandardAttributeTable(parameters); + + DerOctetString val = new DerOctetString((byte[])parameters[CmsAttributeTableParameter.Digest]); + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(dummyOid1, new DerSet(val)); + + table[attr.AttrType] = attr; + + return new AttributeTable(table); + } + }; + + private class UnsignedGenAttributeTableGenerator + : CmsAttributeTableGenerator + { + public AttributeTable GetAttributes( + IDictionary parameters) + { + DerOctetString val = new DerOctetString((byte[])parameters[CmsAttributeTableParameter.Signature]); + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(dummyOid2, new DerSet(val)); + + return new AttributeTable(new DerSet(attr)); + } + }; + + [Test] + public void TestSha1WithRsaEncapsulatedSubjectKeyID() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, + CmsTestUtil.CreateSubjectKeyId(OrigCert.GetPublicKey()).GetKeyIdentifier(), + CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1]; + + ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners()); + + AttributeTable table = ((SignerInformation) signers[0]).SignedAttributes; + Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest]; + + Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets())); + + // + // try using existing signer + // + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigners(sp.GetSignerInfos()); + +// gen.AddCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", "BC")); + gen.AddCertificates(sp.GetCertificates("Collection")); + + bOut.SetLength(0); + + sigOut = gen.Open(bOut, true); + + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedData sd = new CmsSignedData(new CmsProcessableByteArray(testBytes), bOut.ToArray()); + + Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count); + + VerifyEncodedData(bOut); + } + + [Test] + public void TestAttributeGenerators() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + CmsAttributeTableGenerator signedGen = new SignedGenAttributeTableGenerator(); + CmsAttributeTableGenerator unsignedGen = new UnsignedGenAttributeTableGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, + CmsSignedDataStreamGenerator.DigestSha1, signedGen, unsignedGen); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + + // + // check attributes + // + SignerInformationStore signers = sp.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + checkAttribute(signer.GetContentDigest(), signer.SignedAttributes[dummyOid1]); + checkAttribute(signer.GetSignature(), signer.UnsignedAttributes[dummyOid2]); + } + } + + private void checkAttribute( + byte[] expected, + Asn1.Cms.Attribute attr) + { + DerOctetString value = (DerOctetString)attr.AttrValues[0]; + + Assert.AreEqual(new DerOctetString(expected), value); + } + + [Test] + public void TestWithAttributeCertificate() + { + IList certList = new ArrayList(); + + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate(); + + ArrayList attrCerts = new ArrayList(); + attrCerts.Add(attrCert); + IX509Store store = X509StoreFactory.Create( + "AttributeCertificate/Collection", + new X509CollectionStoreParameters(attrCerts)); + + gen.AddAttributeCertificates(store); + + MemoryStream bOut = new MemoryStream(); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + + Assert.AreEqual(4, sp.Version); + + store = sp.GetAttributeCertificates("Collection"); + + ArrayList coll = new ArrayList(store.GetMatches(null)); + + Assert.AreEqual(1, coll.Count); + + Assert.IsTrue(coll.Contains(attrCert)); + } + + [Test] + public void TestSignerStoreReplacement() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + byte[] data = Encoding.ASCII.GetBytes(TestMessage); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, false); + + sigOut.Write(data, 0, data.Length); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + // + // create new Signer + // + MemoryStream original = new MemoryStream(bOut.ToArray(), false); + + bOut.SetLength(0); + + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224); + + gen.AddCertificates(x509Certs); + + sigOut = gen.Open(bOut); + + sigOut.Write(data, 0, data.Length); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + CmsSignedData sd = new CmsSignedData(bOut.ToArray()); + + // + // replace signer + // + MemoryStream newOut = new MemoryStream(); + + CmsSignedDataParser.ReplaceSigners(original, sd.GetSignerInfos(), newOut); + + sd = new CmsSignedData(new CmsProcessableByteArray(data), newOut.ToArray()); + + IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator(); + signerEnum.MoveNext(); + SignerInformation signer = (SignerInformation) signerEnum.Current; + + Assert.AreEqual(signer.DigestAlgOid, CmsSignedDataStreamGenerator.DigestSha224); + + CmsSignedDataParser sp = new CmsSignedDataParser(new CmsTypedStream( + new MemoryStream(data, false)), newOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestEncapsulatedSignerStoreReplacement() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + // + // create new Signer + // + MemoryStream original = new MemoryStream(bOut.ToArray(), false); + + bOut.SetLength(0); + + gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224); + + gen.AddCertificates(x509Certs); + + sigOut = gen.Open(bOut, true); + + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedData sd = new CmsSignedData(bOut.ToArray()); + + // + // replace signer + // + MemoryStream newOut = new MemoryStream(); + + CmsSignedDataParser.ReplaceSigners(original, sd.GetSignerInfos(), newOut); + + sd = new CmsSignedData(newOut.ToArray()); + + IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator(); + signerEnum.MoveNext(); + SignerInformation signer = (SignerInformation) signerEnum.Current; + + Assert.AreEqual(signer.DigestAlgOid, CmsSignedDataStreamGenerator.DigestSha224); + + CmsSignedDataParser sp = new CmsSignedDataParser(newOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestCertStoreReplacement() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + byte[] data = Encoding.ASCII.GetBytes(TestMessage); + + certList.Add(OrigDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut); + + sigOut.Write(data, 0, data.Length); + + sigOut.Close(); + + CheckSigParseable(bOut.ToArray()); + + // + // create new certstore with the right certificates + // + certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // replace certs + // + MemoryStream original = new MemoryStream(bOut.ToArray(), false); + MemoryStream newOut = new MemoryStream(); + + CmsSignedDataParser.ReplaceCertificatesAndCrls(original, x509Certs, null, null, newOut); + + CmsSignedDataParser sp = new CmsSignedDataParser(new CmsTypedStream(new MemoryStream(data, false)), newOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestEncapsulatedCertStoreReplacement() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + // + // create new certstore with the right certificates + // + certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // replace certs + // + MemoryStream original = new MemoryStream(bOut.ToArray(), false); + MemoryStream newOut = new MemoryStream(); + + CmsSignedDataParser.ReplaceCertificatesAndCrls(original, x509Certs, null, null, newOut); + + CmsSignedDataParser sp = new CmsSignedDataParser(newOut.ToArray()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestCertOrdering1() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + x509Certs = sp.GetCertificates("Collection"); + ArrayList a = new ArrayList(x509Certs.GetMatches(null)); + + Assert.AreEqual(2, a.Count); + Assert.AreEqual(OrigCert, a[0]); + Assert.AreEqual(SignCert, a[1]); + } + + [Test] + public void TestCertOrdering2() + { + IList certList = new ArrayList(); + MemoryStream bOut = new MemoryStream(); + + certList.Add(SignCert); + certList.Add(OrigCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + Stream sigOut = gen.Open(bOut, true); + + byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage); + sigOut.Write(testBytes, 0, testBytes.Length); + + sigOut.Close(); + + CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray()); + + sp.GetSignedContent().Drain(); + x509Certs = sp.GetCertificates("Collection"); + ArrayList a = new ArrayList(x509Certs.GetMatches(null)); + + Assert.AreEqual(2, a.Count); + Assert.AreEqual(SignCert, a[0]); + Assert.AreEqual(OrigCert, a[1]); + } + } +} diff --git a/crypto/test/src/cms/test/SignedDataTest.cs b/crypto/test/src/cms/test/SignedDataTest.cs new file mode 100644 index 000000000..96f00eadc --- /dev/null +++ b/crypto/test/src/cms/test/SignedDataTest.cs @@ -0,0 +1,1480 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Cms.Tests +{ + [TestFixture] + public class SignedDataTest + { + private const string OrigDN = "O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair origKP; + private static X509Certificate origCert; + + private const string SignDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + private static AsymmetricCipherKeyPair signKP; + private static X509Certificate signCert; + + private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; +// private static AsymmetricCipherKeyPair reciKP; +// private static X509Certificate reciCert; + + private static X509Crl signCrl; + + private static AsymmetricCipherKeyPair signGostKP; + private static X509Certificate signGostCert; + + private static AsymmetricCipherKeyPair signDsaKP; + private static X509Certificate signDsaCert; + + private static AsymmetricCipherKeyPair signECGostKP; + private static X509Certificate signECGostCert; + + private static AsymmetricCipherKeyPair signECDsaKP; + private static X509Certificate signECDsaCert; + + private static AsymmetricCipherKeyPair OrigKP + { + get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; } + } + + private static AsymmetricCipherKeyPair SignKP + { + get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; } + } + +// private static AsymmetricCipherKeyPair ReciKP +// { +// get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; } +// } + + private static AsymmetricCipherKeyPair SignGostKP + { + get { return signGostKP == null ? (signGostKP = CmsTestUtil.MakeGostKeyPair()) : signGostKP; } + } + + private static AsymmetricCipherKeyPair SignDsaKP + { + get { return signDsaKP == null ? (signDsaKP = CmsTestUtil.MakeDsaKeyPair()) : signDsaKP; } + } + + private static AsymmetricCipherKeyPair SignECGostKP + { + get { return signECGostKP == null ? (signECGostKP = CmsTestUtil.MakeECGostKeyPair()) : signECGostKP; } + } + + private static AsymmetricCipherKeyPair SignECDsaKP + { + get { return signECDsaKP == null ? (signECDsaKP = CmsTestUtil.MakeECDsaKeyPair()) : signECDsaKP; } + } + + private static X509Certificate OrigCert + { + get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, OrigKP, OrigDN)) : origCert; } + } + + private static X509Certificate SignCert + { + get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, OrigKP, OrigDN)) : signCert; } + } + +// private static X509Certificate ReciCert +// { +// get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; } +// } + + private static X509Crl SignCrl + { + get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; } + } + + private static X509Certificate SignGostCert + { + get { return signGostCert == null ? (signGostCert = CmsTestUtil.MakeCertificate(SignGostKP, SignDN, OrigKP, OrigDN)) : signGostCert; } + } + + private static X509Certificate SignECGostCert + { + get { return signECGostCert == null ? (signECGostCert = CmsTestUtil.MakeCertificate(SignECGostKP, SignDN, OrigKP, OrigDN)) : signECGostCert; } + } + + private static X509Certificate SignDsaCert + { + get { return signDsaCert == null ? (signDsaCert = CmsTestUtil.MakeCertificate(SignDsaKP, SignDN, OrigKP, OrigDN)) : signDsaCert; } + } + + private static X509Certificate SignECDsaCert + { + get { return signECDsaCert == null ? (signECDsaCert = CmsTestUtil.MakeCertificate(SignECDsaKP, SignDN, OrigKP, OrigDN)) : signECDsaCert; } + } + + private static readonly byte[] disorderedMessage = Base64.Decode( + "SU9fc3RkaW5fdXNlZABfX2xpYmNfc3RhcnRfbWFpbgBnZXRob3N0aWQAX19n" + + "bW9uX3M="); + + private static readonly byte[] disorderedSet = Base64.Decode( + "MIIYXQYJKoZIhvcNAQcCoIIYTjCCGEoCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCFqswggJUMIIBwKADAgECAgMMg6wwCgYGKyQDAwECBQAwbzEL" + + "MAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbI" + + "dXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwEx" + + "MBEGA1UEAxQKNFItQ0EgMTpQTjAiGA8yMDAwMDMyMjA5NDM1MFoYDzIwMDQw" + + "MTIxMTYwNDUzWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1" + + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh" + + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3" + + "DQEBAQUAA4GPADCBiwKBgQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0I" + + "fe3QMqeGMoCUnyJxwW0k2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg" + + "19e9JPv061wyADOucOIaNAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKaj" + + "LMAw0bu1J0FadQIFAMAAAAEwCgYGKyQDAwECBQADgYEAgFauXpoTLh3Z3pT/" + + "3bhgrxO/2gKGZopWGSWSJPNwq/U3x2EuctOJurj+y2inTcJjespThflpN+7Q" + + "nvsUhXU+jL2MtPlObU0GmLvWbi47cBShJ7KElcZAaxgWMBzdRGqTOdtMv+ev" + + "2t4igGF/q71xf6J2c3pTLWr6P8s6tzLfOCMwggJDMIIBr6ADAgECAgQAuzyu" + + "MAoGBiskAwMBAgUAMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGll" + + "cnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0" + + "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE4wIhgPMjAwMTA4" + + "MjAwODA4MjBaGA8yMDA1MDgyMDA4MDgyMFowSzELMAkGA1UEBhMCREUxEjAQ" + + "BgNVBAoUCVNpZ250cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBT" + + "SUdOVFJVU1QgMTpQTjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAhV12" + + "N2WhlR6f+3CXP57GrBM9la5Vnsu2b92zv5MZqQOPeEsYbZqDCFkYg1bSwsDE" + + "XsGVQqXdQNAGUaapr/EUVVN+hNZ07GcmC1sPeQECgUkxDYjGi4ihbvzxlahj" + + "L4nX+UTzJVBfJwXoIvJ+lMHOSpnOLIuEL3SRhBItvRECxN0CAwEAAaMSMBAw" + + "DgYDVR0PAQH/BAQDAgEGMAoGBiskAwMBAgUAA4GBACDc9Pc6X8sK1cerphiV" + + "LfFv4kpZb9ev4WPy/C6987Qw1SOTElhZAmxaJQBqmDHWlQ63wj1DEqswk7hG" + + "LrvQk/iX6KXIn8e64uit7kx6DHGRKNvNGofPjr1WelGeGW/T2ZJKgmPDjCkf" + + "sIKt2c3gwa2pDn4mmCz/DStUIqcPDbqLMIICVTCCAcGgAwIBAgIEAJ16STAK" + + "BgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1" + + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh" + + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMCIYDzIwMDEwMjAx" + + "MTM0NDI1WhgPMjAwNTAzMjIwODU1NTFaMG8xCzAJBgNVBAYTAkRFMT0wOwYD" + + "VQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0" + + "aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNhIDE6" + + "UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvthihnl" + + "tsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wdbPvg" + + "JyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCAOXFw" + + "VWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIFAAOB" + + "gQBpSRdnDb6AcNVaXSmGo6+kVPIBhot1LzJOGaPyDNpGXxd7LV4tMBF1U7gr" + + "4k1g9BO6YiMWvw9uiTZmn0CfV8+k4fWEuG/nmafRoGIuay2f+ILuT+C0rnp1" + + "4FgMsEhuVNJJAmb12QV0PZII+UneyhAneZuQQzVUkTcVgYxogxdSOzCCAlUw" + + "ggHBoAMCAQICBACdekowCgYGKyQDAwECBQAwbzELMAkGA1UEBhMCREUxPTA7" + + "BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlr" + + "YXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNlItQ2Eg" + + "MTpQTjAiGA8yMDAxMDIwMTEzNDcwN1oYDzIwMDUwMzIyMDg1NTUxWjBvMQsw" + + "CQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1" + + "ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEw" + + "EQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3DQEBAQUAA4GPADCBiwKB" + + "gQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0Ife3QMqeGMoCUnyJxwW0k" + + "2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg19e9JPv061wyADOucOIa" + + "NAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKajLMAw0bu1J0FadQIFAMAA" + + "AAEwCgYGKyQDAwECBQADgYEAV1yTi+2gyB7sUhn4PXmi/tmBxAfe5oBjDW8m" + + "gxtfudxKGZ6l/FUPNcrSc5oqBYxKWtLmf3XX87LcblYsch617jtNTkMzhx9e" + + "qxiD02ufcrxz2EVt0Akdqiz8mdVeqp3oLcNU/IttpSrcA91CAnoUXtDZYwb/" + + "gdQ4FI9l3+qo/0UwggJVMIIBwaADAgECAgQAxIymMAoGBiskAwMBAgUAMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjZSLUNhIDE6UE4wIhgPMjAwMTEwMTUxMzMxNThaGA8yMDA1" + + "MDYwMTA5NTIxN1owbzELMAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVy" + + "dW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3Qx" + + "ITAMBgcCggYBCgcUEwExMBEGA1UEAxQKN1ItQ0EgMTpQTjCBoTANBgkqhkiG" + + "9w0BAQEFAAOBjwAwgYsCgYEAiokD/j6lEP4FexF356OpU5teUpGGfUKjIrFX" + + "BHc79G0TUzgVxqMoN1PWnWktQvKo8ETaugxLkP9/zfX3aAQzDW4Zki6x6GDq" + + "fy09Agk+RJvhfbbIzRkV4sBBco0n73x7TfG/9NTgVr/96U+I+z/1j30aboM6" + + "9OkLEhjxAr0/GbsCBQDAAAABMAoGBiskAwMBAgUAA4GBAHWRqRixt+EuqHhR" + + "K1kIxKGZL2vZuakYV0R24Gv/0ZR52FE4ECr+I49o8FP1qiGSwnXB0SwjuH2S" + + "iGiSJi+iH/MeY85IHwW1P5e+bOMvEOFhZhQXQixOD7totIoFtdyaj1XGYRef" + + "0f2cPOjNJorXHGV8wuBk+/j++sxbd/Net3FtMIICVTCCAcGgAwIBAgIEAMSM" + + "pzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo3Ui1DQSAxOlBOMCIYDzIwMDEx" + + "MDE1MTMzNDE0WhgPMjAwNTA2MDEwOTUyMTdaMG8xCzAJBgNVBAYTAkRFMT0w" + + "OwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5p" + + "a2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNh" + + "IDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvth" + + "ihnltsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wd" + + "bPvgJyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCA" + + "OXFwVWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIF" + + "AAOBgQBi5W96UVDoNIRkCncqr1LLG9vF9SGBIkvFpLDIIbcvp+CXhlvsdCJl" + + "0pt2QEPSDl4cmpOet+CxJTdTuMeBNXxhb7Dvualog69w/+K2JbPhZYxuVFZs" + + "Zh5BkPn2FnbNu3YbJhE60aIkikr72J4XZsI5DxpZCGh6xyV/YPRdKSljFjCC" + + "AlQwggHAoAMCAQICAwyDqzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9" + + "MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVu" + + "aWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1D" + + "QSAxOlBOMCIYDzIwMDAwMzIyMDk0MTI3WhgPMjAwNDAxMjExNjA0NTNaMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjRSLUNBIDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGL" + + "AoGBAI8x26tmrFJanlm100B7KGlRemCD1R93PwdnG7svRyf5ZxOsdGrDszNg" + + "xg6ouO8ZHQMT3NC2dH8TvO65Js+8bIyTm51azF6clEg0qeWNMKiiXbBXa+ph" + + "hTkGbXiLYvACZ6/MTJMJ1lcrjpRF7BXtYeYMcEF6znD4pxOqrtbf9z5hAgUA" + + "wAAAATAKBgYrJAMDAQIFAAOBgQB99BjSKlGPbMLQAgXlvA9jUsDNhpnVm3a1" + + "YkfxSqS/dbQlYkbOKvCxkPGA9NBxisBM8l1zFynVjJoy++aysRmcnLY/sHaz" + + "23BF2iU7WERy18H3lMBfYB6sXkfYiZtvQZcWaO48m73ZBySuiV3iXpb2wgs/" + + "Cs20iqroAWxwq/W/9jCCAlMwggG/oAMCAQICBDsFZ9UwCgYGKyQDAwECBQAw" + + "bzELMAkGA1UEBhMCREUxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNFItQ0Eg" + + "MTpQTjE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxl" + + "a29tbXVuaWthdGlvbiB1bmQgUG9zdDAiGA8xOTk5MDEyMTE3MzUzNFoYDzIw" + + "MDQwMTIxMTYwMDAyWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAozUi1DQSAxOlBOMIGfMA0GCSqG" + + "SIb3DQEBAQUAA4GNADCBiQKBgI4B557mbKQg/AqWBXNJhaT/6lwV93HUl4U8" + + "u35udLq2+u9phns1WZkdM3gDfEpL002PeLfHr1ID/96dDYf04lAXQfombils" + + "of1C1k32xOvxjlcrDOuPEMxz9/HDAQZA5MjmmYHAIulGI8Qg4Tc7ERRtg/hd" + + "0QX0/zoOeXoDSEOBAgTAAAABMAoGBiskAwMBAgUAA4GBAIyzwfT3keHI/n2P" + + "LrarRJv96mCohmDZNpUQdZTVjGu5VQjVJwk3hpagU0o/t/FkdzAjOdfEw8Ql" + + "3WXhfIbNLv1YafMm2eWSdeYbLcbB5yJ1od+SYyf9+tm7cwfDAcr22jNRBqx8" + + "wkWKtKDjWKkevaSdy99sAI8jebHtWz7jzydKMIID9TCCA16gAwIBAgICbMcw" + + "DQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCREUxEjAQBgNVBAoUCVNpZ250" + + "cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBTSUdOVFJVU1QgMTpQ" + + "TjAeFw0wNDA3MzAxMzAyNDZaFw0wNzA3MzAxMzAyNDZaMDwxETAPBgNVBAMM" + + "CFlhY29tOlBOMQ4wDAYDVQRBDAVZYWNvbTELMAkGA1UEBhMCREUxCjAIBgNV" + + "BAUTATEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIWzLlYLQApocXIp" + + "pgCCpkkOUVLgcLYKeOd6/bXAnI2dTHQqT2bv7qzfUnYvOqiNgYdF13pOYtKg" + + "XwXMTNFL4ZOI6GoBdNs9TQiZ7KEWnqnr2945HYx7UpgTBclbOK/wGHuCdcwO" + + "x7juZs1ZQPFG0Lv8RoiV9s6HP7POqh1sO0P/AgMBAAGjggH1MIIB8TCBnAYD" + + "VR0jBIGUMIGRgBQcZzNghfnXoXRm8h1+VITC5caNRqFzpHEwbzELMAkGA1UE" + + "BhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVs" + + "ZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UE" + + "AxQKNVItQ0EgMTpQToIEALs8rjAdBgNVHQ4EFgQU2e5KAzkVuKaM9I5heXkz" + + "bcAIuR8wDgYDVR0PAQH/BAQDAgZAMBIGA1UdIAQLMAkwBwYFKyQIAQEwfwYD" + + "VR0fBHgwdjB0oCygKoYobGRhcDovL2Rpci5zaWdudHJ1c3QuZGUvbz1TaWdu" + + "dHJ1c3QsYz1kZaJEpEIwQDEdMBsGA1UEAxMUQ1JMU2lnblNpZ250cnVzdDE6" + + "UE4xEjAQBgNVBAoTCVNpZ250cnVzdDELMAkGA1UEBhMCREUwYgYIKwYBBQUH" + + "AQEEVjBUMFIGCCsGAQUFBzABhkZodHRwOi8vZGlyLnNpZ250cnVzdC5kZS9T" + + "aWdudHJ1c3QvT0NTUC9zZXJ2bGV0L2h0dHBHYXRld2F5LlBvc3RIYW5kbGVy" + + "MBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYHAoIGAQoMAAQDAQH/MA0G" + + "CSqGSIb3DQEBBQUAA4GBAHn1m3GcoyD5GBkKUY/OdtD6Sj38LYqYCF+qDbJR" + + "6pqUBjY2wsvXepUppEler+stH8mwpDDSJXrJyuzf7xroDs4dkLl+Rs2x+2tg" + + "BjU+ABkBDMsym2WpwgA8LCdymmXmjdv9tULxY+ec2pjSEzql6nEZNEfrU8nt" + + "ZCSCavgqW4TtMYIBejCCAXYCAQEwUTBLMQswCQYDVQQGEwJERTESMBAGA1UE" + + "ChQJU2lnbnRydXN0MSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEUNBIFNJR05U" + + "UlVTVCAxOlBOAgJsxzAJBgUrDgMCGgUAoIGAMBgGCSqGSIb3DQEJAzELBgkq" + + "hkiG9w0BBwEwIwYJKoZIhvcNAQkEMRYEFIYfhPoyfGzkLWWSSLjaHb4HQmaK" + + "MBwGCSqGSIb3DQEJBTEPFw0wNTAzMjQwNzM4MzVaMCEGBSskCAYFMRgWFi92" + + "YXIvZmlsZXMvdG1wXzEvdGVzdDEwDQYJKoZIhvcNAQEFBQAEgYA2IvA8lhVz" + + "VD5e/itUxbFboKxeKnqJ5n/KuO/uBCl1N14+7Z2vtw1sfkIG+bJdp3OY2Cmn" + + "mrQcwsN99Vjal4cXVj8t+DJzFG9tK9dSLvD3q9zT/GQ0kJXfimLVwCa4NaSf" + + "Qsu4xtG0Rav6bCcnzabAkKuNNvKtH8amSRzk870DBg=="); + + private static readonly byte[] xtraCounterSig = Base64.Decode( + "MIIR/AYJKoZIhvcNAQcCoIIR7TCCEekCAQExCzAJBgUrDgMCGgUAMBoGCSqG" + + "SIb3DQEHAaANBAtIZWxsbyB3b3JsZKCCDnkwggTPMIIDt6ADAgECAgRDnYD3" + + "MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5U" + + "ZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmlj" + + "YXRpb24gQXV0aG9yaXR5MB4XDTA4MDkxMjExNDMxMloXDTEwMDkxMjExNDMx" + + "MlowgdgxCzAJBgNVBAYTAklUMSIwIAYDVQQKDBlJbnRlc2EgUy5wLkEuLzA1" + + "MjYyODkwMDE0MSowKAYDVQQLDCFCdXNpbmVzcyBDb2xsYWJvcmF0aW9uICYg" + + "U2VjdXJpdHkxHjAcBgNVBAMMFU1BU1NJTUlMSUFOTyBaSUNDQVJESTERMA8G" + + "A1UEBAwIWklDQ0FSREkxFTATBgNVBCoMDE1BU1NJTUlMSUFOTzEcMBoGA1UE" + + "BRMTSVQ6WkNDTVNNNzZIMTRMMjE5WTERMA8GA1UELhMIMDAwMDI1ODUwgaAw" + + "DQYJKoZIhvcNAQEBBQADgY4AMIGKAoGBALeJTjmyFgx1SIP6c2AuB/kuyHo5" + + "j/prKELTALsFDimre/Hxr3wOSet1TdQfFzU8Lu+EJqgfV9cV+cI1yeH1rZs7" + + "lei7L3tX/VR565IywnguX5xwvteASgWZr537Fkws50bvTEMyYOj1Tf3FZvZU" + + "z4n4OD39KI4mfR9i1eEVIxR3AgQAizpNo4IBoTCCAZ0wHQYDVR0RBBYwFIES" + + "emljY2FyZGlAaW50ZXNhLml0MC8GCCsGAQUFBwEDBCMwITAIBgYEAI5GAQEw" + + "CwYGBACORgEDAgEUMAgGBgQAjkYBBDBZBgNVHSAEUjBQME4GBgQAizABATBE" + + "MEIGCCsGAQUFBwIBFjZodHRwOi8vZS10cnVzdGNvbS5pbnRlc2EuaXQvY2Ff" + + "cHViYmxpY2EvQ1BTX0lOVEVTQS5odG0wDgYDVR0PAQH/BAQDAgZAMIGDBgNV" + + "HSMEfDB6gBQZCQOW0bjFWBt+EORuxPagEgkQqKFcpFowWDELMAkGA1UEBhMC" + + "SVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJbi5U" + + "ZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHmCBDzRARMwOwYDVR0f" + + "BDQwMjAwoC6gLIYqaHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L0NSTC9J" + + "TlRFU0EuY3JsMB0GA1UdDgQWBBTf5ItL8KmQh541Dxt7YxcWI1254TANBgkq" + + "hkiG9w0BAQUFAAOCAQEAgW+uL1CVWQepbC/wfCmR6PN37Sueb4xiKQj2mTD5" + + "UZ5KQjpivy/Hbuf0NrfKNiDEhAvoHSPC31ebGiKuTMFNyZPHfPEUnyYGSxea" + + "2w837aXJFr6utPNQGBRi89kH90sZDlXtOSrZI+AzJJn5QK3F9gjcayU2NZXQ" + + "MJgRwYmFyn2w4jtox+CwXPQ9E5XgxiMZ4WDL03cWVXDLX00EOJwnDDMUNTRI" + + "m9Zv+4SKTNlfFbi9UTBqWBySkDzAelsfB2U61oqc2h1xKmCtkGMmN9iZT+Qz" + + "ZC/vaaT+hLEBFGAH2gwFrYc4/jTBKyBYeU1vsAxsibIoTs1Apgl6MH75qPDL" + + "BzCCBM8wggO3oAMCAQICBEOdgPcwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwOTEy" + + "MTE0MzEyWhcNMTAwOTEyMTE0MzEyWjCB2DELMAkGA1UEBhMCSVQxIjAgBgNV" + + "BAoMGUludGVzYSBTLnAuQS4vMDUyNjI4OTAwMTQxKjAoBgNVBAsMIUJ1c2lu" + + "ZXNzIENvbGxhYm9yYXRpb24gJiBTZWN1cml0eTEeMBwGA1UEAwwVTUFTU0lN" + + "SUxJQU5PIFpJQ0NBUkRJMREwDwYDVQQEDAhaSUNDQVJESTEVMBMGA1UEKgwM" + + "TUFTU0lNSUxJQU5PMRwwGgYDVQQFExNJVDpaQ0NNU003NkgxNEwyMTlZMREw" + + "DwYDVQQuEwgwMDAwMjU4NTCBoDANBgkqhkiG9w0BAQEFAAOBjgAwgYoCgYEA" + + "t4lOObIWDHVIg/pzYC4H+S7IejmP+msoQtMAuwUOKat78fGvfA5J63VN1B8X" + + "NTwu74QmqB9X1xX5wjXJ4fWtmzuV6Lsve1f9VHnrkjLCeC5fnHC+14BKBZmv" + + "nfsWTCznRu9MQzJg6PVN/cVm9lTPifg4Pf0ojiZ9H2LV4RUjFHcCBACLOk2j" + + "ggGhMIIBnTAdBgNVHREEFjAUgRJ6aWNjYXJkaUBpbnRlc2EuaXQwLwYIKwYB" + + "BQUHAQMEIzAhMAgGBgQAjkYBATALBgYEAI5GAQMCARQwCAYGBACORgEEMFkG" + + "A1UdIARSMFAwTgYGBACLMAEBMEQwQgYIKwYBBQUHAgEWNmh0dHA6Ly9lLXRy" + + "dXN0Y29tLmludGVzYS5pdC9jYV9wdWJibGljYS9DUFNfSU5URVNBLmh0bTAO" + + "BgNVHQ8BAf8EBAMCBkAwgYMGA1UdIwR8MHqAFBkJA5bRuMVYG34Q5G7E9qAS" + + "CRCooVykWjBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5BLiBT" + + "LnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9uIEF1" + + "dGhvcml0eYIEPNEBEzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vZS10cnVz" + + "dGNvbS5pbnRlc2EuaXQvQ1JML0lOVEVTQS5jcmwwHQYDVR0OBBYEFN/ki0vw" + + "qZCHnjUPG3tjFxYjXbnhMA0GCSqGSIb3DQEBBQUAA4IBAQCBb64vUJVZB6ls" + + "L/B8KZHo83ftK55vjGIpCPaZMPlRnkpCOmK/L8du5/Q2t8o2IMSEC+gdI8Lf" + + "V5saIq5MwU3Jk8d88RSfJgZLF5rbDzftpckWvq6081AYFGLz2Qf3SxkOVe05" + + "Ktkj4DMkmflArcX2CNxrJTY1ldAwmBHBiYXKfbDiO2jH4LBc9D0TleDGIxnh" + + "YMvTdxZVcMtfTQQ4nCcMMxQ1NEib1m/7hIpM2V8VuL1RMGpYHJKQPMB6Wx8H" + + "ZTrWipzaHXEqYK2QYyY32JlP5DNkL+9ppP6EsQEUYAfaDAWthzj+NMErIFh5" + + "TW+wDGyJsihOzUCmCXowfvmo8MsHMIIEzzCCA7egAwIBAgIEQ52A9zANBgkq" + + "hkiG9w0BAQUFADBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5B" + + "LiBTLnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9u" + + "IEF1dGhvcml0eTAeFw0wODA5MTIxMTQzMTJaFw0xMDA5MTIxMTQzMTJaMIHY" + + "MQswCQYDVQQGEwJJVDEiMCAGA1UECgwZSW50ZXNhIFMucC5BLi8wNTI2Mjg5" + + "MDAxNDEqMCgGA1UECwwhQnVzaW5lc3MgQ29sbGFib3JhdGlvbiAmIFNlY3Vy" + + "aXR5MR4wHAYDVQQDDBVNQVNTSU1JTElBTk8gWklDQ0FSREkxETAPBgNVBAQM" + + "CFpJQ0NBUkRJMRUwEwYDVQQqDAxNQVNTSU1JTElBTk8xHDAaBgNVBAUTE0lU" + + "OlpDQ01TTTc2SDE0TDIxOVkxETAPBgNVBC4TCDAwMDAyNTg1MIGgMA0GCSqG" + + "SIb3DQEBAQUAA4GOADCBigKBgQC3iU45shYMdUiD+nNgLgf5Lsh6OY/6ayhC" + + "0wC7BQ4pq3vx8a98DknrdU3UHxc1PC7vhCaoH1fXFfnCNcnh9a2bO5Xouy97" + + "V/1UeeuSMsJ4Ll+ccL7XgEoFma+d+xZMLOdG70xDMmDo9U39xWb2VM+J+Dg9" + + "/SiOJn0fYtXhFSMUdwIEAIs6TaOCAaEwggGdMB0GA1UdEQQWMBSBEnppY2Nh" + + "cmRpQGludGVzYS5pdDAvBggrBgEFBQcBAwQjMCEwCAYGBACORgEBMAsGBgQA" + + "jkYBAwIBFDAIBgYEAI5GAQQwWQYDVR0gBFIwUDBOBgYEAIswAQEwRDBCBggr" + + "BgEFBQcCARY2aHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L2NhX3B1YmJs" + + "aWNhL0NQU19JTlRFU0EuaHRtMA4GA1UdDwEB/wQEAwIGQDCBgwYDVR0jBHww" + + "eoAUGQkDltG4xVgbfhDkbsT2oBIJEKihXKRaMFgxCzAJBgNVBAYTAklUMRow" + + "GAYDVQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5B" + + "LiAtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ80QETMDsGA1UdHwQ0MDIw" + + "MKAuoCyGKmh0dHA6Ly9lLXRydXN0Y29tLmludGVzYS5pdC9DUkwvSU5URVNB" + + "LmNybDAdBgNVHQ4EFgQU3+SLS/CpkIeeNQ8be2MXFiNdueEwDQYJKoZIhvcN" + + "AQEFBQADggEBAIFvri9QlVkHqWwv8Hwpkejzd+0rnm+MYikI9pkw+VGeSkI6" + + "Yr8vx27n9Da3yjYgxIQL6B0jwt9XmxoirkzBTcmTx3zxFJ8mBksXmtsPN+2l" + + "yRa+rrTzUBgUYvPZB/dLGQ5V7Tkq2SPgMySZ+UCtxfYI3GslNjWV0DCYEcGJ" + + "hcp9sOI7aMfgsFz0PROV4MYjGeFgy9N3FlVwy19NBDicJwwzFDU0SJvWb/uE" + + "ikzZXxW4vVEwalgckpA8wHpbHwdlOtaKnNodcSpgrZBjJjfYmU/kM2Qv72mk" + + "/oSxARRgB9oMBa2HOP40wSsgWHlNb7AMbImyKE7NQKYJejB++ajwywcxggM8" + + "MIIDOAIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5UZS5TLkEu" + + "IFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmljYXRpb24g" + + "QXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYB+" + + "lH2cwLqc91mP8prvgSV+RRzk13dJdZvdoVjgQoFrPhBiZCNIEoHvIhMMA/sM" + + "X6euSRZk7EjD24FasCEGYyd0mJVLEy6TSPmuW+wWz/28w3a6IWXBGrbb/ild" + + "/CJMkPgLPGgOVD1WDwiNKwfasiQSFtySf5DPn3jFevdLeMmEY6GCAjIwggEV" + + "BgkqhkiG9w0BCQYxggEGMIIBAgIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYD" + + "VQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAt" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJ" + + "KoZIhvcNAQEBBQAEgYBHlOULfT5GDigIvxP0qZOy8VbpntmzaPF55VV4buKV" + + "35J+uHp98gXKp0LrHM69V5IRKuyuQzHHFBqsXxsRI9o6KoOfgliD9Xc+BeMg" + + "dKzQhBhBYoFREq8hQM0nSbqDNHYAQyNHMzUA/ZQUO5dlFuH8Dw3iDYAhNtfd" + + "PrlchKJthDCCARUGCSqGSIb3DQEJBjGCAQYwggECAgEBMGAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkCBEOdgPcwCQYF" + + "Kw4DAhoFADANBgkqhkiG9w0BAQEFAASBgEeU5Qt9PkYOKAi/E/Spk7LxVume" + + "2bNo8XnlVXhu4pXfkn64en3yBcqnQusczr1XkhEq7K5DMccUGqxfGxEj2joq" + + "g5+CWIP1dz4F4yB0rNCEGEFigVESryFAzSdJuoM0dgBDI0czNQD9lBQ7l2UW" + + "4fwPDeINgCE2190+uVyEom2E"); + + private void VerifySignatures( + CmsSignedData s, + byte[] contentDigest) + { + IX509Store x509Certs = s.GetCertificates("Collection"); + + SignerInformationStore signers = s.GetSignerInfos(); + ICollection c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + + if (contentDigest != null) + { + Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest())); + } + } + } + + private void VerifySignatures( + CmsSignedData s) + { + VerifySignatures(s, null); + } + + [Test] + public void TestDetachedVerification() + { + byte[] data = Encoding.ASCII.GetBytes("Hello World!"); + CmsProcessable msg = new CmsProcessableByteArray(data); + + IList certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5); + + gen.AddCertificates(x509Certs); + + CmsSignedData s = gen.Generate(msg); + + IDictionary hashes = new Hashtable(); + hashes.Add(CmsSignedDataGenerator.DigestSha1, CalculateHash("SHA1", data)); + hashes.Add(CmsSignedDataGenerator.DigestMD5, CalculateHash("MD5", data)); + + s = new CmsSignedData(hashes, s.GetEncoded()); + + VerifySignatures(s, null); + } + + private byte[] CalculateHash( + string digestName, + byte[] data) + { + IDigest digest = DigestUtilities.GetDigest(digestName); + digest.BlockUpdate(data, 0, data.Length); + return DigestUtilities.DoFinal(digest); + } + + [Test] + public void TestSha1AndMD5WithRsaEncapsulatedRepeated() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5); + + gen.AddCertificates(x509Certs); + + CmsSignedData s = gen.Generate(msg, true); + + s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded()))); + + x509Certs = s.GetCertificates("Collection"); + + SignerInformationStore signers = s.GetSignerInfos(); + + Assert.AreEqual(2, signers.Count); + + SignerID sid = null; + ICollection c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + sid = signer.SignerID; + + Assert.IsTrue(signer.Verify(cert)); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[signer.DigestAlgOid]; + + AttributeTable table = signer.SignedAttributes; + Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest]; + + Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets())); + } + + c = signers.GetSigners(sid); + + Assert.AreEqual(2, c.Count); + + // + // try using existing signer + // + + gen = new CmsSignedDataGenerator(); + + gen.AddSigners(s.GetSignerInfos()); + + gen.AddCertificates(s.GetCertificates("Collection")); + gen.AddCrls(s.GetCrls("Collection")); + + s = gen.Generate(msg, true); + + s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded()))); + + x509Certs = s.GetCertificates("Collection"); + + signers = s.GetSignerInfos(); + c = signers.GetSigners(); + + Assert.AreEqual(2, c.Count); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.AreEqual(true, signer.Verify(cert)); + } + + CheckSignerStoreReplacement(s, signers); + } + + // NB: C# build doesn't support "no attributes" version of CmsSignedDataGenerator.Generate +// [Test] +// public void TestSha1WithRsaNoAttributes() +// { +// IList certList = new ArrayList(); +// CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello world!")); +// +// certList.Add(OrigCert); +// certList.Add(SignCert); +// +// IX509Store x509Certs = X509StoreFactory.Create( +// "Certificate/Collection", +// new X509CollectionStoreParameters(certList)); +// +// CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); +// +// gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); +// +// gen.AddCertificates(x509Certs); +// +// CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false); +// +// // +// // compute expected content digest +// // +// IDigest md = DigestUtilities.GetDigest("SHA1"); +// +// byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!"); +// md.BlockUpdate(testBytes, 0, testBytes.Length); +// byte[] hash = DigestUtilities.DoFinal(md); +// +// VerifySignatures(s, hash); +// } + + [Test] + public void TestSha1WithRsaAndAttributeTable() + { + byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!"); + + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(testBytes); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + IDigest md = DigestUtilities.GetDigest("SHA1"); + md.BlockUpdate(testBytes, 0, testBytes.Length); + byte[] hash = DigestUtilities.DoFinal(md); + + Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest, + new DerSet(new DerOctetString(hash))); + + Asn1EncodableVector v = new Asn1EncodableVector(attr); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1, + new AttributeTable(v), null); + + gen.AddCertificates(x509Certs); + + CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, null, false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CmsSignedData(msg, s.GetEncoded()); + + // + // compute expected content digest + // + VerifySignatures(s, hash); + } + + [Test] + public void TestSha1WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestSha1WithRsaEncapsulatedSubjectKeyID() + { + SubjectKeyIDTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestSha1WithRsaPss() + { + rsaPssTest("SHA1", CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestSha224WithRsaPss() + { + rsaPssTest("SHA224", CmsSignedDataGenerator.DigestSha224); + } + + [Test] + public void TestSha256WithRsaPss() + { + rsaPssTest("SHA256", CmsSignedDataGenerator.DigestSha256); + } + + [Test] + public void TestSha384WithRsaPss() + { + rsaPssTest("SHA384", CmsSignedDataGenerator.DigestSha384); + } + + [Test] + public void TestSha224WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha224); + } + + [Test] + public void TestSha256WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha256); + } + + [Test] + public void TestRipeMD128WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD128); + } + + [Test] + public void TestRipeMD160WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD160); + } + + [Test] + public void TestRipeMD256WithRsaEncapsulated() + { + EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD256); + } + + [Test] + public void TestECDsaEncapsulated() + { + EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestECDsaEncapsulatedSubjectKeyID() + { + SubjectKeyIDTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestECDsaSha224Encapsulated() + { + EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha224); + } + + [Test] + public void TestECDsaSha256Encapsulated() + { + EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha256); + } + + [Test] + public void TestECDsaSha384Encapsulated() + { + EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha384); + } + + [Test] + public void TestECDsaSha512Encapsulated() + { + EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha512); + } + + [Test] + public void TestECDsaSha512EncapsulatedWithKeyFactoryAsEC() + { +// X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(_signEcDsaKP.getPublic().getEncoded()); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(SignECDsaKP.Public).GetDerEncoded(); +// PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(_signEcDsaKP.Private.getEncoded()); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(SignECDsaKP.Private).GetDerEncoded(); +// KeyFactory keyFact = KeyFactory.GetInstance("EC", "BC"); +// KeyPair kp = new KeyPair(keyFact.generatePublic(pubSpec), keyFact.generatePrivate(privSpec)); + AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair( + PublicKeyFactory.CreateKey(pubEnc), + PrivateKeyFactory.CreateKey(privEnc)); + + EncapsulatedTest(kp, SignECDsaCert, CmsSignedDataGenerator.DigestSha512); + } + + [Test] + public void TestDsaEncapsulated() + { + EncapsulatedTest(SignDsaKP, SignDsaCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestDsaEncapsulatedSubjectKeyID() + { + SubjectKeyIDTest(SignDsaKP, SignDsaCert, CmsSignedDataGenerator.DigestSha1); + } + + [Test] + public void TestGost3411WithGost3410Encapsulated() + { + EncapsulatedTest(SignGostKP, SignGostCert, CmsSignedDataGenerator.DigestGost3411); + } + + [Test] + public void TestGost3411WithECGost3410Encapsulated() + { + EncapsulatedTest(SignECGostKP, SignECGostCert, CmsSignedDataGenerator.DigestGost3411); + } + + [Test] + public void TestSha1WithRsaCounterSignature() + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(SignCert); + certList.Add(OrigCert); + + crlList.Add(SignCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(SignKP.Private, SignCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + CmsSignedData s = gen.Generate(msg, true); + SignerInformation origSigner = (SignerInformation) new ArrayList(s.GetSignerInfos().GetSigners())[0]; + SignerInformationStore counterSigners1 = gen.GenerateCounterSigners(origSigner); + SignerInformationStore counterSigners2 = gen.GenerateCounterSigners(origSigner); + + SignerInformation signer1 = SignerInformation.AddCounterSigners(origSigner, counterSigners1); + SignerInformation signer2 = SignerInformation.AddCounterSigners(signer1, counterSigners2); + + SignerInformationStore cs = signer2.GetCounterSignatures(); + ICollection csSigners = cs.GetSigners(); + Assert.AreEqual(2, csSigners.Count); + + foreach (SignerInformation cSigner in csSigners) + { + ICollection certCollection = x509Certs.GetMatches(cSigner.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsNull(cSigner.SignedAttributes[Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtContentType]); + Assert.IsTrue(cSigner.Verify(cert)); + } + } + + private void rsaPssTest( + string digestName, + string digestOID) + { + IList certList = new ArrayList(); + byte[] msgBytes = Encoding.ASCII.GetBytes("Hello World!"); + CmsProcessable msg = new CmsProcessableByteArray(msgBytes); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.EncryptionRsaPss, digestOID); + + gen.AddCertificates(x509Certs); + + CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false); + + // + // compute expected content digest + // + IDigest md = DigestUtilities.GetDigest(digestName); + md.BlockUpdate(msgBytes, 0, msgBytes.Length); + byte[] expectedDigest = DigestUtilities.DoFinal(md); + + VerifySignatures(s, expectedDigest); + } + + private void SubjectKeyIDTest( + AsymmetricCipherKeyPair signaturePair, + X509Certificate signatureCert, + string digestAlgorithm) + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(signatureCert); + certList.Add(OrigCert); + + crlList.Add(SignCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(signaturePair.Private, + CmsTestUtil.CreateSubjectKeyId(signatureCert.GetPublicKey()).GetKeyIdentifier(), + digestAlgorithm); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + CmsSignedData s = gen.Generate(msg, true); + + Assert.AreEqual(3, s.Version); + + MemoryStream bIn = new MemoryStream(s.GetEncoded(), false); + Asn1InputStream aIn = new Asn1InputStream(bIn); + + s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject())); + + x509Certs = s.GetCertificates("Collection"); + x509Crls = s.GetCrls("Collection"); + + SignerInformationStore signers = s.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + + // + // check for CRLs + // + ArrayList crls = new ArrayList(x509Crls.GetMatches(null)); + + Assert.AreEqual(1, crls.Count); + + Assert.IsTrue(crls.Contains(SignCrl)); + + // + // try using existing signer + // + + gen = new CmsSignedDataGenerator(); + + gen.AddSigners(s.GetSignerInfos()); + + gen.AddCertificates(s.GetCertificates("Collection")); + gen.AddCrls(s.GetCrls("Collection")); + + s = gen.Generate(msg, true); + + bIn = new MemoryStream(s.GetEncoded(), false); + aIn = new Asn1InputStream(bIn); + + s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject())); + + x509Certs = s.GetCertificates("Collection"); + x509Crls = s.GetCrls("Collection"); + + signers = s.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + + CheckSignerStoreReplacement(s, signers); + } + + private void EncapsulatedTest( + AsymmetricCipherKeyPair signaturePair, + X509Certificate signatureCert, + string digestAlgorithm) + { + IList certList = new ArrayList(); + IList crlList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(signatureCert); + certList.Add(OrigCert); + + crlList.Add(SignCrl); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509Crls = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(signaturePair.Private, signatureCert, digestAlgorithm); + + gen.AddCertificates(x509Certs); + gen.AddCrls(x509Crls); + + CmsSignedData s = gen.Generate(msg, true); + + s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded()))); + + x509Certs = s.GetCertificates("Collection"); + x509Crls = s.GetCrls("Collection"); + + SignerInformationStore signers = s.GetSignerInfos(); + ICollection c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + + // + // check for CRLs + // + ArrayList crls = new ArrayList(x509Crls.GetMatches(null)); + + Assert.AreEqual(1, crls.Count); + + Assert.IsTrue(crls.Contains(SignCrl)); + + // + // try using existing signer + // + + gen = new CmsSignedDataGenerator(); + + gen.AddSigners(s.GetSignerInfos()); + + gen.AddCertificates(s.GetCertificates("Collection")); + gen.AddCrls(s.GetCrls("Collection")); + + s = gen.Generate(msg, true); + + s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded()))); + + x509Certs = s.GetCertificates("Collection"); + x509Crls = s.GetCrls("Collection"); + + signers = s.GetSignerInfos(); + c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + + CheckSignerStoreReplacement(s, signers); + } + + // + // signerInformation store replacement test. + // + private void CheckSignerStoreReplacement( + CmsSignedData orig, + SignerInformationStore signers) + { + CmsSignedData s = CmsSignedData.ReplaceSigners(orig, signers); + + IX509Store x509Certs = s.GetCertificates("Collection"); + + signers = s.GetSignerInfos(); + ICollection c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + } + + [Test] + public void TestUnsortedAttributes() + { + CmsSignedData s = new CmsSignedData(new CmsProcessableByteArray(disorderedMessage), disorderedSet); + + IX509Store x509Certs = s.GetCertificates("Collection"); + + SignerInformationStore signers = s.GetSignerInfos(); + ICollection c = signers.GetSigners(); + + foreach (SignerInformation signer in c) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate) certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + } + + [Test] + public void TestNullContentWithSigner() + { + IList certList = new ArrayList(); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData s = gen.Generate(null, false); + + s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded()))); + + VerifySignatures(s); + } + + [Test] + public void TestWithAttributeCertificate() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(SignDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate(); + + ArrayList attrCerts = new ArrayList(); + attrCerts.Add(attrCert); + + IX509Store store = X509StoreFactory.Create( + "AttributeCertificate/Collection", + new X509CollectionStoreParameters(attrCerts)); + + gen.AddAttributeCertificates(store); + + CmsSignedData sd = gen.Generate(msg); + + Assert.AreEqual(4, sd.Version); + + store = sd.GetAttributeCertificates("Collection"); + + ArrayList coll = new ArrayList(store.GetMatches(null)); + + Assert.AreEqual(1, coll.Count); + + Assert.IsTrue(coll.Contains(attrCert)); + + // + // create new certstore + // + certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // replace certs + // + sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null); + + VerifySignatures(sd); + } + + [Test] + public void TestCertStoreReplacement() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(SignDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData sd = gen.Generate(msg); + + // + // create new certstore + // + certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // replace certs + // + sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null); + + VerifySignatures(sd); + } + + [Test] + public void TestEncapsulatedCertStoreReplacement() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(SignDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData sd = gen.Generate(msg, true); + + // + // create new certstore + // + certList = new ArrayList(); + certList.Add(OrigCert); + certList.Add(SignCert); + + x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // + // replace certs + // + sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null); + + VerifySignatures(sd); + } + + [Test] + public void TestCertOrdering1() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(OrigCert); + certList.Add(SignCert); + certList.Add(SignDsaCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData sd = gen.Generate(msg, true); + + x509Certs = sd.GetCertificates("Collection"); + ArrayList a = new ArrayList(x509Certs.GetMatches(null)); + + Assert.AreEqual(3, a.Count); + Assert.AreEqual(OrigCert, a[0]); + Assert.AreEqual(SignCert, a[1]); + Assert.AreEqual(SignDsaCert, a[2]); + } + + [Test] + public void TestCertOrdering2() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(SignCert); + certList.Add(SignDsaCert); + certList.Add(OrigCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData sd = gen.Generate(msg, true); + + x509Certs = sd.GetCertificates("Collection"); + ArrayList a = new ArrayList(x509Certs.GetMatches(null)); + + Assert.AreEqual(3, a.Count); + Assert.AreEqual(SignCert, a[0]); + Assert.AreEqual(SignDsaCert, a[1]); + Assert.AreEqual(OrigCert, a[2]); + } + + [Test] + public void TestSignerStoreReplacement() + { + IList certList = new ArrayList(); + CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!")); + + certList.Add(OrigCert); + certList.Add(SignCert); + + IX509Store x509Certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + CmsSignedDataGenerator gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1); + + gen.AddCertificates(x509Certs); + + CmsSignedData original = gen.Generate(msg, true); + + // + // create new Signer + // + gen = new CmsSignedDataGenerator(); + + gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha224); + + gen.AddCertificates(x509Certs); + + CmsSignedData newSD = gen.Generate(msg, true); + + // + // replace signer + // + CmsSignedData sd = CmsSignedData.ReplaceSigners(original, newSD.GetSignerInfos()); + + IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator(); + signerEnum.MoveNext(); + SignerInformation signer = (SignerInformation) signerEnum.Current; + + Assert.AreEqual(CmsSignedDataGenerator.DigestSha224, signer.DigestAlgOid); + + // we use a parser here as it requires the digests to be correct in the digest set, if it + // isn't we'll get a NullPointerException + CmsSignedDataParser sp = new CmsSignedDataParser(sd.GetEncoded()); + + sp.GetSignedContent().Drain(); + + VerifySignatures(sp); + } + + [Test] + public void TestEncapsulatedSamples() + { + doTestSample("PSSSignDataSHA1Enc.sig"); + doTestSample("PSSSignDataSHA256Enc.sig"); + doTestSample("PSSSignDataSHA512Enc.sig"); + } + + [Test] + public void TestSamples() + { + doTestSample("PSSSignData.data", "PSSSignDataSHA1.sig"); + doTestSample("PSSSignData.data", "PSSSignDataSHA256.sig"); + doTestSample("PSSSignData.data", "PSSSignDataSHA512.sig"); + } + + [Test] + public void TestCounterSig() + { + CmsSignedData sig = new CmsSignedData(GetInput("counterSig.p7m")); + + SignerInformationStore ss = sig.GetSignerInfos(); + ArrayList signers = new ArrayList(ss.GetSigners()); + + SignerInformationStore cs = ((SignerInformation)signers[0]).GetCounterSignatures(); + ArrayList csSigners = new ArrayList(cs.GetSigners()); + Assert.AreEqual(1, csSigners.Count); + + foreach (SignerInformation cSigner in csSigners) + { + ArrayList certCollection = new ArrayList( + sig.GetCertificates("Collection").GetMatches(cSigner.SignerID)); + + X509Certificate cert = (X509Certificate)certCollection[0]; + + Assert.IsNull(cSigner.SignedAttributes[Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtContentType]); + Assert.IsTrue(cSigner.Verify(cert)); + } + + VerifySignatures(sig); + } + + private void doTestSample( + string sigName) + { + CmsSignedData sig = new CmsSignedData(GetInput(sigName)); + VerifySignatures(sig); + } + + private void doTestSample( + string messageName, + string sigName) + { + CmsSignedData sig = new CmsSignedData( + new CmsProcessableByteArray(GetInput(messageName)), + GetInput(sigName)); + + VerifySignatures(sig); + } + + private byte[] GetInput( + string name) + { + return Streams.ReadAll(SimpleTest.GetTestDataAsStream("cms.sigs." + name)); + } + + [Test] + public void TestForMultipleCounterSignatures() + { + CmsSignedData sd = new CmsSignedData(xtraCounterSig); + + foreach (SignerInformation sigI in sd.GetSignerInfos().GetSigners()) + { + SignerInformationStore counter = sigI.GetCounterSignatures(); + IList sigs = new ArrayList(counter.GetSigners()); + + Assert.AreEqual(2, sigs.Count); + } + } + + private void VerifySignatures( + CmsSignedDataParser sp) + { + IX509Store x509Certs = sp.GetCertificates("Collection"); + SignerInformationStore signers = sp.GetSignerInfos(); + + foreach (SignerInformation signer in signers.GetSigners()) + { + ICollection certCollection = x509Certs.GetMatches(signer.SignerID); + + IEnumerator certEnum = certCollection.GetEnumerator(); + certEnum.MoveNext(); + X509Certificate cert = (X509Certificate)certEnum.Current; + + Assert.IsTrue(signer.Verify(cert)); + } + } + } +} diff --git a/crypto/test/src/crypto/examples/DESExample.cs b/crypto/test/src/crypto/examples/DESExample.cs new file mode 100644 index 000000000..c026d3159 --- /dev/null +++ b/crypto/test/src/crypto/examples/DESExample.cs @@ -0,0 +1,396 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Examples +{ + /** + * DesExample is a simple DES based encryptor/decryptor. + *

    + * The program is command line driven, with the input + * and output files specified on the command line. + *

    +	* java org.bouncycastle.crypto.examples.DesExample infile outfile [keyfile]
    +	* 
    + * 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. + *

    + *

    + * When encrypting; + *

      + *
    • the infile is expected to be a byte stream (text or binary)
    • + *
    • there is no keyfile specified on the input line
    • + *
    + *

    + *

    + * When decrypting; + *

  • the infile is expected to be the 60 character wide base64 + * encoded file
  • + *
  • the keyfile is expected to be a base64 encoded file
  • + *

    + *

    + * This example shows how to use the light-weight API, DES and + * the filesystem for message encryption and decryption. + *

    + */ + public class DesExample + { + // Encrypting or decrypting ? + private bool encrypt = true; + + // To hold the initialised DESede cipher + private PaddedBufferedBlockCipher cipher = null; + + // The input stream of bytes to be processed for encryption + private Stream inStr = null; + + // The output stream of bytes to be procssed + private Stream outStr = null; + + // The key + private byte[] key = null; + + /* + * start the application + */ + public static int Main( + string[] args) + { + bool encrypt = true; + string infile = null; + string outfile = null; + string keyfile = null; + + if (args.Length < 2) + { +// Console.Error.WriteLine("Usage: java " + typeof(DesExample).Name + " infile outfile [keyfile]"); + Console.Error.WriteLine("Usage: " + typeof(DesExample).Name + " infile outfile [keyfile]"); + return 1; + } + + keyfile = "deskey.dat"; + infile = args[0]; + outfile = args[1]; + + if (args.Length > 2) + { + encrypt = false; + keyfile = args[2]; + } + + try + { + DesExample de = new DesExample(infile, outfile, keyfile, encrypt); + de.process(); + } + catch (Exception) + { + return 1; + } + + return 0; + } + + // 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, + bool 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 + { + inStr = File.OpenRead(infile); + } + catch (FileNotFoundException e) + { + Console.Error.WriteLine("Input file not found ["+infile+"]"); + throw e; + } + + try + { + outStr = File.Create(outfile); + } + catch (IOException e) + { + Console.Error.WriteLine("Output file not created ["+outfile+"]"); + throw e; + } + + 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 = new SecureRandom(); + + KeyGenerationParameters kgp = new KeyGenerationParameters( + sr, + DesEdeParameters.DesEdeKeyLength * 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 + */ + using (Stream keystream = File.Create(keyfile)) + { + Hex.Encode(key, keystream); + } + } + catch (IOException e) + { + Console.Error.WriteLine("Could not decryption create key file "+ + "["+keyfile+"]"); + throw e; + } + } + else + { + try + { + // TODO This block is a bit dodgy + + // read the key, and Decode from hex encoding + Stream keystream = File.OpenRead(keyfile); +// int len = keystream.available(); + int len = (int) keystream.Length; + byte[] keyhex = new byte[len]; + keystream.Read(keyhex, 0, len); + key = Hex.Decode(keyhex); + } + catch (IOException e) + { + Console.Error.WriteLine("Decryption key file not found, " + + "or not valid ["+keyfile+"]"); + throw e; + } + } + } + + 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 + { + inStr.Close(); + outStr.Flush(); + outStr.Close(); + } + catch (IOException) + { + } + } + + /* + * 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; + while ((inL = inStr.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) + { + Hex.Encode(outblock, 0, outL, outStr); + outStr.WriteByte((byte)'\n'); + } + } + + try + { + /* + * Now, process the bytes that are still buffered + * within the cipher. + */ + outL = cipher.DoFinal(outblock, 0); + if (outL > 0) + { + Hex.Encode(outblock, 0, outL, outStr); + outStr.WriteByte((byte) '\n'); + } + } + catch (CryptoException) + { + + } + } + catch (IOException ioeread) + { + Console.Error.WriteLine(ioeread.StackTrace); + } + } + + /* + * 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 StreamReader(inStr)); + StreamReader br = new StreamReader(inStr); // 'inStr' already buffered + + /* + * 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) + { + outStr.Write(outblock, 0, outL); + } + } + + try + { + /* + * Now, process the bytes that are still buffered + * within the cipher. + */ + outL = cipher.DoFinal(outblock, 0); + if (outL > 0) + { + outStr.Write(outblock, 0, outL); + } + } + catch (CryptoException) + { + + } + } + catch (IOException ioeread) + { + Console.Error.WriteLine(ioeread.StackTrace); + } + } + + } +} diff --git a/crypto/test/src/crypto/io/test/AllTests.cs b/crypto/test/src/crypto/io/test/AllTests.cs new file mode 100644 index 000000000..0296a2dc0 --- /dev/null +++ b/crypto/test/src/crypto/io/test/AllTests.cs @@ -0,0 +1,27 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.IO.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { +// junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("IO tests"); + + suite.Add(new CipherStreamTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/crypto/io/test/CipherStreamTest.cs b/crypto/test/src/crypto/io/test/CipherStreamTest.cs new file mode 100644 index 000000000..8f03c5770 --- /dev/null +++ b/crypto/test/src/crypto/io/test/CipherStreamTest.cs @@ -0,0 +1,166 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.IO.Tests +{ + [TestFixture] + public class CipherStreamTest + { + private const string DATA = "This will be encrypted and then decrypted and checked for correctness"; + + [Test] + public void TestEncryptDecryptA() + { + byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); + byte[] encryptedDataBytes = encryptOnWrite(dataBytes); + + byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes); + string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); + Assert.AreEqual(DATA, decryptedData); + } + + [Test] + public void TestEncryptDecryptB() + { + byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); + byte[] encryptedDataBytes = encryptOnRead(dataBytes); + + byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes); + string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); + Assert.AreEqual(DATA, decryptedData); + } + + [Test] + public void TestEncryptDecryptC() + { + byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); + byte[] encryptedDataBytes = encryptOnWrite(dataBytes); + + byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes); + string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); + Assert.AreEqual(DATA, decryptedData); + } + + [Test] + public void TestEncryptDecryptD() + { + byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); + byte[] encryptedDataBytes = encryptOnRead(dataBytes); + + byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes); + string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); + Assert.AreEqual(DATA, decryptedData); + } + + private byte[] encryptOnWrite(byte[] dataBytes) + { + MemoryStream encryptedDataStream = new MemoryStream(); + IBufferedCipher outCipher = createCipher(true); + CipherStream outCipherStream = new CipherStream(encryptedDataStream, null, outCipher); + outCipherStream.Write(dataBytes, 0, dataBytes.Length); + Assert.AreEqual(0L, encryptedDataStream.Position % outCipher.GetBlockSize()); + + outCipherStream.Close(); + byte[] encryptedDataBytes = encryptedDataStream.ToArray(); + Assert.AreEqual(dataBytes.Length, encryptedDataBytes.Length); + + return encryptedDataBytes; + } + + private byte[] encryptOnRead(byte[] dataBytes) + { + MemoryStream dataStream = new MemoryStream(dataBytes, false); + MemoryStream encryptedDataStream = new MemoryStream(); + IBufferedCipher inCipher = createCipher(true); + CipherStream inCipherStream = new CipherStream(dataStream, inCipher, null); + + int ch; + while ((ch = inCipherStream.ReadByte()) >= 0) + { + encryptedDataStream.WriteByte((byte) ch); + } + + encryptedDataStream.Close(); + inCipherStream.Close(); + + byte[] encryptedDataBytes = encryptedDataStream.ToArray(); + Assert.AreEqual(dataBytes.Length, encryptedDataBytes.Length); + + return encryptedDataBytes; + } + + private byte[] decryptOnRead(byte[] encryptedDataBytes) + { + MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false); + MemoryStream dataStream = new MemoryStream(); + IBufferedCipher inCipher = createCipher(false); + CipherStream inCipherStream = new CipherStream(encryptedDataStream, inCipher, null); + + int ch; + while ((ch = inCipherStream.ReadByte()) >= 0) + { + dataStream.WriteByte((byte) ch); + } + + inCipherStream.Close(); + dataStream.Close(); + + byte[] dataBytes = dataStream.ToArray(); + Assert.AreEqual(encryptedDataBytes.Length, dataBytes.Length); + + return dataBytes; + } + + private byte[] decryptOnWrite(byte[] encryptedDataBytes) + { + MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false); + MemoryStream dataStream = new MemoryStream(); + IBufferedCipher outCipher = createCipher(false); + CipherStream outCipherStream = new CipherStream(dataStream, null, outCipher); + + int ch; + while ((ch = encryptedDataStream.ReadByte()) >= 0) + { + outCipherStream.WriteByte((byte) ch); + } + + outCipherStream.Close(); + encryptedDataStream.Close(); + + byte[] dataBytes = dataStream.ToArray(); + Assert.AreEqual(encryptedDataBytes.Length, dataBytes.Length); + + return dataBytes; + } + + private IBufferedCipher createCipher(bool forEncryption) + { +// IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding"); + + IBlockCipher blockCipher = new AesEngine(); + int bits = 8 * blockCipher.GetBlockSize(); // TODO Is this right? + blockCipher = new CfbBlockCipher(blockCipher, bits); + IBufferedCipher cipher = new BufferedBlockCipher(blockCipher); + +// SecureRandom random = new SecureRandom(); + byte[] keyBytes = new byte[32]; + //random.NextBytes(keyBytes); + KeyParameter key = new KeyParameter(keyBytes); + + byte[] iv = new byte[cipher.GetBlockSize()]; + //random.NextBytes(iv); + + cipher.Init(forEncryption, new ParametersWithIV(key, iv)); + + return cipher; + } + } +} diff --git a/crypto/test/src/crypto/test/AESFastTest.cs b/crypto/test/src/crypto/test/AESFastTest.cs new file mode 100644 index 000000000..5513a0e78 --- /dev/null +++ b/crypto/test/src/crypto/test/AESFastTest.cs @@ -0,0 +1,168 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test vectors from the NIST standard tests and Brian Gladman's vector set + * + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + */ + [TestFixture] + public class AesFastTest + : 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 IBlockCipher _engine = new AesFastEngine(); + + public AesFastTest() + : base(tests, new AesFastEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get + { + return "AESFast"; + } + } + + public override void PerformTest() + { + base.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 (ArgumentException) + { + // expected + } + + try + { + byte[] iv = new byte[16]; + + _engine.Init(true, new ParametersWithIV(null, iv)); + + Fail("failed parameter check"); + } + catch (ArgumentException) + { + // expected + } + } + + public static void Main( + string[] args) + { + AesFastTest test = new AesFastTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/AESLightTest.cs b/crypto/test/src/crypto/test/AESLightTest.cs new file mode 100644 index 000000000..0b5777ba1 --- /dev/null +++ b/crypto/test/src/crypto/test/AESLightTest.cs @@ -0,0 +1,168 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test vectors from the NIST standard tests and Brian Gladman's vector set + * + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + */ + [TestFixture] + public class AesLightTest + : 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 IBlockCipher _engine = new AesLightEngine(); + + public AesLightTest() + : base(tests, new AesLightEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get + { + return "AESLight"; + } + } + + public override void PerformTest() + { + base.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 (ArgumentException) + { + // expected + } + + try + { + byte[] iv = new byte[16]; + + _engine.Init(true, new ParametersWithIV(null, iv)); + + Fail("failed parameter check"); + } + catch (ArgumentException) + { + // expected + } + } + + public static void Main( + string[] args) + { + AesLightTest test = new AesLightTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/AESTest.cs b/crypto/test/src/crypto/test/AESTest.cs new file mode 100644 index 000000000..7b8fc34cf --- /dev/null +++ b/crypto/test/src/crypto/test/AESTest.cs @@ -0,0 +1,178 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Test vectors from the NIST standard tests and Brian Gladman's vector set + /// + /// http://fp.gladman.plus.com/cryptography_technology/rijndael/ + /// + [TestFixture] + public class AesTest : CipherTest + { + internal static SimpleTest[] tests = new SimpleTest[]{ + 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")}; + + public override string Name { get { return "AES"; } } + + public AesTest() + : base(tests, new AesEngine(), new KeyParameter(new byte[16])) + { + } + + private ITestResult WrapTest(int id, byte[] kek, byte[] input, byte[] outBytes) + { + IWrapper wrapper = new AesWrapEngine(); + + wrapper.Init(true, new KeyParameter(kek)); + + try + { + byte[] cText = wrapper.Wrap(input, 0, input.Length); + + if (!Arrays.AreEqual(cText, outBytes)) + { + return new SimpleTestResult(false, Name + ": failed wrap test " + id + + " expected " + Hex.ToHexString(outBytes) + + " got " + Hex.ToHexString(cText)); + } + } + catch (System.Exception e) + { + return new SimpleTestResult(false, Name + ": failed wrap test exception " + e.ToString()); + } + + wrapper.Init(false, new KeyParameter(kek)); + + try + { + byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length); + if (!Arrays.AreEqual(pText, input)) + { + return new SimpleTestResult(false, Name + ": failed unwrap test " + id + + " expected " + Hex.ToHexString(input) + + " got " + Hex.ToHexString(pText)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed unwrap test exception.", e); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public override ITestResult Perform() + { + ITestResult result = base.Perform(); + if (!result.IsSuccessful()) + { + return result; + } + + byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff"); + byte[] out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5"); + 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; + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + AesTest test = new AesTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/AESWrapTest.cs b/crypto/test/src/crypto/test/AESWrapTest.cs new file mode 100644 index 000000000..11b46098e --- /dev/null +++ b/crypto/test/src/crypto/test/AESWrapTest.cs @@ -0,0 +1,214 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Wrap Test + */ + [TestFixture] + public class AesWrapTest + : ITest + { + public string Name + { + get + { + return "AESWrap"; + } + } + + private ITestResult wrapTest( + int id, + byte[] kek, + byte[] inBytes, + byte[] outBytes) + { + IWrapper wrapper = new AesWrapEngine(); + + wrapper.Init(true, new KeyParameter(kek)); + + try + { + byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length); + if (!Arrays.AreEqual(cText, outBytes)) + { + return new SimpleTestResult(false, Name + ": failed wrap test " + id + + " expected " + Hex.ToHexString(outBytes) + + " got " + Hex.ToHexString(cText)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed wrap test exception " + e); + } + + wrapper.Init(false, new KeyParameter(kek)); + + try + { + byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length); + if (!Arrays.AreEqual(pText, inBytes)) + { + return new SimpleTestResult(false, Name + ": failed unwrap test " + id + + " expected " + Hex.ToHexString(inBytes) + + " got " + Hex.ToHexString(pText)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed unwrap test exception.", e); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public ITestResult Perform() + { + byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff"); + byte[] out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5"); + ITestResult 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; + } + + IWrapper 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, Name + ": failed unwrap state test."); + } + catch (InvalidOperationException) + { + // expected + } + catch (InvalidCipherTextException e) + { + return new SimpleTestResult(false, Name + ": unexpected exception: " + e, e); + } + + try + { + wrapper.Init(false, key); + + wrapper.Wrap(buf, 0, buf.Length); + + return new SimpleTestResult(false, Name + ": failed unwrap state test."); + } + catch (InvalidOperationException) + { + // expected + } + + // + // short test + // + try + { + wrapper.Init(false, key); + + wrapper.Unwrap(buf, 0, buf.Length / 2); + + return new SimpleTestResult(false, Name + ": failed unwrap short test."); + } + catch (InvalidCipherTextException) + { + // expected + } + + try + { + wrapper.Init(true, key); + + wrapper.Wrap(buf, 0, 15); + + return new SimpleTestResult(false, Name + ": failed wrap length test."); + } + catch (DataLengthException) + { + // expected + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + AesWrapTest test = new AesWrapTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/AllTests.cs b/crypto/test/src/crypto/test/AllTests.cs new file mode 100644 index 000000000..1cb1b965d --- /dev/null +++ b/crypto/test/src/crypto/test/AllTests.cs @@ -0,0 +1,47 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class AllTests + { + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("Lightweight Crypto Tests"); + suite.Add(new AllTests()); + suite.Add(new GcmReorderTest()); + return suite; + } + } + + [Test] + public void TestCrypto() + { + foreach (Org.BouncyCastle.Utilities.Test.ITest test in RegressionTest.tests) + { + SimpleTestResult result = (SimpleTestResult)test.Perform(); + + if (!result.IsSuccessful()) + { + Assert.Fail(result.ToString()); + } + } + } + + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + Suite.Run(el); + } + } +} diff --git a/crypto/test/src/crypto/test/BlockCipherMonteCarloTest.cs b/crypto/test/src/crypto/test/BlockCipherMonteCarloTest.cs new file mode 100644 index 000000000..1a46a3201 --- /dev/null +++ b/crypto/test/src/crypto/test/BlockCipherMonteCarloTest.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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 + : SimpleTest + { + int id; + int iterations; + IBlockCipher engine; + ICipherParameters param; + byte[] input; + byte[] output; + + public BlockCipherMonteCarloTest( + int id, + int iterations, + IBlockCipher engine, + ICipherParameters 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 override string Name + { + get { return engine.AlgorithmName + " Monte Carlo Test " + id; } + } + + public override void PerformTest() + { + BufferedBlockCipher cipher = new BufferedBlockCipher(engine); + + cipher.Init(true, param); + + byte[] outBytes = new byte[input.Length]; + + Array.Copy(input, 0, outBytes, 0, outBytes.Length); + + for (int i = 0; i != iterations; i++) + { + int len1 = cipher.ProcessBytes(outBytes, 0, outBytes.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len1); + } + + if (!AreEqual(outBytes, output)) + { + Fail("failed - " + "expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes)); + } + + cipher.Init(false, param); + + for (int i = 0; i != iterations; i++) + { + int len1 = cipher.ProcessBytes(outBytes, 0, outBytes.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len1); + } + + if (!AreEqual(input, outBytes)) + { + Fail("failed reversal"); + } + } + } +} diff --git a/crypto/test/src/crypto/test/BlockCipherVectorTest.cs b/crypto/test/src/crypto/test/BlockCipherVectorTest.cs new file mode 100644 index 000000000..1ce9fa477 --- /dev/null +++ b/crypto/test/src/crypto/test/BlockCipherVectorTest.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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 + : SimpleTest + { + int id; + IBlockCipher engine; + ICipherParameters param; + byte[] input; + byte[] output; + + public BlockCipherVectorTest( + int id, + IBlockCipher engine, + ICipherParameters 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 override string Name + { + get + { + return engine.AlgorithmName + " Vector Test " + id; + } + } + + public override void PerformTest() + { + BufferedBlockCipher cipher = new BufferedBlockCipher(engine); + + cipher.Init(true, param); + + byte[] outBytes = new byte[input.Length]; + + int len1 = cipher.ProcessBytes(input, 0, input.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len1); + + if (!AreEqual(outBytes, output)) + { + Fail("failed - " + "expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes)); + } + + cipher.Init(false, param); + + int len2 = cipher.ProcessBytes(output, 0, output.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len2); + + if (!AreEqual(input, outBytes)) + { + Fail("failed reversal got " + Hex.ToHexString(outBytes)); + } + } + } +} diff --git a/crypto/test/src/crypto/test/BlowfishTest.cs b/crypto/test/src/crypto/test/BlowfishTest.cs new file mode 100644 index 000000000..780dd3abd --- /dev/null +++ b/crypto/test/src/crypto/test/BlowfishTest.cs @@ -0,0 +1,55 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Blowfish tester - vectors from http://www.counterpane.com/vectors.txt + [TestFixture] + public class BlowfishTest + : CipherTest + { + public override string Name + { + get { return "Blowfish"; } + } + + internal static SimpleTest[] tests = new SimpleTest[]{ + 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") + }; + + public BlowfishTest() + : base(tests, new BlowfishEngine(), new KeyParameter(new byte[16])) + { + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + ITest test = new BlowfishTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + } +} diff --git a/crypto/test/src/crypto/test/CAST6Test.cs b/crypto/test/src/crypto/test/CAST6Test.cs new file mode 100644 index 000000000..7517b6737 --- /dev/null +++ b/crypto/test/src/crypto/test/CAST6Test.cs @@ -0,0 +1,57 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Cast6 tester - vectors from http://www.ietf.org/rfc/rfc2612.txt + [TestFixture] + public class Cast6Test : CipherTest + { + public override string Name + { + get { return "CAST6"; } + } + + internal static SimpleTest[] tests = new SimpleTest[] + { + 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") + }; + + public Cast6Test() + : base(tests, new Cast6Engine(), new KeyParameter(new byte[16])) + { + } + + public static void Main( + string[] args) + { + ITest test = new Cast6Test(); + ITestResult result = test.Perform(); + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/CCMTest.cs b/crypto/test/src/crypto/test/CCMTest.cs new file mode 100644 index 000000000..4a54fb4f9 --- /dev/null +++ b/crypto/test/src/crypto/test/CCMTest.cs @@ -0,0 +1,268 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * First four test vectors from + * NIST Special Publication 800-38C. + */ + [TestFixture] + public class CcmTest + : 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 override void PerformTest() + { + 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) + { + Array.Copy(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); + + // + // 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) + { + // expected + } + + try + { + ccm = new CcmBlockCipher(new DesEngine()); + + Fail("incorrect block size not picked up"); + } + catch (ArgumentException) + { + // expected + } + + try + { + ccm.Init(false, new KeyParameter(K1)); + + Fail("illegal argument not picked up"); + } + catch (ArgumentException) + { + // expected + } + } + + private void checkVectors( + int count, + CcmBlockCipher ccm, + byte[] k, + int macSize, + byte[] n, + byte[] a, + byte[] p, + byte[] t, + byte[] c) + { + byte[] fa = new byte[a.Length / 2]; + byte[] la = new byte[a.Length - (a.Length / 2)]; + Array.Copy(a, 0, fa, 0, fa.Length); + Array.Copy(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) + { + 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); + +// ccm.Init(true, new AeadParameters(new KeyParameter(k), macSize, n, a)); +// +// byte[] enc = ccm.ProcessPacket(p, 0, p.Length); + + if (!AreEqual(c, enc)) + { + Fail("encrypted stream fails to match in test " + count + " with " + additionalDataType); + } + +// ccm.Init(false, new AeadParameters(new KeyParameter(k), macSize, n, a)); +// +// byte[] dec = ccm.ProcessPacket(enc, 0, enc.Length); + + ccm.Init(false, new AeadParameters(new KeyParameter(k), 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]; + + Array.Copy(tmp, 0, dec, 0, len); + + if (!AreEqual(p, dec)) + { + Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType); + } + + 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) + { + byte[] p = Encoding.ASCII.GetBytes("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]; + + Array.Copy(tmp, 0, dec, 0, len); + + if (!AreEqual(p, dec)) + { + Fail("decrypted stream fails to match in test " + count); + } + } + + public override string Name + { + get { return "CCM"; } + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + RunTest(new CcmTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/CMacTest.cs b/crypto/test/src/crypto/test/CMacTest.cs new file mode 100644 index 000000000..35f5735b9 --- /dev/null +++ b/crypto/test/src/crypto/test/CMacTest.cs @@ -0,0 +1,286 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * CMAC tester - Official Test Vectors. + */ + [TestFixture] + public class CMacTest + : SimpleTest + { + private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c"); + private static readonly byte[] keyBytes192 = Hex.Decode( + "8e73b0f7da0e6452c810f32b809079e5" + + "62f8ead2522c6b7b"); + private static readonly byte[] keyBytes256 = Hex.Decode( + "603deb1015ca71be2b73aef0857d7781" + + "1f352c073b6108d72d9810a30914dff4"); + + private static readonly byte[] input0 = Hex.Decode(""); + private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a"); + private static readonly byte[] input40 = Hex.Decode( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411"); + private static readonly byte[] input64 = Hex.Decode( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710"); + + private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746"); + private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c"); + private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827"); + private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe"); + + private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367"); + private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184"); + private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e"); + private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11"); + + private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983"); + private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c"); + private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6"); + private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410"); + + public CMacTest() + { + } + + public override void PerformTest() + { + IBlockCipher cipher = new AesFastEngine(); + IMac mac = new CMac(cipher, 128); + + //128 bytes key + + KeyParameter key = new KeyParameter(keyBytes128); + + // 0 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + byte[] outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k128_m0)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k128_m0) + " got " + + Hex.ToHexString(outBytes)); + } + + // 16 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k128_m16)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k128_m16) + " got " + + Hex.ToHexString(outBytes)); + } + + // 40 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k128_m40)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k128_m40) + " got " + + Hex.ToHexString(outBytes)); + } + + // 64 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k128_m64)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k128_m64) + " got " + + Hex.ToHexString(outBytes)); + } + + //192 bytes key + key = new KeyParameter(keyBytes192); + + // 0 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k192_m0)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k192_m0) + " got " + + Hex.ToHexString(outBytes)); + } + + // 16 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k192_m16)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k192_m16) + " got " + + Hex.ToHexString(outBytes)); + } + + // 40 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k192_m40)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k192_m40) + " got " + + Hex.ToHexString(outBytes)); + } + + // 64 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k192_m64)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k192_m64) + " got " + + Hex.ToHexString(outBytes)); + } + + //256 bytes key + + key = new KeyParameter(keyBytes256); + + // 0 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k256_m0)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k256_m0) + " got " + + Hex.ToHexString(outBytes)); + } + + // 16 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k256_m16)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k256_m16) + " got " + + Hex.ToHexString(outBytes)); + } + + // 40 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k256_m40)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k256_m40) + " got " + + Hex.ToHexString(outBytes)); + } + + // 64 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output_k256_m64)) + { + Fail("Failed - expected " + + Hex.ToHexString(output_k256_m64) + " got " + + Hex.ToHexString(outBytes)); + } + } + + public override string Name + { + get { return "CMac"; } + } + + public static void Main( + string[] args) + { + RunTest(new CMacTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/CTSTest.cs b/crypto/test/src/crypto/test/CTSTest.cs new file mode 100644 index 000000000..9d001bc68 --- /dev/null +++ b/crypto/test/src/crypto/test/CTSTest.cs @@ -0,0 +1,192 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// CTS tester + [TestFixture] + public class CTSTest : ITest + { + public string Name + { + get + { + return "CTS"; + } + } + + internal static byte[] in1; + + internal static byte[] in2; + + internal static byte[] out1; + + internal static byte[] out2; + + internal static byte[] out3; + + private class CTSTester : ITest + { + private void InitBlock(CTSTest enclosingInstance) + { + this.enclosingInstance = enclosingInstance; + } + private CTSTest enclosingInstance; + + public string Name + { + get + { + return "CTS"; + } + } + + public CTSTest Enclosing_Instance + { + get + { + return enclosingInstance; + } + + } + + private int id; + private IBlockCipher cipher; + private ICipherParameters parameters; + private byte[] input; + private byte[] output; + + internal CTSTester(CTSTest enclosingInstance, int id, IBlockCipher cipher, ICipherParameters parameters, byte[] input, byte[] output) + { + InitBlock(enclosingInstance); + this.id = id; + this.cipher = cipher; + this.parameters = parameters; + this.input = input; + this.output = output; + } + + public virtual ITestResult Perform() + { + byte[] outBytes = new byte[input.Length]; + BufferedBlockCipher engine = new CtsBlockCipher(cipher); + + engine.Init(true, parameters); + + int len = engine.ProcessBytes(input, 0, input.Length, outBytes, 0); + + try + { + engine.DoFinal(outBytes, len); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": encryption exception - " + e.ToString()); + } + + for (int i = 0; i != output.Length; i++) + { + if (outBytes[i] != output[i]) + { + return new SimpleTestResult(false, Name + ": failed encryption expected " + + Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes)); + } + } + + engine.Init(false, parameters); + + len = engine.ProcessBytes(output, 0, output.Length, outBytes, 0); + + try + { + engine.DoFinal(outBytes, len); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": decryption exception - " + e.ToString()); + } + + for (int i = 0; i != input.Length; i++) + { + if (outBytes[i] != input[i]) + { + return new SimpleTestResult(false, Name + ": failed encryption expected " + + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + } + + public CTSTest() + { + } + + public virtual ITestResult Perform() + { + byte[] key1 = new byte[]{(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + byte[] key2 = new byte[]{(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF, (byte) 0xee, (byte) 0xff }; + byte[] iv = new byte[]{1, 2, 3, 4, 5, 6, 7, 8}; + + ITest test = new CTSTester(this, 1, new DesEngine(), new KeyParameter(key1), in1, out1); + ITestResult result = test.Perform(); + + if (!result.IsSuccessful()) + { + return result; + } + + test = new CTSTester(this, 2, new CbcBlockCipher(new DesEngine()), new ParametersWithIV(new KeyParameter(key1), iv), in1, out2); + result = test.Perform(); + + if (!result.IsSuccessful()) + { + return result; + } + + test = new CTSTester(this, 3, new CbcBlockCipher(new SkipjackEngine()), new ParametersWithIV(new KeyParameter(key2), iv), in2, out3); + result = test.Perform(); + + if (!result.IsSuccessful()) + { + return result; + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + CTSTest test = new CTSTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + static CTSTest() + { + in1 = Hex.Decode("4e6f7720697320746865207420"); + in2 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa"); + out1 = Hex.Decode("9952f131588465033fa40e8a98"); + out2 = Hex.Decode("358f84d01eb42988dc34efb994"); + out3 = Hex.Decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6"); + } + } +} diff --git a/crypto/test/src/crypto/test/CamelliaLightTest.cs b/crypto/test/src/crypto/test/CamelliaLightTest.cs new file mode 100644 index 000000000..2247178f2 --- /dev/null +++ b/crypto/test/src/crypto/test/CamelliaLightTest.cs @@ -0,0 +1,80 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713 + */ + [TestFixture] + public class CamelliaLightTest + : 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"), + }; + + public CamelliaLightTest() + : base(tests, new CamelliaLightEngine(), new KeyParameter(new byte[32])) + { + } + + public override string Name + { + get { return "CamelliaLight"; } + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + RunTest(new CamelliaLightTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/CamelliaTest.cs b/crypto/test/src/crypto/test/CamelliaTest.cs new file mode 100644 index 000000000..a134546b7 --- /dev/null +++ b/crypto/test/src/crypto/test/CamelliaTest.cs @@ -0,0 +1,80 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713 + */ + [TestFixture] + public class CamelliaTest + : 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"), + }; + + public CamelliaTest() + : base(tests, new CamelliaEngine(), new KeyParameter(new byte[32])) + { + } + + public override string Name + { + get { return "Camellia"; } + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + RunTest(new CamelliaTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/Cast5Test.cs b/crypto/test/src/crypto/test/Cast5Test.cs new file mode 100644 index 000000000..ea2e0c540 --- /dev/null +++ b/crypto/test/src/crypto/test/Cast5Test.cs @@ -0,0 +1,49 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Cast tester - vectors from http://www.ietf.org/rfc/rfc2144.txt + [TestFixture] + public class Cast5Test + : CipherTest + { + public override string Name + { + get { return "Cast5"; } + } + + internal static SimpleTest[] testlist = new SimpleTest[]{ + 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")}; + + public Cast5Test() + : base(testlist , new Cast5Engine(), new KeyParameter(new byte[16])) + { + } + + public static void Main( + string[] args) + { + ITest test = new Cast5Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/CipherTest.cs b/crypto/test/src/crypto/test/CipherTest.cs new file mode 100644 index 000000000..a893e0239 --- /dev/null +++ b/crypto/test/src/crypto/test/CipherTest.cs @@ -0,0 +1,117 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + public abstract class CipherTest + : SimpleTest + { + private SimpleTest[] _tests; + private IBlockCipher _engine; + private KeyParameter _validKey; + +// protected CipherTest( +// SimpleTest[] tests) +// { +// _tests = tests; +// } + + protected CipherTest( + SimpleTest[] tests, + IBlockCipher engine, + KeyParameter validKey) + { + _tests = tests; + _engine = engine; + _validKey = validKey; + } + + public override void PerformTest() + { + for (int i = 0; i != _tests.Length; i++) + { + _tests[i].PerformTest(); + } + + if (_engine != null) + { + // + // state tests + // + byte[] buf = new byte[16]; + + try + { + _engine.ProcessBlock(buf, 0, buf, 0); + + Fail("failed initialisation check"); + } + catch (InvalidOperationException) + { + // expected + } + + bufferSizeCheck((_engine)); + } + } + + private void bufferSizeCheck( + IBlockCipher 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) + { + // expected + } + + try + { + engine.ProcessBlock(correctBuf, 0, shortBuf, 0); + + Fail("failed short output check"); + } + catch (DataLengthException) + { + // expected + } + + engine.Init(false, _validKey); + + try + { + engine.ProcessBlock(shortBuf, 0, correctBuf, 0); + + Fail("failed short input check"); + } + catch (DataLengthException) + { + // expected + } + + try + { + engine.ProcessBlock(correctBuf, 0, shortBuf, 0); + + Fail("failed short output check"); + } + catch (DataLengthException) + { + // expected + } + } + } +} diff --git a/crypto/test/src/crypto/test/DESTest.cs b/crypto/test/src/crypto/test/DESTest.cs new file mode 100644 index 000000000..cf1022eae --- /dev/null +++ b/crypto/test/src/crypto/test/DESTest.cs @@ -0,0 +1,214 @@ +using System; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tests +{ + internal class DesParityTest + : SimpleTest + { + public override string Name + { + get { return "DESParityTest"; } + } + + public override 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 " + Hex.ToHexString(k1In) + + " expected " + Hex.ToHexString(k1Out)); + } + } + + DesParameters.SetOddParity(k2In); + + for (int i = 0; i != k2In.Length; i++) + { + if (k2In[i] != k2Out[i]) + { + Fail("Failed " + + "got " + Hex.ToHexString(k2In) + + " expected " + Hex.ToHexString(k2Out)); + } + } + } + } + + internal class KeyGenTest + : SimpleTest + { + public override string Name + { + get { return "KeyGenTest"; } + } + + public override 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."); + } + } + } + + internal class DesParametersTest + : SimpleTest + { + private static readonly 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 override string Name + { + get { return "DesParameters"; } + } + + public override void PerformTest() + { + try + { + DesParameters.IsWeakKey(new byte[4], 0); + Fail("no exception on small key"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("key material too short.")) + { + Fail("wrong exception"); + } + } + + try + { + new DesParameters(weakKeys); + Fail("no exception on weak key"); + } + catch (ArgumentException e) + { + if (!e.Message.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 FIPS 81 + */ + [TestFixture] + public class DesTest + : CipherTest + { + static string input1 = "4e6f77206973207468652074696d6520666f7220616c6c20"; + static string input2 = "4e6f7720697320746865"; + static string input3 = "4e6f7720697320746865aabbcc"; + + static SimpleTest[] tests = + { + new BlockCipherVectorTest(0, new DesEngine(), + new DesParameters(Hex.Decode("0123456789abcdef")), + input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"), + new BlockCipherVectorTest(1, new CbcBlockCipher(new DesEngine()), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input1, "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"), + new BlockCipherVectorTest(2, new CfbBlockCipher(new DesEngine(), 8), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input2, "f31fda07011462ee187f"), + new BlockCipherVectorTest(3, new CfbBlockCipher(new DesEngine(), 64), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input1, "f3096249c7f46e51a69e839b1a92f78403467133898ea622"), + new BlockCipherVectorTest(4, new OfbBlockCipher(new DesEngine(), 8), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input2, "f34a2850c9c64985d684"), + new BlockCipherVectorTest(5, new CfbBlockCipher(new DesEngine(), 64), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input3, "f3096249c7f46e51a69e0954bf"), + new BlockCipherVectorTest(6, new OfbBlockCipher(new DesEngine(), 64), + new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")), + input3, "f3096249c7f46e5135f2c0eb8b"), + new DesParityTest(), + new DesParametersTest(), + new KeyGenTest() + }; + + public DesTest() + : base(tests, new DesEngine(), new DesParameters(new byte[8])) + { + } + + public override string Name + { + get { return "DES"; } + } + + public static void Main( + string[] args) + { + RunTest(new DesTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/DESedeTest.cs b/crypto/test/src/crypto/test/DESedeTest.cs new file mode 100644 index 000000000..aa61844f2 --- /dev/null +++ b/crypto/test/src/crypto/test/DESedeTest.cs @@ -0,0 +1,187 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ +/** + * DESede tester + */ + [TestFixture] + public class DesEdeTest + :CipherTest + { + private static readonly 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, + }; + + private const string input1 = "4e6f77206973207468652074696d6520666f7220616c6c20"; +// private const string input2 = "4e6f7720697320746865"; + + private 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") + }; + + public DesEdeTest() + : base(tests, new DesEdeEngine(), new DesEdeParameters(new byte[16])) + { + } + + private void WrapTest( + int id, + byte[] kek, + byte[] iv, + byte[] input, + byte[] output) + { + IWrapper wrapper = new DesEdeWrapEngine(); + + wrapper.Init(true, new ParametersWithIV(new DesEdeParameters(kek), iv)); + + try + { + byte[] cText = wrapper.Wrap(input, 0, input.Length); + if (!AreEqual(cText, output)) + { + Fail(": failed wrap test " + id + " expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(cText)); + } + } + catch (Exception e) + { + Fail("failed wrap test exception: " + e.ToString(), e); + } + + wrapper.Init(false, new DesEdeParameters(kek)); + + try + { + byte[] pText = wrapper.Unwrap(output, 0, output.Length); + if (!AreEqual(pText, input)) + { + Fail("failed unwrap test " + id + " expected " + Hex.ToHexString(input) + + " got " + Hex.ToHexString(pText)); + } + } + catch (Exception e) + { + Fail("failed unwrap test exception: " + e.ToString(), e); + } + } + + public override void PerformTest() + { + base.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 (ArgumentException) + { + // expected + } + + try + { + DesEdeParameters.IsWeakKey(new byte[4], 0); + Fail("no exception on small key"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("key material too short.")) + { + Fail("wrong exception"); + } + } + + try + { + new DesEdeParameters(weakKey); + Fail("no exception on weak key"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("attempt to create weak DESede key")) + { + Fail("wrong exception"); + } + } + } + + public override string Name + { + get { return "DESede"; } + } + + public static void Main( + string[] args) + { + RunTest(new DesEdeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/DHKEKGeneratorTest.cs b/crypto/test/src/crypto/test/DHKEKGeneratorTest.cs new file mode 100644 index 000000000..eee408f97 --- /dev/null +++ b/crypto/test/src/crypto/test/DHKEKGeneratorTest.cs @@ -0,0 +1,79 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto.Agreement.Kdf; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// DHKEK Generator tests - from RFC 2631. + [TestFixture] + public class DHKekGeneratorTest + : SimpleTest + { + private byte[] seed1 = Hex.Decode("000102030405060708090a0b0c0d0e0f10111213"); + private DerObjectIdentifier alg1 = PkcsObjectIdentifiers.IdAlgCms3DesWrap; + private byte[] result1 = Hex.Decode("a09661392376f7044d9052a397883246b67f5f1ef63eb5fb"); + + private byte[] seed2 = Hex.Decode("000102030405060708090a0b0c0d0e0f10111213"); + private DerObjectIdentifier alg2 = PkcsObjectIdentifiers.IdAlgCmsRC2Wrap; + private byte[] partyAInfo = Hex.Decode( + "0123456789abcdeffedcba9876543201" + + "0123456789abcdeffedcba9876543201" + + "0123456789abcdeffedcba9876543201" + + "0123456789abcdeffedcba9876543201"); + private byte[] result2 = Hex.Decode("48950c46e0530075403cce72889604e0"); + + public DHKekGeneratorTest() + { + } + + public override 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, + IDerivationFunction kdf, + IDerivationParameters parameters, + byte[] result) + { + byte[] data = new byte[result.Length]; + + kdf.Init(parameters); + + kdf.GenerateBytes(data, 0, data.Length); + + if (!AreEqual(result, data)) + { + Fail("DHKekGenerator failed generator test " + count); + } + } + + public override string Name + { + get { return "DHKekGenerator"; } + } + + public static void Main( + string[] args) + { + RunTest(new DHKekGeneratorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/DHTest.cs b/crypto/test/src/crypto/test/DHTest.cs new file mode 100644 index 000000000..b460f41a5 --- /dev/null +++ b/crypto/test/src/crypto/test/DHTest.cs @@ -0,0 +1,403 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class DHTest + : SimpleTest + { + private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16); + private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16); + + private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16); + private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16); + + public override string Name + { + get { return "DH"; } + } + + private void doTestDH( + int size, + BigInteger g, + BigInteger p) + { + DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g, p); + + // + // generate first pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + // + // generate second pair + // + pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private; + + // + // 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 doTestDHBasic( + 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.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + + checkKeySize(privateValueSize, pv1); + // + // generate second pair + // + pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private; + + 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.X.BitLength != privateValueSize) + { + Fail("limited key check failed for key size " + privateValueSize); + } + } + } + + private void doTestGPWithRandom( + DHKeyPairGenerator kpGen) + { + // + // generate first pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + // + // generate second pair + // + pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private; + + // + // 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 doTestSimpleWithRandom( + DHBasicKeyPairGenerator kpGen) + { + // + // generate first pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + // + // generate second pair + // + pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private; + + // + // 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 dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams); + DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator(); + + kpGen.Init(dhkgParams); + + return kpGen; + } + + private DHKeyPairGenerator getDHKeyPairGenerator( + BigInteger g, + BigInteger p) + { + DHParameters dhParams = new DHParameters(p, g); + DHKeyGenerationParameters dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams); + DHKeyPairGenerator kpGen = new DHKeyPairGenerator(); + + kpGen.Init(dhkgParams); + + return kpGen; + } + + /** + * this test is can take quiet a while + */ + private void doTestGeneration( + int size) + { + DHParametersGenerator pGen = new DHParametersGenerator(); + + pGen.Init(size, 10, new SecureRandom()); + + DHParameters dhParams = pGen.GenerateParameters(); + + if (dhParams.L != 0) + { + Fail("DHParametersGenerator failed to set J to 0 in generated DHParameters"); + } + + DHKeyGenerationParameters dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams); + + DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator(); + + kpGen.Init(dhkgParams); + + // + // generate first pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + + // + // generate second pair + // + dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), pu1.Parameters); + + kpGen.Init(dhkgParams); + + pair = kpGen.GenerateKeyPair(); + + DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private; + + // + // 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"); + } + } + + public override void PerformTest() + { + doTestDHBasic(512, 0, g512, p512); + doTestDHBasic(768, 0, g768, p768); + doTestDHBasic(1024, 0, g1024, p1024); + + doTestDHBasic(512, 64, g512, p512); + doTestDHBasic(768, 128, g768, p768); + doTestDHBasic(1024, 256, g1024, p1024); + + doTestDH(512, g512, p512); + doTestDH(768, g768, p768); + doTestDH(1024, g1024, p1024); + + // + // generation test. + // + doTestGeneration(256); + + // + // with random test + // + DHBasicKeyPairGenerator kpBasicGen = getDHBasicKeyPairGenerator(g512, p512, 0); + + doTestSimpleWithRandom(kpBasicGen); + + DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g512, p512); + + doTestGPWithRandom(kpGen); + + // + // parameter tests + // + DHAgreement dh = new DHAgreement(); + AsymmetricCipherKeyPair dhPair = kpGen.GenerateKeyPair(); + + try + { + dh.Init(dhPair.Public); + Fail("DHAgreement key check failed"); + } + catch (ArgumentException) + { + // ignore + } + + DHKeyPairGenerator kpGen768 = getDHKeyPairGenerator(g768, p768); + + try + { + dh.Init(dhPair.Private); + + dh.CalculateAgreement((DHPublicKeyParameters)kpGen768.GenerateKeyPair().Public, BigInteger.ValueOf(100)); + + Fail("DHAgreement agreement check failed"); + } + catch (ArgumentException) + { + // ignore + } + + DHBasicAgreement dhBasic = new DHBasicAgreement(); + AsymmetricCipherKeyPair dhBasicPair = kpBasicGen.GenerateKeyPair(); + + try + { + dhBasic.Init(dhBasicPair.Public); + Fail("DHBasicAgreement key check failed"); + } + catch (ArgumentException) + { + // expected + } + + DHBasicKeyPairGenerator kpBasicGen768 = getDHBasicKeyPairGenerator(g768, p768, 0); + + try + { + dhBasic.Init(dhPair.Private); + + dhBasic.CalculateAgreement((DHPublicKeyParameters)kpBasicGen768.GenerateKeyPair().Public); + + Fail("DHBasicAgreement agreement check failed"); + } + catch (ArgumentException) + { + // expected + } + } + + public static void Main( + string[] args) + { + ITest test = new DHTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/DSATest.cs b/crypto/test/src/crypto/test/DSATest.cs new file mode 100644 index 000000000..0e6367150 --- /dev/null +++ b/crypto/test/src/crypto/test/DSATest.cs @@ -0,0 +1,615 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors. + [TestFixture] + public class DsaTest + : SimpleTest + { + public override string Name + { + get { return "DSA"; } + } + + internal BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16); + internal BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16); + + public override void PerformTest() + { + byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); + byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded"); + + SecureRandom random = FixedSecureRandom.From(k1, k2); + + byte[] keyData = Hex.Decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); + + SecureRandom keyRandom = FixedSecureRandom.From(keyData, keyData); + + BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403"); + BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365"); + DsaParametersGenerator pGen = new DsaParametersGenerator(); + + pGen.Init(512, 80, random); + + DsaParameters parameters = pGen.GenerateParameters(); + DsaValidationParameters pValid = parameters.ValidationParameters; + + if (pValid.Counter != 105) + { + Fail("Counter wrong"); + } + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + Fail("p or q wrong"); + } + + DsaKeyPairGenerator dsaKeyGen = new DsaKeyPairGenerator(); + DsaKeyGenerationParameters genParam = new DsaKeyGenerationParameters(keyRandom, parameters); + + dsaKeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = dsaKeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, keyRandom); + + DsaSigner dsa = new DsaSigner(); + + dsa.Init(true, param); + + byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArrayUnsigned(); + BigInteger[] sig = dsa.GenerateSignature(message); + + if (!r.Equals(sig[0])) + { + Fail("r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + dsa.Init(false, pair.Public); + + 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 parameters = pGen.GenerateParameters(); + + DsaValidationParameters pv = parameters.ValidationParameters; + + if (pv.Counter != 5) + { + Fail("counter incorrect"); + } + + if (!AreEqual(seed, pv.GetSeed())) + { + Fail("seed incorrect"); + } + + if (!parameters.Q.Equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16))) + { + Fail("Q incorrect"); + } + + if (!parameters.P.Equals(new BigInteger( + "E0A67598CD1B763B" + + "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" + + "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" + + "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" + + "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" + + "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16))) + { + Fail("P incorrect"); + } + + if (!parameters.G.Equals(new BigInteger( + "D29D5121B0423C27" + + "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" + + "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" + + "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" + + "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" + + "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16))) + { + Fail("G incorrect"); + } + + DsaKeyPairGenerator kpGen = new DsaKeyPairGenerator(); + + kpGen.Init(new DsaKeyGenerationParameters(FixedSecureRandom.From(Hex.Decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), parameters)); + + AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); + + DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public; + DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private; + + if (!pub.Y.Equals(new BigInteger( + "25282217F5730501" + + "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" + + "A3F10986140CBB97C726938060473C8EC97B4731DB004293" + + "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" + + "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" + + "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16))) + { + Fail("Y value incorrect"); + } + + if (!priv.X.Equals( + new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16))) + { + Fail("X value incorrect"); + } + + DsaSigner signer = new DsaSigner(); + + signer.Init(true, new ParametersWithRandom(kp.Private, FixedSecureRandom.From(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.Public); + + 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 parameters = pGen.GenerateParameters(); + + DsaValidationParameters pv = parameters.ValidationParameters; + + if (pv.Counter != 21) + { + Fail("counter incorrect"); + } + + if (!AreEqual(seed, pv.GetSeed())) + { + Fail("seed incorrect"); + } + + if (!parameters.Q.Equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16))) + { + Fail("Q incorrect"); + } + + if (!parameters.P.Equals(new BigInteger( + "C196BA05AC29E1F9C3C72D56DFFC6154" + + "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" + + "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" + + "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" + + "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" + + "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" + + "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" + + "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" + + "5320121496DC65B3930E38047294FF877831A16D5228418D" + + "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" + + "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16))) + { + Fail("P incorrect"); + } + + if (!parameters.G.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( + FixedSecureRandom.From(Hex.Decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), parameters)); + + AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); + + DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public; + DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private; + + if (!pub.Y.Equals(new BigInteger( + "70035C9A3B225B258F16741F3941FBF0" + + "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" + + "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" + + "02F7A621405B754909D757F97290E1FE5036E904CF593446" + + "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" + + "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" + + "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" + + "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" + + "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" + + "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" + + "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16))) + { + Fail("Y value incorrect"); + } + + if (!priv.X.Equals( + new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16))) + { + Fail("X value incorrect"); + } + + DsaSigner signer = new DsaSigner(); + + signer.Init(true, new ParametersWithRandom(kp.Private, + FixedSecureRandom.From(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.Public); + + 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 parameters = pGen.GenerateParameters(); + + DsaValidationParameters pv = parameters.ValidationParameters; + + if (pv.Counter != 12) + { + Fail("counter incorrect"); + } + + if (!AreEqual(seed, pv.GetSeed())) + { + Fail("seed incorrect"); + } + + if (!parameters.Q.Equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16))) + { + Fail("Q incorrect"); + } + + if (!parameters.P.Equals(new BigInteger( + "F56C2A7D366E3EBDEAA1891FD2A0D099" + + "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" + + "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" + + "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" + + "5909132627F51A0C866877E672E555342BDF9355347DBD43" + + "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" + + "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" + + "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" + + "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" + + "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" + + "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16))) + { + Fail("P incorrect"); + } + + if (!parameters.G.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( + FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), parameters)); + + AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); + + DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public; + DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private; + + if (!pub.Y.Equals(new BigInteger( + "2828003D7C747199143C370FDD07A286" + + "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" + + "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" + + "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" + + "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" + + "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" + + "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" + + "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" + + "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" + + "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" + + "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16))) + { + Fail("Y value incorrect"); + } + + if (!priv.X.Equals( + new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16))) + { + Fail("X value incorrect"); + } + + DsaSigner signer = new DsaSigner(); + + signer.Init(true, new ParametersWithRandom(kp.Private, + FixedSecureRandom.From(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.Public); + + 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 parameters = pGen.GenerateParameters(); + + DsaValidationParameters pv = parameters.ValidationParameters; + + if (pv.Counter != 20) + { + Fail("counter incorrect"); + } + + if (!AreEqual(seed, pv.GetSeed())) + { + Fail("seed incorrect"); + } + + if (!parameters.Q.Equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16))) + { + Fail("Q incorrect"); + } + + if (!parameters.P.Equals(new BigInteger( + "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" + + "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" + + "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" + + "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" + + "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" + + "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" + + "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" + + "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" + + "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" + + "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" + + "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" + + "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" + + "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" + + "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" + + "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" + + "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16))) + { + Fail("P incorrect"); + } + + if (!parameters.G.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( + FixedSecureRandom.From(Hex.Decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), parameters)); + + AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); + + DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public; + DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private; + + if (!pub.Y.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.X.Equals( + new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16))) + { + Fail("X value incorrect"); + } + + DsaSigner signer = new DsaSigner(); + + signer.Init(true, new ParametersWithRandom(kp.Private, + FixedSecureRandom.From(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.Public); + + if (!signer.VerifySignature(msg, sig[0], sig[1])) + { + Fail("signature not verified"); + } + } + + public static void Main( + string[] args) + { + RunTest(new DsaTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private class DsaTestSecureRandom + : FixedSecureRandom + { + private bool first = true; + + public DsaTestSecureRandom(byte[] value) + : base(Arrays.Clone(value)) + { + } + + public override void NextBytes(byte[] bytes) + { + if (first) + { + base.NextBytes(bytes); + first = false; + } + else + { + bytes[bytes.Length - 1] = 2; + } + } + } + } +} diff --git a/crypto/test/src/crypto/test/DigestRandomNumberTest.cs b/crypto/test/src/crypto/test/DigestRandomNumberTest.cs new file mode 100644 index 000000000..cee2e354e --- /dev/null +++ b/crypto/test/src/crypto/test/DigestRandomNumberTest.cs @@ -0,0 +1,163 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class DigestRandomNumberTest + : SimpleTest + { + private static readonly byte[] ZERO_SEED = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + private static readonly byte[] TEST_SEED = Hex.Decode("81dcfafc885914057876"); + + private static readonly byte[] expected0SHA1 = Hex.Decode("95bca677b3d4ff793213c00892d2356ec729ee02"); + private static readonly byte[] noCycle0SHA1 = Hex.Decode("d57ccd0eb12c3938d59226412bc1268037b6b846"); + private static readonly byte[] expected0SHA256 = Hex.Decode("587e2dfd597d086e47ddcd343eac983a5c913bef8c6a1a560a5c1bc3a74b0991"); + private static readonly byte[] noCycle0SHA256 = Hex.Decode("e5776c4483486ba7be081f4e1b9dafbab25c8fae290fd5474c1ceda2c16f9509"); + private static readonly byte[] expected100SHA1 = Hex.Decode("b9d924092546e0876cafd4937d7364ebf9efa4be"); + private static readonly byte[] expected100SHA256 = Hex.Decode("fbc4aa54b948b99de104c44563a552899d718bb75d1941cc62a2444b0506abaf"); + private static readonly byte[] expectedTestSHA1 = Hex.Decode("e9ecef9f5306daf1ac51a89a211a64cb24415649"); + private static readonly byte[] expectedTestSHA256 = Hex.Decode("bdab3ca831b472a2fa09bd1bade541ef16c96640a91fcec553679a136061de98"); + + private static readonly byte[] sha1Xors = Hex.Decode("7edcc1216934f3891b03ffa65821611a3e2b1f79"); + private static readonly byte[] sha256Xors = Hex.Decode("5ec48189cc0aa71e79c707bc3c33ffd47bbba368a83d6cfebf3cd3969d7f3eed"); + + public override string Name + { + get { return "DigestRandomNumber"; } + } + + private void doExpectedTest(IDigest digest, int seed, byte[] expected) + { + doExpectedTest(digest, seed, expected, null); + } + + private void doExpectedTest(IDigest 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(IDigest 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(IDigest 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.AlgorithmName); + } + if (ands[i] != 0) + { + Fail("and test failed for " + digest.AlgorithmName); + } + if ((ors[i] & 0xff) != 0xff) + { + Fail("or test failed for " + digest.AlgorithmName); + } + if (xors[i] != expectedXors[i]) + { + Fail("xor test failed for " + digest.AlgorithmName); + } + } + } + + public override void PerformTest() + { + 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); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + RunTest(new DigestRandomNumberTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/DigestTest.cs b/crypto/test/src/crypto/test/DigestTest.cs new file mode 100644 index 000000000..533e87181 --- /dev/null +++ b/crypto/test/src/crypto/test/DigestTest.cs @@ -0,0 +1,143 @@ +using System; + +using Org.BouncyCastle.Crypto; + +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + public abstract class DigestTest + : SimpleTest + { + private IDigest digest; + private string[] input; + private string[] results; + + protected DigestTest( + IDigest digest, + string[] input, + string[] results) + { + this.digest = digest; + this.input = input; + this.results = results; + } + + public override string Name + { + get { return digest.AlgorithmName; } + } + + public override 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])); + + // + // clone test + // + digest.BlockUpdate(lastV, 0, lastV.Length/2); + + // clone the Digest + IDigest d = CloneDigest(digest); + + digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2); + digest.DoFinal(resBuf, 0); + + if (!AreEqual(lastDigest, resBuf)) + { + Fail("failing clone vector test", results[results.Length - 1], Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2); + d.DoFinal(resBuf, 0); + + if (!AreEqual(lastDigest, resBuf)) + { + Fail("failing second clone vector test", results[results.Length - 1], Hex.ToHexString(resBuf)); + } + } + + private byte[] toByteArray( + string input) + { + byte[] bytes = new byte[input.Length]; + + for (int i = 0; i != bytes.Length; i++) + { + bytes[i] = (byte)input[i]; + } + + return bytes; + } + + private void vectorTest( + IDigest digest, + int count, + byte[] resBuf, + byte[] input, + byte[] expected) + { + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(resBuf, 0); + + if (!AreEqual(resBuf, expected)) + { + Fail("Vector " + count + " failed got " + Hex.ToHexString(resBuf)); + } + } + + protected abstract IDigest CloneDigest(IDigest digest); + + // + // 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"); + } + } + + 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"); + } + } + } +} diff --git a/crypto/test/src/crypto/test/EAXTest.cs b/crypto/test/src/crypto/test/EAXTest.cs new file mode 100644 index 000000000..c6be118b2 --- /dev/null +++ b/crypto/test/src/crypto/test/EAXTest.cs @@ -0,0 +1,352 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class EaxTest + : SimpleTest + { + private static readonly byte[] K1 = Hex.Decode("233952DEE4D5ED5F9B9C6D6FF80FF478"); + private static readonly byte[] N1 = Hex.Decode("62EC67F9C3A4A407FCB2A8C49031A8B3"); + private static readonly byte[] A1 = Hex.Decode("6BFB914FD07EAE6B"); + private static readonly byte[] P1 = Hex.Decode(""); + private static readonly byte[] C1 = Hex.Decode("E037830E8389F27B025A2D6527E79D01"); + private static readonly byte[] T1 = Hex.Decode("E037830E8389F27B025A2D6527E79D01"); + + private static readonly byte[] K2 = Hex.Decode("91945D3F4DCBEE0BF45EF52255F095A4"); + private static readonly byte[] N2 = Hex.Decode("BECAF043B0A23D843194BA972C66DEBD"); + private static readonly byte[] A2 = Hex.Decode("FA3BFD4806EB53FA"); + private static readonly byte[] P2 = Hex.Decode("F7FB"); + private static readonly byte[] C2 = Hex.Decode("19DD5C4C9331049D0BDAB0277408F67967E5"); + private static readonly byte[] T2 = Hex.Decode("5C4C9331049D0BDAB0277408F67967E5"); + + private static readonly byte[] K3 = Hex.Decode("01F74AD64077F2E704C0F60ADA3DD523"); + private static readonly byte[] N3 = Hex.Decode("70C3DB4F0D26368400A10ED05D2BFF5E"); + private static readonly byte[] A3 = Hex.Decode("234A3463C1264AC6"); + private static readonly byte[] P3 = Hex.Decode("1A47CB4933"); + private static readonly byte[] C3 = Hex.Decode("D851D5BAE03A59F238A23E39199DC9266626C40F80"); + private static readonly byte[] T3 = Hex.Decode("3A59F238A23E39199DC9266626C40F80"); + + private static readonly byte[] K4 = Hex.Decode("D07CF6CBB7F313BDDE66B727AFD3C5E8"); + private static readonly byte[] N4 = Hex.Decode("8408DFFF3C1A2B1292DC199E46B7D617"); + private static readonly byte[] A4 = Hex.Decode("33CCE2EABFF5A79D"); + private static readonly byte[] P4 = Hex.Decode("481C9E39B1"); + private static readonly byte[] C4 = Hex.Decode("632A9D131AD4C168A4225D8E1FF755939974A7BEDE"); + private static readonly byte[] T4 = Hex.Decode("D4C168A4225D8E1FF755939974A7BEDE"); + + private static readonly byte[] K5 = Hex.Decode("35B6D0580005BBC12B0587124557D2C2"); + private static readonly byte[] N5 = Hex.Decode("FDB6B06676EEDC5C61D74276E1F8E816"); + private static readonly byte[] A5 = Hex.Decode("AEB96EAEBE2970E9"); + private static readonly byte[] P5 = Hex.Decode("40D0C07DA5E4"); + private static readonly byte[] C5 = Hex.Decode("071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"); + private static readonly byte[] T5 = Hex.Decode("CB0677E536F73AFE6A14B74EE49844DD"); + + private static readonly byte[] K6 = Hex.Decode("BD8E6E11475E60B268784C38C62FEB22"); + private static readonly byte[] N6 = Hex.Decode("6EAC5C93072D8E8513F750935E46DA1B"); + private static readonly byte[] A6 = Hex.Decode("D4482D1CA78DCE0F"); + private static readonly byte[] P6 = Hex.Decode("4DE3B35C3FC039245BD1FB7D"); + private static readonly byte[] C6 = Hex.Decode("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"); + private static readonly byte[] T6 = Hex.Decode("ABB8644FD6CCB86947C5E10590210A4F"); + + private static readonly byte[] K7 = Hex.Decode("7C77D6E813BED5AC98BAA417477A2E7D"); + private static readonly byte[] N7 = Hex.Decode("1A8C98DCD73D38393B2BF1569DEEFC19"); + private static readonly byte[] A7 = Hex.Decode("65D2017990D62528"); + private static readonly byte[] P7 = Hex.Decode("8B0A79306C9CE7ED99DAE4F87F8DD61636"); + private static readonly byte[] C7 = Hex.Decode("02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"); + private static readonly byte[] T7 = Hex.Decode("137327D10649B0AA6E1C181DB617D7F2"); + + private static readonly byte[] K8 = Hex.Decode("5FFF20CAFAB119CA2FC73549E20F5B0D"); + private static readonly byte[] N8 = Hex.Decode("DDE59B97D722156D4D9AFF2BC7559826"); + private static readonly byte[] A8 = Hex.Decode("54B9F04E6A09189A"); + private static readonly byte[] P8 = Hex.Decode("1BDA122BCE8A8DBAF1877D962B8592DD2D56"); + private static readonly byte[] C8 = Hex.Decode("2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"); + private static readonly byte[] T8 = Hex.Decode("3B60450599BD02C96382902AEF7F832A"); + + private static readonly byte[] K9 = Hex.Decode("A4A4782BCFFD3EC5E7EF6D8C34A56123"); + private static readonly byte[] N9 = Hex.Decode("B781FCF2F75FA5A8DE97A9CA48E522EC"); + private static readonly byte[] A9 = Hex.Decode("899A175897561D7E"); + private static readonly byte[] P9 = Hex.Decode("6CF36720872B8513F6EAB1A8A44438D5EF11"); + private static readonly byte[] C9 = Hex.Decode("0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"); + private static readonly byte[] T9 = Hex.Decode("E7F6D2231618102FDB7FE55FF1991700"); + + private static readonly byte[] K10 = Hex.Decode("8395FCF1E95BEBD697BD010BC766AAC3"); + private static readonly byte[] N10 = Hex.Decode("22E7ADD93CFC6393C57EC0B3C17D6B44"); + private static readonly byte[] A10 = Hex.Decode("126735FCC320D25A"); + private static readonly byte[] P10 = Hex.Decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7"); + private static readonly byte[] C10 = Hex.Decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"); + private static readonly byte[] T10 = Hex.Decode("CFC46AFC253B4652B1AF3795B124AB6E"); + + private static readonly byte[] K11 = Hex.Decode("8395FCF1E95BEBD697BD010BC766AAC3"); + private static readonly byte[] N11 = Hex.Decode("22E7ADD93CFC6393C57EC0B3C17D6B44"); + private static readonly byte[] A11 = Hex.Decode("126735FCC320D25A"); + private static readonly byte[] P11 = Hex.Decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7"); + private static readonly byte[] C11 = Hex.Decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC"); + private static readonly byte[] T11 = Hex.Decode("CFC46AFC"); + + private const int NONCE_LEN = 8; + private const int MAC_LEN = 8; + private const int AUTHEN_LEN = 20; + + public override string Name + { + get { return "EAX"; } + } + + public override void PerformTest() + { + 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 AesEngine()); + 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) + { + // expected + } + + try + { + eax.Init(false, new KeyParameter(K1)); + + Fail("illegal argument not picked up"); + } + catch (ArgumentException) + { + // expected + } + + randomTests(); + } + + private void checkVectors( + int count, + byte[] k, + int macSize, + byte[] n, + byte[] a, + byte[] p, + byte[] t, + byte[] c) + { + byte[] fa = new byte[a.Length / 2]; + byte[] la = new byte[a.Length - (a.Length / 2)]; + Array.Copy(a, 0, fa, 0, fa.Length); + Array.Copy(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) + { + 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) + { + 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]; + + Array.Copy(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, + IAeadBlockCipher eax, + byte[] k, + byte[] n) + { + byte[] p = Encoding.ASCII.GetBytes("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]; + + Array.Copy(tmp, 0, dec, 0, len); + + if (!AreEqual(p, dec)) + { + Fail("decrypted stream fails to match in test " + count); + } + } + + private void randomTests() + { + SecureRandom srng = new SecureRandom(); + for (int i = 0; i < 10; ++i) + { + randomTest(srng); + } + } + + private void randomTest( + SecureRandom srng) + { + int DAT_LEN = srng.Next(1024); + 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 parameters = new AeadParameters(sessKey, MAC_LEN * 8, nonce, authen); + eaxCipher.Init(true, parameters); + + 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, parameters); + 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ECDHKEKGeneratorTest.cs b/crypto/test/src/crypto/test/ECDHKEKGeneratorTest.cs new file mode 100644 index 000000000..250b2ca22 --- /dev/null +++ b/crypto/test/src/crypto/test/ECDHKEKGeneratorTest.cs @@ -0,0 +1,80 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto.Agreement.Kdf; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// ECDHKEK Generator tests. + [TestFixture] + public class ECDHKekGeneratorTest + : SimpleTest + { + private byte[] seed1 = Hex.Decode("db4a8daba1f98791d54e940175dd1a5f3a0826a1066aa9b668d4dc1e1e0790158dcad1533c03b44214d1b61fefa8b579"); + private DerObjectIdentifier alg1 = NistObjectIdentifiers.IdAes256Wrap; + private byte[] result1 = Hex.Decode("8ecc6d85caf25eaba823a7d620d4ab0d33e4c645f2"); + + private byte[] seed2 = Hex.Decode("75d7487b5d3d2bfb3c69ce0365fe64e3bfab5d0d63731628a9f47eb8fddfa28c65decaf228a0b38f0c51c6a3356d7c56"); + private DerObjectIdentifier alg2 = NistObjectIdentifiers.IdAes128Wrap; + private byte[] result2 = Hex.Decode("042be1faca3a4a8fc859241bfb87ba35"); + + private byte[] seed3 = Hex.Decode("fdeb6d809f997e8ac174d638734dc36d37aaf7e876e39967cd82b1cada3de772449788461ee7f856bad9305627f8e48b"); + private DerObjectIdentifier alg3 = PkcsObjectIdentifiers.IdAlgCms3DesWrap; + private byte[] result3 = Hex.Decode("bcd701fc92109b1b9d6f3b6497ad5ca9627fa8a597010305"); + + public ECDHKekGeneratorTest() + { + } + + public override 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, + IDerivationFunction kdf, + IDerivationParameters parameters, + byte[] result) + { + byte[] data = new byte[result.Length]; + + kdf.Init(parameters); + + kdf.GenerateBytes(data, 0, data.Length); + + if (!AreEqual(result, data)) + { + Fail("ECDHKekGenerator failed generator test " + count); + } + } + + public override string Name + { + get { return "ECDHKekGenerator"; } + } + + public static void Main( + string[] args) + { + RunTest(new ECDHKekGeneratorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ECGOST3410Test.cs b/crypto/test/src/crypto/test/ECGOST3410Test.cs new file mode 100644 index 000000000..c04ba9047 --- /dev/null +++ b/crypto/test/src/crypto/test/ECGOST3410Test.cs @@ -0,0 +1,335 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * ECGOST3410 tests are taken from GOST R 34.10-2001. + */ + [TestFixture] + public class ECGost3410Test + : SimpleTest + { + private static readonly byte[] hashmessage = Hex.Decode("3042453136414534424341374533364339313734453431443642453241453435"); + + /** + * ECGOST3410 over the field Fp
    + */ + BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395"); + BigInteger s = new BigInteger("574973400270084654178925310019147038455227042649098563933718999175515839552"); + + byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").ToByteArray(); + + private readonly SecureRandom k; + + public ECGost3410Test() + { + k = FixedSecureRandom.From(kData); + } + + private void ecGOST3410_TEST() + { + BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("7"), // a + new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + new FpPoint(curve, + new FpFieldElement(mod_p,new BigInteger("2")), // x + new FpFieldElement(mod_p,new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280"))), // y + new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECGOST3410", + new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d + parameters); + + 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( + "ECGOST3410", + new FpPoint(curve, + new FpFieldElement(mod_p, new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403")), // x + new FpFieldElement(mod_p, new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994"))), // y + parameters); + + ecgost3410.Init(false, pubKey); + if (!ecgost3410.VerifySignature(message, sig[0], sig[1])) + { + Fail("verification fails"); + } + } + + /** + * Test Sign and 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 + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("7"), // a + new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + new FpPoint(curve, + new FpFieldElement(mod_p,new BigInteger("2")), // x + new FpFieldElement(mod_p,new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280"))), // y + new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q + + ECKeyPairGenerator pGen = new ECKeyPairGenerator(); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( + parameters, + random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + ECGost3410Signer ecgost3410 = new ECGost3410Signer(); + + ecgost3410.Init(true, param); + + //get hash message using the digest GOST3411. + byte[] message = Encoding.ASCII.GetBytes("Message for sign"); + Gost3411Digest gost3411 = new Gost3411Digest(); + gost3411.BlockUpdate(message, 0, message.Length); + byte[] hashmessage = new byte[gost3411.GetDigestSize()]; + gost3411.DoFinal(hashmessage, 0); + + BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage); + + ecgost3410.Init(false, pair.Public); + + if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * Test Sign and 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 + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a + new BigInteger("166")); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + new FpPoint(curve, + new FpFieldElement(mod_p, new BigInteger("1")), // x + new FpFieldElement(mod_p, new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"))), // y + new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323")); // q + + ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410"); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( + parameters, + random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + ECGost3410Signer ecgost3410 = new ECGost3410Signer(); + + ecgost3410.Init(true, param); + + BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage); + + ecgost3410.Init(false, pair.Public); + + if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * Test Sign and 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 + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a + new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595")); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + new FpPoint(curve, + new FpFieldElement(mod_p,new BigInteger("1")), // x + new FpFieldElement(mod_p,new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124"))), // y + new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703")); // q + + ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410"); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( + parameters, + random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + ECGost3410Signer ecgost3410 = new ECGost3410Signer(); + + ecgost3410.Init(true, param); + + BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage); + + ecgost3410.Init(false, pair.Public); + + if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * Test Sign and 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 + + FpCurve curve = new FpCurve( + mod_p, // p + new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a + new BigInteger("32858")); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + new FpPoint(curve, + new FpFieldElement(mod_p,new BigInteger("0")), // x + new FpFieldElement(mod_p,new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"))), // y + new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601")); // q + + ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410"); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( + parameters, + random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + ECGost3410Signer ecgost3410 = new ECGost3410Signer(); + + ecgost3410.Init(true, param); + + BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage); + + ecgost3410.Init(false, pair.Public); + + if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + public override string Name + { + get { return "ECGOST3410"; } + } + + public override void PerformTest() + { + ecGOST3410_TEST(); + ecGOST3410_TestParam(); + ecGOST3410_AParam(); + ecGOST3410_BParam(); + ecGOST3410_CParam(); + } + + public static void Main( + string[] args) + { + ECGost3410Test test = new ECGost3410Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ECIESTest.cs b/crypto/test/src/crypto/test/ECIESTest.cs new file mode 100644 index 000000000..383750b14 --- /dev/null +++ b/crypto/test/src/crypto/test/ECIESTest.cs @@ -0,0 +1,246 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Test for ECIES - Elliptic Curve Integrated Encryption Scheme + [TestFixture] + public class EcIesTest + : SimpleTest + { + public EcIesTest() + { + } + + public override string Name + { + get { return "ECIES"; } + } + + private void StaticTest() + { + FpCurve curve = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G + new BigInteger("6277101735386680763835789423176059013767194773182842284081")); // n + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDH", + new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d + parameters); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDH", + curve.DecodePoint(Hex.Decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q + parameters); + + 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 }; + IesParameters p = new IesParameters(d, e, 64); + + i1.Init(true, p1.Private, p2.Public, p); + i2.Init(false, p2.Private, p1.Public, 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); + + i1.Init(true, p1.Private, p2.Public, p); + i2.Init(false, p2.Private, p1.Public, p); + + message = Hex.Decode("1234567890abcdef"); + + out1 = i1.ProcessBlock(message, 0, message.Length); + + if (!AreEqual(out1, Hex.Decode("b8a06ea5c2b9df28b58a0a90a734cde8c9c02903e5c220021fe4417410d1e53a32a71696"))) + { + 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 DoTest( + AsymmetricCipherKeyPair p1, + AsymmetricCipherKeyPair p2) + { + // + // 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.Private, p2.Public, p); + i2.Init(false, p2.Private, p1.Public, 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.Private, p2.Public, p); + i2.Init(false, p2.Private, p1.Public, 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 override void PerformTest() + { + StaticTest(); + + FpCurve curve = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G + new BigInteger("6277101735386680763835789423176059013767194773182842284081")); // n + + ECKeyPairGenerator eGen = new ECKeyPairGenerator(); + KeyGenerationParameters gParam = new ECKeyGenerationParameters(parameters, new SecureRandom()); + + eGen.Init(gParam); + + AsymmetricCipherKeyPair p1 = eGen.GenerateKeyPair(); + AsymmetricCipherKeyPair p2 = eGen.GenerateKeyPair(); + + DoTest(p1, p2); + } + + public static void Main( + string[] args) + { + RunTest(new EcIesTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ECNRTest.cs b/crypto/test/src/crypto/test/ECNRTest.cs new file mode 100644 index 000000000..c477fe625 --- /dev/null +++ b/crypto/test/src/crypto/test/ECNRTest.cs @@ -0,0 +1,115 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * ECNR tests. + */ + [TestFixture] + public class EcNrTest + : 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")); + + private readonly SecureRandom k; + + public EcNrTest() + { + k = FixedSecureRandom.From(kData); + } + + private void ecNR239bitPrime() + { + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + parameters); + + 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 + parameters); + + ecnr.Init(false, pubKey); + if (!ecnr.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + public override string Name + { + get + { + return "ECNR"; + } + } + + public override void PerformTest() + { + ecNR239bitPrime(); + } + + public static void Main( + string[] args) + { + EcNrTest test = new EcNrTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ECTest.cs b/crypto/test/src/crypto/test/ECTest.cs new file mode 100644 index 000000000..70702e730 --- /dev/null +++ b/crypto/test/src/crypto/test/ECTest.cs @@ -0,0 +1,919 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * ECDSA tests are taken from X9.62. + */ + [TestFixture] + public class ECTest + : SimpleTest + { + /** + * X9.62 - 1998,
    + * J.3.1, Page 152, ECDSA over the field Fp
    + * an example with 192 bit prime + */ + [Test] + public void TestECDsa192bitPrime() + { + BigInteger r = new BigInteger("3342403536405981729393488334694600415596881826869351677613"); + BigInteger s = new BigInteger("5735822328888155254683894997897571951568553642892029982342"); + + byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("6140507067065001063065065565667405560006161556565665656654")); + + SecureRandom k = FixedSecureRandom.From(kData); + + FpCurve curve = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G + new BigInteger("6277101735386680763835789423176059013767194773182842284081")); // n + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d + parameters); + + 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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q + parameters); + + ecdsa.Init(false, pubKey); + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("verification fails"); + } + } + + [Test] + public void TestDecode() + { + FpCurve curve = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + + ECPoint p = curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")); + + if (!p.X.ToBigInteger().Equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16))) + { + Fail("x uncompressed incorrectly"); + } + + if (!p.Y.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,
    + * J.3.2, Page 155, ECDSA over the field Fp
    + * an example with 239 bit prime + */ + [Test] + public void TestECDsa239bitPrime() + { + BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176"); + BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783"); + + byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655")); + + SecureRandom k = FixedSecureRandom.From(kData); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + parameters); + + 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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + parameters); + + ecdsa.Init(false, pubKey); + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + + /** + * X9.62 - 1998,
    + * J.2.1, Page 100, ECDSA over the field F2m
    + * an example with 191 bit binary field + */ + [Test] + public void TestECDsa191bitBinary() + { + BigInteger r = new BigInteger("87194383164871543355722284926904419997237591535066528048"); + BigInteger s = new BigInteger("308992691965804947361541664549085895292153777025772063598"); + + byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("1542725565216523985789236956265265265235675811949404040041")); + + SecureRandom k = FixedSecureRandom.From(kData); + + F2mCurve curve = new F2mCurve( + 191, // m + 9, //k + new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), // a + new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB")), // G + new BigInteger("1569275433846670190958947355803350458831205595451630533029"), // n + BigInteger.Two); // h + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("1275552191113212300012030439187146164646146646466749494799"), // d + parameters); + + 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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1")), // Q + parameters); + + ecdsa.Init(false, pubKey); + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * X9.62 - 1998,
    + * J.2.1, Page 100, ECDSA over the field F2m
    + * an example with 191 bit binary field + */ + [Test] + public void TestECDsa239bitBinary() + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174"); + + byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = FixedSecureRandom.From(kData); + + F2mCurve curve = new F2mCurve( + 239, // m + 36, //k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); // h + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + parameters); + + 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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + parameters); + + ecdsa.Init(false, pubKey); + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + // L 4.1 X9.62 2005 + [Test] + public void TestECDsaP224Sha224() + { + X9ECParameters p = NistNamedCurves.GetByName("P-224"); + ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d + parameters); + SecureRandom k = FixedSecureRandom.From(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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + parameters.Curve.DecodePoint(Hex.Decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q + parameters); + + dsa.Init(false, pubKey); + if (!dsa.VerifySignature(M, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + [Test] + public void TestECDsaSecP224k1Sha256() + { + X9ECParameters p = SecNamedCurves.GetByName("secp224k1"); + ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("BE6F6E91FE96840A6518B56F3FE21689903A64FA729057AB872A9F51", 16), // d + parameters); + SecureRandom k = FixedSecureRandom.From(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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + parameters.Curve.DecodePoint(Hex.Decode("04C5C9B38D3603FCCD6994CBB9594E152B658721E483669BB42728520F484B537647EC816E58A8284D3B89DFEDB173AFDC214ECA95A836FA7C")), // Q + parameters); + + dsa.Init(false, pubKey); + if (!dsa.VerifySignature(M, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + // L4.2 X9.62 2005 + [Test] + public void TestECDsaP256Sha256() + { + X9ECParameters p = NistNamedCurves.GetByName("P-256"); + ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("20186677036482506117540275567393538695075300175221296989956723148347484984008"), // d + parameters); + SecureRandom k = FixedSecureRandom.From(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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + parameters.Curve.DecodePoint(Hex.Decode("03596375E6CE57E0F20294FC46BDFCFD19A39F8161B58695B3EC5B3D16427C274D")), // Q + parameters); + + dsa.Init(false, pubKey); + if (!dsa.VerifySignature(M, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + [Test] + public void TestECDsaP224OneByteOver() + { + X9ECParameters p = NistNamedCurves.GetByName("P-224"); + ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d + parameters); + SecureRandom k = FixedSecureRandom.From(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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + parameters.Curve.DecodePoint(Hex.Decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q + parameters); + + dsa.Init(false, pubKey); + if (!dsa.VerifySignature(M, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + // L4.3 X9.62 2005 + [Test] + public void TestECDsaP521Sha512() + { + X9ECParameters p = NistNamedCurves.GetByName("P-521"); + ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("617573726813476282316253885608633222275541026607493641741273231656161177732180358888434629562647985511298272498852936680947729040673640492310550142822667389"), // d + parameters); + SecureRandom k = FixedSecureRandom.From(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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + parameters.Curve.DecodePoint(Hex.Decode("020145E221AB9F71C5FE740D8D2B94939A09E2816E2167A7D058125A06A80C014F553E8D6764B048FB6F2B687CEC72F39738F223D4CE6AFCBFF2E34774AA5D3C342CB3")), // Q + parameters); + + dsa.Init(false, pubKey); + if (!dsa.VerifySignature(M, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * General test for long digest. + */ + [Test] + public void TestECDsa239bitBinaryAndLargeDigest() + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("144940322424411242416373536877786566515839911620497068645600824084578597"); + + byte[] kData = BigIntegers.AsUnsignedByteArray( + new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = FixedSecureRandom.From(kData); + + F2mCurve curve = new F2mCurve( + 239, // m + 36, //k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint( + Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); // h + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + parameters); + + 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." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + + // Verify the signature + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint( + Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + parameters); + + ecdsa.Init(false, pubKey); + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * key generation test + */ + [Test] + public void TestECDsaKeyGenTest() + { + SecureRandom random = new SecureRandom(); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + + ECKeyPairGenerator pGen = new ECKeyPairGenerator(); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( + parameters, + random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + ECDsaSigner ecdsa = new ECDsaSigner(); + + ecdsa.Init(true, param); + + byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray(); + BigInteger[] sig = ecdsa.GenerateSignature(message); + + ecdsa.Init(false, pair.Public); + + if (!ecdsa.VerifySignature(message, sig[0], sig[1])) + { + Fail("signature fails"); + } + } + + /** + * Basic Key Agreement Test + */ + [Test] + public void TestECBasicAgreementTest() + { + SecureRandom random = new SecureRandom(); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + + ECKeyPairGenerator pGen = new ECKeyPairGenerator(); + ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(parameters, random); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair p1 = pGen.GenerateKeyPair(); + AsymmetricCipherKeyPair p2 = pGen.GenerateKeyPair(); + + // + // two way + // + IBasicAgreement e1 = new ECDHBasicAgreement(); + IBasicAgreement e2 = new ECDHBasicAgreement(); + + e1.Init(p1.Private); + e2.Init(p2.Private); + + BigInteger k1 = e1.CalculateAgreement(p2.Public); + BigInteger k2 = e2.CalculateAgreement(p1.Public); + + if (!k1.Equals(k2)) + { + Fail("calculated agreement test failed"); + } + + // + // two way + // + e1 = new ECDHCBasicAgreement(); + e2 = new ECDHCBasicAgreement(); + + e1.Init(p1.Private); + e2.Init(p2.Private); + + k1 = e1.CalculateAgreement(p2.Public); + k2 = e2.CalculateAgreement(p1.Public); + + if (!k1.Equals(k2)) + { + Fail("calculated agreement test failed"); + } + } + + [Test] + public void TestECMqvTestVector1() + { + // Test Vector from GEC-2 + + X9ECParameters x9 = SecNamedCurves.GetByName("secp160r1"); + ECDomainParameters p = new ECDomainParameters( + x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + + AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("0251B4496FECC406ED0E75A24A3C03206251419DC0")), p), + new ECPrivateKeyParameters( + new BigInteger("AA374FFC3CE144E6B073307972CB6D57B2A4E982", 16), p)); + + AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("03D99CE4D8BF52FA20BD21A962C6556B0F71F4CA1F")), p), + new ECPrivateKeyParameters( + new BigInteger("149EC7EA3A220A887619B3F9E5B4CA51C7D1779C", 16), p)); + + AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("0349B41E0E9C0369C2328739D90F63D56707C6E5BC")), p), + new ECPrivateKeyParameters( + new BigInteger("45FB58A92A17AD4B15101C66E74F277E2B460866", 16), p)); + + AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.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"); + } + } + + [Test] + public void TestECMqvTestVector2() + { + // Test Vector from GEC-2 + + X9ECParameters x9 = SecNamedCurves.GetByName("sect163k1"); + ECDomainParameters p = new ECDomainParameters( + x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + + AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("03037D529FA37E42195F10111127FFB2BB38644806BC")), p), + new ECPrivateKeyParameters( + new BigInteger("03A41434AA99C2EF40C8495B2ED9739CB2155A1E0D", 16), p)); + + AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("02015198E74BC2F1E5C9A62B80248DF0D62B9ADF8429")), p), + new ECPrivateKeyParameters( + new BigInteger("032FC4C61A8211E6A7C4B8B0C03CF35F7CF20DBD52", 16), p)); + + AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.DecodePoint(Hex.Decode("03072783FAAB9549002B4F13140B88132D1C75B3886C")), p), + new ECPrivateKeyParameters( + new BigInteger("57E8A78E842BF4ACD5C315AA0569DB1703541D96", 16), p)); + + AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair( + new ECPublicKeyParameters( + p.Curve.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"); + } + } + + [Test] + public void TestECMqvRandom() + { + SecureRandom random = new SecureRandom(); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // 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.Private, + (ECPrivateKeyParameters)U2.Private, + (ECPublicKeyParameters)U2.Public)); + BigInteger ux = u.CalculateAgreement(new MqvPublicParameters( + (ECPublicKeyParameters)V1.Public, + (ECPublicKeyParameters)V2.Public)); + + ECMqvBasicAgreement v = new ECMqvBasicAgreement(); + v.Init(new MqvPrivateParameters( + (ECPrivateKeyParameters)V1.Private, + (ECPrivateKeyParameters)V2.Private, + (ECPublicKeyParameters)V2.Public)); + BigInteger vx = v.CalculateAgreement(new MqvPublicParameters( + (ECPublicKeyParameters)U1.Public, + (ECPublicKeyParameters)U2.Public)); + + if (ux.Equals(vx)) + return ux; + + return null; + } + + public override string Name + { + get { return "EC"; } + } + + public override void PerformTest() + { + TestDecode(); + 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/crypto/test/src/crypto/test/ElGamalTest.cs b/crypto/test/src/crypto/test/ElGamalTest.cs new file mode 100644 index 000000000..1caa70387 --- /dev/null +++ b/crypto/test/src/crypto/test/ElGamalTest.cs @@ -0,0 +1,278 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class ElGamalTest + : SimpleTest + { + private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16); + private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16); + + private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16); + private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16); + + private static readonly BigInteger yPgpBogusPSamp = new BigInteger("de4688497cc05b45fe8559bc9918c45afcad69b74123a7236eba409fd9de8ea34c7869839ee9df35e3d97576145d089841aa65b5b4e061fae52c37e430354269a02496b8ed8456f2d0d7c9b0db985fbcb21ae9f78507ed6e3a29db595b201b1a4f931c7d791eede65ccf918e8a61cf146859151c78c41ad48853694623467d78", 16); + private static readonly BigInteger xPgpBogusPSamp = new BigInteger("cbaf780f2cfe4f987bbc5fcb0738bbd7912060ccfdf37cbfeea65c0fd857e74a8df6cc359375f28cf5725d081813c614410a78cbe4b06d677beea9ff0fa10b1dbc47a6ed8c5b8466d6a95d6574029dbdf72596392e1b6b230faf9916dc8455821c10527a375a4d1c8a54947d1fe714d321aca25ad486b4b456506999fd2fd11a", 16); + private static readonly BigInteger gPgpBogusPSamp = new BigInteger("153ffe9522076d1cbd6e75f0816a0fc2ebd8b0e0091406587387a1763022088a03b411eed07ff50efb82b21f1608c352d10f63ba7e7e981a2f3387cec8af2915953d00493857663ae8919f517fe90f1d2abe7af4305a344b10d1a25d75f65902cd7fd775853d3ac43d7c5253ad666e1e63ee98cdcb10af81273d4ff053ff07d51", 16); + private static readonly BigInteger pPgpBogusPSamp = new BigInteger("15061b26cdab4e865098a01c86f13b03220104c5443e950658b36b85245aa0c616a0c0d8d99c454bea087c172315e45b3bc9b925443948a2b6ba47608a6035b9a79a4ef34a78d7274a12ede8364f02d5030db864988643d7e92753df603bd69fbd2682ab0af64d1a866d1131a2cb13333cedb0a9e6eefddd9fff8154d34c2daab", 16); + private const int lPgpBogusPSamp = 0; + + public override string Name + { + get { return "ElGamal"; } + } + + private void doTestEnc( + int size, + int privateValueSize, + BigInteger g, + BigInteger p) + { + ElGamalParameters dhParams = new ElGamalParameters(p, g, privateValueSize); + ElGamalKeyGenerationParameters ekgParams = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams); + ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator(); + + kpGen.Init(ekgParams); + + // + // generate pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters) pair.Public; + ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters) pair.Private; + + 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) + { + // expected + } + + try + { + bytes[0] = (byte)0xff; + + e.ProcessBlock(bytes, 0, bytes.Length - 1); + + Fail("out of range block not detected"); + } + catch (DataLengthException) + { + // expected + } + + try + { + bytes[0] = (byte)0x7f; + + e.ProcessBlock(bytes, 0, bytes.Length - 1); + } + catch (DataLengthException) + { + Fail("in range block failed"); + } + } + + private void checkKeySize( + int privateValueSize, + ElGamalPrivateKeyParameters priv) + { + if (privateValueSize != 0) + { + if (priv.X.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 doTestGeneration( + int size) + { + ElGamalParametersGenerator pGen = new ElGamalParametersGenerator(); + + pGen.Init(size, 10, new SecureRandom()); + + ElGamalParameters elParams = pGen.GenerateParameters(); + + if (elParams.L != 0) + { + Fail("ElGamalParametersGenerator failed to set L to 0 in generated ElGamalParameters"); + } + + ElGamalKeyGenerationParameters ekgParams = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams); + + ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator(); + + kpGen.Init(ekgParams); + + // + // generate first pair + // + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.Public; + ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.Private; + + 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"); + } + } + + [Test] + public 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"); + } + } + + [Test] + public void TestEnc512() + { + doTestEnc(512, 0, g512, p512); + doTestEnc(512, 64, g512, p512); + } + + [Test] + public void TestEnc768() + { + doTestEnc(768, 0, g768, p768); + doTestEnc(768, 128, g768, p768); + } + + [Test] + public void TestEnc1024() + { + doTestEnc(1024, 0, g1024, p1024); + } + + [Test] + public void TestGeneration258() + { + doTestGeneration(258); + } + + [Test] + public void TestInitCheck() + { + try + { + new ElGamalEngine().ProcessBlock(new byte[]{ 1 }, 0, 1); + Fail("failed initialisation check"); + } + catch (InvalidOperationException) + { + // expected + } + } + + public override void PerformTest() + { + TestInvalidP(); + TestEnc512(); + TestEnc768(); + TestEnc1024(); + TestGeneration258(); + TestInitCheck(); + } + + public static void Main( + string[] args) + { + RunTest(new ElGamalTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/EqualsHashCodeTest.cs b/crypto/test/src/crypto/test/EqualsHashCodeTest.cs new file mode 100644 index 000000000..05cc9ad53 --- /dev/null +++ b/crypto/test/src/crypto/test/EqualsHashCodeTest.cs @@ -0,0 +1,262 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + internal class DHTestKeyParameters + : DHKeyParameters + { + public DHTestKeyParameters( + bool isPrivate, + DHParameters parameters) + : base(isPrivate, parameters) + { + } + } + + internal class ElGamalTestKeyParameters + : ElGamalKeyParameters + { + public ElGamalTestKeyParameters( + bool isPrivate, + ElGamalParameters parameters) + : base(isPrivate, parameters) + { + } + } + + [TestFixture] + public class EqualsHashCodeTest + : SimpleTest + { + private static object Other = new object(); + + public override string Name + { + get { 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.GetHashCode() != equalsA.GetHashCode()) + { + Fail("hashCode equality failed"); + } + } + + [Test] + public void TestDH() + { + BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + DHParameters dhParams = new DHParameters(p512, g512); + DHKeyGenerationParameters parameters = new DHKeyGenerationParameters(new SecureRandom(), dhParams); DHKeyPairGenerator kpGen = new DHKeyPairGenerator(); + + kpGen.Init(parameters); + + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public; + DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private; + + DHPublicKeyParameters pu2 = new DHPublicKeyParameters(pu1.Y, pu1.Parameters); + DHPrivateKeyParameters pv2 = new DHPrivateKeyParameters(pv1.X, pv1.Parameters); + DHPublicKeyParameters pu3 = new DHPublicKeyParameters(pv1.X, pu1.Parameters); + DHPrivateKeyParameters pv3 = new DHPrivateKeyParameters(pu1.Y, pu1.Parameters); + + doTest(pu1, pu2, pu3); + doTest(pv1, pv2, pv3); + + DHParameters pr1 = pu1.Parameters; + DHParameters pr2 = new DHParameters( + pr1.P, pr1.G, pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters); + DHParameters pr3 = new DHParameters( + pr1.P.Add(BigInteger.Two), pr1.G, pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters); + + doTest(pr1, pr2, pr3); + + pr3 = new DHParameters( + pr1.P, pr1.G.Add(BigInteger.One), pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters); + + doTest(pr1, pr2, pr3); + + pu2 = new DHPublicKeyParameters(pu1.Y, pr2); + pv2 = new DHPrivateKeyParameters(pv1.X, 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.Parameters); + + doTest(k1, k2, k3); + } + + [Test] + public void TestElGamal() + { + BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + ElGamalParameters dhParams = new ElGamalParameters(p512, g512); + ElGamalKeyGenerationParameters parameters = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams); ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator(); + + kpGen.Init(parameters); + + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + ElGamalPublicKeyParameters pu1 = (ElGamalPublicKeyParameters)pair.Public; + ElGamalPrivateKeyParameters pv1 = (ElGamalPrivateKeyParameters)pair.Private; + + ElGamalPublicKeyParameters pu2 = new ElGamalPublicKeyParameters(pu1.Y, pu1.Parameters); + ElGamalPrivateKeyParameters pv2 = new ElGamalPrivateKeyParameters(pv1.X, pv1.Parameters); + ElGamalPublicKeyParameters pu3 = new ElGamalPublicKeyParameters(pv1.X, pu1.Parameters); + ElGamalPrivateKeyParameters pv3 = new ElGamalPrivateKeyParameters(pu1.Y, pu1.Parameters); + + doTest(pu1, pu2, pu3); + doTest(pv1, pv2, pv3); + + ElGamalParameters pr1 = pu1.Parameters; + ElGamalParameters pr2 = new ElGamalParameters(pr1.P, pr1.G); + ElGamalParameters pr3 = new ElGamalParameters(pr1.G, pr1.P); + + doTest(pr1, pr2, pr3); + + pu2 = new ElGamalPublicKeyParameters(pu1.Y, pr2); + pv2 = new ElGamalPrivateKeyParameters(pv1.X, 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.Parameters); + + doTest(k1, k2, k3); + } + + [Test] + public void TestDsa() + { + 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); + } + + [Test] + public void TestGost3410() + { + 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 override void PerformTest() + { + TestDH(); + TestElGamal(); + TestGost3410(); + TestDsa(); + } + + public static void Main( + string[] args) + { + RunTest(new EqualsHashCodeTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/GCMTest.cs b/crypto/test/src/crypto/test/GCMTest.cs new file mode 100644 index 000000000..60630c6e4 --- /dev/null +++ b/crypto/test/src/crypto/test/GCMTest.cs @@ -0,0 +1,589 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Modes.Gcm; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// + /// Test vectors from "The Galois/Counter Mode of Operation (GCM)", McGrew/Viega, Appendix B + /// + [TestFixture] + public class GcmTest + : SimpleTest + { + private static readonly string[][] TestVectors = new string[][] + { + new string[] + { + "Test Case 1", + "00000000000000000000000000000000", + "", + "", + "000000000000000000000000", + "", + "58e2fccefa7e3061367f1d57a4e7455a", + }, + new string[] + { + "Test Case 2", + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "", + "000000000000000000000000", + "0388dace60b6a392f328c2b971b2fe78", + "ab6e47d42cec13bdf53a67b21257bddf", + }, + new string[] + { + "Test Case 3", + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b391aafd255", + "", + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091473f5985", + "4d5c2af327cd64a62cf35abd2ba6fab4", + }, + new string[] + { + "Test Case 4", + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091", + "5bc94fbc3221a5db94fae95ae7121a47", + }, + new string[] + { + "Test Case 5", + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbad", + "61353b4c2806934a777ff51fa22a4755" + + "699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b42" + + "4989b5e1ebac0f07c23f4598", + "3612d2e79e3b0785561be14aaca2fccb", + }, + new string[] + { + "Test Case 6", + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728" + + "c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + "8ce24998625615b603a033aca13fb894" + + "be9112a5c3a211a8ba262a3cca7e2ca7" + + "01e4a9a4fba43c90ccdcb281d48c7c6f" + + "d62875d2aca417034c34aee5", + "619cc5aefffe0bfa462af43c1699d050", + }, + new string[] + { + "Test Case 7", + "00000000000000000000000000000000" + + "0000000000000000", + "", + "", + "000000000000000000000000", + "", + "cd33b28ac773f74ba00ed1f312572435", + }, + new string[] + { + "Test Case 8", + "00000000000000000000000000000000" + + "0000000000000000", + "00000000000000000000000000000000", + "", + "000000000000000000000000", + "98e7247c07f0fe411c267e4384b0f600", + "2ff58d80033927ab8ef4d4587514f0fb", + }, + new string[] + { + "Test Case 9", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b391aafd255", + "", + "cafebabefacedbaddecaf888", + "3980ca0b3c00e841eb06fac4872a2757" + + "859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f47" + + "18e2448b2fe324d9ccda2710acade256", + "9924a7c8587336bfb118024db8674a14", + }, + new string[] + { + "Test Case 10", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbaddecaf888", + "3980ca0b3c00e841eb06fac4872a2757" + + "859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f47" + + "18e2448b2fe324d9ccda2710", + "2519498e80f1478f37ba55bd6d27618c", + }, + new string[] + { + "Test Case 11", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbad", + "0f10f599ae14a154ed24b36e25324db8" + + "c566632ef2bbb34f8347280fc4507057" + + "fddc29df9a471f75c66541d4d4dad1c9" + + "e93a19a58e8b473fa0f062f7", + "65dcc57fcf623a24094fcca40d3533f8", + }, + new string[] + { + "Test Case 12", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728" + + "c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + "d27e88681ce3243c4830165a8fdcf9ff" + + "1de9a1d8e6b447ef6ef7b79828666e45" + + "81e79012af34ddd9e2f037589b292db3" + + "e67c036745fa22e7e9b7373b", + "dcf566ff291c25bbb8568fc3d376a6d9", + }, + new string[] + { + "Test Case 13", + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + "", + "", + "000000000000000000000000", + "", + "530f8afbc74536b9a963b4f1c4cb738b", + }, + new string[] + { + "Test Case 14", + "00000000000000000000000000000000" + + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "", + "000000000000000000000000", + "cea7403d4d606b6e074ec5d3baf39d18", + "d0d1c8a799996bf0265b98b5d48ab919", + }, + new string[] + { + "Test Case 15", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b391aafd255", + "", + "cafebabefacedbaddecaf888", + "522dc1f099567d07f47f37a32a84427d" + + "643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838" + + "c5f61e6393ba7a0abcc9f662898015ad", + "b094dac5d93471bdec1a502270e3cc6c", + }, + new string[] + { + "Test Case 16", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbaddecaf888", + "522dc1f099567d07f47f37a32a84427d" + + "643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838" + + "c5f61e6393ba7a0abcc9f662", + "76fc6ece0f4e1768cddf8853bb2d551b", + }, + new string[] + { + "Test Case 17", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "cafebabefacedbad", + "c3762df1ca787d32ae47c13bf19844cb" + + "af1ae14d0b976afac52ff7d79bba9de0" + + "feb582d33934a4f0954cc2363bc73f78" + + "62ac430e64abe499f47c9b1f", + "3a337dbf46a792c45e454913fe2ea8f2", + }, + new string[] + { + "Test Case 18", + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728" + + "c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + "5a8def2f0c9e53f1f75d7853659e2a20" + + "eeb2b22aafde6419a058ab4f6f746bf4" + + "0fc0c3b780f244452da3ebf1c5d82cde" + + "a2418997200ef82e44ae7e3f", + "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", + }, + }; + + public override string Name + { + get { return "GCM"; } + } + + public override void PerformTest() + { + for (int i = 0; i < TestVectors.Length; ++i) + { + runTestCase(TestVectors[i]); + } + + randomTests(); + } + + private void runTestCase( + string[] testVector) + { + for (int macLength = 12; macLength <= 16; ++macLength) + { + runTestCase(testVector, macLength); + } + } + + private void runTestCase( + string[] testVector, + int macLength) + { + 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]; + Array.Copy(t, T, 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( + IGcmMultiplier encM, + IGcmMultiplier decM, + string testName, + byte[] K, + byte[] IV, + byte[] A, + byte[] P, + byte[] C, + byte[] T) + { + byte[] fa = new byte[A.Length / 2]; + byte[] la = new byte[A.Length - (A.Length / 2)]; + Array.Copy(A, 0, fa, 0, fa.Length); + Array.Copy(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( + IGcmMultiplier encM, + IGcmMultiplier decM, + string testName, + byte[] K, + byte[] IV, + byte[] A, + byte[] SA, + byte[] P, + byte[] C, + byte[] T) + { + 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 = new AeadParameters(null, parameters.MacSize, parameters.GetNonce(), parameters.GetAssociatedText()); + encCipher.Init(true, keyReuseParams); + decCipher.Init(false, keyReuseParams); + checkTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T); + checkTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T); + } + + private GcmBlockCipher initCipher( + IGcmMultiplier m, + bool forEncryption, + AeadParameters parameters) + { + GcmBlockCipher c = new GcmBlockCipher(new AesFastEngine(), m); + c.Init(forEncryption, parameters); + return c; + } + + private void checkTestCase( + GcmBlockCipher encCipher, + GcmBlockCipher decCipher, + string testName, + byte[] SA, + byte[] P, + byte[] C, + byte[] T) + { + 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) + { +// Console.WriteLine("" + enc.Length + "/" + len); + Fail("encryption reported incorrect length: " + testName); + } + + byte[] mac = encCipher.GetMac(); + + byte[] data = new byte[P.Length]; + Array.Copy(enc, data, data.Length); + byte[] tail = new byte[enc.Length - P.Length]; + Array.Copy(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]; + Array.Copy(dec, data, data.Length); + + if (!AreEqual(P, data)) + { + Fail("incorrect decrypt in: " + testName); + } + } + + private void randomTests() + { + SecureRandom srng = new SecureRandom(); + for (int i = 0; i < 10; ++i) + { + randomTest(srng, null); + randomTest(srng, new BasicGcmMultiplier()); + randomTest(srng, new Tables8kGcmMultiplier()); + randomTest(srng, new Tables64kGcmMultiplier()); + } + } + + private void randomTest( + SecureRandom srng, + IGcmMultiplier m) + { + int kLength = 16 + 8 * srng.Next(3); + byte[] K = new byte[kLength]; + srng.NextBytes(K); + + int pLength = srng.Next(65536); + byte[] P = new byte[pLength]; + srng.NextBytes(P); + + int aLength = srng.Next(256); + byte[] A = new byte[aLength]; + srng.NextBytes(A); + + int saLength = srng.Next(256); + byte[] SA = new byte[saLength]; + srng.NextBytes(SA); + + int ivLength = 1 + srng.Next(256); + byte[] IV = new byte[ivLength]; + srng.NextBytes(IV); + + GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine(), m); + AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A); + cipher.Init(true, parameters); + byte[] C = new byte[cipher.GetOutputSize(P.Length)]; + int predicted = cipher.GetUpdateOutputSize(P.Length); + + int split = srng.Next(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]; + Array.Copy(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 = srng.Next(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"); + } + } + + public static void Main( + string[] args) + { + RunTest(new GcmTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/GOST28147MacTest.cs b/crypto/test/src/crypto/test/GOST28147MacTest.cs new file mode 100644 index 000000000..5f3188f48 --- /dev/null +++ b/crypto/test/src/crypto/test/GOST28147MacTest.cs @@ -0,0 +1,105 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * GOST 28147 MAC tester + */ + [TestFixture] + public class Gost28147MacTest + : ITest + { + // + // 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 ITestResult Perform() + { + // test1 + IMac mac = new Gost28147Mac(); + KeyParameter key = new KeyParameter(gkeyBytes1); + + mac.Init(key); + + mac.BlockUpdate(input3, 0, input3.Length); + + byte[] outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output7)) + { + return new SimpleTestResult(false, Name + ": Failed test 1 - expected " + + Hex.ToHexString(output7) + + " got " + Hex.ToHexString(outBytes)); + } + + // test2 + key = new KeyParameter(gkeyBytes2); + + ParametersWithSBox gparam = new ParametersWithSBox(key, Gost28147Engine.GetSBox("E-A")); + + mac.Init(gparam); + + mac.BlockUpdate(input4, 0, input4.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output8)) + { + return new SimpleTestResult(false, Name + ": Failed test 2 - expected " + + Hex.ToHexString(output8) + + " got " + Hex.ToHexString(outBytes)); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public string Name + { + get { return "Gost28147Mac"; } + } + + public static void Main( + string[] args) + { + ITest test = new Gost28147MacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/GOST28147Test.cs b/crypto/test/src/crypto/test/GOST28147Test.cs new file mode 100644 index 000000000..5b6753517 --- /dev/null +++ b/crypto/test/src/crypto/test/GOST28147Test.cs @@ -0,0 +1,334 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Gost28147Test + : 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 + + }; + + private const int Gost28147_KEY_LENGTH = 32; + + private byte[] generateKey(byte[] startkey) + { + byte[] newKey = new byte[Gost28147_KEY_LENGTH]; + + Gost3411Digest digest = new Gost3411Digest(); + + digest.BlockUpdate(startkey, 0, startkey.Length); + digest.DoFinal(newKey, 0); + + return newKey; + } + + public Gost28147Test() + : base(tests, new Gost28147Engine(), new KeyParameter(new byte[32])) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + //advanced tests with Gost28147KeyGenerator: + //encrypt on hesh message; ECB mode: + byte[] inBytes = Hex.Decode("4e6f77206973207468652074696d6520666f7220616c6c20"); + byte[] output = Hex.Decode("8ad3c8f56b27ff1fbd46409359bdc796bc350e71aac5f5c0"); + byte[] outBytes = new byte[inBytes.Length]; + + byte[] key = generateKey(Hex.Decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!! + // System.out.println(new string(Hex.Encode(key))); + ICipherParameters 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(inBytes, 0, inBytes.Length, outBytes, 0); + try + { + cipher.DoFinal(outBytes, len1); + } + catch (CryptoException e) + { + Fail("failed - exception " + e.ToString(), e); + } + + if (outBytes.Length != output.Length) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + " got " + + Hex.ToHexString(outBytes)); + } + + for (int i = 0; i != outBytes.Length; i++) + { + if (outBytes[i] != output[i]) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + } + + + //encrypt on hesh message; CFB mode: + inBytes = Hex.Decode("bc350e71aac5f5c2"); + output = Hex.Decode("0ebbbafcf38f14a5"); + outBytes = new byte[inBytes.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(inBytes, 0, inBytes.Length, outBytes, 0); + try + { + cipher.DoFinal(outBytes, len1); + } + catch (CryptoException e) + { + Fail("failed - exception " + e.ToString(), e); + } + if (outBytes.Length != output.Length) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + for (int i = 0; i != outBytes.Length; i++) + { + if (outBytes[i] != output[i]) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + } + + + //encrypt on hesh message; CFB mode: + inBytes = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f"); + output = Hex.Decode("64988982819f0a1655e226e19ecad79d10cc73bac95c5d7da034786c12294225"); + outBytes = new byte[inBytes.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(inBytes, 0, inBytes.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len1); + + if (outBytes.Length != output.Length) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + + for (int i = 0; i != outBytes.Length; i++) + { + if (outBytes[i] != output[i]) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + } + + //encrypt on hesh message; OFB mode: + inBytes = Hex.Decode("bc350e71aa11345709acde"); + output = Hex.Decode("1bcc2282707c676fb656dc"); + outBytes = new byte[inBytes.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(inBytes, 0, inBytes.Length, outBytes, 0); + + cipher.DoFinal(outBytes, len1); + + if (outBytes.Length != output.Length) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + + for (int i = 0; i != outBytes.Length; i++) + { + if (outBytes[i] != output[i]) + { + Fail("failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + } + } + + public override string Name + { + get { return "Gost28147"; } + } + + public static void Main( + string[] args) + { + ITest test = new Gost28147Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/GOST3410Test.cs b/crypto/test/src/crypto/test/GOST3410Test.cs new file mode 100644 index 000000000..f54662770 --- /dev/null +++ b/crypto/test/src/crypto/test/GOST3410Test.cs @@ -0,0 +1,1604 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Gost3410Test + : ITest + { + private static readonly byte[] hashmessage = Hex.Decode("3042453136414534424341374533364339313734453431443642453241453435"); + + private static byte[] zeroTwo(int length) + { + byte[] data = new byte[length]; + data[data.Length - 1] = 0x02; + return data; + } + + private class Gost3410_TEST1_512 + : ITest + { + public string Name + { + get { return "Gost3410-TEST1-512"; } + } + + FixedSecureRandom init_random = FixedSecureRandom.From(Hex.Decode("00005EC900007341"), zeroTwo(64)); + FixedSecureRandom random = FixedSecureRandom.From(Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A")); + FixedSecureRandom keyRandom = FixedSecureRandom.From(Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046")); + + BigInteger pValue = new BigInteger("EE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3", 16); + BigInteger qValue = new BigInteger("98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("3e5f895e276d81d2d52c0763270a458157b784c57abdbd807bc44fd43a32ac06",16); + BigInteger s = new BigInteger("3f0dd5d4400d47c08e4ce505ff7434b6dbf729592e37c74856dab85115a60955",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(512, 1, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (parameters.ValidationParameters == null) + { + return new SimpleTestResult(false, Name + "validation parameters wrong"); + } + + if (parameters.ValidationParameters.C != 29505 + || parameters.ValidationParameters.X0 != 24265) + { + return new SimpleTestResult(false, Name + "validation parameters values wrong"); + } + + if (!init_random.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'init_random'."); + } + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + if (!keyRandom.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'keyRandom'."); + } + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer gost3410 = new Gost3410Signer(); + + gost3410.Init(true, param); + + BigInteger[] sig = gost3410.GenerateSignature(hashmessage); + + if (!random.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'random'."); + } + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + gost3410.Init(false, pair.Public); + + if (gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_TEST2_512 + : ITest + { + public string Name + { + get { return "Gost3410-TEST2-512"; } + } + + FixedSecureRandom init_random = FixedSecureRandom.From(Hex.Decode("000000003DFC46F1000000000000000D"), zeroTwo(64)); + FixedSecureRandom random = FixedSecureRandom.From(Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A")); + FixedSecureRandom keyRandom = FixedSecureRandom.From(Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046")); + + BigInteger pValue = new BigInteger("8b08eb135af966aab39df294538580c7da26765d6d38d30cf1c06aae0d1228c3316a0e29198460fad2b19dc381c15c888c6dfd0fc2c565abb0bf1faff9518f85", 16); + BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("7c07c8cf035c2a1cb2b7fae5807ac7cd623dfca7a1a68f6d858317822f1ea00d",16); + BigInteger s = new BigInteger("7e9e036a6ff87dbf9b004818252b1f6fc310bdd4d17cb8c37d9c36c7884de60c",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(512, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!init_random.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'init_random'."); + } + + if (parameters.ValidationParameters == null) + { + return new SimpleTestResult(false, Name + ": validation parameters wrong"); + } + + if (parameters.ValidationParameters.CL != 13 + || parameters.ValidationParameters.X0L != 1039943409) + { + return new SimpleTestResult(false, Name + ": validation parameters values wrong"); + } + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + if (!keyRandom.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'keyRandom'."); + } + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!random.IsExhausted) + { + return new SimpleTestResult(false, Name + + ": unexpected number of bytes used from 'random'."); + } + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (!Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + } + + private class Gost3410_TEST1_1024 + : ITest + { + public string Name + { + get { return "Gost3410-TEST1-1024"; } + } + + private class SecureRandomImpl1 : SecureRandom + { + bool firstInt = true; + + public override int NextInt() + { + string x0 = "0xA565"; + string c = "0x538B"; + + if (firstInt) + { + firstInt = false; + return NumberParsing.DecodeIntFromHex(x0); + } + return NumberParsing.DecodeIntFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + + byte[] d = Hex.Decode("02"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl1(); + + private class SecureRandomImpl2 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl2(); + + private class SecureRandomImpl3 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl3(); + + BigInteger pValue = new BigInteger("ab8f37938356529e871514c1f48c5cbce77b2f4fc9a2673ac2c1653da8984090c0ac73775159a26bef59909d4c9846631270e16653a6234668f2a52a01a39b921490e694c0f104b58d2e14970fccb478f98d01e975a1028b9536d912de5236d2dd2fc396b77153594d4178780e5f16f718471e2111c8ce64a7d7e196fa57142d", 16); + BigInteger qValue = new BigInteger("bcc02ca0ce4f0753ec16105ee5d530aa00d39f3171842ab2c334a26b5f576e0f", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("a8790aabbd5a998ff524bad048ac69cd1faff2dab048265c8d60d1471c44a9ee",16); + BigInteger s = new BigInteger("30df5ba32ac77170b9632559bef7d37620017756dff3fea1088b4267db0944b8",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 1, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_TEST2_1024 + : ITest + { + public string Name + { + get { return "Gost3410-TEST2-1024"; } + } + + private class SecureRandomImpl4 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x3DFC46F1"; + string c = "0xD"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + + byte[] d = Hex.Decode("02"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl4(); + + private class SecureRandomImpl5 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl5(); + + private class SecureRandomImpl6 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl6(); + + BigInteger pValue = new BigInteger("e2c4191c4b5f222f9ac2732562f6d9b4f18e7fb67a290ea1e03d750f0b9806755fc730d975bf3faa606d05c218b35a6c3706919aab92e0c58b1de4531c8fa8e7af43c2bff016251e21b2870897f6a27ac4450bca235a5b748ad386e4a0e4dfcb09152435abcfe48bd0b126a8122c7382f285a9864615c66decddf6afd355dfb7", 16); + BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("81d69a192e9c7ac21fc07da41bd07e230ba6a94eb9f3c1fd104c7bd976733ca5",16); + BigInteger s = new BigInteger("315c879c8414f35feb4deb15e7cc0278c48e6ca1596325d6959338d860b0c47a",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_AParam + : ITest + { + public string Name + { + get { return "Gost3410-AParam"; } + } + + private class SecureRandomImpl7 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x520874F5"; + string c = "0xEE39ADB3"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + + byte[] d = Hex.Decode("02"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl7(); + + private class SecureRandomImpl8 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl8(); + + private class SecureRandomImpl9 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl9(); + + BigInteger pValue = new BigInteger("b4e25efb018e3c8b87505e2a67553c5edc56c2914b7e4f89d23f03f03377e70a2903489dd60e78418d3d851edb5317c4871e40b04228c3b7902963c4b7d85d52b9aa88f2afdbeb28da8869d6df846a1d98924e925561bd69300b9ddd05d247b5922d967cbb02671881c57d10e5ef72d3e6dad4223dc82aa1f7d0294651a480df", 16); + BigInteger qValue = new BigInteger("972432a437178b30bd96195b773789ab2fff15594b176dd175b63256ee5af2cf", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("64a8856628e5669d85f62cd763dd4a99bc56d33dc0e1859122855d141e9e4774",16); + BigInteger s = new BigInteger("319ebac97092b288d469a4b988248794f60c865bc97858d9a3135c6d1a1bf2dd",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_BParam + : ITest + { + public string Name + { + get { return "Gost3410-BParam"; } + } + + private class SecureRandomImpl10 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x5B977CDB"; + string c = "0x6E9692DD"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + byte[] d = Hex.Decode("bc3cbbdb7e6f848286e19ad9a27a8e297e5b71c53dd974cdf60f937356df69cbc97a300ccc71685c553046147f11568c4fddf363d9d886438345a62c3b75963d6546adfabf31b31290d12cae65ecb8309ef66782"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl10(); + + private class SecureRandomImpl11 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl11(); + + private class SecureRandomImpl12 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl12(); + + BigInteger pValue = new BigInteger("c6971fc57524b30c9018c5e621de15499736854f56a6f8aee65a7a404632b3540f09020f67f04dc2e6783b141dceffd21a703035b7d0187c6e12cb4229922bafdb2225b73e6b23a0de36e20047065aea000c1a374283d0ad8dc1981e3995f0bb8c72526041fcb98ae6163e1e71a669d8364e9c4c3188f673c5f8ee6fadb41abf", 16); + BigInteger qValue = new BigInteger("b09d634c10899cd7d4c3a7657403e05810b07c61a688bab2c37f475e308b0607", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("860d82c60e9502cd00c0e9e1f6563feafec304801974d745c5e02079946f729e",16); + BigInteger s = new BigInteger("7ef49264ef022801aaa03033cd97915235fbab4c823ed936b0f360c22114688a",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_CParam + : ITest + { + public string Name + { + get { return "Gost3410-CParam"; } + } + + private class SecureRandomImpl13 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x43848744"; + string c = "0xB50A826D"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + byte[] d = Hex.Decode("7F575E8194BC5BDF"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl13(); + + private class SecureRandomImpl14 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl14(); + + private class SecureRandomImpl15 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl15(); + + BigInteger pValue = new BigInteger("9d88e6d7fe3313bd2e745c7cdd2ab9ee4af3c8899e847de74a33783ea68bc30588ba1f738c6aaf8ab350531f1854c3837cc3c860ffd7e2e106c3f63b3d8a4c034ce73942a6c3d585b599cf695ed7a3c4a93b2b947b7157bb1a1c043ab41ec8566c6145e938a611906de0d32e562494569d7e999a0dda5c879bdd91fe124df1e9", 16); + BigInteger qValue = new BigInteger("fadd197abd19a1b4653eecf7eca4d6a22b1f7f893b641f901641fbb555354faf", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("4deb95a0b35e7ed7edebe9bef5a0f93739e16b7ff27fe794d989d0c13159cfbc",16); + BigInteger s = new BigInteger("e1d0d30345c24cfeb33efde3deee5fbbda78ddc822b719d860cd0ba1fb6bd43b",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_DParam + : ITest + { + public string Name + { + get { return "Gost3410-DParam"; } + } + + private class SecureRandomImpl16 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x13DA8B9D"; + string c = "0xA0E9DE4B"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + + byte[] d = Hex.Decode("41ab97857f42614355d32db0b1069f109a4da283676c7c53a68185b4"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl16(); + + private class SecureRandomImpl17 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl17(); + + private class SecureRandomImpl18 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl18(); + + BigInteger pValue = new BigInteger("80f102d32b0fd167d069c27a307adad2c466091904dbaa55d5b8cc7026f2f7a1919b890cb652c40e054e1e9306735b43d7b279eddf9102001cd9e1a831fe8a163eed89ab07cf2abe8242ac9dedddbf98d62cddd1ea4f5f15d3a42a6677bdd293b24260c0f27c0f1d15948614d567b66fa902baa11a69ae3bceadbb83e399c9b5", 16); + BigInteger qValue = new BigInteger("f0f544c418aac234f683f033511b65c21651a6078bda2d69bb9f732867502149", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("712592d285b792e33b8a9a11e8e6c4f512ddf0042972bbfd1abb0a93e8fc6f54",16); + BigInteger s = new BigInteger("2cf26758321258b130d5612111339f09ceb8668241f3482e38baa56529963f07",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_AExParam + : ITest + { + public string Name + { + get { return "Gost3410-AExParam"; } + } + + private class SecureRandomImpl19 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0xD05E9F14"; + string c = "0x46304C5F"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + byte[] d = Hex.Decode("35ab875399cda33c146ca629660e5a5e5c07714ca326db032dd6751995cdb90a612b9228932d8302704ec24a5def7739c5813d83"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl19(); + + private class SecureRandomImpl20 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl20(); + + private class SecureRandomImpl21 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl21(); + + BigInteger pValue = new BigInteger("ca3b3f2eee9fd46317d49595a9e7518e6c63d8f4eb4d22d10d28af0b8839f079f8289e603b03530784b9bb5a1e76859e4850c670c7b71c0df84ca3e0d6c177fe9f78a9d8433230a883cd82a2b2b5c7a3306980278570cdb79bf01074a69c9623348824b0c53791d53c6a78cab69e1cfb28368611a397f50f541e16db348dbe5f", 16); + BigInteger qValue = new BigInteger("cae4d85f80c147704b0ca48e85fb00a9057aa4acc44668e17f1996d7152690d9", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("90892707282f433398488f19d31ac48523a8e2ded68944e0da91c6895ee7045e",16); + BigInteger s = new BigInteger("3be4620ee88f1ee8f9dd63c7d145b7e554839feeca125049118262ea4651e9de",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_BExParam + : ITest + { + public string Name + { + get { return "Gost3410-BExParam"; } + } + + private class SecureRandomImpl22 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x7A007804"; + string c = "0xD31A4FF7"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + byte[] d = Hex.Decode("7ec123d161477762838c2bea9dbdf33074af6d41d108a066a1e7a07ab3048de2"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl22(); + + private class SecureRandomImpl23 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl23(); + + private class SecureRandomImpl24 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl24(); + + BigInteger pValue = new BigInteger("9286dbda91eccfc3060aa5598318e2a639f5ba90a4ca656157b2673fb191cd0589ee05f4cef1bd13508408271458c30851ce7a4ef534742bfb11f4743c8f787b11193ba304c0e6bca25701bf88af1cb9b8fd4711d89f88e32b37d95316541bf1e5dbb4989b3df13659b88c0f97a3c1087b9f2d5317d557dcd4afc6d0a754e279", 16); + BigInteger qValue = new BigInteger("c966e9b3b8b7cdd82ff0f83af87036c38f42238ec50a876cd390e43d67b6013f", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("8f79a582513df84dc247bcb624340cc0e5a34c4324a20ce7fe3ab8ff38a9db71",16); + BigInteger s = new BigInteger("7508d22fd6cbb45efd438cb875e43f137247088d0f54b29a7c91f68a65b5fa85",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + private class Gost3410_CExParam + : ITest + { + public string Name + { + get { return "Gost3410-CExParam"; } + } + + private class SecureRandomImpl25 : SecureRandom + { + bool firstLong = true; + + public override long NextLong() + { + string x0 = "0x162AB910"; + string c = "0x93F828D3"; + + if (firstLong) + { + firstLong = false; + return NumberParsing.DecodeLongFromHex(x0); + } + return NumberParsing.DecodeLongFromHex(c); + } + + public override void NextBytes(byte[] bytes) + { + byte[] d = Hex.Decode("ca82cce78a738bc46f103d53b9bf809745ec845e4f6da462606c51f60ecf302e31204b81"); + + Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length); + } + }; + SecureRandom init_random = new SecureRandomImpl25(); + + private class SecureRandomImpl26 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"); + + int i; + + for (i = 0; i < (bytes.Length - k.Length); i += k.Length) + { + Array.Copy(k, 0, bytes, i, k.Length); + } + + if (i > bytes.Length) + { + Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length)); + } + else + { + Array.Copy(k, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom random = new SecureRandomImpl26(); + + private class SecureRandomImpl27 : SecureRandom + { + public override void NextBytes(byte[] bytes) + { + byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"); + + int i; + + for (i = 0; i < (bytes.Length - x.Length); i += x.Length) + { + Array.Copy(x, 0, bytes, i, x.Length); + } + + if (i > bytes.Length) + { + Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length)); + } + else + { + Array.Copy(x, 0, bytes, i, bytes.Length - i); + } + } + }; + SecureRandom keyRandom = new SecureRandomImpl27(); + + BigInteger pValue = new BigInteger("b194036ace14139d36d64295ae6c50fc4b7d65d8b340711366ca93f383653908ee637be428051d86612670ad7b402c09b820fa77d9da29c8111a8496da6c261a53ed252e4d8a69a20376e6addb3bdcd331749a491a184b8fda6d84c31cf05f9119b5ed35246ea4562d85928ba1136a8d0e5a7e5c764ba8902029a1336c631a1d", 16); + BigInteger qValue = new BigInteger("96120477df0f3896628e6f4a88d83c93204c210ff262bccb7dae450355125259", 16); + + public ITestResult Perform() + { + BigInteger r = new BigInteger("169fdb2dc09f690b71332432bfec806042e258fa9a21dafe73c6abfbc71407d9",16); + BigInteger s = new BigInteger("9002551808ae40d19f6f31fb67e4563101243cf07cffd5f2f8ff4c537b0c9866",16); + Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator(); + + pGen.Init(1024, 2, init_random); + + Gost3410Parameters parameters = pGen.GenerateParameters(); + + if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q)) + { + return new SimpleTestResult(false, Name + ": p or q wrong"); + } + + Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator(); + Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters); + + Gost3410KeyGen.Init(genParam); + + AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair(); + + ParametersWithRandom param = new ParametersWithRandom(pair.Private, random); + + Gost3410Signer Gost3410 = new Gost3410Signer(); + + Gost3410.Init(true, param); + + BigInteger[] sig = Gost3410.GenerateSignature(hashmessage); + + if (!r.Equals(sig[0])) + { + return new SimpleTestResult(false, Name + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r.ToString(16) + SimpleTest.NewLine + + " got : " + sig[0].ToString(16)); + } + + if (!s.Equals(sig[1])) + { + return new SimpleTestResult(false, Name + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s.ToString(16) + SimpleTest.NewLine + + " got : " + sig[1].ToString(16)); + } + + Gost3410.Init(false, pair.Public); + + if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1])) + { + return new SimpleTestResult(true, Name + ": Okay"); + } + else + { + return new SimpleTestResult(false, Name + ": verification fails"); + } + } + } + + ITest[] 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 Name + { + get { return "Gost3410"; } + } + + public ITestResult Perform() + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult result = tests[i].Perform(); + + if (!result.IsSuccessful()) + { + return result; + } + } + + return new SimpleTestResult(true, "Gost3410: Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Gost3410Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/GOST3411DigestTest.cs b/crypto/test/src/crypto/test/GOST3411DigestTest.cs new file mode 100644 index 000000000..1826b28c9 --- /dev/null +++ b/crypto/test/src/crypto/test/GOST3411DigestTest.cs @@ -0,0 +1,79 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Gost3411DigestTest + : DigestTest + { + private static readonly 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 readonly string[] digests = + { + "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0", + "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb", + "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011", + "73b70a39497de53a6e08c67b6d4db853540f03e9389299d9b0156ef7e85d0f61" + }; + + // If S-box = D-Test (see: digest/GOST3411Digest.cs; function:E(byte[] in, byte[] key); string: ICipherParameters p = new Gost28147Parameters(key, "D-Test");) +// private static readonly string[] digests = +// { +// "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d", +// "b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa", +// "471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208", +// "95c1af627c356496d80274330b2cff6a10c67b5f597087202f94d06d2338cf8e" +// }; + + // 1 million 'a' + static private string million_a_digest = "8693287aa62f9478f7cb312ec0866b6c4e4a0f11160441e8f4ffcd2715dd554f"; + + public Gost3411DigestTest() + : base(new Gost3411Digest(), messages, digests) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + millionATest(million_a_digest); + } + + protected override IDigest CloneDigest(IDigest digest) + { + return new Gost3411Digest((Gost3411Digest)digest); + } + + public static void Main( + string[] args) + { + ITest test = new Gost3411DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/GcmReorderTest.cs b/crypto/test/src/crypto/test/GcmReorderTest.cs new file mode 100644 index 000000000..54d17f4f4 --- /dev/null +++ b/crypto/test/src/crypto/test/GcmReorderTest.cs @@ -0,0 +1,362 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Modes.Gcm; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class GcmReorderTest + { + private static readonly byte[] H; + private static readonly SecureRandom random = new SecureRandom(); + private static readonly IGcmMultiplier mul = new Tables64kGcmMultiplier(); + private static readonly IGcmExponentiator exp = new Tables1kGcmExponentiator(); + private static readonly byte[] Empty = new byte[0]; + + static GcmReorderTest() + { + H = new byte[16]; + random.NextBytes(H); + mul.Init(Arrays.Clone(H)); + exp.Init(Arrays.Clone(H)); + } + + [Test] + public void TestCombine() + { + 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); + + Assert.IsTrue(Arrays.AreEqual(ghashAC, ghashCombine)); + } + } + + [Test] + public void TestConcatAuth() + { + 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_val = GHASH(PA, Empty); + byte[] ghashConcat = concatAuth_GHASH(ghashP_, (long)P.Length * 8, ghashA_, (long)A.Length * 8); + + Assert.IsTrue(Arrays.AreEqual(ghashPA_val, ghashConcat)); + } + } + + [Test] + public void TestConcatCrypt() + { + 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); + + Assert.IsTrue(Arrays.AreEqual(ghash_PA, ghashConcat)); + } + } + + [Test] + public void TestExp() + { + { + byte[] buf1 = new byte[16]; + buf1[0] = 0x80; + + byte[] buf2 = new byte[16]; + + for (int pow = 0; pow != 100; ++pow) + { + exp.ExponentiateX(pow, buf2); + + Assert.IsTrue(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); + + Assert.IsTrue(Arrays.AreEqual(expected, actual)); + } + } + + [Test] + public void TestMultiply() + { + byte[] expected = Arrays.Clone(H); + mul.MultiplyH(expected); + + Assert.IsTrue(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); + Assert.IsTrue(Arrays.AreEqual(expected, multiply(a, H))); + Assert.IsTrue(Arrays.AreEqual(expected, multiply(H, a))); + + expected = Arrays.Clone(b); + mul.MultiplyH(expected); + Assert.IsTrue(Arrays.AreEqual(expected, multiply(b, H))); + Assert.IsTrue(Arrays.AreEqual(expected, multiply(H, b))); + + Assert.IsTrue(Arrays.AreEqual(multiply(a, b), multiply(b, a))); + } + } + + private byte[] randomBlocks(int upper) + { + byte[] bs = new byte[16 * random.Next(upper)]; + random.NextBytes(bs); + return bs; + } + + private byte[] randomBytes(int upper) + { + byte[] bs = new byte[random.Next(upper)]; + random.NextBytes(bs); + return bs; + } + + private byte[] concatArrays(byte[] a, byte[] b) + { + byte[] ab = new byte[a.Length + b.Length]; + Array.Copy(a, 0, ab, 0, a.Length); + Array.Copy(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 = System.Math.Min(A.Length - pos, 16); + Array.Copy(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 = System.Math.Min(C.Length - pos, 16); + Array.Copy(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]; + UInt64_To_BE((ulong)bitlenA, tmp, 0); + UInt64_To_BE((ulong)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 void UInt64_To_BE(ulong n, byte[] bs, int off) + { + UInt32_To_BE((uint)(n >> 32), bs, off); + UInt32_To_BE((uint)(n), bs, off + 4); + } + + private static void UInt32_To_BE(uint n, byte[] bs, int off) + { + bs[ off] = (byte)(n >> 24); + bs[++off] = (byte)(n >> 16); + bs[++off] = (byte)(n >> 8); + bs[++off] = (byte)(n ); + } + + 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); + } + + bool lsb = (tmp[15] & 1) != 0; + shiftRight(tmp); + if (lsb) + { + // R = new byte[]{ 0xe1, ... }; + //GcmUtilities.Xor(tmp, R); + tmp[0] ^= (byte)0xe1; + } + } + } + + return c; + } + + private static void shiftRight(byte[] block) + { + int i = 0; + byte bit = 0; + for (;;) + { + byte b = block[i]; + block[i] = (byte)((b >> 1) | bit); + if (++i == 16) break; + bit = (byte)(b << 7); + } + } + } +} diff --git a/crypto/test/src/crypto/test/HCFamilyTest.cs b/crypto/test/src/crypto/test/HCFamilyTest.cs new file mode 100644 index 000000000..0904bc9eb --- /dev/null +++ b/crypto/test/src/crypto/test/HCFamilyTest.cs @@ -0,0 +1,192 @@ +using System; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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
    +	 * 
    + * See HCFamilyVecTest for a more exhaustive test based on the ecrypt vectors. + */ + public class HCFamilyTest + : SimpleTest + { + private static readonly byte[] MSG = new byte[64]; + + private static readonly string[][] HC128_VerifiedTest = new string[][] + { + new string[]{ + "Set 2, vector# 0", + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "82001573A003FD3B7FD72FFB0EAF63AA" + + "C62F12DEB629DCA72785A66268EC758B" + + "1EDB36900560898178E0AD009ABF1F49" + + "1330DC1C246E3D6CB264F6900271D59C" + }, + new string[]{ + "Set 6, vector# 0", + "0053A6F94C9FF24598EB3E91E4378ADD", + "0D74DB42A91077DE45AC137AE148AF16", + "2E1ED12A8551C05AF41FF39D8F9DF933" + + "122B5235D48FC2A6F20037E69BDBBCE8" + + "05782EFC16C455A4B3FF06142317535E" + + "F876104C32445138CB26EBC2F88A684C" + }, + new string[]{ + "Set 6, vector# 1", + "0558ABFE51A4F74A9DF04396E93C8FE2", + "167DE44BB21980E74EB51C83EA51B81F", + "4F864BF3C96D0363B1903F0739189138" + + "F6ED2BC0AF583FEEA0CEA66BA7E06E63" + + "FB28BF8B3CA0031D24ABB511C57DD17B" + + "FC2861C32400072CB680DF2E58A5CECC" + }, + new string[]{ + "Set 6, vector# 2", + "0A5DB00356A9FC4FA2F5489BEE4194E7", + "1F86ED54BB2289F057BE258CF35AC128", + "82168AB0023B79AAF1E6B4D823855E14" + + "A7084378036A951B1CFEF35173875ED8" + + "6CB66AB8410491A08582BE40080C3102" + + "193BA567F9E95D096C3CC60927DD7901" + }, + new string[]{ + "Set 6, vector# 3", + "0F62B5085BAE0154A7FA4DA0F34699EC", + "288FF65DC42B92F960C72E95FC63CA31", + "1CD8AEDDFE52E217E835D0B7E84E2922" + + "D04B1ADBCA53C4522B1AA604C42856A9" + + "0AF83E2614BCE65C0AECABDD8975B557" + + "00D6A26D52FFF0888DA38F1DE20B77B7" + } + }; + + private static readonly string[][] HC256_VerifiedTest = new string[][] + { + new string[]{ + "Set 2, vector# 0", + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "5B078985D8F6F30D42C5C02FA6B67951" + + "53F06534801F89F24E74248B720B4818" + + "CD9227ECEBCF4DBF8DBF6977E4AE14FA" + + "E8504C7BC8A9F3EA6C0106F5327E6981" + }, + new string[]{ + "Set 2, vector# 9", + "09090909090909090909090909090909", + "00000000000000000000000000000000", + "F5C2926651AEED9AF1A9C2F04C03D081" + + "2145B56AEA46EB283A25A4C9E3D8BEB4" + + "821B418F06F2B9DCDF1A85AB8C02CD14" + + "62E1BBCAEC9AB0E99AA6AFF918BA627C" + }, + new string[]{ + "Set 2, vector#135", + "87878787878787878787878787878787", + "00000000000000000000000000000000", + "CEC0C3852E3B98233EBCB975C10B1191" + + "3C69F2275EB97A1402EDF16C6FBE19BE" + + "79D65360445BCB63676E6553B609A065" + + "0155C3B22DD1975AC0F3F65063A2E16E" + }, + new string[]{ + "Set 6, vector# 0", + "0053A6F94C9FF24598EB3E91E4378ADD" + + "3083D6297CCF2275C81B6EC11467BA0D", + "0D74DB42A91077DE45AC137AE148AF16" + + "7DE44BB21980E74EB51C83EA51B81F86", + "23D9E70A45EB0127884D66D9F6F23C01" + + "D1F88AFD629270127247256C1FFF91E9" + + "1A797BD98ADD23AE15BEE6EEA3CEFDBF" + + "A3ED6D22D9C4F459DB10C40CDF4F4DFF" + }, + new string[]{ + "Set 6, vector# 1", + "0558ABFE51A4F74A9DF04396E93C8FE2" + + "3588DB2E81D4277ACD2073C6196CBF12", + "167DE44BB21980E74EB51C83EA51B81F" + + "86ED54BB2289F057BE258CF35AC1288F", + "C44B5262F2EAD9C018213127686DB742" + + "A72D3F2D61D18F0F4E7DE5B4F7ADABE0" + + "7E0C82033B139F02BAACB4E2F2D0BE30" + + "110C3A8A2B621523756692877C905DD0" + }, + new string[]{ + "Set 6, vector# 2", + "0A5DB00356A9FC4FA2F5489BEE4194E7" + + "3A8DE03386D92C7FD22578CB1E71C417", + "1F86ED54BB2289F057BE258CF35AC128" + + "8FF65DC42B92F960C72E95FC63CA3198", + "9D13AA06122F4F03AE60D507701F1ED0" + + "63D7530FF35EE76CAEDCBFB01D8A239E" + + "FA4A44B272DE9B4092E2AD56E87C3A60" + + "89F5A074D1F6E5B8FC6FABEE0C936F06" + }, + new string[]{ + "Set 6, vector# 3", + "0F62B5085BAE0154A7FA4DA0F34699EC" + + "3F92E5388BDE3184D72A7DD02376C91C", + "288FF65DC42B92F960C72E95FC63CA31" + + "98FF66CD349B0269D0379E056CD33AA1", + "C8632038DA61679C4685288B37D3E232" + + "7BC2D28C266B041FE0CA0D3CFEED8FD5" + + "753259BAB757168F85EA96ADABD823CA" + + "4684E918423E091565713FEDDE2CCFE0" + } + }; + + public override string Name + { + get { return "HC-128 and HC-256"; } + } + + public override void PerformTest() + { + IStreamCipher 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(IStreamCipher 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/crypto/test/src/crypto/test/HCFamilyVecTest.cs b/crypto/test/src/crypto/test/HCFamilyVecTest.cs new file mode 100644 index 000000000..00b0ee75c --- /dev/null +++ b/crypto/test/src/crypto/test/HCFamilyVecTest.cs @@ -0,0 +1,184 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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 + */ + [TestFixture] + public class HCFamilyVecTest + : SimpleTest + { + private class PeekableLineReader + : StreamReader + { + public PeekableLineReader(Stream s) + : base(s) + { + peek = base.ReadLine(); + } + + public string PeekLine() + { + return peek; + } + + public override string ReadLine() + { + string tmp = peek; + peek = base.ReadLine(); + return tmp; + } + + private string peek; + } + + public override string Name + { + get { return "HC-128 and HC-256"; } + } + + public override void PerformTest() + { + RunTests(new HC128Engine(), "hc128/ecrypt_HC-128.txt"); + RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_128K_128IV.txt"); + RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_256K_128IV.txt"); + RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_128K_256IV.txt"); + RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_256K_256IV.txt"); + } + + private void RunTests(IStreamCipher hc, string fileName) + { + Stream resource = SimpleTest.GetTestDataAsStream( + "hc256." + fileName.Replace('/', '.')); + PeekableLineReader r = new PeekableLineReader(resource); + RunAllVectors(hc, fileName, r); + } + + private void RunAllVectors(IStreamCipher hc, string fileName, PeekableLineReader r) + { + for (;;) + { + string line = r.ReadLine(); + if (line == null) + break; + + line = line.Trim(); + + if (line.StartsWith("Set ")) + { + RunVector(hc, fileName, r, line.Replace(":", "")); + } + } + } + + private void RunVector(IStreamCipher hc, string fileName, PeekableLineReader r, string vectorName) + { +// Console.WriteLine(fileName + " => " + vectorName); + string hexKey = ReadBlock(r); + string hexIV = ReadBlock(r); + + ICipherParameters 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); +// Console.WriteLine(fileName + " => " + vectorName + " failed at " + lead); return; + } + break; + } + + int posA = lead.IndexOf('['); + int posB = lead.IndexOf(".."); + int posC = lead.IndexOf(']'); + int start = Int32.Parse(lead.Substring(posA + 1, posB - (posA + 1))); + int end = Int32.Parse(lead.Substring(posB + 2, posC - (posB + 2))); + + if (start % 64 != 0 || (end - start != 63)) + throw new InvalidOperationException(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); +// Console.WriteLine(fileName + " => " + vectorName + " failed at " + lead); return; + } + } + } + + private static string ReadBlock(PeekableLineReader r) + { + 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/IDEATest.cs b/crypto/test/src/crypto/test/IDEATest.cs new file mode 100644 index 000000000..6ae822271 --- /dev/null +++ b/crypto/test/src/crypto/test/IDEATest.cs @@ -0,0 +1,57 @@ +#if INCLUDE_IDEA + +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class IdeaTest + : CipherTest + { + public override string Name + { + get { return "IDEA"; } + } + + internal static SimpleTest[] tests = new SimpleTest[] + { + new BlockCipherVectorTest(0, new IdeaEngine(), + new KeyParameter(Hex.Decode("00112233445566778899AABBCCDDEEFF")), + "000102030405060708090a0b0c0d0e0f", + "ed732271a7b39f475b4b2b6719f194bf"), + new BlockCipherVectorTest(0, new IdeaEngine(), + new KeyParameter(Hex.Decode("00112233445566778899AABBCCDDEEFF")), + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "b8bc6ed5c899265d2bcfad1fc6d4287d") + }; + + public IdeaTest() + : base(tests, new IdeaEngine(), new KeyParameter(new byte[32])) + { + } + + public static void Main( + string[] args) + { + ITest test = new IdeaTest(); + ITestResult result = test.Perform(); + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} + +#endif diff --git a/crypto/test/src/crypto/test/ISAACTest.cs b/crypto/test/src/crypto/test/ISAACTest.cs new file mode 100644 index 000000000..1782bbc98 --- /dev/null +++ b/crypto/test/src/crypto/test/ISAACTest.cs @@ -0,0 +1,196 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * ISAAC Test - see http://www.burtleburtle.net/bob/rand/isaacafa.html + */ + [TestFixture] + public class IsaacTest + : SimpleTest + { + byte[] outBase = 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 override string Name + { + get { return "ISAAC"; } + } + + public override void PerformTest() + { + IsaacEngine engine = new IsaacEngine(); + + doTest(engine, Hex.Decode("00000000"), outBase); + 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[] input = new byte[output.Length]; + byte[] enc = new byte[output.Length]; + engine.Init(true, new KeyParameter(key)); + engine.ProcessBytes(input, 0, input.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, input)) + { + Fail("plaintext mismatch"); + } + } + + public static void Main( + string[] args) + { + RunTest(new IsaacTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ISO9796Test.cs b/crypto/test/src/crypto/test/ISO9796Test.cs new file mode 100644 index 000000000..562238bca --- /dev/null +++ b/crypto/test/src/crypto/test/ISO9796Test.cs @@ -0,0 +1,961 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// test vectors from ISO 9796-1 and ISO 9796-2 edition 1. + [TestFixture] + public class ISO9796Test + : 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[] 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 override string Name + { + get { return "ISO9796"; } + } + + private bool 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 bool 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; + } + + [Test] + public virtual void DoTest1() + { + 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"); + } + } + + [Test] + public virtual void DoTest2() + { + 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"); + } + } + + [Test] + public virtual void DoTest3() + { + 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"); + } + } + + [Test] + public virtual void DoTest4() + { + 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.BlockUpdate(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.BlockUpdate(msg4, 1, msg4.Length - 1); + + if (!eng.VerifySignature(data)) + { + 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.BlockUpdate(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"); + } + } + + [Test] + public virtual void DoTest5() + { + 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.BlockUpdate(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.BlockUpdate(msg5, 1, msg5.Length - 1); + + if (!eng.VerifySignature(data)) + { + 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.BlockUpdate(msg5, 0, msg5.Length); + + if (eng.VerifySignature(sig5)) + { + Fail("failed ISO9796-2 updateWithRecovered verify fail Test 5"); + } + } + + // + // against a zero length string + // + [Test] + public virtual void DoTest6() + { + 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"); + } + } + + [Test] + public virtual void DoTest7() + { + 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.BlockUpdate(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.BlockUpdate(msg7, 1, msg7.Length - 1); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 7"); + } + + if (!IsSameAs(msg7, 0, eng.GetRecoveredMessage())) + { + Fail("failed ISO9796-2 recovery Test 7"); + } + } + + [Test] + public virtual void DoTest8() + { + 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.BlockUpdate(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.BlockUpdate(msg8, 1, msg8.Length - 1); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 8"); + } + } + + [Test] + public virtual void DoTest9() + { + 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.BlockUpdate(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.BlockUpdate(msg9, 1, msg9.Length - 1); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 9"); + } + } + + [Test] + public virtual void DoTest10() + { + 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 + // + IDigest 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.BlockUpdate(msg9, 1, msg9.Length - 1); + + data = eng.GenerateSignature(); + + eng.Init(false, pubParameters); + + eng.Update(msg9[0]); + eng.BlockUpdate(msg9, 1, msg9.Length - 1); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 10"); + } + } + } + + [Test] + public virtual void DoTest11() + { + 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 + // + IDigest dig = new Sha1Digest(); + Iso9796d2PssSigner eng = new Iso9796d2PssSigner(rsa, dig, dig.GetDigestSize()); + + // + // check message bounds + // + eng.Init(true, privParameters); + + eng.BlockUpdate(m1, 0, m1.Length); + + data = eng.GenerateSignature(); + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m2, 0, m2.Length); + + if (eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 m2 verify Test 11"); + } + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m3, 0, m3.Length); + + if (eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 m3 verify Test 11"); + } + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m1, 0, m1.Length); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 11"); + } + } + + [Test] + public virtual void DoTest12() + { + 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 - Regular Signing + // + IDigest dig = new Sha1Digest(); + Iso9796d2Signer eng = new Iso9796d2Signer(rsa, dig); + + // + // check message bounds + // + eng.Init(true, privParameters); + + eng.BlockUpdate(m1, 0, m1.Length); + + data = eng.GenerateSignature(); + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m2, 0, m2.Length); + + if (eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 m2 verify Test 12"); + } + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m3, 0, m3.Length); + + if (eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 m3 verify Test 12"); + } + + eng.Init(false, pubParameters); + + eng.BlockUpdate(m1, 0, m1.Length); + + if (!eng.VerifySignature(data)) + { + Fail("failed ISO9796-2 verify Test 12"); + } + } + + [Test] + public void DoTest13() + { + 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); + + IAsymmetricBlockCipher rsaEngine = new RsaBlindedEngine(); + IDigest 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.BlockUpdate(challenge, 0, challenge.Length); + + byte[] sig = signer.GenerateSignature(); + + // verify + signer.Init(false, pubParams); + signer.BlockUpdate(challenge, 0, challenge.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("basic verification failed"); + } + + // === LETS ACTUALLY DO SOME RECOVERY, USING INPUT FROM INTERNAL AUTHENTICATE === + + signer.Reset(); + + string args0 = "482E20D1EDDED34359C38F5E7C01203F9D6B2641CDCA5C404D49ADAEDE034C7481D781D043722587761C90468DE69C6585A1E8B9C322F90E1B580EEDAB3F6007D0C366CF92B4DB8B41C8314929DCE2BE889C0129123484D2FD3D12763D2EBFD12AC8E51D7061AFCA1A53DEDEC7B9A617472A78C952CCC72467AE008E5F132994"; + + digest = new Sha1Digest(); + + signer = new Iso9796d2Signer(rsaEngine, digest, true); + + + signer.Init(false, pubParams); + byte[] signature = Hex.Decode(args0); + signer.UpdateWithRecoveredMessage(signature); + signer.BlockUpdate(challenge, 0, challenge.Length); + + if (!signer.VerifySignature(signature)) + { + Fail("recovered + challenge signature failed"); + } + + // === FINALLY, USING SHA-256 === + + signer.Reset(); + + digest = new Sha256Digest(); + + // NOTE setting implicit 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; + byte[] nonce = new byte[nonceLength]; + SecureRandom rnd = new SecureRandom(); + + rnd.NextBytes(nonce); + + signer.BlockUpdate(nonce, 0, nonce.Length); + signer.BlockUpdate(challenge, 0, challenge.Length); + byte[] sig3 = signer.GenerateSignature(); + + signer.Init(false, pubParams); + signer.UpdateWithRecoveredMessage(sig3); + signer.BlockUpdate(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 readonly 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 readonly byte[] shortPartialSig = Base64.Decode( + "sb8yyKk6HM1cJhICScMx7QRQunRyrZ1fbI42+T+TBGNjOknvzKuvG7aftGX7" + + "O/RXuYgk6LTxpXv7+O5noUhMBsR2PKaHveuylU1WSPmDxDCui3kp4frqVH0w" + + "8Vjpl5CsKqBsmKkbGCKE+smM0xFXhYxV8QUTB2XsWNCQiFiHPgwbpfWzZUNY" + + "QPWd0A99P64EuUIYz1tkkDnLFmwQ19/PJu1a8orIQInmkVYWSsBsZ/7Ks6lx" + + "nDHpAvgiRe+OXmJ/yuQy1O3FJYdyoqvjYRPBu3qYeBK9+9L3lExLilImH5aD" + + "nJznaXcO8QFOxVPbrF2s4GdPIMDonEyAHdrnzoghlg=="); + + [Test] + public void DoShortPartialTest() + { + 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); + + byte[] recoveredMessage = pssSign.GetRecoveredMessage(); + pssSign.BlockUpdate(longMessage, recoveredMessage.Length, longMessage.Length - recoveredMessage.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"); + } + } + + [Test] + public void DoFullMessageTest() + { + 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); + + IAsymmetricBlockCipher 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.BlockUpdate(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 override void PerformTest() + { + 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/crypto/test/src/crypto/test/ISO9797Alg3MacTest.cs b/crypto/test/src/crypto/test/ISO9797Alg3MacTest.cs new file mode 100644 index 000000000..9d5d8b6b7 --- /dev/null +++ b/crypto/test/src/crypto/test/ISO9797Alg3MacTest.cs @@ -0,0 +1,99 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class ISO9797Alg3MacTest + : SimpleTest + { + static byte[] keyBytes = Hex.Decode("7CA110454A1A6E570131D9619DC1376E"); + static byte[] ivBytes = Hex.Decode("0000000000000000"); + + static byte[] input1 = Encoding.ASCII.GetBytes("Hello World !!!!"); + + static byte[] output1 = Hex.Decode("F09B856213BAB83B"); + + public ISO9797Alg3MacTest() + { + } + + public override void PerformTest() + { + KeyParameter key = new KeyParameter(keyBytes); + IBlockCipher cipher = new DesEngine(); + IMac mac = new ISO9797Alg3Mac(cipher); + + // + // standard DAC - zero IV + // + mac.Init(key); + + mac.BlockUpdate(input1, 0, input1.Length); + + byte[] outBytes = new byte[8]; + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output1)) + { + Fail("Failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes)); + } + + // + // reset + // + mac.Reset(); + + mac.Init(key); + + for (int i = 0; i != input1.Length / 2; i++) + { + mac.Update(input1[i]); + } + + mac.BlockUpdate(input1, input1.Length / 2, input1.Length - (input1.Length / 2)); + + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output1)) + { + Fail("Reset failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes)); + } + } + + public override string Name + { + get + { + return "ISO9797Alg3Mac"; + } + } + + public static void Main( + string[] args) + { + ISO9797Alg3MacTest test = new ISO9797Alg3MacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/KDF1GeneratorTest.cs b/crypto/test/src/crypto/test/KDF1GeneratorTest.cs new file mode 100644 index 000000000..89c8d5453 --- /dev/null +++ b/crypto/test/src/crypto/test/KDF1GeneratorTest.cs @@ -0,0 +1,103 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * KDF1 tests - vectors from ISO 18033. + */ + [TestFixture] + public class Kdf1GeneratorTest + : 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; + private byte[] mask3= Hex.Decode( + "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e" + + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa" + + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5" + + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb"); + + public Kdf1GeneratorTest() + { + seed3 = seed2; + } + + public override 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) + { + // expected + } + } + + private void checkMask( + int count, + IDerivationFunction 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 override string Name + { + get { return "KDF1"; } + } + + public static void Main( + string[] args) + { + RunTest(new Kdf1GeneratorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/KDF2GeneratorTest.cs b/crypto/test/src/crypto/test/KDF2GeneratorTest.cs new file mode 100644 index 000000000..e184e0b40 --- /dev/null +++ b/crypto/test/src/crypto/test/KDF2GeneratorTest.cs @@ -0,0 +1,115 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * KDF2 tests - vectors from ISO 18033. + */ + [TestFixture] + public class Kdf2GeneratorTest + : SimpleTest + { + private static readonly byte[] seed1 = Hex.Decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d"); + private static readonly byte[] mask1 = Hex.Decode( + "df79665bc31dc5a62f70535e52c53015b9d37d412ff3c119343959" + + "9e1b628774c50d9ccb78d82c425e4521ee47b8c36a4bcffe8b8112a8" + + "9312fc04420a39de99223890e74ce10378bc515a212b97b8a6447ba6" + + "a8870278f0262727ca041fa1aa9f7b5d1cf7f308232fe861"); + + private static readonly byte[] seed2 = Hex.Decode( + "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741" + + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4"); + private static readonly byte[] mask2 = Hex.Decode( + "10a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb456" + + "68f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb13" + + "19fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbac" + + "a19f6410ee1fcb260892670e0814c348664f6a7248aaf998a3acc6"); + private static readonly byte[] adjustedMask2 = Hex.Decode( + "10a2403db42a8743cb989de86e668d168cbe6046e23ff26f741e87949a3bba1311ac1" + + "79f819a3d18412e9eb45668f2923c087c1299005f8d5fd42ca257bc93e8fee0c5a0d2" + + "a8aa70185401fbbd99379ec76c663e9a29d0b70f3fe261a59cdc24875a60b4aacb131" + + "9fa11c3365a8b79a44669f26fba933d012db213d7e3b16349"); + + private static readonly byte[] sha1Mask = Hex.Decode( + "0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32" + + "052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a2519" + + "2985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837ee" + + "a4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807"); + + private static readonly byte[] seed3 = Hex.Decode("CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A"); + private static readonly byte[] mask3 = Hex.Decode("744AB703F5BC082E59185F6D049D2D367DB245C2"); + + private static readonly byte[] seed4 = Hex.Decode("0499B502FC8B5BAFB0F4047E731D1F9FD8CD0D8881"); + private static readonly byte[] mask4 = Hex.Decode("03C62280C894E103C680B13CD4B4AE740A5EF0C72547292F82DC6B1777F47D63BA9D1EA732DBF386"); + + public Kdf2GeneratorTest() + { + } + + public override 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) + { + // expected + } + } + + private void checkMask( + int count, + IDerivationFunction 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 override string Name + { + get { return "KDF2"; } + } + + public static void Main( + string[] args) + { + RunTest(new Kdf2GeneratorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} \ No newline at end of file diff --git a/crypto/test/src/crypto/test/MD2DigestTest.cs b/crypto/test/src/crypto/test/MD2DigestTest.cs new file mode 100644 index 000000000..e9d2cb88f --- /dev/null +++ b/crypto/test/src/crypto/test/MD2DigestTest.cs @@ -0,0 +1,204 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for MD2 + * from RFC1319 by B.Kaliski of RSA Laboratories April 1992 + * + */ + [TestFixture] + public class MD2DigestTest + : ITest + { + static private string testVec1 = ""; + static private string resVec1 = "8350e5a3e24c153df2275c9f80692773"; + static private string testVec2 = "61"; + static private string resVec2 = "32ec01ec4a6dac72c0ab96fb34c0b5d1"; + static private string testVec3 = "616263"; + static private string resVec3 = "da853b0d3f88d99b30283a69e6ded6bb"; + static private string testVec4 = "6d65737361676520646967657374"; + static private string resVec4 = "ab4f496bfb2a530b219ff33031fe06b0"; + static private string testVec5 = "6162636465666768696a6b6c6d6e6f707172737475767778797a"; + static private string resVec5 = "4e8ddff3650292ab5a4108c3aa47940b"; + static private string testVec6 = "4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839"; + static private string resVec6 = "da33def2a42df13975352846c30338cd"; + static private string testVec7 = "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930"; + static private string resVec7 = "d5976f79d83d3a0dc9806c3c66f3efd8"; + + public string Name + { + get { return "MD2"; } + } + + public ITestResult Perform() + { + IDigest digest = new MD2Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + byte[] bytes = Hex.Decode(testVec1); + digest.BlockUpdate(bytes, 0, bytes.Length); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + // + // test 5 + // + bytes = Hex.Decode(testVec5); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec5.Equals(resStr)) + { + return new SimpleTestResult(false, + //System.err.println( + "MD2 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec5 + + SimpleTest.NewLine + + " got : " + resStr); + } + // + // test 6 + // + bytes = Hex.Decode(testVec6); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec6.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 6" + + SimpleTest.NewLine + + " expected: " + resVec6 + + SimpleTest.NewLine + + " got : " + resStr); + } + // + // test 7 + // + bytes = Hex.Decode(testVec7); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec7.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD2 failing standard vector test 7" + + SimpleTest.NewLine + + " expected: " + resVec7 + + SimpleTest.NewLine + + " got : " + resStr); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new MD2DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/MD4DigestTest.cs b/crypto/test/src/crypto/test/MD4DigestTest.cs new file mode 100644 index 000000000..89b5d7949 --- /dev/null +++ b/crypto/test/src/crypto/test/MD4DigestTest.cs @@ -0,0 +1,176 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for MD4 from RFC 1320. + */ + [TestFixture] + public class MD4DigestTest + : ITest + { +// static private string testVec1 = ""; + static private string resVec1 = "31d6cfe0d16ae931b73c59d7e0c089c0"; + + static private string testVec2 = "61"; + static private string resVec2 = "bde52cb31de33e46245e05fbdbd6fb24"; + + static private string testVec3 = "616263"; + static private string resVec3 = "a448017aaf21d8525fc10ae87aa6729d"; + + static private string testVec4 = "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930"; + static private string resVec4 = "e33b4ddc9c38f2199c3e7b164fcc0536"; + + public string Name + { + get { return "MD4"; } + } + + public ITestResult Perform() + { + IDigest digest = new MD4Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length/2); + + // clone the IDigest + IDigest d = new MD4Digest((MD4Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD4 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new MD4DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/MD5DigestTest.cs b/crypto/test/src/crypto/test/MD5DigestTest.cs new file mode 100644 index 000000000..b38e06391 --- /dev/null +++ b/crypto/test/src/crypto/test/MD5DigestTest.cs @@ -0,0 +1,175 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Standard vector test for MD5 from "Handbook of Applied Cryptography", page 345. + [TestFixture] + public class MD5DigestTest + : ITest + { +// static private string testVec1 = ""; + static private string resVec1 = "d41d8cd98f00b204e9800998ecf8427e"; + + static private string testVec2 = "61"; + static private string resVec2 = "0cc175b9c0f1b6a831c399e269772661"; + + static private string testVec3 = "616263"; + static private string resVec3 = "900150983cd24fb0d6963f7d28e17f72"; + + static private string testVec4 = "6162636465666768696a6b6c6d6e6f707172737475767778797a"; + static private string resVec4 = "c3fcd3d76192e4007dfb496cca67e13b"; + + public string Name + { + get { return "MD5"; } + } + + public ITestResult Perform() + { + IDigest digest = new MD5Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length/2); + + // clone the IDigest + IDigest d = new MD5Digest((MD5Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "MD5 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new MD5DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/MD5HMacTest.cs b/crypto/test/src/crypto/test/MD5HMacTest.cs new file mode 100644 index 000000000..101b8be3c --- /dev/null +++ b/crypto/test/src/crypto/test/MD5HMacTest.cs @@ -0,0 +1,91 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// MD5 HMac Test, test vectors from RFC 2202 + [TestFixture] + public class MD5HMacTest + : ITest + { + public string Name + { + get { return "MD5HMac"; } + } + + internal static readonly string[] keys = new string[]{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "0102030405060708090a0b0c0d0e0f10111213141516171819", "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}; + internal static readonly string[] digests = new string[]{"9294727a3638bb1c13f48ef8158bfc9d", "750c783e6ab0b503eaa86e310a5db738", "56be34521d144c88dbb8c733f0e8b3f6", "697eaf0aca3a3aea3a75164746ffaa79", "56461ef2342edc00f9bab995690efd4c", "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", "6f630fad67cda0ee1fb1f562db3aa53e"}; + internal static readonly string[] messages = new string[]{"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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new MD5Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + "Vector " + i + " failed"); + } + } + + // test reset + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new MD5HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/MGF1GeneratorTest.cs b/crypto/test/src/crypto/test/MGF1GeneratorTest.cs new file mode 100644 index 000000000..ee67ffa1c --- /dev/null +++ b/crypto/test/src/crypto/test/MGF1GeneratorTest.cs @@ -0,0 +1,103 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * MGF1 tests - vectors from ISO 18033 for KDF1 (equivalent). + */ + [TestFixture] + public class Mgf1GeneratorTest + : 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; + private byte[] mask3= Hex.Decode( + "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e" + + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa" + + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5" + + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb"); + + public Mgf1GeneratorTest() + { + seed3 = seed2; + } + + public override 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) + { + // expected + } + } + + private void checkMask( + int count, + IDerivationFunction 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 override string Name + { + get { return "MGF1"; } + } + + public static void Main( + string[] args) + { + RunTest(new Mgf1GeneratorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} \ No newline at end of file diff --git a/crypto/test/src/crypto/test/MacTest.cs b/crypto/test/src/crypto/test/MacTest.cs new file mode 100644 index 000000000..9a58f8a8c --- /dev/null +++ b/crypto/test/src/crypto/test/MacTest.cs @@ -0,0 +1,214 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// MAC tester - vectors from + /// FIP 81 and + /// FIP 113. + /// + [TestFixture] + public class MacTest + : ITest + { + public string Name + { + get { return "IMac"; } + } + + internal static byte[] keyBytes; + internal static byte[] ivBytes; + internal static byte[] input1; + internal static byte[] output1; + internal static byte[] output2; + internal static byte[] output3; + + // + // these aren't NIST vectors, just for regression testing. + // + internal static byte[] input2; + internal static byte[] output4; + internal static byte[] output5; + internal static byte[] output6; + + public MacTest() + { + } + + public virtual ITestResult Perform() + { + KeyParameter key = new KeyParameter(keyBytes); + IBlockCipher cipher = new DesEngine(); + IMac mac = new CbcBlockCipherMac(cipher); + + // + // standard DAC - zero IV + // + mac.Init(key); + + mac.BlockUpdate(input1, 0, input1.Length); + + byte[] outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output1)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes)); + } + + // + // mac with IV. + // + ParametersWithIV param = new ParametersWithIV(key, ivBytes); + + mac.Init(param); + + mac.BlockUpdate(input1, 0, input1.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output2)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output2) + " got " + Hex.ToHexString(outBytes)); + } + + // + // CFB mac with IV - 8 bit CFB mode + // + param = new ParametersWithIV(key, ivBytes); + + mac = new CfbBlockCipherMac(cipher); + + mac.Init(param); + + mac.BlockUpdate(input1, 0, input1.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output3)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output3) + " got " + Hex.ToHexString(outBytes)); + } + + // + // word aligned data - zero IV + // + mac.Init(key); + + mac.BlockUpdate(input2, 0, input2.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output4)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output4) + " got " + Hex.ToHexString(outBytes)); + } + + // + // word aligned data - zero IV - CBC padding + // + mac = new CbcBlockCipherMac(cipher, new Pkcs7Padding()); + + mac.Init(key); + + mac.BlockUpdate(input2, 0, input2.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output5)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output5) + " got " + Hex.ToHexString(outBytes)); + } + + // + // non-word aligned data - zero IV - CBC padding + // + mac.Reset(); + + mac.BlockUpdate(input1, 0, input1.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output6)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output6) + " got " + Hex.ToHexString(outBytes)); + } + + // + // non-word aligned data - zero IV - CBC padding + // + mac.Init(key); + + mac.BlockUpdate(input1, 0, input1.Length); + + outBytes = new byte[4]; + + mac.DoFinal(outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output6)) + { + return new SimpleTestResult(false, Name + ": Failed - expected " + + Hex.ToHexString(output6) + " got " + Hex.ToHexString(outBytes)); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + MacTest test = new MacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + static MacTest() + { + keyBytes = Hex.Decode("0123456789abcdef"); + ivBytes = Hex.Decode("1234567890abcdef"); + input1 = Hex.Decode("37363534333231204e6f77206973207468652074696d6520666f7220"); + output1 = Hex.Decode("f1d30f68"); + output2 = Hex.Decode("58d2e77e"); + output3 = Hex.Decode("cd647403"); + input2 = Hex.Decode("3736353433323120"); + output4 = Hex.Decode("3af549c9"); + output5 = Hex.Decode("188fbdd5"); + output6 = Hex.Decode("7045eecd"); + } + } +} diff --git a/crypto/test/src/crypto/test/ModeTest.cs b/crypto/test/src/crypto/test/ModeTest.cs new file mode 100644 index 000000000..c67dce094 --- /dev/null +++ b/crypto/test/src/crypto/test/ModeTest.cs @@ -0,0 +1,108 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// CFB/OFB Mode test of IV padding. + [TestFixture] + public class ModeTest + : ITest + { + public string Name + { + get { return "ModeTest"; } + } + + public ModeTest() + { + } + + public virtual ITestResult Perform() + { + KeyParameter key = new KeyParameter(Hex.Decode("0011223344556677")); + byte[] input = Hex.Decode("4e6f7720"); + byte[] out1 = new byte[4]; + byte[] out2 = new byte[4]; + + + IBlockCipher 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 (!Arrays.AreEqual(out2, input)) + { + return new SimpleTestResult(false, Name + ": 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 (!Arrays.AreEqual(out2, input)) + { + return new SimpleTestResult(false, Name + ": test 2 - in != out"); + } + + IBlockCipher 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 (!Arrays.AreEqual(out2, input)) + { + return new SimpleTestResult(false, Name + ": 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 (!Arrays.AreEqual(out2, input)) + { + return new SimpleTestResult(false, Name + ": test 4 - in != out"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new ModeTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/NaccacheSternTest.cs b/crypto/test/src/crypto/test/NaccacheSternTest.cs new file mode 100644 index 000000000..faa845059 --- /dev/null +++ b/crypto/test/src/crypto/test/NaccacheSternTest.cs @@ -0,0 +1,354 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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: + *
      + *
    • Toy example from the NaccacheSternPaper
    • + *
    • 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
    • + *
    • 1024 bit test analog to 768 bit test
    • + *
    + */ + [TestFixture, Explicit] + public class NaccacheSternTest + : SimpleTest + { + static bool debug = false; + + static readonly NaccacheSternEngine cryptEng = new NaccacheSternEngine(); + static readonly NaccacheSternEngine decryptEng = new NaccacheSternEngine(); + + static NaccacheSternTest() + { + cryptEng.Debug = debug; + decryptEng.Debug = debug; + } + + // Values from NaccacheStern paper + static readonly BigInteger a = BigInteger.ValueOf(101); + static readonly BigInteger u1 = BigInteger.ValueOf(3); + static readonly BigInteger u2 = BigInteger.ValueOf(5); + static readonly BigInteger u3 = BigInteger.ValueOf(7); + static readonly BigInteger b = BigInteger.ValueOf(191); + static readonly BigInteger v1 = BigInteger.ValueOf(11); + static readonly BigInteger v2 = BigInteger.ValueOf(13); + static readonly BigInteger v3 = BigInteger.ValueOf(17); + + static readonly BigInteger sigma + = u1.Multiply(u2).Multiply(u3).Multiply(v1).Multiply(v2).Multiply(v3); + + static readonly BigInteger p + = BigInteger.Two.Multiply(a).Multiply(u1).Multiply(u2).Multiply(u3).Add(BigInteger.One); + + static readonly BigInteger q + = BigInteger.Two.Multiply(b).Multiply(v1).Multiply(v2).Multiply(v3).Add(BigInteger.One); + + static readonly BigInteger n = p.Multiply(q); + + static readonly BigInteger phi_n + = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One)); + + static readonly BigInteger g = BigInteger.ValueOf(131); + + static readonly IList smallPrimes = new ArrayList(); + + // static final BigInteger paperTest = BigInteger.ValueOf(202); + + static readonly string input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e"; + + static readonly BigInteger paperTest = BigInteger.ValueOf(202); + + // + // to check that we handling byte extension by big number correctly. + // + static readonly string edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e"; + + public override string Name + { + get { return "NaccacheStern"; } + } + + public override 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.Add(u1); + smallPrimes.Add(u2); + smallPrimes.Add(u3); + smallPrimes.Add(v1); + smallPrimes.Add(v2); + smallPrimes.Add(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) + { + Console.WriteLine("initializing encryption engine"); + } + cryptEng.Init(true, pair.Public); + + if (debug) + { + Console.WriteLine("initializing decryption engine"); + } + decryptEng.Init(false, pair.Private); + + 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) + { + Console.WriteLine(); + Console.WriteLine("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.Public).Modulus.BitLength < 768) + { + Console.WriteLine("FAILED: key size is <786 bit, exactly " + + ((NaccacheSternKeyParameters)pair.Public).Modulus.BitLength + " bit"); + Fail("failed key generation (768) length test"); + } + + // Initialize Engines with KeyPair + + if (debug) + { + Console.WriteLine("initializing " + genParam.Strength + " bit encryption engine"); + } + cryptEng.Init(true, pair.Public); + + if (debug) + { + Console.WriteLine("initializing " + genParam.Strength + " bit decryption engine"); + } + decryptEng.Init(false, pair.Private); + + // Basic data input + data = Hex.Decode(input); + + if (!new BigInteger(1, data).Equals(new BigInteger(1, enDeCrypt(data)))) + { + Fail("failed encryption decryption (" + genParam.Strength + ") 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.Strength + ") edgeInput test"); + } + + // + // 1024 Bit Test + // + /* + if (debug) + { + Console.WriteLine(); + Console.WriteLine("1024 Bit TEST"); + } + + // specify key generation parameters + genParam = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 1024, 8, 40, debug); + + pGen.Init(genParam); + pair = pGen.generateKeyPair(); + + if (((NaccacheSternKeyParameters)pair.Public).getModulus().bitLength() < 1024) + { + if (debug) + { + Console.WriteLine("FAILED: key size is <1024 bit, exactly " + + ((NaccacheSternKeyParameters)pair.Public).getModulus().bitLength() + " bit"); + } + Fail("failed key generation (1024) length test"); + } + + // Initialize Engines with KeyPair + + if (debug) + { + Console.WriteLine("initializing " + genParam.getStrength() + " bit encryption engine"); + } + cryptEng.Init(true, pair.Public); + + if (debug) + { + Console.WriteLine("initializing " + genParam.getStrength() + " bit decryption engine"); + } + decryptEng.Init(false, pair.Private); + + if (debug) + { + Console.WriteLine("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 (InvalidOperationException) + { + // expected + } + + if (debug) + { + Console.WriteLine("All tests successful"); + } + } + + private byte[] enDeCrypt( + byte[] input) + { + // create work array + byte[] data = new byte[input.Length]; + Array.Copy(input, 0, data, 0, data.Length); + + // Perform encryption like in the paper from Naccache-Stern + if (debug) + { + Console.WriteLine("encrypting data. Data representation\n" + // + "As string:.... " + new string(data) + "\n" + + "As BigInteger: " + new BigInteger(1, data)); + Console.WriteLine("data length is " + data.Length); + } + + try + { + data = cryptEng.ProcessData(data); + } + catch (InvalidCipherTextException e) + { + if (debug) + { + Console.WriteLine("failed - exception " + e + "\n" + e.Message); + } + Fail("failed - exception " + e + "\n" + e.Message); + } + + if (debug) + { + Console.WriteLine("enrypted data representation\n" + // + "As string:.... " + new string(data) + "\n" + + "As BigInteger: " + new BigInteger(1, data)); + Console.WriteLine("data length is " + data.Length); + } + + try + { + data = decryptEng.ProcessData(data); + } + catch (InvalidCipherTextException e) + { + if (debug) + { + Console.WriteLine("failed - exception " + e + "\n" + e.Message); + } + Fail("failed - exception " + e + "\n" + e.Message); + } + + if (debug) + { + Console.WriteLine("decrypted data representation\n" + // + "As string:.... " + new string(data) + "\n" + + "As BigInteger: " + new BigInteger(1, data)); + Console.WriteLine("data length is " + data.Length); + } + + return data; + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public static void Main( + string[] args) + { + ITest test = new NaccacheSternTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + } +} diff --git a/crypto/test/src/crypto/test/NoekeonTest.cs b/crypto/test/src/crypto/test/NoekeonTest.cs new file mode 100644 index 000000000..b6fff70ce --- /dev/null +++ b/crypto/test/src/crypto/test/NoekeonTest.cs @@ -0,0 +1,59 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Noekeon tester + */ + [TestFixture] + public class NoekeonTest + : CipherTest + { + private static readonly 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") + }; + + public NoekeonTest() + : base(tests, new NoekeonEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get { return "Noekeon"; } + } + + public static void Main( + string[] args) + { + RunTest(new NoekeonTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/NullTest.cs b/crypto/test/src/crypto/test/NullTest.cs new file mode 100644 index 000000000..16a51808f --- /dev/null +++ b/crypto/test/src/crypto/test/NullTest.cs @@ -0,0 +1,88 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class NullTest + : CipherTest + { + static SimpleTest[] tests = + { + new BlockCipherVectorTest(0, new NullEngine(), + new KeyParameter(Hex.Decode("00")), "00", "00") + }; + + public NullTest() + : base(tests, new NullEngine(), new KeyParameter(new byte[2])) + { + } + + public override string Name + { + get { return "Null"; } + } + + public override void PerformTest() + { + base.PerformTest(); + + IBlockCipher 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) + { + // expected + } + + try + { + engine.ProcessBlock(buf, 0, shortBuf, 0); + + Fail("failed short output check"); + } + catch (DataLengthException) + { + // expected + } + } + + public static void Main( + string[] args) + { + RunTest(new NullTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs new file mode 100644 index 000000000..c414f5964 --- /dev/null +++ b/crypto/test/src/crypto/test/OAEPTest.cs @@ -0,0 +1,798 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class OaepTest + : SimpleTest + { + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly 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 + }; + + private static readonly byte[] output3 = Hex.Decode( + "b8246b56a6ed5881aeb585d9a25b2ad790c417e080681bf1ac2bc3deb69d8bce" + + "f0c4366fec400af052a72e9b0effb5b3f2f192dbeaca03c12740057113bf1f06" + + "69ac22e9f3a7852e3c15d913cab0b8863a95c99294ce8674214954610346f4d4" + + "74b26f7c48b42ee68e1f572a1fc4026ac456b4f59f7b621ea1b9d88f64202fb1"); + + private static readonly 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 + : SecureRandom + { + private readonly byte[] seed; + + internal VecRand(byte[] seed) + { + this.seed = seed; + } + + public override void NextBytes( + byte[] bytes) + { + Array.Copy(seed, 0, bytes, 0, bytes.Length); + } + } + + private void BaseOaepTest( + int id, + byte[] pubKeyEnc, + byte[] privKeyEnc, + byte[] output) + { + // + // extract the public key info. + // + Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubKeyEnc); + RsaPublicKeyStructure pubStruct = RsaPublicKeyStructure.GetInstance( + SubjectPublicKeyInfo.GetInstance(pubKeyObj).GetPublicKey()); + + // + // extract the private key info. + // + Asn1Object privKeyObj = Asn1Object.FromByteArray(privKeyEnc); + RsaPrivateKeyStructure privStruct = new RsaPrivateKeyStructure( + (Asn1Sequence) PrivateKeyInfo.GetInstance(privKeyObj).PrivateKey); + + RsaKeyParameters pubParameters = new RsaKeyParameters( + false, + pubStruct.Modulus, + pubStruct.PublicExponent); + + RsaKeyParameters privParameters = new RsaPrivateCrtKeyParameters( + privStruct.Modulus, + privStruct.PublicExponent, + privStruct.PrivateExponent, + privStruct.Prime1, + privStruct.Prime2, + privStruct.Exponent1, + privStruct.Exponent2, + privStruct.Coefficient); + + 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) + { + IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine()); + + cipher.Init(true, new ParametersWithRandom(pubParameters, new VecRand(seed))); + + byte[] outBytes = cipher.ProcessBlock(input, 0, input.Length); + + for (int i = 0; i != output.Length; i++) + { + if (outBytes[i] != output[i]) + { + Fail(label + " failed encryption"); + } + } + + cipher.Init(false, privParameters); + + outBytes = cipher.ProcessBlock(output, 0, output.Length); + + for (int i = 0; i != input.Length; i++) + { + if (outBytes[i] != input[i]) + { + Fail(label + " failed decoding"); + } + } + } + + /* + * RSA vector tests from PKCS#1 page + */ + private static readonly byte[] modulus_1024 = Hex.Decode( + "a8b3b284af8eb50b387034a860f146c4" + + "919f318763cd6c5598c8ae4811a1e0ab" + + "c4c7e0b082d693a5e7fced675cf46685" + + "12772c0cbc64a742c6c630f533c8cc72" + + "f62ae833c40bf25842e984bb78bdbf97" + + "c0107d55bdb662f5c4e0fab9845cb514" + + "8ef7392dd3aaff93ae1e6b667bb3d424" + + "7616d4f5ba10d4cfd226de88d39f16fb"); + + private static readonly byte[] pubExp_1024 = Hex.Decode("010001"); + + private static readonly byte[] privExp_1024 = Hex.Decode( + "53339cfdb79fc8466a655c7316aca85c" + + "55fd8f6dd898fdaf119517ef4f52e8fd" + + "8e258df93fee180fa0e4ab29693cd83b" + + "152a553d4ac4d1812b8b9fa5af0e7f55" + + "fe7304df41570926f3311f15c4d65a73" + + "2c483116ee3d3d2d0af3549ad9bf7cbf" + + "b78ad884f84d5beb04724dc7369b31de" + + "f37d0cf539e9cfcdd3de653729ead5d1"); + + private static readonly byte[] prime1_1024 = Hex.Decode( + "d32737e7267ffe1341b2d5c0d150a81b" + + "586fb3132bed2f8d5262864a9cb9f30a" + + "f38be448598d413a172efb802c21acf1" + + "c11c520c2f26a471dcad212eac7ca39d"); + + private static readonly byte[] prime2_1024 = Hex.Decode( + "cc8853d1d54da630fac004f471f281c7" + + "b8982d8224a490edbeb33d3e3d5cc93c" + + "4765703d1dd791642f1f116a0dd852be" + + "2419b2af72bfe9a030e860b0288b5d77"); + + private static readonly byte[] primeExp1_1024 = Hex.Decode( + "0e12bf1718e9cef5599ba1c3882fe804" + + "6a90874eefce8f2ccc20e4f2741fb0a3" + + "3a3848aec9c9305fbecbd2d76819967d" + + "4671acc6431e4037968db37878e695c1"); + + private static readonly byte[] primeExp2_1024 = Hex.Decode( + "95297b0f95a2fa67d00707d609dfd4fc" + + "05c89dafc2ef6d6ea55bec771ea33373" + + "4d9251e79082ecda866efef13c459e1a" + + "631386b7e354c899f5f112ca85d71583"); + + private static readonly byte[] crtCoef_1024 = Hex.Decode( + "4f456c502493bdc0ed2ab756a3a6ed4d" + + "67352a697d4216e93212b127a63d5411" + + "ce6fa98d5dbefd73263e372814274381" + + "8166ed7dd63687dd2a8ca1d2f4fbd8e1"); + + private static readonly byte[] input_1024_1 = Hex.Decode( + "6628194e12073db03ba94cda9ef95323" + + "97d50dba79b987004afefe34"); + + private static readonly byte[] seed_1024_1 = Hex.Decode( + "18b776ea21069d69776a33e96bad48e1" + + "dda0a5ef"); + + private static readonly byte[] output_1024_1 = Hex.Decode( + "354fe67b4a126d5d35fe36c777791a3f" + + "7ba13def484e2d3908aff722fad468fb" + + "21696de95d0be911c2d3174f8afcc201" + + "035f7b6d8e69402de5451618c21a535f" + + "a9d7bfc5b8dd9fc243f8cf927db31322" + + "d6e881eaa91a996170e657a05a266426" + + "d98c88003f8477c1227094a0d9fa1e8c" + + "4024309ce1ecccb5210035d47ac72e8a"); + + private static readonly byte[] input_1024_2 = Hex.Decode( + "750c4047f547e8e41411856523298ac9" + + "bae245efaf1397fbe56f9dd5"); + + private static readonly byte[] seed_1024_2 = Hex.Decode( + "0cc742ce4a9b7f32f951bcb251efd925" + + "fe4fe35f"); + + private static readonly byte[] output_1024_2 = Hex.Decode( + "640db1acc58e0568fe5407e5f9b701df" + + "f8c3c91e716c536fc7fcec6cb5b71c11" + + "65988d4a279e1577d730fc7a29932e3f" + + "00c81515236d8d8e31017a7a09df4352" + + "d904cdeb79aa583adcc31ea698a4c052" + + "83daba9089be5491f67c1a4ee48dc74b" + + "bbe6643aef846679b4cb395a352d5ed1" + + "15912df696ffe0702932946d71492b44"); + + private static readonly byte[] input_1024_3 = Hex.Decode( + "d94ae0832e6445ce42331cb06d531a82" + + "b1db4baad30f746dc916df24d4e3c245" + + "1fff59a6423eb0e1d02d4fe646cf699d" + + "fd818c6e97b051"); + + private static readonly byte[] seed_1024_3 = Hex.Decode( + "2514df4695755a67b288eaf4905c36ee" + + "c66fd2fd"); + + private static readonly byte[] output_1024_3 = Hex.Decode( + "423736ed035f6026af276c35c0b3741b" + + "365e5f76ca091b4e8c29e2f0befee603" + + "595aa8322d602d2e625e95eb81b2f1c9" + + "724e822eca76db8618cf09c5343503a4" + + "360835b5903bc637e3879fb05e0ef326" + + "85d5aec5067cd7cc96fe4b2670b6eac3" + + "066b1fcf5686b68589aafb7d629b02d8" + + "f8625ca3833624d4800fb081b1cf94eb"); + + private static readonly byte[] input_1024_4 = Hex.Decode( + "52e650d98e7f2a048b4f86852153b97e" + + "01dd316f346a19f67a85"); + + private static readonly byte[] seed_1024_4 = Hex.Decode( + "c4435a3e1a18a68b6820436290a37cef" + + "b85db3fb"); + + private static readonly byte[] output_1024_4 = Hex.Decode( + "45ead4ca551e662c9800f1aca8283b05" + + "25e6abae30be4b4aba762fa40fd3d38e" + + "22abefc69794f6ebbbc05ddbb1121624" + + "7d2f412fd0fba87c6e3acd888813646f" + + "d0e48e785204f9c3f73d6d8239562722" + + "dddd8771fec48b83a31ee6f592c4cfd4" + + "bc88174f3b13a112aae3b9f7b80e0fc6" + + "f7255ba880dc7d8021e22ad6a85f0755"); + + private static readonly byte[] input_1024_5 = Hex.Decode( + "8da89fd9e5f974a29feffb462b49180f" + + "6cf9e802"); + + private static readonly byte[] seed_1024_5 = Hex.Decode( + "b318c42df3be0f83fea823f5a7b47ed5" + + "e425a3b5"); + + private static readonly byte[] output_1024_5 = Hex.Decode( + "36f6e34d94a8d34daacba33a2139d00a" + + "d85a9345a86051e73071620056b920e2" + + "19005855a213a0f23897cdcd731b4525" + + "7c777fe908202befdd0b58386b1244ea" + + "0cf539a05d5d10329da44e13030fd760" + + "dcd644cfef2094d1910d3f433e1c7c6d" + + "d18bc1f2df7f643d662fb9dd37ead905" + + "9190f4fa66ca39e869c4eb449cbdc439"); + + private static readonly byte[] input_1024_6 = Hex.Decode("26521050844271"); + + private static readonly byte[] seed_1024_6 = Hex.Decode( + "e4ec0982c2336f3a677f6a356174eb0c" + + "e887abc2"); + + private static readonly byte[] output_1024_6 = Hex.Decode( + "42cee2617b1ecea4db3f4829386fbd61" + + "dafbf038e180d837c96366df24c097b4" + + "ab0fac6bdf590d821c9f10642e681ad0" + + "5b8d78b378c0f46ce2fad63f74e0ad3d" + + "f06b075d7eb5f5636f8d403b9059ca76" + + "1b5c62bb52aa45002ea70baace08ded2" + + "43b9d8cbd62a68ade265832b56564e43" + + "a6fa42ed199a099769742df1539e8255"); + + private static readonly byte[] modulus_1027 = Hex.Decode( + "051240b6cc0004fa48d0134671c078c7" + + "c8dec3b3e2f25bc2564467339db38853" + + "d06b85eea5b2de353bff42ac2e46bc97" + + "fae6ac9618da9537a5c8f553c1e35762" + + "5991d6108dcd7885fb3a25413f53efca" + + "d948cb35cd9b9ae9c1c67626d113d57d" + + "de4c5bea76bb5bb7de96c00d07372e96" + + "85a6d75cf9d239fa148d70931b5f3fb0" + + "39"); + + private static readonly byte[] pubExp_1027 = Hex.Decode("010001"); + + private static readonly byte[] privExp_1027 = Hex.Decode( + "0411ffca3b7ca5e9e9be7fe38a85105e" + + "353896db05c5796aecd2a725161eb365" + + "1c8629a9b862b904d7b0c7b37f8cb5a1" + + "c2b54001018a00a1eb2cafe4ee4e9492" + + "c348bc2bedab4b9ebbf064e8eff322b9" + + "009f8eec653905f40df88a3cdc49d456" + + "7f75627d41aca624129b46a0b7c698e5" + + "e65f2b7ba102c749a10135b6540d0401"); + + private static readonly byte[] prime1_1027 = Hex.Decode( + "027458c19ec1636919e736c9af25d609" + + "a51b8f561d19c6bf6943dd1ee1ab8a4a" + + "3f232100bd40b88decc6ba235548b6ef" + + "792a11c9de823d0a7922c7095b6eba57" + + "01"); + + private static readonly byte[] prime2_1027 = Hex.Decode( + "0210ee9b33ab61716e27d251bd465f4b" + + "35a1a232e2da00901c294bf22350ce49" + + "0d099f642b5375612db63ba1f2038649" + + "2bf04d34b3c22bceb909d13441b53b51" + + "39"); + + private static readonly byte[] primeExp1_1027 = Hex.Decode( + "39fa028b826e88c1121b750a8b242fa9" + + "a35c5b66bdfd1fa637d3cc48a84a4f45" + + "7a194e7727e49f7bcc6e5a5a412657fc" + + "470c7322ebc37416ef458c307a8c0901"); + + private static readonly byte[] primeExp2_1027 = Hex.Decode( + "015d99a84195943979fa9e1be2c3c1b6" + + "9f432f46fd03e47d5befbbbfd6b1d137" + + "1d83efb330a3e020942b2fed115e5d02" + + "be24fd92c9019d1cecd6dd4cf1e54cc8" + + "99"); + + private static readonly byte[] crtCoef_1027 = Hex.Decode( + "01f0b7015170b3f5e42223ba30301c41" + + "a6d87cbb70e30cb7d3c67d25473db1f6" + + "cbf03e3f9126e3e97968279a865b2c2b" + + "426524cfc52a683d31ed30eb984be412" + + "ba"); + + private static readonly byte[] input_1027_1 = Hex.Decode( + "4a86609534ee434a6cbca3f7e962e76d" + + "455e3264c19f605f6e5ff6137c65c56d" + + "7fb344cd52bc93374f3d166c9f0c6f9c" + + "506bad19330972d2"); + + private static readonly byte[] seed_1027_1 = Hex.Decode( + "1cac19ce993def55f98203f6852896c9" + + "5ccca1f3"); + + private static readonly byte[] output_1027_1 = Hex.Decode( + "04cce19614845e094152a3fe18e54e33" + + "30c44e5efbc64ae16886cb1869014cc5" + + "781b1f8f9e045384d0112a135ca0d12e" + + "9c88a8e4063416deaae3844f60d6e96f" + + "e155145f4525b9a34431ca3766180f70" + + "e15a5e5d8e8b1a516ff870609f13f896" + + "935ced188279a58ed13d07114277d75c" + + "6568607e0ab092fd803a223e4a8ee0b1" + + "a8"); + + private static readonly byte[] input_1027_2 = Hex.Decode( + "b0adc4f3fe11da59ce992773d9059943" + + "c03046497ee9d9f9a06df1166db46d98" + + "f58d27ec074c02eee6cbe2449c8b9fc5" + + "080c5c3f4433092512ec46aa793743c8"); + + private static readonly byte[] seed_1027_2 = Hex.Decode( + "f545d5897585e3db71aa0cb8da76c51d" + + "032ae963"); + + private static readonly byte[] output_1027_2 = Hex.Decode( + "0097b698c6165645b303486fbf5a2a44" + + "79c0ee85889b541a6f0b858d6b6597b1" + + "3b854eb4f839af03399a80d79bda6578" + + "c841f90d645715b280d37143992dd186" + + "c80b949b775cae97370e4ec97443136c" + + "6da484e970ffdb1323a20847821d3b18" + + "381de13bb49aaea66530c4a4b8271f3e" + + "ae172cd366e07e6636f1019d2a28aed1" + + "5e"); + + private static readonly byte[] input_1027_3 = Hex.Decode( + "bf6d42e701707b1d0206b0c8b45a1c72" + + "641ff12889219a82bdea965b5e79a96b" + + "0d0163ed9d578ec9ada20f2fbcf1ea3c" + + "4089d83419ba81b0c60f3606da99"); + + private static readonly byte[] seed_1027_3 = Hex.Decode( + "ad997feef730d6ea7be60d0dc52e72ea" + + "cbfdd275"); + + private static readonly byte[] output_1027_3 = Hex.Decode( + "0301f935e9c47abcb48acbbe09895d9f" + + "5971af14839da4ff95417ee453d1fd77" + + "319072bb7297e1b55d7561cd9d1bb24c" + + "1a9a37c619864308242804879d86ebd0" + + "01dce5183975e1506989b70e5a834341" + + "54d5cbfd6a24787e60eb0c658d2ac193" + + "302d1192c6e622d4a12ad4b53923bca2" + + "46df31c6395e37702c6a78ae081fb9d0" + + "65"); + + private static readonly byte[] input_1027_4 = Hex.Decode( + "fb2ef112f5e766eb94019297934794f7" + + "be2f6fc1c58e"); + + private static readonly byte[] seed_1027_4 = Hex.Decode( + "136454df5730f73c807a7e40d8c1a312" + + "ac5b9dd3"); + + private static readonly byte[] output_1027_4 = Hex.Decode( + "02d110ad30afb727beb691dd0cf17d0a" + + "f1a1e7fa0cc040ec1a4ba26a42c59d0a" + + "796a2e22c8f357ccc98b6519aceb682e" + + "945e62cb734614a529407cd452bee3e4" + + "4fece8423cc19e55548b8b994b849c7e" + + "cde4933e76037e1d0ce44275b08710c6" + + "8e430130b929730ed77e09b015642c55" + + "93f04e4ffb9410798102a8e96ffdfe11" + + "e4"); + + private static readonly byte[] input_1027_5 = Hex.Decode( + "28ccd447bb9e85166dabb9e5b7d1adad" + + "c4b9d39f204e96d5e440ce9ad928bc1c" + + "2284"); + + private static readonly byte[] seed_1027_5 = Hex.Decode( + "bca8057f824b2ea257f2861407eef63d" + + "33208681"); + + private static readonly byte[] output_1027_5 = Hex.Decode( + "00dbb8a7439d90efd919a377c54fae8f" + + "e11ec58c3b858362e23ad1b8a4431079" + + "9066b99347aa525691d2adc58d9b06e3" + + "4f288c170390c5f0e11c0aa3645959f1" + + "8ee79e8f2be8d7ac5c23d061f18dd74b" + + "8c5f2a58fcb5eb0c54f99f01a8324756" + + "8292536583340948d7a8c97c4acd1e98" + + "d1e29dc320e97a260532a8aa7a758a1e" + + "c2"); + + private static readonly byte[] input_1027_6 = Hex.Decode("f22242751ec6b1"); + + private static readonly byte[] seed_1027_6 = Hex.Decode( + "2e7e1e17f647b5ddd033e15472f90f68" + + "12f3ac4e"); + + private static readonly 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) + { + EncDec(keySize + " " + no, pubParam, privParam, seed, input, output); + } + + public override string Name + { + get { return "OAEP"; } + } + + public override void PerformTest() + { + 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.Modulus, + pubParam.Exponent, + 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.Modulus, + pubParam.Exponent, + 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); + } + + public static void Main( + string[] args) + { + RunTest(new OaepTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/OCBTest.cs b/crypto/test/src/crypto/test/OCBTest.cs new file mode 100644 index 000000000..051aa665a --- /dev/null +++ b/crypto/test/src/crypto/test/OCBTest.cs @@ -0,0 +1,261 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test vectors from the "work in progress" Internet-Draft The OCB Authenticated-Encryption + * Algorithm + */ + public class OcbTest + : SimpleTest + { + private const string K = "000102030405060708090A0B0C0D0E0F"; + private const string N = "000102030405060708090A0B"; + + // Each test vector contains the strings A, P, C in order + private static readonly string[][] TestVectors = new string[][] + { + new string[]{ "", "", "197B9C3C441D3C83EAFB2BEF633B9182" }, + new string[]{ "0001020304050607", "0001020304050607", + "92B657130A74B85A16DC76A46D47E1EAD537209E8A96D14E" }, + new string[]{ "0001020304050607", "", "98B91552C8C009185044E30A6EB2FE21" }, + new string[]{ "", "0001020304050607", "92B657130A74B85A971EFFCAE19AD4716F88E87B871FBEED" }, + new string[]{ "000102030405060708090A0B0C0D0E0F", "000102030405060708090A0B0C0D0E0F", + "BEA5E8798DBE7110031C144DA0B26122776C9924D6723A1F" + "C4524532AC3E5BEB" }, + new string[]{ "000102030405060708090A0B0C0D0E0F", "", "7DDB8E6CEA6814866212509619B19CC6" }, + new string[]{ "", "000102030405060708090A0B0C0D0E0F", + "BEA5E8798DBE7110031C144DA0B2612213CC8B747807121A" + "4CBB3E4BD6B456AF" }, + new string[]{ "000102030405060708090A0B0C0D0E0F1011121314151617", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "BEA5E8798DBE7110031C144DA0B26122FCFCEE7A2A8D4D48" + "5FA94FC3F38820F1DC3F3D1FD4E55E1C" }, + new string[]{ "000102030405060708090A0B0C0D0E0F1011121314151617", "", + "282026DA3068BC9FA118681D559F10F6" }, + new string[]{ "", "000102030405060708090A0B0C0D0E0F1011121314151617", + "BEA5E8798DBE7110031C144DA0B26122FCFCEE7A2A8D4D48" + "6EF2F52587FDA0ED97DC7EEDE241DF68" }, + new string[]{ + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F", + "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A6" + + "57149D53773463CBB2A040DD3BD5164372D76D7BB6824240" }, + new string[]{ "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F", "", + "E1E072633BADE51A60E85951D9C42A1B" }, + new string[]{ + "", + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F", + "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A6" + + "57149D53773463CB4A3BAE824465CFDAF8C41FC50C7DF9D9" }, + new string[]{ + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F2021222324252627", + "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A6" + + "57149D53773463CB68C65778B058A635659C623211DEEA0D" + "E30D2C381879F4C8" }, + new string[]{ "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F2021222324252627", + "", "7AEB7A69A1687DD082CA27B0D9A37096" }, + new string[]{ + "", + "000102030405060708090A0B0C0D0E0F1011121314151617" + "18191A1B1C1D1E1F2021222324252627", + "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A6" + + "57149D53773463CB68C65778B058A635060C8467F4ABAB5E" + "8B3C2067A2E115DC" }, + }; + + public override string Name + { + get { return "OCB"; } + } + + public override void PerformTest() + { + for (int i = 0; i < TestVectors.Length; ++i) + { + RunTestCase("Test Case " + i, TestVectors[i]); + } + + RunLongerTestCase(128, 128, Hex.Decode("B2B41CBF9B05037DA7F16C24A35C1C94")); + RunLongerTestCase(192, 128, Hex.Decode("1529F894659D2B51B776740211E7D083")); + RunLongerTestCase(256, 128, Hex.Decode("42B83106E473C0EEE086C8D631FD4C7B")); + RunLongerTestCase(128, 96, Hex.Decode("1A4F0654277709A5BDA0D380")); + RunLongerTestCase(192, 96, Hex.Decode("AD819483E01DD648978F4522")); + RunLongerTestCase(256, 96, Hex.Decode("CD2E41379C7E7C4458CCFB4A")); + RunLongerTestCase(128, 64, Hex.Decode("B7ECE9D381FE437F")); + RunLongerTestCase(192, 64, Hex.Decode("DE0574C87FF06DF9")); + RunLongerTestCase(256, 64, Hex.Decode("833E45FF7D332F7E")); + } + + private void RunTestCase(string testName, string[] testVector) + { + RunTestCase(testName, testVector, 128); + } + + private void RunTestCase(string testName, string[] testVector, int macLengthBits) + { + byte[] key = Hex.Decode(K); + byte[] nonce = Hex.Decode(N); + + int pos = 0; + byte[] A = Hex.Decode(testVector[pos++]); + byte[] P = Hex.Decode(testVector[pos++]); + byte[] C = Hex.Decode(testVector[pos++]); + + int macLengthBytes = macLengthBits / 8; + + // TODO Variations processing AAD and cipher bytes incrementally + + KeyParameter keyParameter = new KeyParameter(key); + AeadParameters aeadParameters = new AeadParameters(keyParameter, macLengthBits, nonce, A); + + OcbBlockCipher encCipher = InitCipher(true, aeadParameters); + OcbBlockCipher decCipher = InitCipher(false, aeadParameters); + + CheckTestCase(encCipher, decCipher, testName, macLengthBytes, P, C); + CheckTestCase(encCipher, decCipher, testName + " (reused)", macLengthBytes, P, C); + + // TODO Key reuse + } + + private OcbBlockCipher InitCipher(bool forEncryption, AeadParameters parameters) + { + OcbBlockCipher c = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); + c.Init(forEncryption, parameters); + return c; + } + + private void CheckTestCase(OcbBlockCipher encCipher, OcbBlockCipher decCipher, string testName, + int macLengthBytes, byte[] P, byte[] C) + { + byte[] tag = Arrays.Copy(C, C.Length - macLengthBytes, macLengthBytes); + + { + 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 aesKeySize, int tagLen, byte[] expectedOutput) + { + KeyParameter key = new KeyParameter(new byte[aesKeySize / 8]); + byte[] N = new byte[12]; + + IAeadBlockCipher c1 = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); + c1.Init(true, new AeadParameters(key, tagLen, N)); + + IAeadBlockCipher c2 = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); + + long total = 0; + + byte[] S = new byte[128]; + + for (int i = 0; i < 128; ++i) + { + N[11] = (byte) i; + + c2.Init(true, new AeadParameters(key, tagLen, N)); + + total += UpdateCiphers(c1, c2, S, i, true, true); + total += UpdateCiphers(c1, c2, S, i, false, true); + 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 int UpdateCiphers(IAeadBlockCipher c1, IAeadBlockCipher c2, byte[] S, int i, + bool includeAAD, bool includePlaintext) + { + 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; + } + + public static void Main( + string[] args) + { + RunTest(new OcbTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/PSSBlindTest.cs b/crypto/test/src/crypto/test/PSSBlindTest.cs new file mode 100644 index 000000000..d887a8f08 --- /dev/null +++ b/crypto/test/src/crypto/test/PSSBlindTest.cs @@ -0,0 +1,399 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /* + * RSA PSS test vectors for PKCS#1 V2.1 with blinding + */ + [TestFixture] + public class PssBlindTest + : SimpleTest + { + private readonly int DATA_LENGTH = 1000; + private readonly int NUM_TESTS = 50; + private readonly int NUM_TESTS_WITH_KEY_GENERATION = 10; + + private class FixedRandom + : SecureRandom + { + private readonly byte[] vals; + + public FixedRandom( + byte[] vals) + { + this.vals = vals; + } + + public override void NextBytes( + byte[] bytes) + { + Array.Copy(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 override string Name + { + get { return "PssBlindTest"; } + } + + private void testSig( + int id, + RsaKeyParameters pub, + RsaKeyParameters prv, + byte[] slt, + byte[] msg, + byte[] sig) + { + 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 parameters = new RsaBlindingParameters(pub, blindFactor); + + // generate a blind signature + blindSigner.Init(true, new ParametersWithRandom(parameters, new FixedRandom(slt))); + + blindSigner.BlockUpdate(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, parameters); + + 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.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(s)) + { + Fail("test " + id + " failed PssSigner verification"); + } + } + + private bool isProcessingOkay( + RsaKeyParameters pub, + RsaKeyParameters prv, + byte[] data, + SecureRandom random) + { + 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 parameters = new RsaBlindingParameters(pub, blindFactor); + + // generate a blind signature + blindSigner.Init(true, new ParametersWithRandom(parameters, random)); + + blindSigner.BlockUpdate(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, parameters); + + byte[] s = blindingEngine.ProcessBlock(blindedSig, 0, blindedSig.Length); + + //verify signature with PssSigner + pssEng.Init(false, pub); + pssEng.BlockUpdate(data, 0, data.Length); + + return pssEng.VerifySignature(s); + } + + public override void PerformTest() + { + 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}; + + for (int j = 0, i = 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.Public, (RsaKeyParameters)pair.Private, data, random)) + { + failed++; + } + } + } + + if (failed != 0) + { + Fail("loop test with key generation failed - failures: " + failed); + } + } + + public static void Main( + string[] args) + { + RunTest(new PssBlindTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/PSSTest.cs b/crypto/test/src/crypto/test/PSSTest.cs new file mode 100644 index 000000000..91d8d3a6e --- /dev/null +++ b/crypto/test/src/crypto/test/PSSTest.cs @@ -0,0 +1,338 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// RSA PSS test vectors for PKCS#1 V2.1 + [TestFixture] + public class PssTest + : SimpleTest + { + private const int DataLength = 1000; + private const int NumTests = 500; + + private class FixedRandom + : SecureRandom + { + private readonly byte[] vals; + + public FixedRandom( + byte[] vals) + { + this.vals = vals; + } + + public override void NextBytes( + byte[] bytes) + { + Array.Copy(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 override string Name + { + get { return "PSSTest"; } + } + + private void doTestSig( + int id, + RsaKeyParameters pub, + RsaKeyParameters prv, + byte[] slt, + byte[] msg, + byte[] sig) + { + PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); + + eng.Init(true, new ParametersWithRandom(prv, new FixedRandom(slt))); + + eng.BlockUpdate(msg, 0, msg.Length); + + byte[] s = eng.GenerateSignature(); + + if (!AreEqual(s, sig)) + { + Fail("test " + id + " failed generation"); + } + + eng.Init(false, pub); + + eng.BlockUpdate(msg, 0, msg.Length); + + if (!eng.VerifySignature(s)) + { + Fail("test " + id + " failed verification"); + } + } + + public override void PerformTest() + { + doTestSig(1, pub1, prv1, slt1a, msg1a, sig1a); + doTestSig(2, pub1, prv1, slt1b, msg1b, sig1b); + doTestSig(3, pub2, prv2, slt2a, msg2a, sig2a); + doTestSig(4, pub2, prv2, slt2b, msg2b, sig2b); + doTestSig(5, pub4, prv4, slt4a, msg4a, sig4a); + doTestSig(6, pub4, prv4, slt4b, msg4b, sig4b); + doTestSig(7, pub8, prv8, slt8a, msg8a, sig8a); + doTestSig(8, pub8, prv8, slt8b, msg8b, sig8b); + doTestSig(9, pub9, prv9, slt9a, msg9a, sig9a); + doTestSig(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[DataLength]; + + SecureRandom random = new SecureRandom(); + random.NextBytes(data); + + for (int j = 0; j < NumTests; j++) + { + eng.Init(true, new ParametersWithRandom(prv8, random)); + + eng.BlockUpdate(data, 0, data.Length); + + byte[] s = eng.GenerateSignature(); + + eng.Init(false, pub8); + + eng.BlockUpdate(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[DataLength]; + + random.NextBytes(data); + + for (int j = 0; j < NumTests; j++) + { + eng.Init(true, new ParametersWithRandom(prv8, random)); + + eng.BlockUpdate(data, 0, data.Length); + + byte[] s = eng.GenerateSignature(); + + eng.Init(false, pub8); + + eng.BlockUpdate(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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/PaddingTest.cs b/crypto/test/src/crypto/test/PaddingTest.cs new file mode 100644 index 000000000..6f41d754c --- /dev/null +++ b/crypto/test/src/crypto/test/PaddingTest.cs @@ -0,0 +1,171 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * General Padding tests. + */ + [TestFixture] + public class PaddingTest : SimpleTest + { + public PaddingTest() + { + } + + private void blockCheck( + PaddedBufferedBlockCipher cipher, + IBlockCipherPadding padding, + KeyParameter key, + byte[] data) + { + byte[] outBytes = new byte[data.Length + 8]; + byte[] dec = new byte[data.Length]; + + try + { + cipher.Init(true, key); + + int len = cipher.ProcessBytes(data, 0, data.Length, outBytes, 0); + + len += cipher.DoFinal(outBytes, len); + + cipher.Init(false, key); + + int decLen = cipher.ProcessBytes(outBytes, 0, len, dec, 0); + + decLen += cipher.DoFinal(dec, decLen); + + if (!AreEqual(data, dec)) + { + Fail("failed to decrypt - i = " + data.Length + ", padding = " + padding.PaddingName); + } + } + catch (Exception e) + { + Fail("Exception - " + e.ToString(), e); + } + } + + public void doTestPadding( + IBlockCipherPadding 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.PaddingName); + } + } + + // + // zero test + // + if (ZeroVector != null) + { + data = new byte[8]; + padding.AddPadding(data, 4); + + if (!AreEqual(data, ZeroVector)) + { + Fail("failed zero test for " + padding.PaddingName); + } + } + + for (int i = 1; i != 200; i++) + { + data = new byte[i]; + + rand.NextBytes(data); + + blockCheck(cipher, padding, key, data); + } + } + + public override void PerformTest() + { + SecureRandom rand = new SecureRandom(new byte[20]); + + rand.SetSeed(DateTime.Now.Ticks); + + doTestPadding(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.Message)) + { + Fail("wrong exception for corrupt padding: " + e); + } + } + + doTestPadding(new ISO10126d2Padding(), rand, + null, + null); + + doTestPadding(new X923Padding(), rand, + null, + null); + + doTestPadding(new TbcPadding(), rand, + Hex.Decode("ffffff0000000000"), + Hex.Decode("00000000ffffffff")); + + doTestPadding(new ZeroBytePadding(), rand, + Hex.Decode("ffffff0000000000"), + null); + + doTestPadding(new ISO7816d4Padding(), rand, + Hex.Decode("ffffff8000000000"), + Hex.Decode("0000000080000000")); + } + + public override string Name + { + get { return "PaddingTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PaddingTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/Pkcs12Test.cs b/crypto/test/src/crypto/test/Pkcs12Test.cs new file mode 100644 index 000000000..29d5a3942 --- /dev/null +++ b/crypto/test/src/crypto/test/Pkcs12Test.cs @@ -0,0 +1,101 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// test for Pkcs12 key generation - vectors from + /// + /// http://www.drh-consultancy.demon.co.uk/test.txt + /// + [TestFixture] + public class Pkcs12Test + : SimpleTest + { + public override string Name + { + get { return "Pkcs12Test"; } + } + + internal char[] password1 = new char[]{'s', 'm', 'e', 'g'}; + internal char[] password2 = new char[]{'q', 'u', 'e', 'e', 'g'}; + + private void Run1(int id, char[] password, byte[] salt, int iCount, byte[] result) + { + PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha1Digest()); + + generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password), salt, iCount); + + ICipherParameters key = generator.GenerateDerivedParameters("DESEDE", 24 * 8); + + if (!Arrays.AreEqual(result, ((KeyParameter) key).GetKey())) + { + Fail("id " + id + " Failed"); + } + } + + private void 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 parameters = (ParametersWithIV) + generator.GenerateDerivedParameters("DES", 64, 64); + + if (!Arrays.AreEqual(result, parameters.GetIV())) + { + Fail("id " + id + " Failed"); + } + } + + private void Run3(int id, char[] password, byte[] salt, int iCount, byte[] result) + { + PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha1Digest()); + + generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password), salt, iCount); + + ICipherParameters key = generator.GenerateDerivedMacParameters(160); + + if (!Arrays.AreEqual(result, ((KeyParameter) key).GetKey())) + { + Fail("id " + id + " Failed"); + } + } + + public override void PerformTest() + { + Run1(1, password1, Hex.Decode("0A58CF64530D823F"), 1, Hex.Decode("8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3")); + Run2(2, password1, Hex.Decode("0A58CF64530D823F"), 1, Hex.Decode("79993DFE048D3B76")); + Run1(3, password1, Hex.Decode("642B99AB44FB4B1F"), 1, Hex.Decode("F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966")); + Run2(4, password1, Hex.Decode("642B99AB44FB4B1F"), 1, Hex.Decode("C0A38D64A79BEA1D")); + Run3(5, password1, Hex.Decode("3D83C0E4546AC140"), 1, Hex.Decode("8D967D88F6CAA9D714800AB3D48051D63F73A312")); + Run1(6, password2, Hex.Decode("05DEC959ACFF72F7"), 1000, Hex.Decode("ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4")); + Run2(7, password2, Hex.Decode("05DEC959ACFF72F7"), 1000, Hex.Decode("11DEDAD7758D4860")); + Run1(8, password2, Hex.Decode("1682C0FC5B3F7EC5"), 1000, Hex.Decode("483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F")); + Run2(9, password2, Hex.Decode("1682C0FC5B3F7EC5"), 1000, Hex.Decode("9D461D1B00355C50")); + Run3(10, password2, Hex.Decode("263216FCC2FAB31C"), 1000, Hex.Decode("5EC4C7A80DF652294C3925B6489A7AB857C83476")); + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs12Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/Pkcs5Test.cs b/crypto/test/src/crypto/test/Pkcs5Test.cs new file mode 100644 index 000000000..8066e8e41 --- /dev/null +++ b/crypto/test/src/crypto/test/Pkcs5Test.cs @@ -0,0 +1,243 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + + /// A test class for Pkcs5 PbeS2 with PBKDF2 (Pkcs5 v2.0) using + /// test vectors provider at + /// + /// RSA's Pkcs5 Page + ///
    + /// The vectors are Base 64 encoded and encrypted using the password "password" + /// (without quotes). They should all yield the same PrivateKeyInfo object. + ///
    + [TestFixture] + public class Pkcs5Test + : SimpleTest + { + public override string Name + { + get { return "Pkcs5Test"; } + } + + /// encrypted using des-cbc. + internal static byte[] sample1; + + /// encrypted using des-ede3-cbc. + internal static byte[] sample2; + + /// encrypted using rc2-cbc. + internal static byte[] sample3; + + internal static byte[] result; + + private class PbeTest + : SimpleTest + { + private Pkcs5Test enclosingInstance; + + private void InitBlock( + Pkcs5Test enclosingInstance) + { + this.enclosingInstance = enclosingInstance; + } + + public override string Name + { + get { return cipher.AlgorithmName + " Pkcs5S2 Test " + id; } + } + + public Pkcs5Test Enclosing_Instance + { + get { return enclosingInstance; } + } + + internal int id; + internal BufferedBlockCipher cipher; + internal byte[] sample; + internal int keySize; + + internal PbeTest( + Pkcs5Test enclosingInstance, + int id, + BufferedBlockCipher cipher, + byte[] sample, + int keySize) + { + InitBlock(enclosingInstance); + + this.id = id; + this.cipher = cipher; + this.sample = sample; + this.keySize = keySize; + } + + public override void PerformTest() + { + char[] password = "password".ToCharArray(); + PbeParametersGenerator generator = new Pkcs5S2ParametersGenerator(); + + EncryptedPrivateKeyInfo info = null; + try + { + info = EncryptedPrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(sample)); + } + catch (System.Exception e) + { + Fail("failed construction - exception " + e.ToString(), e); + } + + PbeS2Parameters alg = PbeS2Parameters.GetInstance(info.EncryptionAlgorithm.Parameters); + Pbkdf2Params func = Pbkdf2Params.GetInstance(alg.KeyDerivationFunc.Parameters); + EncryptionScheme scheme = alg.EncryptionScheme; + + if (func.KeyLength != null) + { + keySize = func.KeyLength.IntValue * 8; + } + + int iterationCount = func.IterationCount.IntValue; + byte[] salt = func.GetSalt(); + + generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt, iterationCount); + + DerObjectIdentifier algOid = scheme.ObjectID; + + byte[] iv; + if (algOid.Equals(PkcsObjectIdentifiers.RC2Cbc)) + { + RC2CbcParameter rc2Params = RC2CbcParameter.GetInstance(scheme.Asn1Object); + iv = rc2Params.GetIV(); + } + else + { + iv = ((Asn1OctetString) scheme.Asn1Object).GetOctets(); + } + + ICipherParameters param = new ParametersWithIV( + generator.GenerateDerivedParameters(algOid.Id, keySize), iv); + + cipher.Init(false, param); + + byte[] data = info.GetEncryptedData(); + byte[] outBytes = new byte[cipher.GetOutputSize(data.Length)]; + int len = cipher.ProcessBytes(data, 0, data.Length, outBytes, 0); + + try + { + len += cipher.DoFinal(outBytes, 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 (outBytes[i] != result[i]) + { + Fail("failed comparison"); + } + } + } + } + + public override void PerformTest() + { + BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEngine())); + SimpleTest test = new PbeTest(this, 0, cipher, sample1, 64); + + test.PerformTest(); + + cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEdeEngine())); + test = new PbeTest(this, 1, cipher, sample2, 192); + + test.PerformTest(); + + cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new RC2Engine())); + test = new PbeTest(this, 2, cipher, sample3, 0); + + test.PerformTest(); + + // + // RFC 3211 tests + // + char[] password = "password".ToCharArray(); + PbeParametersGenerator generator = new Pkcs5S2ParametersGenerator(); + + byte[] salt = Hex.Decode("1234567878563412"); + + generator.Init( + PbeParametersGenerator.Pkcs5PasswordToBytes(password), + salt, + 5); + + if (!AreEqual(((KeyParameter)generator.GenerateDerivedParameters("DES", 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("DESEDE", 192)).GetKey(), + Hex.Decode("6a8970bf68c92caea84a8df28510858607126380cc47ab2d"))) + { + Fail("192 test failed"); + } + + generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt, 60000); + if (!AreEqual(((KeyParameter)generator.GenerateDerivedParameters("DESEDE", 192)).GetKey(), + Hex.Decode("29aaef810c12ecd2236bbcfb55407f9852b5573dc1c095bb"))) + { + Fail("192 (60000) test failed"); + } + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs5Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + static Pkcs5Test() + { + 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"); + sample2 = Base64.Decode("MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA" + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/" + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8" + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5" + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi" + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ" + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8" + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr" + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB"); + sample3 = Base64.Decode("MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA" + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop" + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f" + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21" + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6" + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1" + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz" + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH" + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO" + "6DA="); + result = Hex.Decode("30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100" + "debbfc2c09d61bada2a9462f24224e54cc6b3cc0755f15ce318ef57e79df17026b6a85cc" + "a12428027245045df2052a329a2f9ad3d17b78a10572ad9b22bf343b020301000102402d" + "90a96adcec472743527bc023153d8f0d6e96b40c8ed228276d467d843306429f8670559b" + "f376dd41857f6397c2fc8d95e0e53ed62de420b855430ee4a1b8a1022100ffcaf0838239" + "31e073ff534f06a5d415b3d414bc614a4544a3dff7ed271817eb022100deea30242117db" + "2d3b8837f58f1da530ff83cf9283680da33683ec4e583610f1022100e6026381adb0a683" + "f16a8f4c096b462979b9e4277cc89f3ed8a905b46fa9ff9f02210097c146d4d1d2b3dbaf" + "53a504ff51674c5c271800de84d003f4f10ac6ab36e38102202bfa141f10bda874e1017d" + "845e82767c1c38e82745daf421f0c8cd09d7652387"); + } + } +} diff --git a/crypto/test/src/crypto/test/RC2Test.cs b/crypto/test/src/crypto/test/RC2Test.cs new file mode 100644 index 000000000..177c1817d --- /dev/null +++ b/crypto/test/src/crypto/test/RC2Test.cs @@ -0,0 +1,58 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + + /// RC2 tester - vectors from ftp://ftp.isi.edu/in-notes/rfc2268.txt + /// + /// RFC 2268 "A Description of the RC2(r) Encryption Algorithm" + /// + + [TestFixture] + public class RC2Test:CipherTest + { + public override string Name + { + get { return "RC2"; } + } + + internal static BlockCipherVectorTest[] tests = new BlockCipherVectorTest[]{ + 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")}; + + public RC2Test() + :base(tests, new RC2Engine(), new RC2Parameters(new byte[16])) + { + } + + public static void Main( + string[] args) + { + ITest test = new RC2Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RC2WrapTest.cs b/crypto/test/src/crypto/test/RC2WrapTest.cs new file mode 100644 index 000000000..fc27acd2c --- /dev/null +++ b/crypto/test/src/crypto/test/RC2WrapTest.cs @@ -0,0 +1,123 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * RC2 wrap tester + */ + [TestFixture] + public class RC2WrapTest + : ITest + { + private class RFCRandom + : SecureRandom + { + public override void NextBytes( + byte[] nextBytes) + { + Array.Copy(Hex.Decode("4845cce7fd1250"), 0, nextBytes, 0, nextBytes.Length); + } + } + + private ITestResult wrapTest( + int id, + ICipherParameters paramsWrap, + ICipherParameters paramsUnwrap, + byte[] inBytes, + byte[] outBytes) + { + IWrapper wrapper = new RC2WrapEngine(); + + wrapper.Init(true, paramsWrap); + + try + { + byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length); + if (!Arrays.AreEqual(cText, outBytes)) + { + return new SimpleTestResult(false, Name + ": failed wrap test " + id + + " expected " + Hex.ToHexString(outBytes) + + " got " + Hex.ToHexString(cText)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed wrap test exception " + e, e); + } + + wrapper.Init(false, paramsUnwrap); + + try + { + byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length); + if (!Arrays.AreEqual(pText, inBytes)) + { + return new SimpleTestResult(false, Name + ": failed unwrap test " + id + + " expected " + Hex.ToHexString(inBytes) + + " got " + Hex.ToHexString(pText)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": failed unwrap test exception " + e, e); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public ITestResult 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. + // + ICipherParameters paramWrap = new ParametersWithRandom(new ParametersWithIV(new RC2Parameters(kek1, 40), iv1), new RFCRandom()); + ICipherParameters paramUnwrap = new RC2Parameters(kek1, 40); + + ITestResult result = wrapTest(1, paramWrap, paramUnwrap, in1, out1); + + if (!result.IsSuccessful()) + { + return result; + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public string Name + { + get { return "RC2Wrap"; } + } + + public static void Main( + string[] args) + { + ITest test = new RC2WrapTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RC4Test.cs b/crypto/test/src/crypto/test/RC4Test.cs new file mode 100644 index 000000000..7c1ac9162 --- /dev/null +++ b/crypto/test/src/crypto/test/RC4Test.cs @@ -0,0 +1,59 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// RC4 Test + [TestFixture] + public class RC4Test + : ITest + { + public string Name + { + get { return "RC4"; } + } + + internal StreamCipherVectorTest[] tests = new StreamCipherVectorTest[]{ + 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 virtual ITestResult Perform() + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult res = tests[i].Perform(); + + if (!res.IsSuccessful()) + { + return res; + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RC4Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RC5Test.cs b/crypto/test/src/crypto/test/RC5Test.cs new file mode 100644 index 000000000..e50878a0e --- /dev/null +++ b/crypto/test/src/crypto/test/RC5Test.cs @@ -0,0 +1,201 @@ +using System; + +using NUnit.Framework; + +using System.Text; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + + +namespace Org.BouncyCastle.Crypto.Tests +{ + + /** + * RC5 tester - vectors from ftp://ftp.nordu.net/rfc/rfc2040.txt + * + * RFC 2040 "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms" + */ + [TestFixture] + public class RC5Test: ITest + { + 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 Name + { + get { return "RC5"; } + } + + public ITestResult Perform() + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult res = tests[i].Perform(); + + if (!res.IsSuccessful()) + { + return res; + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + RC5Test test = new RC5Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RC6Test.cs b/crypto/test/src/crypto/test/RC6Test.cs new file mode 100644 index 000000000..4f59ec4e9 --- /dev/null +++ b/crypto/test/src/crypto/test/RC6Test.cs @@ -0,0 +1,54 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// RC6 Test - test vectors from AES Submitted RSA Reference implementation. + /// ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/aes/rc6-unix-refc.tar + /// + [TestFixture] + public class RC6Test + : CipherTest + { + public override string Name + { + get { return "RC6"; } + } + + internal static SimpleTest[] tests = new SimpleTest[]{ + 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")}; + + public RC6Test() + : base(tests, new RC6Engine(), new KeyParameter(new byte[32])) + { + } + + public static void Main( + string[] args) + { + ITest test = new RC6Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RFC3211WrapTest.cs b/crypto/test/src/crypto/test/RFC3211WrapTest.cs new file mode 100644 index 000000000..bdef7c999 --- /dev/null +++ b/crypto/test/src/crypto/test/RFC3211WrapTest.cs @@ -0,0 +1,216 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Wrap Test based on RFC3211 test vectors + */ + [TestFixture] + public class Rfc3211WrapTest + : SimpleTest + { + // Note: These test data assume the Rfc3211WrapEngine will call SecureRandom.NextBytes + + SecureRandom r1 = FixedSecureRandom.From( + new byte[]{ 0xC4, 0x36, 0xF5, 0x41 }); + + SecureRandom r2 = FixedSecureRandom.From( + new byte[]{ 0xFA, 0x06, 0x0A, 0x45 }); + + public override string Name + { + get { return "RFC3211Wrap"; } + } + + private void doWrapTest( + int id, + IBlockCipher engine, + byte[] kek, + byte[] iv, + SecureRandom rand, + byte[] inBytes, + byte[] outBytes) + { + IWrapper wrapper = new Rfc3211WrapEngine(engine); + + wrapper.Init(true, new ParametersWithRandom( + new ParametersWithIV(new KeyParameter(kek), iv), rand)); + + byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length); + if (!AreEqual(cText, outBytes)) + { + Fail("failed Wrap test " + id + " expected " + + Hex.ToHexString(outBytes) + " got " + Hex.ToHexString(cText)); + } + + wrapper.Init(false, new ParametersWithIV(new KeyParameter(kek), iv)); + + byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length); + if (!AreEqual(pText, inBytes)) + { + Fail("rfailed Unwrap test " + id + " expected " + + Hex.ToHexString(inBytes) + " got " + Hex.ToHexString(pText)); + } + } + + private void doTestCorruption() + { + byte[] kek = Hex.Decode("D1DAA78615F287E6"); + byte[] iv = Hex.Decode("EFE598EF21B33D6D"); + + IWrapper 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.Message.Equals("wrapped key corrupted")) + { + Fail("wrong exception on length"); + } + } + + block = Hex.Decode("08639D838C627C897323A2F8C436F541"); + doTestChecksum(kek, iv, block, wrapper); + + block = Hex.Decode("08736D838C627C897323A2F8C436F541"); + doTestChecksum(kek, iv, block, wrapper); + + block = Hex.Decode("08739D638C627C897323A2F8C436F541"); + doTestChecksum(kek, iv, block, wrapper); + } + + private void doTestChecksum( + byte[] kek, + byte[] iv, + byte[] block, + IWrapper wrapper) + { + encryptBlock(kek, iv, block); + + try + { + wrapper.Unwrap(block, 0, block.Length); + + Fail("bad checksum not detected"); + } + catch (InvalidCipherTextException e) + { + if (!e.Message.Equals("wrapped key fails checksum")) + { + Fail("wrong exception"); + } + } + } + + private void encryptBlock(byte[] key, byte[] iv, byte[] cekBlock) + { + IBlockCipher 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 override void PerformTest() + { + doWrapTest(1, new DesEngine(), Hex.Decode("D1DAA78615F287E6"), Hex.Decode("EFE598EF21B33D6D"), r1, Hex.Decode("8C627C897323A2F8"), Hex.Decode("B81B2565EE373CA6DEDCA26A178B0C10")); + doWrapTest(2, new DesEdeEngine(), Hex.Decode("6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"), Hex.Decode("BAF1CA7931213C4E"), r2, + Hex.Decode("8C637D887223A2F965B566EB014B0FA5D52300A3F7EA40FFFC577203C71BAF3B"), + Hex.Decode("C03C514ABDB9E2C5AAC038572B5E24553876B377AAFB82ECA5A9D73F8AB143D9EC74E6CAD7DB260C")); + + doTestCorruption(); + + IWrapper wrapper = new Rfc3211WrapEngine(new DesEngine()); + ParametersWithIV parameters = new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]); + byte[] buf = new byte[16]; + + try + { + wrapper.Init(true, parameters); + + wrapper.Unwrap(buf, 0, buf.Length); + + Fail("failed Unwrap state test."); + } + catch (InvalidOperationException) + { + // expected + } + catch (InvalidCipherTextException e) + { + Fail("unexpected exception: " + e, e); + } + + try + { + wrapper.Init(false, parameters); + + wrapper.Wrap(buf, 0, buf.Length); + + Fail("failed Unwrap state test."); + } + catch (InvalidOperationException) + { + // expected + } + + // + // short test + // + try + { + wrapper.Init(false, parameters); + + wrapper.Unwrap(buf, 0, buf.Length / 2); + + Fail("failed Unwrap short test."); + } + catch (InvalidCipherTextException) + { + // expected + } + } + + public static void Main( + string[] args) + { + RunTest(new Rfc3211WrapTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RSABlindedTest.cs b/crypto/test/src/crypto/test/RSABlindedTest.cs new file mode 100644 index 000000000..80d6e8e49 --- /dev/null +++ b/crypto/test/src/crypto/test/RSABlindedTest.cs @@ -0,0 +1,449 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class RsaBlindedTest + : 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 override string Name + { + get { return "RSABlinded"; } + } + + private void doTestStrictPkcs1Length(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + IAsymmetricBlockCipher 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.Message.Equals("block incorrect size")) + { + Fail("RSA: failed - exception " + e.ToString(), e); + } + } + + + // Create the encoding with StrictLengthEnabled=false (done thru environment in Java version) + Pkcs1Encoding.StrictLengthEnabled = 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); + } + + Pkcs1Encoding.StrictLengthEnabled = true; + } + + private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated"); + } + + private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type"); + } + + private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect"); + } + + private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block"); + } + + private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage) + { + IAsymmetricBlockCipher 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.Message.Equals(expectedMessage)) + { + Fail("RSA: failed - exception " + e.ToString(), e); + } + } + } + + private void doTestOaep(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + // + // OAEP - public encrypt, private decrypt + // + IAsymmetricBlockCipher 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(Hex.ToHexString(data))) + { + Fail("failed OAEP Test"); + } + } + + public override 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 + // + IAsymmetricBlockCipher 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(Hex.ToHexString(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(Hex.ToHexString(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(Hex.ToHexString(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(Hex.ToHexString(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.Public).Modulus.BitLength < 768) + { + Fail("failed key generation (768) length test"); + } + + eng.Init(true, pair.Public); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString(), e); + } + + eng.Init(false, pair.Private); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString(), e); + } + + if (!input.Equals(Hex.ToHexString(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.Public); + + if (((RsaKeyParameters)pair.Public).Modulus.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.Private); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString(), e); + } + + if (!input.Equals(Hex.ToHexString(data))) + { + Fail("failed key generation (1024) test"); + } + + doTestOaep(pubParameters, privParameters); + doTestStrictPkcs1Length(pubParameters, privParameters); + doTestDudPkcs1Block(pubParameters, privParameters); + doTestMissingDataPkcs1Block(pubParameters, privParameters); + doTestTruncatedPkcs1Block(pubParameters, privParameters); + doTestWrongPaddingPkcs1Block(pubParameters, privParameters); + + try + { + new RsaBlindedEngine().ProcessBlock(new byte[]{ 1 }, 0, 1); + Fail("failed initialisation check"); + } + catch (InvalidOperationException) + { + // expected + } + } + + public static void Main( + string[] args) + { + ITest test = new RsaBlindedTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs new file mode 100644 index 000000000..687e9ee4f --- /dev/null +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -0,0 +1,126 @@ +using System; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + public class RegressionTest + { + public static ITest[] tests = new ITest[] + { + 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 Cast5Test(), + new Cast6Test(), + new Gost28147Test(), +#if INCLUDE_IDEA + new IdeaTest(), +#endif + new RsaBlindedTest(), + new RsaTest(), + new ISO9796Test(), + new ISO9797Alg3MacTest(), + new MD2DigestTest(), + new MD4DigestTest(), + new MD5DigestTest(), + new PssBlindTest(), + 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 DHKekGeneratorTest(), + new ECDHKekGeneratorTest(), + new ShortenedDigestTest(), + new EqualsHashCodeTest(), + new TeaTest(), + new XteaTest(), + new Rfc3211WrapTest(), + new SeedTest(), + new NaccacheSternTest(), + new Salsa20Test(), + new CMacTest(), + new EaxTest(), + new GcmTest(), + new HCFamilyTest(), + new HCFamilyVecTest(), + new IsaacTest(), + new NoekeonTest(), + new VmpcKsa3Test(), + new VmpcMacTest(), + new VmpcTest(), + new Srp6Test(), + new SCryptTest(), + new NullTest(), + new SipHashTest(), + new OcbTest(), + }; + + public static void Main( + string[] args) + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult result = tests[i].Perform(); + + Console.WriteLine(result); + } + } + } +} diff --git a/crypto/test/src/crypto/test/RijndaelTest.cs b/crypto/test/src/crypto/test/RijndaelTest.cs new file mode 100644 index 000000000..f714c83eb --- /dev/null +++ b/crypto/test/src/crypto/test/RijndaelTest.cs @@ -0,0 +1,135 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test vectors from the NIST standard tests and Brian Gladman's vector set + * + * http://fp.gladman.plus.com/cryptography_technology/rijndael/ + */ + [TestFixture] + public class RijndaelTest + : 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") + }; + + public RijndaelTest() + : base(tests, new RijndaelEngine(128), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get { return "Rijndael"; } + } + + public static void Main( + string[] args) + { + ITest test = new RijndaelTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/RipeMD128DigestTest.cs b/crypto/test/src/crypto/test/RipeMD128DigestTest.cs new file mode 100644 index 000000000..61d70f3f8 --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD128DigestTest.cs @@ -0,0 +1,135 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * RipeMD128 IDigest Test + */ + [TestFixture] + public class RipeMD128DigestTest: ITest + { + readonly static string[] messages = + { + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + + readonly static string[] digests = { + "cdf26213a150dc3ecb610f18f6b38b46", + "86be7afa339d0fc7cfc785e72f578d33", + "c14a12199c66e4ba84636b0f69144c77", + "9e327b3d6e523062afc1132d7df9d1b8", + "fd2aa607f71dc8f510714922b371834e", + "a1aa0689d0fafa2ddc22e88b49133a06", + "d1e959eb179c911faea4624c60c5c702", + "3f45ef194732c2dbb2c4a2c769795fa3" + }; + + readonly static string MillionADigest = "4a7f5723f954eba1216c9d8f6320431f"; + + public string Name + { + get { return "RipeMD128"; } + } + + public ITestResult Perform() + { + IDigest digest = new RipeMD128Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + digest.BlockUpdate(m, 0, m.Length); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test 2 + // + byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]); + + digest.BlockUpdate(mm, 0, mm.Length/2); + + // clone the IDigest + IDigest d = new RipeMD128Digest((RipeMD128Digest)digest); + + digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "RipeMD128 failing clone test" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + d.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "RipeMD128 failing clone test - part 2" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + for (int i = 0; i < 1000000; i++) + { + digest.Update((byte)'a'); + } + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest))) + { + return new SimpleTestResult(false, Name + ": Million a's failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD128DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/RipeMD128HMacTest.cs b/crypto/test/src/crypto/test/RipeMD128HMacTest.cs new file mode 100644 index 000000000..2f6a2d979 --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD128HMacTest.cs @@ -0,0 +1,100 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * RipeMD128 HMac Test, test vectors from RFC 2286 + */ + [TestFixture] + public class RipeMD128HMacTest: ITest + { + readonly static string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + readonly static string[] digests = { + "fbf61f9492aa4bbf81c172e84e0734db", + "875f828862b6b334b427c55f9f7ff09b", + "09f0b2846d2f543da363cbec8d62a38d", + "bdbbd7cf03e44b5aa60af815be4d2294", + "e79808f24b25fd031c155f0d551d9a3a", + "dc732928de98104a1f59d373c150acbb", + "5c6bec96793e16d40690c237635f30c5" + }; + + readonly 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 Name + { + get { return "RipeMD128HMac"; } + } + + public ITestResult Perform() + { + HMac hmac = new HMac(new RipeMD128Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD128HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RipeMD160DigestTest.cs b/crypto/test/src/crypto/test/RipeMD160DigestTest.cs new file mode 100644 index 000000000..347c64d49 --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD160DigestTest.cs @@ -0,0 +1,135 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * RipeMD160 IDigest Test + */ + [TestFixture] + public class RipeMD160DigestTest + : ITest + { + readonly static string[] messages = + { + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + + readonly static string[] digests = { + "9c1185a5c5e9fc54612808977ee8f548b2258d31", + "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", + "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", + "5d0689ef49d2fae572b881b123a85ffa21595f36", + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc", + "12a053384a9c0c88e405a06c27dcf49ada62eb2b", + "b0e20b6e3116640286ed3a87a5713079b21f5189", + "9b752e45573d4b39f4dbd3323cab82bf63326bfb" + }; + + readonly static string MillionADigest = "52783243c1697bdbe16d37f97f68f08325dc1528"; + + public string Name + { + get { return "RipeMD160"; } + } + + public ITestResult Perform() + { + IDigest digest = new RipeMD160Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + digest.BlockUpdate(m, 0, m.Length); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test 2 + // + byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]); + + digest.BlockUpdate(mm, 0, mm.Length/2); + + // clone the IDigest + IDigest d = new RipeMD160Digest((RipeMD160Digest)digest); + + digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "RipeMD160 failing clone test" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + d.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "RipeMD160 failing clone test - part 2" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + for (int i = 0; i < 1000000; i++) + { + digest.Update((byte)'a'); + } + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest))) + { + return new SimpleTestResult(false, Name + ": Million a's failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD160DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RipeMD160HMacTest.cs b/crypto/test/src/crypto/test/RipeMD160HMacTest.cs new file mode 100644 index 000000000..cc87a535f --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD160HMacTest.cs @@ -0,0 +1,102 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * RipeMD160 HMac Test, test vectors from RFC 2286 + */ + [TestFixture] + public class RipeMD160HMacTest + : ITest + { + readonly static string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + readonly static string[] digests = { + "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668", + "dda6c0213a485a9e24f4742064a7f033b43c4069", + "b0b105360de759960ab4f35298e116e295d8e7c1", + "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4", + "7619693978f91d90539ae786500ff3d8e0518e39", + "6466ca07ac5eac29e1bd523e5ada7605b791fd8b", + "69ea60798d71616cce5fd0871e23754cd75d5a0a" + }; + + readonly 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 Name + { + get { return "RipeMD160HMac"; } + } + + public ITestResult Perform() + { + HMac hmac = new HMac(new RipeMD160Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD160HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/RipeMD256DigestTest.cs b/crypto/test/src/crypto/test/RipeMD256DigestTest.cs new file mode 100644 index 000000000..909200d64 --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD256DigestTest.cs @@ -0,0 +1,104 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// RipeMD256 IDigest Test + [TestFixture] + public class RipeMD256DigestTest + : ITest + { + public string Name + { + get { return "RipeMD256"; } + } + + internal static readonly string[] messages = new string[]{"", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + internal static readonly string[] digests = new string[]{"02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d", "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925", "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65", "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e", "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133", "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f", "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8", "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"}; + + internal const string MillionADigest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978"; + + public virtual ITestResult Perform() + { + IDigest digest = new RipeMD256Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + digest.BlockUpdate(m, 0, m.Length); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed" + " expected: " + digests[i] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + } + } + + // + // test 2 + // + byte[] m2 = Encoding.ASCII.GetBytes(messages[messages.Length - 1]); + digest.BlockUpdate(m2, 0, m2.Length / 2); + + // clone the IDigest + IDigest d = new RipeMD256Digest((RipeMD256Digest) digest); + + digest.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1]))) + { + return new SimpleTestResult(false, "RipeMD256 failing clone test" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2); + d.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1]))) + { + return new SimpleTestResult(false, "RipeMD256 failing clone test - part 2" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + } + + for (int i = 0; i < 1000000; i++) + { + digest.Update((byte) 'a'); + } + + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest))) + { + return new SimpleTestResult(false, Name + ": Million a's failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD256DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RipeMD320DigestTest.cs b/crypto/test/src/crypto/test/RipeMD320DigestTest.cs new file mode 100644 index 000000000..253cb9d9a --- /dev/null +++ b/crypto/test/src/crypto/test/RipeMD320DigestTest.cs @@ -0,0 +1,105 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// RipeMD320 IDigest Test + [TestFixture] + public class RipeMD320DigestTest + : ITest + { + public string Name + { + get { return "RipeMD320"; } + } + + internal static readonly string[] messages = new string[]{"", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + internal static readonly string[] digests = new string[]{"22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8", "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d", "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197", "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009", "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac", "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4", "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"}; + + internal const string MillionADigest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66"; + + public virtual ITestResult Perform() + { + IDigest digest = new RipeMD320Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + digest.BlockUpdate(m, 0, m.Length); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + Console.WriteLine(Name + ": Vector " + i + " failed" + " expected: " + digests[i] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test 2 + // + byte[] m2 = Encoding.ASCII.GetBytes(messages[messages.Length - 1]); + + digest.BlockUpdate(m2, 0, m2.Length / 2); + + // clone the IDigest + IDigest d = new RipeMD320Digest((RipeMD320Digest) digest); + + digest.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1]))) + { + return new SimpleTestResult(false, "RipeMD320 failing clone test" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2); + d.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1]))) + { + return new SimpleTestResult(false, "RipeMD320 failing clone test - part 2" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf)); + } + + for (int i = 0; i < 1000000; i++) + { + digest.Update((byte) 'a'); + } + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest))) + { + return new SimpleTestResult(false, Name + ": Million a's failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new RipeMD320DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RsaTest.cs b/crypto/test/src/crypto/test/RsaTest.cs new file mode 100644 index 000000000..c343f0ba5 --- /dev/null +++ b/crypto/test/src/crypto/test/RsaTest.cs @@ -0,0 +1,596 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class RsaTest + : 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 override string Name + { + get { return "RSA"; } + } + + private void doTestStrictPkcs1Length(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + IAsymmetricBlockCipher 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.Message.Equals("block incorrect size")) + { + Fail("RSA: failed - exception " + e.ToString(), e); + } + } + + + // Create the encoding with StrictLengthEnabled=false (done thru environment in Java version) + Pkcs1Encoding.StrictLengthEnabled = 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); + } + + Pkcs1Encoding.StrictLengthEnabled = true; + } + + private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated"); + } + + private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type"); + } + + private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect"); + } + + private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block"); + } + + private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage) + { + IAsymmetricBlockCipher 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.Message.Equals(expectedMessage)) + { + Fail("RSA: failed - exception " + e.ToString(), e); + } + } + } + + private void doTestOaep(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) + { + // + // OAEP - public encrypt, private decrypt + // + IAsymmetricBlockCipher 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(Hex.ToHexString(data))) + { + Fail("failed OAEP Test"); + } + } + + // TODO Move this when other JCE tests are ported from Java + /** + * signature with a "forged signature" (sig block not at end of plain text) + */ + private void doTestBadSig()//PrivateKey priv, PublicKey pub) + { +// Signature sig = Signature.getInstance("SHA1WithRSAEncryption", "BC"); + ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption"); +// KeyPairGenerator fact; +// KeyPair keyPair; +// byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + +// fact = KeyPairGenerator.getInstance("RSA", "BC"); + RsaKeyPairGenerator fact = new RsaKeyPairGenerator(); + +// fact.initialize(768, new SecureRandom()); + RsaKeyGenerationParameters factParams = new RsaKeyGenerationParameters( +// BigInteger.ValueOf(0x11), new SecureRandom(), 768, 25); + BigInteger.ValueOf(3), new SecureRandom(), 768, 25); + fact.Init(factParams); + +// keyPair = fact.generateKeyPair(); +// +// PrivateKey signingKey = keyPair.getPrivate(); +// PublicKey verifyKey = keyPair.getPublic(); + AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair(); + + AsymmetricKeyParameter priv = keyPair.Private; + AsymmetricKeyParameter pub = keyPair.Public; + +// testBadSig(signingKey, verifyKey); + + + + + +// MessageDigest sha1 = MessageDigest.getInstance("SHA1", "BC"); + IDigest sha1 = DigestUtilities.GetDigest("SHA1"); + +// Cipher signer = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC"); +// IBufferedCipher signer = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding"); + IAsymmetricBlockCipher signer = new Pkcs1Encoding(new RsaEngine()); + +// signer.init(Cipher.ENCRYPT_MODE, priv); + signer.Init(true, priv); + +// byte[] block = new byte[signer.getBlockSize()]; +// byte[] block = new byte[signer.GetBlockSize()]; + byte[] block = new byte[signer.GetInputBlockSize()]; + +// sha1.update((byte)0); + sha1.Update(0); + +// byte[] sigHeader = Hex.decode("3021300906052b0e03021a05000414"); + byte[] sigHeader = Hex.Decode("3021300906052b0e03021a05000414"); +// System.arraycopy(sigHeader, 0, block, 0, sigHeader.length); + Array.Copy(sigHeader, 0, block, 0, sigHeader.Length); + +// sha1.digest(block, sigHeader.length, sha1.getDigestLength()); + sha1.DoFinal(block, sigHeader.Length); + +// System.arraycopy(sigHeader, 0, block, +// sigHeader.length + sha1.getDigestLength(), sigHeader.length); + Array.Copy(sigHeader, 0, block, + sigHeader.Length + sha1.GetDigestSize(), sigHeader.Length); + +// byte[] sigBytes = signer.doFinal(block); + byte[] sigBytes = signer.ProcessBlock(block, 0, block.Length); + +// Signature verifier = Signature.getInstance("SHA1WithRSA", "BC"); + ISigner verifier = SignerUtilities.GetSigner("SHA1WithRSA"); + +// verifier.initVerify(pub); + verifier.Init(false, pub); + +// verifier.update((byte)0); + verifier.Update(0); + +// if (verifier.verify(sig)) + if (verifier.VerifySignature(sigBytes)) + { +// fail("bad signature passed"); + Fail("bad signature passed"); + } + } + + private void testZeroBlock(ICipherParameters encParameters, ICipherParameters decParameters) + { + IAsymmetricBlockCipher 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 override 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 + // + IAsymmetricBlockCipher eng = new RsaEngine(); + + eng.Init(true, pubParameters); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("RSA: failed - exception " + e.ToString()); + } + + eng.Init(false, privParameters); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!edgeInput.Equals(Hex.ToHexString(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()); + } + + eng.Init(false, privParameters); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!input.Equals(Hex.ToHexString(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()); + } + + eng.Init(false, privParameters); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!input.Equals(Hex.ToHexString(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()); + } + + eng.Init(false, pubParameters); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!input.Equals(Hex.ToHexString(data))) + { + Fail("failed PKCS1 private/public Test"); + } + + testZeroBlock(pubParameters, privParameters); + testZeroBlock(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.Public).Modulus.BitLength < 768) + { + Fail("failed key generation (768) length test"); + } + + eng.Init(true, pair.Public); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + eng.Init(false, pair.Private); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!input.Equals(Hex.ToHexString(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.Public); + + if (((RsaKeyParameters)pair.Public).Modulus.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()); + } + + eng.Init(false, pair.Private); + + try + { + data = eng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString()); + } + + if (!input.Equals(Hex.ToHexString(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.Private; + BigInteger pqDiff = privKey.P.Subtract(privKey.Q).Abs(); + + if (pqDiff.BitLength < 5) + { + Fail("P and Q too close in RSA key pair"); + } + } + + doTestBadSig(); + doTestOaep(pubParameters, privParameters); + doTestStrictPkcs1Length(pubParameters, privParameters); + doTestDudPkcs1Block(pubParameters, privParameters); + doTestMissingDataPkcs1Block(pubParameters, privParameters); + doTestTruncatedPkcs1Block(pubParameters, privParameters); + doTestWrongPaddingPkcs1Block(pubParameters, privParameters); + + try + { + new RsaEngine().ProcessBlock(new byte[]{ 1 }, 0, 1); + Fail("failed initialisation check"); + } + catch (InvalidOperationException) + { + // expected + } + } + + public static void Main( + string[] args) + { + ITest test = new RsaTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SCryptTest.cs b/crypto/test/src/crypto/test/SCryptTest.cs new file mode 100644 index 000000000..c055ab718 --- /dev/null +++ b/crypto/test/src/crypto/test/SCryptTest.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// + /// scrypt test vectors from "Stronger Key Derivation Via Sequential Memory-hard Functions" Appendix B. + /// (http://www.tarsnap.com/scrypt/scrypt.pdf) + /// + [TestFixture] + public class SCryptTest + : SimpleTest + { + public override string Name + { + get { return "SCrypt"; } + } + + public override void PerformTest() + { + using (StreamReader sr = new StreamReader(SimpleTest.GetTestDataAsStream("scrypt.TestVectors.txt"))) + { + int count = 0; + string line = sr.ReadLine(); + + while (line != null) + { + ++count; + string header = line; + StringBuilder data = new StringBuilder(); + + while (!IsEndData(line = sr.ReadLine())) + { + data.Append(line.Replace(" ", "")); + } + + int start = header.IndexOf('(') + 1; + int limit = header.LastIndexOf(')'); + string argStr = header.Substring(start, limit - start); + string[] args = argStr.Split(','); + + 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); + } + } + } + } + } + + private static bool IsEndData(string line) + { + return line == null || line.StartsWith("scrypt"); + } + + private static byte[] ExtractQuotedString(string arg) + { + arg = arg.Trim(); + arg = arg.Substring(1, arg.Length - 2); + return Encoding.ASCII.GetBytes(arg); + } + + private static int ExtractInteger(string arg) + { + return int.Parse(arg.Trim()); + } + + public static void Main( + string[] args) + { + RunTest(new SCryptTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SEEDTest.cs b/crypto/test/src/crypto/test/SEEDTest.cs new file mode 100644 index 000000000..2fcb242cc --- /dev/null +++ b/crypto/test/src/crypto/test/SEEDTest.cs @@ -0,0 +1,65 @@ +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * SEED tester - vectors http://www.ietf.org/rfc/rfc4009.txt + */ + [TestFixture] + public class SeedTest + : 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"), + }; + + public SeedTest() + : base(tests, new SeedEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get { return "SEED"; } + } + + public static void Main( + string[] args) + { + RunTest(new SeedTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA1DigestTest.cs b/crypto/test/src/crypto/test/SHA1DigestTest.cs new file mode 100644 index 000000000..22a5c8f46 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA1DigestTest.cs @@ -0,0 +1,151 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// Standard vector test for SHA-1 from "Handbook of Applied Cryptography", page 345. + [TestFixture] + public class Sha1DigestTest + : SimpleTest + { + //static private string testVec1 = ""; + static private string resVec1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; + + static private string testVec2 = "61"; + static private string resVec2 = "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"; + + static private string testVec3 = "616263"; + static private string resVec3 = "a9993e364706816aba3e25717850c26c9cd0d89d"; + + static private string testVec4 = "6162636465666768696a6b6c6d6e6f707172737475767778797a"; + static private string resVec4 = "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"; + + public override string Name + { + get { return "SHA1"; } + } + + public override void PerformTest() + { + IDigest digest = new Sha1Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + Fail("failing standard vector test 1" + SimpleTest.NewLine + + " expected: " + resVec1 + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + Fail("failing standard vector test 2" + SimpleTest.NewLine + + " expected: " + resVec2 + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + Fail("failing standard vector test 3" + SimpleTest.NewLine + + " expected: " + resVec3 + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + Fail("failing standard vector test 4" + SimpleTest.NewLine + + " expected: " + resVec4 + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length / 2); + + // clone the IDigest + IDigest d = new Sha1Digest((Sha1Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + Fail("failing standard vector test 5" + SimpleTest.NewLine + + " expected: " + resVec4 + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + Fail("failing standard vector test 5" + SimpleTest.NewLine + + " expected: " + resVec4 + SimpleTest.NewLine + + " got : " + resStr); + } + } + + public static void Main( + string[] args) + { + RunTest(new Sha1DigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA1HMacTest.cs b/crypto/test/src/crypto/test/SHA1HMacTest.cs new file mode 100644 index 000000000..865f5b58b --- /dev/null +++ b/crypto/test/src/crypto/test/SHA1HMacTest.cs @@ -0,0 +1,93 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// SHA1 HMac Test, test vectors from RFC 2202 + [TestFixture] + public class Sha1HMacTest + : ITest + { + public string Name + { + get { return "SHA1HMac"; } + } + + public static readonly string[] keys = new string[]{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "0102030405060708090a0b0c0d0e0f10111213141516171819", "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}; + public static readonly string[] digests = new string[]{"b617318655057264e28bc0b6fb378c8ef146be00", "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", "125d7342b9ac11cd91a39af48aa17b4f63f175d3", "4c9007f4026250c6bc8414f9bf50c86c2d7235da", "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", "aa4ae5e15272d00e95705637ce8a3b55ed402112", "e8e99d0f45237d786d6bbaa7965c7808bbff1a91", "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", "aa4ae5e15272d00e95705637ce8a3b55ed402112", "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"}; + public static readonly string[] messages = new string[]{"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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new Sha1Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test reset + // + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha1HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA224DigestTest.cs b/crypto/test/src/crypto/test/SHA224DigestTest.cs new file mode 100644 index 000000000..37035c30f --- /dev/null +++ b/crypto/test/src/crypto/test/SHA224DigestTest.cs @@ -0,0 +1,200 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for SHA-224 from RFC 3874 - only the last three are in + * the RFC. + */ + [TestFixture] + public class Sha224DigestTest + : ITest + { + private const string testVec1 = ""; + private const string resVec1 = "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"; + + private const string testVec2 = "61"; + private const string resVec2 = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"; + + private const string testVec3 = "616263"; + private const string resVec3 = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"; + + private const string testVec4 = "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071"; + private const string resVec4 = "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"; + + // 1 million 'a' + private const string testVec5 = "61616161616161616161"; + private const string resVec5 = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"; + + public string Name + { + get { return "SHA224"; } + } + + public ITestResult Perform() + { + IDigest digest = new Sha224Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length/2); + + // clone the IDigest + IDigest d = new Sha224Digest((Sha224Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // test 6 + bytes = Hex.Decode(testVec5); + for ( int i = 0; i < 100000; i++ ) + { + digest.BlockUpdate(bytes, 0, bytes.Length); + } + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec5.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-224 failing standard vector test 6" + + SimpleTest.NewLine + + " expected: " + resVec5 + + SimpleTest.NewLine + + " got : " + resStr); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha224DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA224HMacTest.cs b/crypto/test/src/crypto/test/SHA224HMacTest.cs new file mode 100644 index 000000000..06c6ea1cb --- /dev/null +++ b/crypto/test/src/crypto/test/SHA224HMacTest.cs @@ -0,0 +1,122 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// SHA224 HMac Test, test vectors from RFC + [TestFixture] + public class Sha224HMacTest + : ITest + { + public string Name + { + get { return "SHA224HMac"; } + } + + public static readonly string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + public static readonly string[] digests = + { + "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", + "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44", + "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea", + "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a", + "0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c", + "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e", + "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1" + }; + + public static readonly 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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new Sha224Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test reset + // + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha224HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA256DigestTest.cs b/crypto/test/src/crypto/test/SHA256DigestTest.cs new file mode 100644 index 000000000..67f0c2397 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA256DigestTest.cs @@ -0,0 +1,205 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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. + */ + [TestFixture] + public class Sha256DigestTest + : ITest + { +// static private string testVec1 = ""; + static private string resVec1 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + + static private string testVec2 = "61"; + static private string resVec2 = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"; + + static private string testVec3 = "616263"; + static private string resVec3 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; + + static private string testVec4 = "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071"; + static private string resVec4 = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"; + + // 1 million 'a' + static private string testVec5 = "61616161616161616161"; + static private string resVec5 = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"; + + public string Name + { + get { return "SHA256"; } + } + + public ITestResult Perform() + { + IDigest digest = new Sha256Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length/2); + + // clone the IDigest + IDigest d = new Sha256Digest((Sha256Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // test 6 + bytes = Hex.Decode(testVec5); + for ( int i = 0; i < 100000; i++ ) + { + digest.BlockUpdate(bytes, 0, bytes.Length); + } + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec5.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-256 failing standard vector test 6" + + SimpleTest.NewLine + + " expected: " + resVec5 + + SimpleTest.NewLine + + " got : " + resStr); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha256DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } + +} diff --git a/crypto/test/src/crypto/test/SHA256HMacTest.cs b/crypto/test/src/crypto/test/SHA256HMacTest.cs new file mode 100644 index 000000000..a9016af21 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA256HMacTest.cs @@ -0,0 +1,122 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// SHA256 HMac Test, test vectors from RFC + [TestFixture] + public class Sha256HMacTest + : ITest + { + public string Name + { + get { return "SHA256HMac"; } + } + + public static readonly string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + public static readonly string[] digests = + { + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", + "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", + "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", + "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5", + "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", + "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2" + }; + + public static readonly 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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new Sha256Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test reset + // + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha256HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA384DigestTest.cs b/crypto/test/src/crypto/test/SHA384DigestTest.cs new file mode 100644 index 000000000..70c26edcc --- /dev/null +++ b/crypto/test/src/crypto/test/SHA384DigestTest.cs @@ -0,0 +1,203 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * 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. + */ + [TestFixture] + public class Sha384DigestTest + : ITest + { +// static private string testVec1 = ""; + static private string resVec1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; + + static private string testVec2 = "61"; + static private string resVec2 = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"; + + static private string testVec3 = "616263"; + static private string resVec3 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"; + + static private string testVec4 = "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475"; + static private string resVec4 = "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"; + + // 1 million 'a' + static private string testVec5 = "61616161616161616161"; + static private string resVec5 = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"; + + public string Name + { + get { return "SHA384"; } + } + + public ITestResult Perform() + { + IDigest digest = new Sha384Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 1" + + SimpleTest.NewLine + + " expected: " + resVec1 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 2" + + SimpleTest.NewLine + + " expected: " + resVec2 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 3" + + SimpleTest.NewLine + + " expected: " + resVec3 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 4" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length/2); + + // clone the IDigest + IDigest d = new Sha384Digest((Sha384Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 5" + + SimpleTest.NewLine + + " expected: " + resVec4 + + SimpleTest.NewLine + + " got : " + resStr); + } + + // test 6 + bytes = Hex.Decode(testVec5); + for ( int i = 0; i < 100000; i++ ) + { + digest.BlockUpdate(bytes, 0, bytes.Length); + } + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec5.Equals(resStr)) + { + return new SimpleTestResult(false, + "SHA-384 failing standard vector test 6" + + SimpleTest.NewLine + + " expected: " + resVec5 + + SimpleTest.NewLine + + " got : " + resStr); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha384DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA384HMacTest.cs b/crypto/test/src/crypto/test/SHA384HMacTest.cs new file mode 100644 index 000000000..0caba12c4 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA384HMacTest.cs @@ -0,0 +1,122 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// SHA384 HMac Test, test vectors from RFC + [TestFixture] + public class Sha384HMacTest + : ITest + { + public string Name + { + get { return "SHA384HMac"; } + } + + public static readonly string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + public static readonly string[] digests = + { + "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6", + "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649", + "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27", + "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb", + "3abf34c3503b2a23a46efc619baef897f4c8e42c934ce55ccbae9740fcbc1af4ca62269e2a37cd88ba926341efe4aeea", + "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952", + "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e" + }; + + public static readonly 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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new Sha384Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test reset + // + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha384HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA3DigestTest.cs b/crypto/test/src/crypto/test/SHA3DigestTest.cs new file mode 100644 index 000000000..2b8ae4a63 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA3DigestTest.cs @@ -0,0 +1,374 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * SHA3 Digest Test + */ + [TestFixture] + public class Sha3DigestTest + : SimpleTest + { + readonly static string[] messages = { + "", + "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67", + "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e" + }; + + readonly 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 + }; + + readonly static string[] digests224 = { + "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", + "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe", + "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab", + "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53", + "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0", + "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5" + }; + + readonly static string[] digests256 = { + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15", + "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d", + "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed", + "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03", + "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4" + }; + + readonly static string[] digests384 = { + "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", + "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3", + "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b", + "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398", + "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4", + "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315" + }; + + readonly static string[] digests512 = { + "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", + "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609", + "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760", + "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c", + "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e", + "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8" + }; + + // test vectors from http://www.di-mgt.com.au/hmac_sha3_testvectors.html + readonly 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") + }; + + readonly static string[] macData = + { + "4869205468657265", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + + "dddddddddddddddddddddddddddddddddddd", + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365" + + "642062792074686520484d414320616c676f726974686d2e", + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365\n" + + "642062792074686520484d414320616c676f726974686d2e" + }; + + readonly static string[] mac224 = + { + "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc", + "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414", + "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449", + "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b", + "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff", + "ba13009405a929f398b348885caa5419191bb948ada32194afc84104", + "92649468be236c3c72c189909c063b13f994be05749dc91310db639e" + }; + + readonly static string[] mac256 = + { + "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821", + "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1", + "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260", + "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd", + "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6", + "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02", + "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484" + }; + + readonly static string[] mac384 = + { + "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048", + "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d", + "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c", + "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693", + "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f", + "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9", + "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5" + }; + + readonly static string[] mac512 = + { + "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755", + "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb", + "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66", + "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb", + "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5", + "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572", + "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8" + }; + + readonly static KeyParameter truncKey = new KeyParameter(Hex.Decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")); + readonly static byte[] truncData = Hex.Decode("546573742057697468205472756e636174696f6e"); + + readonly static byte[] trunc224 = Hex.Decode("f52bbcfd654264e7133085c5e69b72c3"); + readonly static byte[] trunc256 = Hex.Decode("745e7e687f8335280d54202ef13cecc6"); + readonly static byte[] trunc384 = Hex.Decode("fa9aea2bc1e181e47cbb8c3df243814d"); + readonly static byte[] trunc512 = Hex.Decode("04c929fead434bba190dacfa554ce3f5"); + + readonly static byte[] xtremeData = Hex.Decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f"); + + public override string Name + { + get { return "SHA3"; } + } + + private void TestDigest(IDigest 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.BlockUpdate(data, 0, data.Length); + } + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[i]), hash)) + { + Fail("sha3 mismatch on " + digest.AlgorithmName + " index " + i); + } + } + + byte[] k64 = new byte[1024 * 64]; + + for (int i = 0; i != k64.Length; i++) + { + k64[i] = (byte)'a'; + } + + digest.BlockUpdate(k64, 0, k64.Length); + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash)) + { + Fail("sha3 mismatch on " + digest.AlgorithmName + " 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.AlgorithmName + " 64k a single"); + } + + + for (int i = 0; i != k64.Length; i++) + { + k64[i] = (byte)('a' + (i % 26)); + } + + digest.BlockUpdate(k64, 0, k64.Length); + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + { + Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k alpha"); + } + + for (int i = 0; i != 64; i++) + { + digest.Update(k64[i * 1024]); + digest.BlockUpdate(k64, i * 1024 + 1, 1023); + } + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + { + Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k chunked alpha"); + } + + TestDigestDoFinal(digest); + + // + // extremely long data test + // + //Console.WriteLine("Starting very long"); + //for (int i = 0; i != 16384; i++) + //{ + // for (int j = 0; j != 1024; j++) + // { + // digest.BlockUpdate(xtremeData, 0, xtremeData.Length); + // } + //} + + //digest.DoFinal(hash, 0); + + //if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 2]), hash)) + //{ + // Fail("sha3 mismatch on " + digest.AlgorithmName + " extreme data test"); + //} + //Console.WriteLine("Done"); + } + + private void TestDigestDoFinal(IDigest 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()]; + Array.Copy(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.AlgorithmName); + } + } + } + + private void TestMac(IDigest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected) + { + IMac 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.BlockUpdate(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.AlgorithmName); + } + } + + { + mac = new HMac(digest); + + mac.Init(truncKey); + + mac.BlockUpdate(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.AlgorithmName); + } + } + } + } + + public override 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 virtual IDigest CloneDigest(IDigest digest) + { + return new Sha3Digest((Sha3Digest)digest); + } + + public static void Main( + string[] args) + { + RunTest(new Sha3DigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA512DigestTest.cs b/crypto/test/src/crypto/test/SHA512DigestTest.cs new file mode 100644 index 000000000..c8096b7db --- /dev/null +++ b/crypto/test/src/crypto/test/SHA512DigestTest.cs @@ -0,0 +1,165 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// + /// 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. + /// + [TestFixture] + public class Sha512DigestTest + : ITest + { + public string Name + { + get { return "SHA512"; } + } + + //private static string testVec1 = ""; + private static string resVec1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; + + private static string testVec2 = "61"; + private static string resVec2 = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"; + + private static string testVec3 = "616263"; + private static string resVec3 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; + + private static string testVec4 = "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475"; + private static string resVec4 = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"; + + // 1 million 'a' + private static string testVec5 = "61616161616161616161"; + private static string resVec5 = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"; + + public virtual ITestResult Perform() + { + IDigest digest = new Sha512Digest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + string resStr; + + // + // test 1 + // + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec1.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 1" + SimpleTest.NewLine + " expected: " + resVec1 + SimpleTest.NewLine + " got : " + resStr); + } + + // + // test 2 + // + byte[] bytes = Hex.Decode(testVec2); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec2.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 2" + SimpleTest.NewLine + " expected: " + resVec2 + SimpleTest.NewLine + " got : " + resStr); + } + + // + // test 3 + // + bytes = Hex.Decode(testVec3); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec3.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 3" + SimpleTest.NewLine + " expected: " + resVec3 + SimpleTest.NewLine + " got : " + resStr); + } + + // + // test 4 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length); + + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 4" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr); + } + + // + // test 5 + // + bytes = Hex.Decode(testVec4); + + digest.BlockUpdate(bytes, 0, bytes.Length / 2); + + // clone the IDigest + IDigest d = new Sha512Digest((Sha512Digest)digest); + + digest.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2); + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 5" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr); + } + + d.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2); + d.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec4.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 5" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr); + } + + // test 6 + bytes = Hex.Decode(testVec5); + for (int i = 0; i < 100000; i++) + { + digest.BlockUpdate(bytes, 0, bytes.Length); + } + digest.DoFinal(resBuf, 0); + + resStr = Hex.ToHexString(resBuf); + if (!resVec5.Equals(resStr)) + { + return new SimpleTestResult(false, "SHA-512 failing standard vector test 6" + SimpleTest.NewLine + " expected: " + resVec5 + SimpleTest.NewLine + " got : " + resStr); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha512DigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA512HMacTest.cs b/crypto/test/src/crypto/test/SHA512HMacTest.cs new file mode 100644 index 000000000..c091a7220 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA512HMacTest.cs @@ -0,0 +1,123 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + + /// SHA512 HMac Test, test vectors from RFC + [TestFixture] + public class Sha512HMacTest + : ITest + { + public string Name + { + get { return "SHA512HMac"; } + } + + public static readonly string[] keys = + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4a656665", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }; + + public static readonly string[] digests = + { + "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854", + "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737", + "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb", + "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd", + "415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b", + "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", + "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58" + }; + + public static readonly 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 virtual ITestResult Perform() + { + HMac hmac = new HMac(new Sha512Digest()); + byte[] resBuf = new byte[hmac.GetMacSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + if (messages[i].StartsWith("0x")) + { + m = Hex.Decode(messages[i].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); + hmac.BlockUpdate(m, 0, m.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed"); + } + } + + // + // test reset + // + int vector = 0; // vector used for test + byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); + if (messages[vector].StartsWith("0x")) + { + m2 = Hex.Decode(messages[vector].Substring(2)); + } + hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + hmac.Reset(); + hmac.BlockUpdate(m2, 0, m2.Length); + hmac.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) + { + return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new Sha512HMacTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA512t224DigestTest.cs b/crypto/test/src/crypto/test/SHA512t224DigestTest.cs new file mode 100644 index 000000000..a3d68e1ab --- /dev/null +++ b/crypto/test/src/crypto/test/SHA512t224DigestTest.cs @@ -0,0 +1,62 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for SHA-512/224 from FIPS 180-4. + * + * Note, only the last 2 message entries are FIPS originated.. + */ + public class Sha512t224DigestTest + : DigestTest + { + private static string[] messages = + { + "", + "a", + "abc", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + }; + + private static string[] digests = + { + "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4", + "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327", + "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA", + "23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9" + }; + + // 1 million 'a' + private const string million_a_digest = "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287"; + + internal Sha512t224DigestTest() + : base(new Sha512tDigest(224), messages, digests) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + millionATest(million_a_digest); + } + + protected override IDigest CloneDigest(IDigest digest) + { + return new Sha512tDigest((Sha512tDigest)digest); + } + + public static void Main( + string[] args) + { + RunTest(new Sha512t224DigestTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/SHA512t256DigestTest.cs b/crypto/test/src/crypto/test/SHA512t256DigestTest.cs new file mode 100644 index 000000000..c957aa660 --- /dev/null +++ b/crypto/test/src/crypto/test/SHA512t256DigestTest.cs @@ -0,0 +1,62 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for SHA-512/256 from FIPS 180-4. + * + * Note, only the last 2 message entries are FIPS originated.. + */ + public class Sha512t256DigestTest + : DigestTest + { + private static string[] messages = + { + "", + "a", + "abc", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + }; + + private static string[] digests = + { + "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a", + "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8", + "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23", + "3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A" + }; + + // 1 million 'a' + private const string million_a_digest = "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21"; + + internal Sha512t256DigestTest() + : base(new Sha512tDigest(256), messages, digests) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + millionATest(million_a_digest); + } + + protected override IDigest CloneDigest(IDigest digest) + { + return new Sha512tDigest((Sha512tDigest)digest); + } + + public static void Main( + string[] args) + { + RunTest(new Sha512t256DigestTest()); + } + } +} diff --git a/crypto/test/src/crypto/test/SRP6Test.cs b/crypto/test/src/crypto/test/SRP6Test.cs new file mode 100644 index 000000000..3b80e2c16 --- /dev/null +++ b/crypto/test/src/crypto/test/SRP6Test.cs @@ -0,0 +1,300 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Srp6Test + : SimpleTest + { + private static BigInteger FromHex(string hex) + { + return new BigInteger(1, Hex.Decode(hex)); + } + + // 1024 bit example prime from RFC5054 and corresponding generator + private static readonly BigInteger N_1024 = FromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + + "FD5138FE8376435B9FC61D2FC0EB06E3"); + private static readonly BigInteger g_1024 = BigInteger.Two; + + private readonly SecureRandom random = new SecureRandom(); + + public override string Name + { + get { return "SRP6"; } + } + + public override void PerformTest() + { + 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() + { + byte[] I = Encoding.UTF8.GetBytes("alice"); + byte[] P = Encoding.UTF8.GetBytes("password123"); + 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 = Srp6Utilities.CalculateK(new Sha1Digest(), N, g); + if (!k.Equals(expect_k)) + { + Fail("wrong value of 'k'"); + } + + BigInteger x = Srp6Utilities.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'"); + } + + Srp6Client client = new MySrp6Client(a); + client.Init(N, g, new Sha1Digest(), random); + + BigInteger A = client.GenerateClientCredentials(s, I, P); + if (!A.Equals(expect_A)) + { + Fail("wrong value of 'A'"); + } + + Srp6Server server = new MySrp6Server(b); + server.Init(N, g, v, new Sha1Digest(), random); + + BigInteger B = server.GenerateServerCredentials(); + if (!B.Equals(expect_B)) + { + Fail("wrong value of 'B'"); + } + + BigInteger u = Srp6Utilities.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) + { + DHParametersGenerator paramGen = new DHParametersGenerator(); + paramGen.Init(bits, 25, random); + DHParameters parameters = paramGen.GenerateParameters(); + + BigInteger g = parameters.G; + BigInteger p = parameters.P; + + testMutualVerification(p, g); + } + + private void testMutualVerification(BigInteger N, BigInteger g) + { + byte[] I = Encoding.UTF8.GetBytes("username"); + byte[] P = Encoding.UTF8.GetBytes("password"); + 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 = Encoding.UTF8.GetBytes("username"); + byte[] P = Encoding.UTF8.GetBytes("password"); + 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(BigInteger.Zero); + Fail("Client failed to detect invalid value for 'B'"); + } + catch (CryptoException) + { + // Expected + } + + try + { + client.CalculateSecret(N); + Fail("Client failed to detect invalid value for 'B'"); + } + catch (CryptoException) + { + // Expected + } + } + + private void testServerCatchesBadA(BigInteger N, BigInteger g) + { + byte[] I = Encoding.UTF8.GetBytes("username"); + byte[] P = Encoding.UTF8.GetBytes("password"); + 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(BigInteger.Zero); + Fail("Client failed to detect invalid value for 'A'"); + } + catch (CryptoException) + { + // Expected + } + + try + { + server.CalculateSecret(N); + Fail("Client failed to detect invalid value for 'A'"); + } + catch (CryptoException) + { + // Expected + } + } + + public static void Main(string[] args) + { + RunTest(new Srp6Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Assert.AreEqual(Name + ": Okay", resultText); + } + + private class MySrp6Client + : Srp6Client + { + private readonly BigInteger nonRandomPrivA; + + internal MySrp6Client(BigInteger nonRandomPrivA) + { + this.nonRandomPrivA = nonRandomPrivA; + } + + protected override BigInteger SelectPrivateValue() + { + return nonRandomPrivA; + } + } + + private class MySrp6Server + : Srp6Server + { + private readonly BigInteger nonRandomPrivB; + + internal MySrp6Server(BigInteger nonRandomPrivB) + { + this.nonRandomPrivB = nonRandomPrivB; + } + + protected override BigInteger SelectPrivateValue() + { + return nonRandomPrivB; + } + } + } +} diff --git a/crypto/test/src/crypto/test/Salsa20Test.cs b/crypto/test/src/crypto/test/Salsa20Test.cs new file mode 100644 index 000000000..9e7549ae7 --- /dev/null +++ b/crypto/test/src/crypto/test/Salsa20Test.cs @@ -0,0 +1,261 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Salsa20 Test + */ + [TestFixture] + public class Salsa20Test + : SimpleTest + { + private static readonly byte[] zeroes = Hex.Decode( + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000"); + + private static readonly string set1v0_0 = + "4DFA5E481DA23EA09A31022050859936" + + "DA52FCEE218005164F267CB65F5CFD7F" + + "2B4F97E0FF16924A52DF269515110A07" + + "F9E460BC65EF95DA58F740B7D1DBB0AA"; + + private static readonly string set1v0_192 = + "DA9C1581F429E0A00F7D67E23B730676" + + "783B262E8EB43A25F55FB90B3E753AEF" + + "8C6713EC66C51881111593CCB3E8CB8F" + + "8DE124080501EEEB389C4BCB6977CF95"; + + private static readonly string set1v0_256 = + "7D5789631EB4554400E1E025935DFA7B" + + "3E9039D61BDC58A8697D36815BF1985C" + + "EFDF7AE112E5BB81E37ECF0616CE7147" + + "FC08A93A367E08631F23C03B00A8DA2F"; + + private static readonly string set1v0_448 = + "B375703739DACED4DD4059FD71C3C47F" + + "C2F9939670FAD4A46066ADCC6A564578" + + "3308B90FFB72BE04A6B147CBE38CC0C3" + + "B9267C296A92A7C69873F9F263BE9703"; + + private static readonly string set1v9_0 = + "0471076057830FB99202291177FBFE5D" + + "38C888944DF8917CAB82788B91B53D1C" + + "FB06D07A304B18BB763F888A61BB6B75" + + "5CD58BEC9C4CFB7569CB91862E79C459"; + + private static readonly string set1v9_192 = + "D1D7E97556426E6CFC21312AE3811425" + + "9E5A6FB10DACBD88E4354B0472556935" + + "2B6DA5ACAFACD5E266F9575C2ED8E6F2" + + "EFE4B4D36114C3A623DD49F4794F865B"; + + private static readonly string set1v9_256 = + "AF06FAA82C73291231E1BD916A773DE1" + + "52FD2126C40A10C3A6EB40F22834B8CC" + + "68BD5C6DBD7FC1EC8F34165C517C0B63" + + "9DB0C60506D3606906B8463AA0D0EC2F"; + + private static readonly string set1v9_448 = + "AB3216F1216379EFD5EC589510B8FD35" + + "014D0AA0B613040BAE63ECAB90A9AF79" + + "661F8DA2F853A5204B0F8E72E9D9EB4D" + + "BA5A4690E73A4D25F61EE7295215140C"; + + private static readonly string set6v0_0 = + "F5FAD53F79F9DF58C4AEA0D0ED9A9601" + + "F278112CA7180D565B420A48019670EA" + + "F24CE493A86263F677B46ACE1924773D" + + "2BB25571E1AA8593758FC382B1280B71"; + + private static readonly string set6v0_65472 = + "B70C50139C63332EF6E77AC54338A407" + + "9B82BEC9F9A403DFEA821B83F7860791" + + "650EF1B2489D0590B1DE772EEDA4E3BC" + + "D60FA7CE9CD623D9D2FD5758B8653E70"; + + private static readonly string set6v0_65536 = + "81582C65D7562B80AEC2F1A673A9D01C" + + "9F892A23D4919F6AB47B9154E08E699B" + + "4117D7C666477B60F8391481682F5D95" + + "D96623DBC489D88DAA6956B9F0646B6E"; + + private static readonly string set6v1_0 = + "3944F6DC9F85B128083879FDF190F7DE" + + "E4053A07BC09896D51D0690BD4DA4AC1" + + "062F1E47D3D0716F80A9B4D85E6D6085" + + "EE06947601C85F1A27A2F76E45A6AA87"; + + private static readonly string set6v1_65472 = + "36E03B4B54B0B2E04D069E690082C8C5" + + "92DF56E633F5D8C7682A02A65ECD1371" + + "8CA4352AACCB0DA20ED6BBBA62E177F2" + + "10E3560E63BB822C4158CAA806A88C82"; + + private static readonly string set6v1_65536 = + "1B779E7A917C8C26039FFB23CF0EF8E0" + + "8A1A13B43ACDD9402CF5DF38501098DF" + + "C945A6CC69A6A17367BC03431A86B3ED" + + "04B0245B56379BF997E25800AD837D7D"; + + public override string Name + { + get { return "Salsa20"; } + } + + public override void PerformTest() + { + salsa20Test1(new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")), + set1v0_0, set1v0_192, set1v0_256, set1v0_448); + salsa20Test1(new ParametersWithIV(new KeyParameter(Hex.Decode("00400000000000000000000000000000")), Hex.Decode("0000000000000000")), + set1v9_0, set1v9_192, set1v9_256, set1v9_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(); + } + + private void salsa20Test1( + ICipherParameters parameters, + string v0, + string v192, + string v256, + string v448) + { + IStreamCipher salsa = new Salsa20Engine(); + byte[] buf = new byte[64]; + + salsa.Init(true, parameters); + + 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", v0, buf); + } + break; + case 3: + if (!AreEqual(buf, Hex.Decode(v192))) + { + mismatch("v192", v192, buf); + } + break; + case 4: + if (!AreEqual(buf, Hex.Decode(v256))) + { + mismatch("v256", v256, buf); + } + break; + default: + // ignore + break; + } + } + + 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( + ICipherParameters parameters, + string v0, + string v65472, + string v65536) + { + IStreamCipher salsa = new Salsa20Engine(); + byte[] buf = new byte[64]; + + salsa.Init(true, parameters); + + 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 + break; + } + } + } + + private void mismatch( + string name, + string expected, + byte[] found) + { + Fail("mismatch on " + name, expected, Hex.ToHexString(found)); + } + + private void reinitBug() + { + KeyParameter key = new KeyParameter(Hex.Decode("80000000000000000000000000000000")); + ParametersWithIV parameters = new ParametersWithIV(key, Hex.Decode("0000000000000000")); + + IStreamCipher salsa = new Salsa20Engine(); + + salsa.Init(true, parameters); + + try + { + salsa.Init(true, key); + Fail("Salsa20 should throw exception if no IV in Init"); + } + catch (ArgumentException) + { + } + } + + public static void Main( + string[] args) + { + RunTest(new Salsa20Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SerpentTest.cs b/crypto/test/src/crypto/test/SerpentTest.cs new file mode 100644 index 000000000..2467797e9 --- /dev/null +++ b/crypto/test/src/crypto/test/SerpentTest.cs @@ -0,0 +1,119 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class SerpentTest: 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") + }; + + public SerpentTest() + : base(tests, new SerpentEngine(), new KeyParameter(new byte[32])) + { + } + + public override string Name + { + get { return "Serpent"; } + } + + public static void Main( + string[] args) + { + ITest test = new SerpentTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/ShortenedDigestTest.cs b/crypto/test/src/crypto/test/ShortenedDigestTest.cs new file mode 100644 index 000000000..4956b5b39 --- /dev/null +++ b/crypto/test/src/crypto/test/ShortenedDigestTest.cs @@ -0,0 +1,98 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class ShortenedDigestTest : SimpleTest + { + public override void PerformTest() + { + IDigest 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 (ArgumentException) + { + // expected + } + + try + { + new ShortenedDigest(new Sha1Digest(), 50); + + Fail("short digest not caught"); + } + catch (ArgumentException) + { + // expected + } + } + + public override string Name + { + get { return "ShortenedDigest"; } + } + + public static void Main( + string[] args) + { + RunTest(new ShortenedDigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} \ No newline at end of file diff --git a/crypto/test/src/crypto/test/SipHashTest.cs b/crypto/test/src/crypto/test/SipHashTest.cs new file mode 100644 index 000000000..81b6f64ae --- /dev/null +++ b/crypto/test/src/crypto/test/SipHashTest.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /// + /// 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. + /// + [TestFixture] + public class SipHashTest + : SimpleTest + { + public override string Name + { + get { return "SipHash"; } + } + + public override void PerformTest() + { + byte[] key = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] input = Hex.Decode("000102030405060708090a0b0c0d0e"); + + long expected = unchecked((long)0xa129ca6149be45e5); + + SipHash mac = new SipHash(); + mac.Init(new KeyParameter(key)); + mac.BlockUpdate(input, 0, input.Length); + + long result = mac.DoFinal(); + if (expected != result) + { + Fail("Result does not match expected value for DoFinal()"); + } + + // NOTE: Little-endian representation of 0xa129ca6149be45e5 + byte[] expectedBytes = Hex.Decode("e545be4961ca29a1"); + + mac.BlockUpdate(input, 0, input.Length); + + 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)"); + } + } + + public static void Main( + string[] args) + { + RunTest(new SipHashTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/SkipjackTest.cs b/crypto/test/src/crypto/test/SkipjackTest.cs new file mode 100644 index 000000000..d9fe6e4b4 --- /dev/null +++ b/crypto/test/src/crypto/test/SkipjackTest.cs @@ -0,0 +1,46 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class SkipjackTest + : CipherTest + { + public override string Name + { + get { return "SKIPJACK"; } + } + + internal static SimpleTest[] tests = new SimpleTest[]{ + new BlockCipherVectorTest(0, new SkipjackEngine(), new KeyParameter(Hex.Decode("00998877665544332211")), "33221100ddccbbaa", "2587cae27a12d300")}; + + public SkipjackTest() + : base(tests, new SkipjackEngine(), new KeyParameter(new byte[16])) + { + } + + public static void Main( + string[] args) + { + ITest test = new SkipjackTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/StreamCipherVectorTest.cs b/crypto/test/src/crypto/test/StreamCipherVectorTest.cs new file mode 100644 index 000000000..ead2f16c3 --- /dev/null +++ b/crypto/test/src/crypto/test/StreamCipherVectorTest.cs @@ -0,0 +1,68 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * a basic test that takes a stream cipher, key parameter, and an input + * and output string. + */ + public class StreamCipherVectorTest: ITest + { + int id; + IStreamCipher cipher; + ICipherParameters param; + byte[] input; + byte[] output; + + public StreamCipherVectorTest( + int id, + IStreamCipher cipher, + ICipherParameters 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 Name + { + get { return cipher.AlgorithmName + " Vector Test " + id; } + } + + public ITestResult Perform() + { + cipher.Init(true, param); + + byte[] outBytes = new byte[input.Length]; + + cipher.ProcessBytes(input, 0, input.Length, outBytes, 0); + + if (!Arrays.AreEqual(outBytes, output)) + { + return new SimpleTestResult(false, Name + ": failed - " + + "expected " + Hex.ToHexString(output) + + " got " + Hex.ToHexString(outBytes)); + } + + cipher.Init(false, param); + + cipher.ProcessBytes(output, 0, output.Length, outBytes, 0); + + if (!Arrays.AreEqual(input, outBytes)) + { + return new SimpleTestResult(false, Name + ": failed reversal"); + } + + return new SimpleTestResult(true, Name + ": OKAY"); + } + } +} diff --git a/crypto/test/src/crypto/test/TEATest.cs b/crypto/test/src/crypto/test/TEATest.cs new file mode 100644 index 000000000..525941dbf --- /dev/null +++ b/crypto/test/src/crypto/test/TEATest.cs @@ -0,0 +1,59 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm + */ + [TestFixture] + public class TeaTest + : CipherTest + { + private static readonly 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"), + }; + + public TeaTest() + : base(tests, new TeaEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get { return "TEA"; } + } + + public static void Main( + string[] args) + { + RunTest(new TeaTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/TigerDigestTest.cs b/crypto/test/src/crypto/test/TigerDigestTest.cs new file mode 100644 index 000000000..6fec60185 --- /dev/null +++ b/crypto/test/src/crypto/test/TigerDigestTest.cs @@ -0,0 +1,140 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + + /** + * Tiger Digest Test + */ + [TestFixture] + public class TigerDigestTest + : ITest + { + readonly 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+-" + }; + + readonly static string[] digests = { + "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3", + "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93", + "DD00230799F5009FEC6DEBC838BB6A27DF2B9D6F110C7937", + "F71C8583902AFB879EDFE610F82C0D4786A3A534504486B5", + "38F41D9D9A710A10C3727AC0DEEAA270727D9F926EC10139", + "48CEEB6308B87D46E95D656112CDF18D97915F9765658957", + "631ABDD103EB9A3D245B6DFD4D77B257FC7439501D1568DD", + "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25", + "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25" + }; + + readonly static string hash64k = "FDF4F5B35139F48E710E421BE5AF411DE1A8AAC333F26204"; + + public string Name + { + get { return "Tiger"; } + } + + public ITestResult Perform() + { + IDigest digest = new TigerDigest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + + for (int i = 0; i < messages.Length; i++) + { + byte[] m = Encoding.ASCII.GetBytes(messages[i]); + digest.BlockUpdate(m, 0, m.Length); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) + { + return new SimpleTestResult(false, Name + ": Vector " + i + " failed got " + Hex.ToHexString(resBuf)); + } + } + + // + // test 2 + // + byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]); + + digest.BlockUpdate(mm, 0, mm.Length/2); + + // clone the IDigest + IDigest d = new TigerDigest((TigerDigest)digest); + + digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "Tiger failing clone test" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2); + d.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1]))) + { + return new SimpleTestResult(false, + "Tiger failing clone test - part 2" + + SimpleTest.NewLine + + " expected: " + digests[digests.Length-1] + + SimpleTest.NewLine + + " got : " + Hex.ToHexString(resBuf)); + } + + for (int i = 0; i < 65536; i++) + { + digest.Update((byte)(i & 0xff)); + } + digest.DoFinal(resBuf, 0); + + if (!Arrays.AreEqual(resBuf, Hex.Decode(hash64k))) + { + return new SimpleTestResult(false, Name + ": Million a's failed"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new TigerDigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/TwofishTest.cs b/crypto/test/src/crypto/test/TwofishTest.cs new file mode 100644 index 000000000..9425d2e60 --- /dev/null +++ b/crypto/test/src/crypto/test/TwofishTest.cs @@ -0,0 +1,54 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class TwofishTest + : CipherTest + { + public override string Name + { + get { return "Twofish"; } + } + + internal static string key1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; + internal static string key2 = "000102030405060708090a0b0c0d0e0f1011121314151617"; + internal static string key3 = "000102030405060708090a0b0c0d0e0f"; + + internal static string input = "000102030405060708090A0B0C0D0E0F"; + + internal static SimpleTest[] tests = new SimpleTest[]{ + 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")}; + + public TwofishTest() + : base(tests, new TwofishEngine(), new KeyParameter(new byte[32])) + { + } + + public static void Main( + string[] args) + { + ITest test = new TwofishTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/VMPCKSA3Test.cs b/crypto/test/src/crypto/test/VMPCKSA3Test.cs new file mode 100644 index 000000000..a25105b77 --- /dev/null +++ b/crypto/test/src/crypto/test/VMPCKSA3Test.cs @@ -0,0 +1,112 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * VMPC Test + */ + [TestFixture] + public class VmpcKsa3Test + : SimpleTest + { + private static readonly byte[] input = new byte[1000000]; + + public override string Name + { + get { return "VMPC-KSA3"; } + } + + private void checkByte(byte[] array, int position, byte b) + { + if (array[position] != b) + { + Fail("Fail on position " + position, + Hex.ToHexString(new byte[] { b }), + Hex.ToHexString(new byte[] { array[position] })); + } + } + + public override void PerformTest() + { + byte[] key = Hex.Decode("9661410AB797D8A9EB767C21172DF6C7"); + byte[] iv = Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155"); + ICipherParameters kp = new KeyParameter(key); + ICipherParameters kpwiv = new ParametersWithIV(kp, iv); + + VmpcKsa3Engine engine = new VmpcKsa3Engine(); + + try + { + engine.Init(true, kp); + Fail("Init failed to throw expected exception"); + } + catch (ArgumentException) + { + // 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/VMPCMacTest.cs b/crypto/test/src/crypto/test/VMPCMacTest.cs new file mode 100644 index 000000000..0ddb5506f --- /dev/null +++ b/crypto/test/src/crypto/test/VMPCMacTest.cs @@ -0,0 +1,68 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class VmpcMacTest + : SimpleTest + { + public override string Name + { + get { return "VMPC-MAC"; } + } + + public static void Main( + string[] args) + { + RunTest(new VmpcMacTest()); + } + + private static byte[] output1 = Hex.Decode("9BDA16E2AD0E284774A3ACBC8835A8326C11FAAD"); + + public override void PerformTest() + { + ICipherParameters kp = new KeyParameter( + Hex.Decode("9661410AB797D8A9EB767C21172DF6C7")); + ICipherParameters 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.BlockUpdate(m, 0, m.Length); + + byte[] output = new byte[20]; + mac.DoFinal(output, 0); + + if (!Arrays.AreEqual(output, output1)) + { + Fail("Fail", + Hex.ToHexString(output1), + Hex.ToHexString(output)); + } + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/VMPCTest.cs b/crypto/test/src/crypto/test/VMPCTest.cs new file mode 100644 index 000000000..6186c4733 --- /dev/null +++ b/crypto/test/src/crypto/test/VMPCTest.cs @@ -0,0 +1,112 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * VMPC Test + */ + [TestFixture] + public class VmpcTest + : SimpleTest + { + private static readonly byte[] input = new byte[1000000]; + + public override string Name + { + get { return "VMPC"; } + } + + private void checkByte(byte[] array, int position, byte b) + { + if (array[position] != b) + { + Fail("Fail on position " + position, + Hex.ToHexString(new byte[] { b }), + Hex.ToHexString(new byte[] { array[position] })); + } + } + + public override void PerformTest() + { + byte[] key = Hex.Decode("9661410AB797D8A9EB767C21172DF6C7"); + byte[] iv = Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155"); + ICipherParameters kp = new KeyParameter(key); + ICipherParameters kpwiv = new ParametersWithIV(kp, iv); + + VmpcEngine engine = new VmpcEngine(); + + try + { + engine.Init(true, kp); + Fail("Init failed to throw expected exception"); + } + catch (ArgumentException) + { + // 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()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs b/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs new file mode 100644 index 000000000..865408f6a --- /dev/null +++ b/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs @@ -0,0 +1,147 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * ISO vector test for Whirlpool + * + */ + [TestFixture] + public class WhirlpoolDigestTest + : SimpleTest + { + private static string[][] _isoVectors = + { + new string[] + { + "", + "19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3" + }, + new string[] + { + "a", + "8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A" + }, + new string[] + { + "abc", + "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5" + }, + new string[] + { + "message digest", + "378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E" + }, + new string[] + { + "abcdefghijklmnopqrstuvwxyz", + "F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B" + }, + new string[] + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467" + }, + new string[] + { + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B" + }, + new string[] + { + "abcdbcdecdefdefgefghfghighijhijk", + "2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD" + } + }; + + private static string _millionAResultVector = "0C99005BEB57EFF50A7CF005560DDF5D29057FD86B20BFD62DECA0F1CCEA4AF51FC15490EDDC47AF32BB2B66C34FF9AD8C6008AD677F77126953B226E4ED8B01"; + + private static string _thirtyOneZeros = "3E3F188F8FEBBEB17A933FEAF7FE53A4858D80C915AD6A1418F0318E68D49B4E459223CD414E0FBC8A57578FD755D86E827ABEF4070FC1503E25D99E382F72BA"; + + public override string Name + { + get + { + return "Whirlpool"; + } + } + + public override void PerformTest() + { + for (int i = 0; i < _isoVectors.Length; i++) + { + performStandardVectorTest("ISO vector test ["+i+"]", _isoVectors[i][0], + _isoVectors[i][1]); + } + + byte[] thirtyOneZeros = new byte[31]; + performStandardVectorTest("31 zeroes test", + thirtyOneZeros, _thirtyOneZeros); + + byte[] millionAInByteArray = new byte[1000000]; +// Arrays.fill(millionAInByteArray, (byte)'a'); + for (int ai = 0; ai < millionAInByteArray.Length; ++ai) + { + millionAInByteArray[ai] = (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 != resStr.ToUpper()) + { + Fail(testTitle, resultsAsHex, resStr); + } + } + + private void performStandardVectorTest(string testTitle, string inputBytesAsString, + string resultsAsHex) + { + doPerformTest(testTitle, Encoding.ASCII.GetBytes(inputBytesAsString), resultsAsHex); + } + + private string createHexOutputFromDigest(byte[] digestBytes) + { + IDigest digest = new WhirlpoolDigest(); + byte[] resBuf = new byte[digest.GetDigestSize()]; + digest.BlockUpdate(digestBytes, 0, digestBytes.Length); + digest.DoFinal(resBuf, 0); + return Hex.ToHexString(resBuf); + } + + public static void Main( + string[] args) + { + WhirlpoolDigestTest test = new WhirlpoolDigestTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/XTEATest.cs b/crypto/test/src/crypto/test/XTEATest.cs new file mode 100644 index 000000000..a1ea65298 --- /dev/null +++ b/crypto/test/src/crypto/test/XTEATest.cs @@ -0,0 +1,59 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm + */ + [TestFixture] + public class XteaTest + : CipherTest + { + private static readonly 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"), + }; + + public XteaTest() + : base(tests, new XteaEngine(), new KeyParameter(new byte[16])) + { + } + + public override string Name + { + get { return "XTEA"; } + } + + public static void Main( + string[] args) + { + RunTest(new XteaTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/math/ec/test/AllTests.cs b/crypto/test/src/math/ec/test/AllTests.cs new file mode 100644 index 000000000..f5d7d2249 --- /dev/null +++ b/crypto/test/src/math/ec/test/AllTests.cs @@ -0,0 +1,27 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +namespace Org.BouncyCastle.Math.EC.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { +// junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("EC Math tests"); + + suite.Add(new ECPointTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs new file mode 100644 index 000000000..e71ee653a --- /dev/null +++ b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs @@ -0,0 +1,73 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Math.EC.Tests +{ + /** + * Compares the performance of the the window NAF point multiplication against + * conventional point multiplication. + */ + [TestFixture, Explicit] + public class ECPointPerformanceTest + { + public const int NUM_ROUNDS = 100; + + private void randMult(string curveName) + { + X9ECParameters spec = SecNamedCurves.GetByName(curveName); + + BigInteger n = spec.N; + ECPoint g = (ECPoint) spec.G; + SecureRandom random = new SecureRandom(); //SecureRandom.getInstance("SHA1PRNG", "SUN"); + BigInteger k = new BigInteger(n.BitLength - 1, random); + + ECPoint qMultiply = null; + long startTime = DateTimeUtilities.CurrentUnixMs(); + for (int i = 0; i < NUM_ROUNDS; i++) + { + qMultiply = g.Multiply(k); + } + long endTime = DateTimeUtilities.CurrentUnixMs(); + + double avgDuration = (double) (endTime - startTime) / NUM_ROUNDS; + Console.WriteLine(curveName); + Console.Write("Millis : "); + Console.WriteLine(avgDuration); + Console.WriteLine(); + } + + [Test] + public void TestMultiply() + { + randMult("sect163k1"); + randMult("sect163r2"); + randMult("sect233k1"); + randMult("sect233r1"); + randMult("sect283k1"); + randMult("sect283r1"); + randMult("sect409k1"); + randMult("sect409r1"); + randMult("sect571k1"); + randMult("sect571r1"); + randMult("secp224k1"); + randMult("secp224r1"); + randMult("secp256k1"); + randMult("secp256r1"); + randMult("secp521r1"); + } + + // public static void Main(string argv[]) + // { + // ECMultiplyPerformanceTest test = new ECMultiplyPerformanceTest(); + // Test.testMultiply(); + // } + } +} diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs new file mode 100644 index 000000000..4c8b2d8fc --- /dev/null +++ b/crypto/test/src/math/ec/test/ECPointTest.cs @@ -0,0 +1,451 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Math.EC.Tests +{ + /** + * 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. + */ + [TestFixture] + public class ECPointTest + { + /** + * 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 Fp. + */ + public class Fp + { + internal static readonly BigInteger q = new BigInteger("29"); + + internal static readonly BigInteger a = new BigInteger("4"); + + internal static readonly BigInteger b = new BigInteger("20"); + + internal static readonly FpCurve curve = new FpCurve(q, a, b); + + internal static readonly FpPoint infinity = (FpPoint) curve.Infinity; + + internal static readonly int[] pointSource = { 5, 22, 16, 27, 13, 6, 14, 6 }; + + internal static FpPoint[] p = new FpPoint[pointSource.Length / 2]; + + /** + * Creates the points on the curve with literature values. + */ + internal static void createPoints() + { + for (int i = 0; i < pointSource.Length / 2; i++) + { + FpFieldElement x = new FpFieldElement(q, new BigInteger( + pointSource[2 * i].ToString())); + FpFieldElement y = new FpFieldElement(q, new BigInteger( + pointSource[2 * i + 1].ToString())); + p[i] = new FpPoint(curve, x, y); + } + } + } + + /** + * Nested class containing sample literature values for F2m. + */ + public class F2m + { + // Irreducible polynomial for TPB z^4 + z + 1 + internal const int m = 4; + + internal const int k1 = 1; + + // a = z^3 + internal static readonly F2mFieldElement aTpb = new F2mFieldElement(m, k1, + new BigInteger("8", 16)); + + // b = z^3 + 1 + internal static readonly F2mFieldElement bTpb = new F2mFieldElement(m, k1, + new BigInteger("9", 16)); + + internal static readonly F2mCurve curve = new F2mCurve(m, k1, aTpb + .ToBigInteger(), bTpb.ToBigInteger()); + + internal static readonly F2mPoint infinity = (F2mPoint) curve.Infinity; + + internal static readonly string[] pointSource = { "2", "f", "c", "c", "1", "1", "b", "2" }; + + internal static F2mPoint[] p = new F2mPoint[pointSource.Length / 2]; + + /** + * Creates the points on the curve with literature values. + */ + internal static void createPoints() + { + for (int i = 0; i < pointSource.Length / 2; i++) + { + F2mFieldElement x = new F2mFieldElement(m, k1, + new BigInteger(pointSource[2 * i], 16)); + F2mFieldElement y = new F2mFieldElement(m, k1, + new BigInteger(pointSource[2 * i + 1], 16)); + p[i] = new F2mPoint(curve, x, y); + } + } + } + + [SetUp] + 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). + */ + [Test] + public void TestPointCreationConsistency() + { + try + { + FpPoint bad = new FpPoint(Fp.curve, new FpFieldElement( + Fp.q, new BigInteger("12")), null); + Assert.Fail(); + } + catch (ArgumentException) + { + // Expected + } + + try + { + FpPoint bad = new FpPoint(Fp.curve, null, + new FpFieldElement(Fp.q, new BigInteger("12"))); + Assert.Fail(); + } + catch (ArgumentException) + { + // Expected + } + + try + { + F2mPoint bad = new F2mPoint(F2m.curve, new F2mFieldElement( + F2m.m, F2m.k1, new BigInteger("1011")), null); + Assert.Fail(); + } + catch (ArgumentException) + { + // Expected + } + + try + { + F2mPoint bad = new F2mPoint(F2m.curve, null, + new F2mFieldElement(F2m.m, F2m.k1, + new BigInteger("1011"))); + Assert.Fail(); + } + catch (ArgumentException) + { + // Expected + } + } + + /** + * Tests ECPoint.add() 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) + { + Assert.AreEqual(p[2], p[0].Add(p[1]), "p0 plus p1 does not equal p2"); + Assert.AreEqual(p[2], p[1].Add(p[0]), "p1 plus p0 does not equal p2"); + for (int i = 0; i < p.Length; i++) + { + Assert.AreEqual(p[i], p[i].Add(infinity), "Adding infinity failed"); + Assert.AreEqual(p[i], infinity.Add(p[i]), "Adding to infinity failed"); + } + } + + /** + * Calls implTestAdd() for Fp and + * F2m. + */ + [Test] + public void TestAdd() + { + implTestAdd(Fp.p, Fp.infinity); + implTestAdd(F2m.p, F2m.infinity); + } + + /** + * Tests ECPoint.twice() against literature values. + * + * @param p + * The array of literature values. + */ + private void implTestTwice(ECPoint[] p) + { + Assert.AreEqual(p[3], p[0].Twice(), "Twice incorrect"); + Assert.AreEqual(p[3], p[0].Add(p[0]), "Add same point incorrect"); + } + + /** + * Calls implTestTwice() for Fp and + * F2m. + */ + [Test] + public void TestTwice() + { + implTestTwice(Fp.p); + implTestTwice(F2m.p); + } + + /** + * Goes through all points on an elliptic curve and checks, if adding a + * point k-times is the same as multiplying the point by + * k, for all k. 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; + int i = 1; + do + { + adder = adder.Add(p); + multiplier = p.Multiply(new BigInteger(i.ToString())); + Assert.AreEqual(adder, multiplier, + "Results of add() and multiply() are inconsistent " + i); + i++; + } + while (!(adder.Equals(infinity))); + } + + /** + * Calls implTestAllPoints() for the small literature curves, + * both for Fp and F2m. + */ + [Test] + 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); + } + } + + /** + * Simple shift-and-add multiplication. Serves as reference implementation + * to verify (possibly faster) implementations in + * {@link org.bouncycastle.math.ec.ECPoint ECPoint}. + * + * @param p + * The point to multiply. + * @param k + * The multiplier. + * @return The result of the point multiplication kP. + */ + private ECPoint multiply(ECPoint p, BigInteger k) + { + ECPoint q = p.Curve.Infinity; + int t = k.BitLength; + for (int i = 0; i < t; i++) + { + if (k.TestBit(i)) + { + q = q.Add(p); + } + p = p.Twice(); + } + return 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 multiply(). This method chooses a + * random number by which the given point p is multiplied. + * + * @param p + * The point to be multiplied. + * @param numBits + * The bitlength of the random number by which p + * is multiplied. + */ + private void implTestMultiply(ECPoint p, int numBits) + { + BigInteger k = new BigInteger(numBits, secRand); + ECPoint reff = multiply(p, k); + ECPoint q = p.Multiply(k); + Assert.AreEqual(reff, q, "ECPoint.multiply is incorrect"); + } + + /** + * Checks, if the point multiplication algorithm of the given point yields + * the same result as point multiplication done by the reference + * implementation given in multiply(). This method tests + * multiplication of p by every number of bitlength + * numBits 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.Two.Pow(numBits); + BigInteger k = BigInteger.Zero; + + do + { + ECPoint reff = multiply(p, k); + ECPoint q = p.Multiply(k); + Assert.AreEqual(reff, q, "ECPoint.multiply is incorrect"); + k = k.Add(BigInteger.One); + } + while (k.CompareTo(bound) < 0); + } + + /** + * Tests ECPoint.add() and ECPoint.subtract() + * 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 p. + */ + private void implTestAddSubtract(ECPoint p, ECPoint infinity) + { + Assert.AreEqual(p.Twice(), p.Add(p), "Twice and Add inconsistent"); + Assert.AreEqual(p, p.Twice().Subtract(p), "Twice p - p is not p"); + Assert.AreEqual(infinity, p.Subtract(p), "p - p is not infinity"); + Assert.AreEqual(p, p.Add(infinity), "p plus infinity is not p"); + Assert.AreEqual(p, infinity.Add(p), "infinity plus p is not p"); + Assert.AreEqual(infinity, infinity.Add(infinity), "infinity plus infinity is not infinity "); + } + + /** + * Calls implTestAddSubtract() for literature values, both + * for Fp and F2m. + */ + [Test] + public void TestAddSubtractMultiplySimple() + { + for (int iFp = 0; iFp < Fp.pointSource.Length / 2; iFp++) + { + implTestAddSubtract(Fp.p[iFp], Fp.infinity); + + // Could be any numBits, 6 is chosen at will + implTestMultiplyAll(Fp.p[iFp], 6); + implTestMultiplyAll(Fp.infinity, 6); + } + + for (int iF2m = 0; iF2m < F2m.pointSource.Length / 2; iF2m++) + { + implTestAddSubtract(F2m.p[iF2m], F2m.infinity); + + // Could be any numBits, 6 is chosen at will + implTestMultiplyAll(F2m.p[iF2m], 6); + implTestMultiplyAll(F2m.infinity, 6); + } + } + + /** + * Test encoding with and without point compression. + * + * @param p + * The point to be encoded and decoded. + */ + private void implTestEncoding(ECPoint p) + { + // Not Point Compression + ECPoint unCompP; + + // Point compression + ECPoint compP; + + if (p is FpPoint) + { + unCompP = new FpPoint(p.Curve, p.X, p.Y, false); + compP = new FpPoint(p.Curve, p.X, p.Y, true); + } + else + { + unCompP = new F2mPoint(p.Curve, p.X, p.Y, false); + compP = new F2mPoint(p.Curve, p.X, p.Y, true); + } + + byte[] unCompBarr = unCompP.GetEncoded(); + ECPoint decUnComp = p.Curve.DecodePoint(unCompBarr); + Assert.AreEqual(p, decUnComp, "Error decoding uncompressed point"); + + byte[] compBarr = compP.GetEncoded(); + ECPoint decComp = p.Curve.DecodePoint(compBarr); + Assert.AreEqual(p, decComp, "Error decoding compressed point"); + } + + /** + * Calls implTestAddSubtract(), + * implTestMultiply and implTestEncoding for + * the standard elliptic curves as given in SecNamedCurves. + */ + [Test] + public void TestAddSubtractMultiplyTwiceEncoding() + { + foreach (string name in SecNamedCurves.Names) + { + X9ECParameters x9ECParameters = SecNamedCurves.GetByName(name); + + BigInteger n = x9ECParameters.N; + + // The generator is multiplied by random b to get random q + BigInteger b = new BigInteger(n.BitLength, secRand); + ECPoint g = x9ECParameters.G; + ECPoint q = g.Multiply(b); + + // Get point at infinity on the curve + ECPoint infinity = x9ECParameters.Curve.Infinity; + + implTestAddSubtract(q, infinity); + implTestMultiply(q, n.BitLength); + implTestMultiply(infinity, n.BitLength); + implTestEncoding(q); + } + } + } +} \ No newline at end of file diff --git a/crypto/test/src/math/ec/test/F2mProofer.cs b/crypto/test/src/math/ec/test/F2mProofer.cs new file mode 100644 index 000000000..88e868c34 --- /dev/null +++ b/crypto/test/src/math/ec/test/F2mProofer.cs @@ -0,0 +1,201 @@ +// TODO Need a replacement for the Java properties class to finish this class + +//using System; +//using System.IO; +//using System.Text; +// +//using Org.BouncyCastle.Asn1.Sec; +//using Org.BouncyCastle.Asn1.X9; +//using Org.BouncyCastle.Math.EC; +//using Org.BouncyCastle.Security; +// +//namespace Org.BouncyCastle.Math.EC.Tests +//{ +// public class F2mProofer +// { +// private const int NUM_SAMPLES = 1000; +// +// private static readonly string PATH = "crypto/test/src/org/bouncycastle/math/ec/test/samples/"; +// +// private static readonly string INPUT_FILE_NAME_PREFIX = "Input_"; +// +// private static readonly string RESULT_FILE_NAME_PREFIX = "Output_"; +// +// /** +// * The standard curves on which the tests are done +// */ +// public static readonly string[] Curves = { "sect163r2", "sect233r1", +// "sect283r1", "sect409r1", "sect571r1" }; +// +// private string pointToString(F2mPoint p) +// { +// F2mFieldElement x = (F2mFieldElement) p.X; +// F2mFieldElement y = (F2mFieldElement) p.Y; +// +// int m = x.M; +// int len = m / 2 + 5; +// +// StringBuilder sb = new StringBuilder(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) +// { +// F2mPoint g = (F2mPoint) x9ECParameters.G; +// int m = ((F2mFieldElement) g.X).M; +// +// SecureRandom secRand = new SecureRandom(); //SecureRandom.GetInstance("SHA1PRNG"); +// Properties inputProps = new Properties(); +// for (int i = 0; i < NUM_SAMPLES; i++) +// { +// BigInteger rand = new BigInteger(m, secRand); +// inputProps.put(i.ToString(), rand.ToString(16)); +// } +// string bits = m.ToString(); +// FileStream fos = File.Create(PATH +// + INPUT_FILE_NAME_PREFIX + bits + ".properties"); +// inputProps.store(fos, "Input Samples of length" + bits); +// fos.Close(); +// } +// +// private void multiplyPoints(X9ECParameters x9ECParameters, +// string classPrefix) +// { +// F2mPoint g = (F2mPoint) x9ECParameters.G; +// int m = ((F2mFieldElement) g.X).M; +// +// string inputFileName = PATH + INPUT_FILE_NAME_PREFIX + m +// + ".properties"; +// Properties inputProps = new Properties(); +// FileStream fis = File.OpenRead(inputFileName); +// inputProps.load(fis); +// fis.Close(); +// +// Properties outputProps = new Properties(); +// +// for (int i = 0; i < NUM_SAMPLES; i++) +// { +// BigInteger rand = new BigInteger(inputProps.getProperty(Integer +// .ToString(i)), 16); +// F2mPoint result = (F2mPoint) g.Multiply(rand); +// string resultStr = pointToString(result); +// outputProps.setProperty(i.ToString(), resultStr); +// } +// +// string outputFileName = PATH + RESULT_FILE_NAME_PREFIX + classPrefix +// + "_" + m + ".properties"; +// FileStream fos = File.Create(outputFileName); +// outputProps.store(fos, "Output Samples of length" + m); +// fos.Close(); +// } +// +// private Properties loadResults(string classPrefix, int m) +// { +// FileStream fis = File.OpenRead(PATH +// + RESULT_FILE_NAME_PREFIX + classPrefix + "_" + m + ".properties"); +// Properties res = new Properties(); +// res.load(fis); +// fis.Close(); +// return res; +// } +// +// private void compareResult(X9ECParameters x9ECParameters, +// string classPrefix1, string classPrefix2) +// { +// F2mPoint g = (F2mPoint) x9ECParameters.G; +// int m = ((F2mFieldElement) g.X).M; +// +// 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))) +// { +// Console.Error.WriteLine("Difference found: m = " + m + ", " +// + result1 + " does not equal " + result2); +// } +// } +// +// } +// +// private static void usage() +// { +// Console.Error.WriteLine("Usage: F2mProofer [-init | -Multiply " +// + "| -compare ]"); +// } +// +// public static void Main(string[] args) +// { +// if (args.Length == 0) +// { +// usage(); +// return; +// } +// F2mProofer proofer = new F2mProofer(); +// if (args[0].Equals("-init")) +// { +// Console.WriteLine("Generating random input..."); +// for (int i = 0; i < Curves.Length; i++) +// { +// X9ECParameters x9ECParameters = SecNamedCurves +// .GetByName(Curves[i]); +// proofer.generateRandomInput(x9ECParameters); +// } +// Console.WriteLine("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]; +// Console.WriteLine("Comparing results..."); +// for (int i = 0; i < Curves.Length; i++) +// { +// X9ECParameters x9ECParameters = SecNamedCurves +// .GetByName(Curves[i]); +// proofer.compareResult(x9ECParameters, classPrefix1, +// classPrefix2); +// } +// Console.WriteLine("Successfully compared results in " + PATH); +// } +// else if (args[0].Equals("-Multiply")) +// { +// if (args.Length < 2) +// { +// usage(); +// return; +// } +// string classPrefix = args[1]; +// Console.WriteLine("Multiplying points..."); +// for (int i = 0; i < Curves.Length; i++) +// { +// X9ECParameters x9ECParameters = SecNamedCurves +// .GetByName(Curves[i]); +// proofer.multiplyPoints(x9ECParameters, classPrefix); +// } +// Console.WriteLine("Successfully generated multiplied points in " +// + PATH); +// } +// else +// { +// usage(); +// } +// } +// } +//} diff --git a/crypto/test/src/math/ec/test/TnafTest.cs b/crypto/test/src/math/ec/test/TnafTest.cs new file mode 100644 index 000000000..c04ae00d2 --- /dev/null +++ b/crypto/test/src/math/ec/test/TnafTest.cs @@ -0,0 +1,158 @@ +//using System; +//using System.Text; +// +//using NUnit.Framework; +// +//using Org.BouncyCastle.Asn1.Sec; +//using Org.BouncyCastle.Asn1.X9; +//using Org.BouncyCastle.Math.EC.Multiplier; +//using Org.BouncyCastle.Utilities.Date; +// +//namespace Org.BouncyCastle.Math.EC.Tests +//{ +// [TestFixture, Explicit] +// public class TnafTest +// { +// private Random m_rand = new Random(); +// +// private string ecPointToString( +// ECPoint p) +// { +// StringBuilder sb = new StringBuilder("x = "); +// sb.Append(p.X.ToBigInteger().ToString()); +// sb.Append("; y = "); +// sb.Append(p.Y.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); +// Assert.AreEqual(result, check); +// } +// return result; +// } +// +// private void ImplTestMultiplyTnaf(string curveName) +// { +// X9ECParameters x9ECParameters = SecNamedCurves.GetByName(curveName); +// +// F2mCurve curve = (F2mCurve)x9ECParameters.Curve; +// BigInteger n = curve.N; +// +// // The generator is multiplied by random b to get random q +// BigInteger b = new BigInteger(n.BitLength, m_rand); +// ECPoint g = x9ECParameters.G; +// F2mPoint p = (F2mPoint) g.Multiply(b); +// +// BigInteger k = new BigInteger(n.BitLength, m_rand); +// long now1 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new WTauNafMultiplier()); +// ECPoint refRWTnaf = repeatedMultiply(p, k); +// long now2 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new WNafMultiplier()); +// ECPoint refWnaf = repeatedMultiply(p, k); +// long now3 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new FpNafMultiplier()); +// ECPoint refFpNaf = repeatedMultiply(p, k); +// long now4 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new ReferenceMultiplier()); +// ECPoint reference = repeatedMultiply(p, k); +// long now5 = DateTimeUtilities.CurrentUnixMs(); +// +// Assert.AreEqual(reference, refRWTnaf, "WTNAF multiplication is incorrect"); +// Assert.AreEqual(reference, refFpNaf, "FPNAF multiplication is incorrect"); +// Assert.AreEqual(reference, refWnaf, "WNAF multiplication is incorrect"); +// +// Console.WriteLine(curveName + ": Multiply WTNAF took millis: " + (now2 - now1)); +// Console.WriteLine(curveName + ": Multiply WNAF took millis: " + (now3 - now2)); +// Console.WriteLine(curveName + ": Multiply FPNAF took millis: " + (now4 - now3)); +// Console.WriteLine(curveName + ": Multiply REFE took millis: " + (now5 - now4)); +// +//// Console.WriteLine(curveName + ": refRWTnaf = " + ecPointToString(refRWTnaf)); +//// Console.WriteLine(curveName + ": refWnaf = " + ecPointToString(refWnaf)); +//// Console.WriteLine(curveName + ": refFpNaf = " + ecPointToString(refFpNaf)); +//// Console.WriteLine(curveName + ": reference = " + ecPointToString(reference) + "\n"); +// Console.WriteLine(); +// } +// +// [Test] +// public void TestMultiplyTnaf() +// { +// Console.WriteLine("\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.N; +// +// // The generator is multiplied by random b to get random q +// BigInteger b = new BigInteger(r.BitLength, m_rand); +// ECPoint g = x9ECParameters.G; +// ECPoint p = g.Multiply(b); +// +// BigInteger k = new BigInteger(r.BitLength, m_rand); +// long now1 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new WNafMultiplier()); +// ECPoint refWnaf = repeatedMultiply(p, k); +// long now2 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new FpNafMultiplier()); +// ECPoint refFpNaf = repeatedMultiply(p, k); +// long now3 = DateTimeUtilities.CurrentUnixMs(); +// p.SetECMultiplier(new ReferenceMultiplier()); +// ECPoint reference = repeatedMultiply(p, k); +// long now4 = DateTimeUtilities.CurrentUnixMs(); +// +// Assert.AreEqual(reference, refWnaf, "WNAF multiplication is incorrect"); +// Assert.AreEqual(reference, refFpNaf, "FPNAF multiplication is incorrect"); +// +// Console.WriteLine(curveName + ": Multiply WNAF took millis: " + (now2 - now1)); +// Console.WriteLine(curveName + ": Multiply FPNAF took millis: " + (now3 - now2)); +// Console.WriteLine(curveName + ": Multiply REFE took millis: " + (now4 - now3)); +// +//// Console.WriteLine(curveName + ": refWnaf = " + ecPointToString(refWnaf)); +//// Console.WriteLine(curveName + ": refFpNaf = " + ecPointToString(refFpNaf)); +//// Console.WriteLine(curveName + ": reference = " + ecPointToString(reference)); +// Console.WriteLine(); +// } +// +// [Test] +// public void TestMultiplyWnaf() +// { +// Console.WriteLine("\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"); +// +// Console.WriteLine("\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/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs new file mode 100644 index 000000000..6f2b50140 --- /dev/null +++ b/crypto/test/src/math/test/AllTests.cs @@ -0,0 +1,27 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +namespace Org.BouncyCastle.Math.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { +// junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("Math tests"); + + suite.Add(new BigIntegerTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/math/test/BigIntegerTest.cs b/crypto/test/src/math/test/BigIntegerTest.cs new file mode 100644 index 000000000..2f66a4b59 --- /dev/null +++ b/crypto/test/src/math/test/BigIntegerTest.cs @@ -0,0 +1,1048 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.Tests +{ + [TestFixture] + public class BigIntegerTest + { + private static Random random = new Random(); + + [Test] + public void MonoBug81857() + { + BigInteger b = new BigInteger("18446744073709551616"); + BigInteger exp = BigInteger.Two; + BigInteger mod = new BigInteger("48112959837082048697"); + BigInteger expected = new BigInteger("4970597831480284165"); + + BigInteger manual = b.Multiply(b).Mod(mod); + Assert.AreEqual(expected, manual, "b * b % mod"); + } + + [Test] + public void TestAbs() + { + Assert.AreEqual(zero, zero.Abs()); + + Assert.AreEqual(one, one.Abs()); + Assert.AreEqual(one, minusOne.Abs()); + + Assert.AreEqual(two, two.Abs()); + Assert.AreEqual(two, minusTwo.Abs()); + } + + [Test] + public void TestAdd() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i + j), + val(i).Add(val(j)), + "Problem: " + i + ".Add(" + j + ") should be " + (i + j)); + } + } + } + + [Test] + public void TestAnd() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i & j), + val(i).And(val(j)), + "Problem: " + i + " AND " + j + " should be " + (i & j)); + } + } + } + + [Test] + public void TestAndNot() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i & ~j), + val(i).AndNot(val(j)), + "Problem: " + i + " AND NOT " + j + " should be " + (i & ~j)); + } + } + } + + [Test] + public void TestBitCount() + { + Assert.AreEqual(0, zero.BitCount); + Assert.AreEqual(1, one.BitCount); + Assert.AreEqual(0, minusOne.BitCount); + Assert.AreEqual(1, two.BitCount); + Assert.AreEqual(1, minusTwo.BitCount); + + for (int i = 0; i < 100; ++i) + { + BigInteger pow2 = one.ShiftLeft(i); + + Assert.AreEqual(1, pow2.BitCount); + Assert.AreEqual(i, pow2.Negate().BitCount); + } + + for (int i = 0; i < 10; ++i) + { + BigInteger test = new BigInteger(128, 0, random); + int bitCount = 0; + + for (int bit = 0; bit < test.BitLength; ++bit) + { + if (test.TestBit(bit)) + { + ++bitCount; + } + } + + Assert.AreEqual(bitCount, test.BitCount); + } + } + + [Test] + public void TestBitLength() + { + Assert.AreEqual(0, zero.BitLength); + Assert.AreEqual(1, one.BitLength); + Assert.AreEqual(0, minusOne.BitLength); + Assert.AreEqual(2, two.BitLength); + Assert.AreEqual(1, minusTwo.BitLength); + + for (int i = 0; i < 100; ++i) + { + int bit = i + random.Next(64); + BigInteger odd = new BigInteger(bit, random).SetBit(bit + 1).SetBit(0); + BigInteger pow2 = one.ShiftLeft(bit); + + Assert.AreEqual(bit + 2, odd.BitLength); + Assert.AreEqual(bit + 2, odd.Negate().BitLength); + Assert.AreEqual(bit + 1, pow2.BitLength); + Assert.AreEqual(bit, pow2.Negate().BitLength); + } + } + + [Test] + public void TestClearBit() + { + Assert.AreEqual(zero, zero.ClearBit(0)); + Assert.AreEqual(zero, one.ClearBit(0)); + Assert.AreEqual(two, two.ClearBit(0)); + + Assert.AreEqual(zero, zero.ClearBit(1)); + Assert.AreEqual(one, one.ClearBit(1)); + Assert.AreEqual(zero, two.ClearBit(1)); + + // TODO Tests for clearing bits in negative numbers + + // TODO Tests for clearing extended bits + + for (int i = 0; i < 10; ++i) + { + BigInteger n = new BigInteger(128, random); + + for (int j = 0; j < 10; ++j) + { + int pos = random.Next(128); + BigInteger m = n.ClearBit(pos); + bool test = m.ShiftRight(pos).Remainder(two).Equals(one); + + Assert.IsFalse(test); + } + } + + for (int i = 0; i < 100; ++i) + { + BigInteger pow2 = one.ShiftLeft(i); + BigInteger minusPow2 = pow2.Negate(); + + Assert.AreEqual(zero, pow2.ClearBit(i)); + Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.ClearBit(i)); + + BigInteger bigI = BigInteger.ValueOf(i); + BigInteger negI = bigI.Negate(); + + for (int j = 0; j < 10; ++j) + { + string data = "i=" + i + ", j=" + j; + Assert.AreEqual(bigI.AndNot(one.ShiftLeft(j)), bigI.ClearBit(j), data); + Assert.AreEqual(negI.AndNot(one.ShiftLeft(j)), negI.ClearBit(j), data); + } + } + } + + [Test] + public void TestCompareTo() + { + Assert.AreEqual(0, minusTwo.CompareTo(minusTwo)); + Assert.AreEqual(-1, minusTwo.CompareTo(minusOne)); + Assert.AreEqual(-1, minusTwo.CompareTo(zero)); + Assert.AreEqual(-1, minusTwo.CompareTo(one)); + Assert.AreEqual(-1, minusTwo.CompareTo(two)); + + Assert.AreEqual(1, minusOne.CompareTo(minusTwo)); + Assert.AreEqual(0, minusOne.CompareTo(minusOne)); + Assert.AreEqual(-1, minusOne.CompareTo(zero)); + Assert.AreEqual(-1, minusOne.CompareTo(one)); + Assert.AreEqual(-1, minusOne.CompareTo(two)); + + Assert.AreEqual(1, zero.CompareTo(minusTwo)); + Assert.AreEqual(1, zero.CompareTo(minusOne)); + Assert.AreEqual(0, zero.CompareTo(zero)); + Assert.AreEqual(-1, zero.CompareTo(one)); + Assert.AreEqual(-1, zero.CompareTo(two)); + + Assert.AreEqual(1, one.CompareTo(minusTwo)); + Assert.AreEqual(1, one.CompareTo(minusOne)); + Assert.AreEqual(1, one.CompareTo(zero)); + Assert.AreEqual(0, one.CompareTo(one)); + Assert.AreEqual(-1, one.CompareTo(two)); + + Assert.AreEqual(1, two.CompareTo(minusTwo)); + Assert.AreEqual(1, two.CompareTo(minusOne)); + Assert.AreEqual(1, two.CompareTo(zero)); + Assert.AreEqual(1, two.CompareTo(one)); + Assert.AreEqual(0, two.CompareTo(two)); + } + + [Test] + public void TestConstructors() + { + Assert.AreEqual(BigInteger.Zero, new BigInteger(new byte[]{ 0 })); + Assert.AreEqual(BigInteger.Zero, new BigInteger(new byte[]{ 0, 0 })); + + for (int i = 0; i < 10; ++i) + { + Assert.IsTrue(new BigInteger(i + 3, 0, random).TestBit(0)); + } + + // TODO Other constructors + } + + [Test] + public void TestDivide() + { + for (int i = -5; i <= 5; ++i) + { + try + { + val(i).Divide(zero); + Assert.Fail("expected ArithmeticException"); + } + catch (ArithmeticException) {} + } + + int product = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9; + int productPlus = product + 1; + + BigInteger bigProduct = val(product); + BigInteger bigProductPlus = val(productPlus); + + for (int divisor = 1; divisor < 10; ++divisor) + { + // Exact division + BigInteger expected = val(product / divisor); + + Assert.AreEqual(expected, bigProduct.Divide(val(divisor))); + Assert.AreEqual(expected.Negate(), bigProduct.Negate().Divide(val(divisor))); + Assert.AreEqual(expected.Negate(), bigProduct.Divide(val(divisor).Negate())); + Assert.AreEqual(expected, bigProduct.Negate().Divide(val(divisor).Negate())); + + expected = val((product + 1)/divisor); + + Assert.AreEqual(expected, bigProductPlus.Divide(val(divisor))); + Assert.AreEqual(expected.Negate(), bigProductPlus.Negate().Divide(val(divisor))); + Assert.AreEqual(expected.Negate(), bigProductPlus.Divide(val(divisor).Negate())); + Assert.AreEqual(expected, bigProductPlus.Negate().Divide(val(divisor).Negate())); + } + + for (int rep = 0; rep < 10; ++rep) + { + BigInteger a = new BigInteger(100 - rep, 0, random); + BigInteger b = new BigInteger(100 + rep, 0, random); + BigInteger c = new BigInteger(10 + rep, 0, random); + BigInteger d = a.Multiply(b).Add(c); + BigInteger e = d.Divide(a); + + Assert.AreEqual(b, e); + } + + // Special tests for power of two since uses different code path internally + for (int i = 0; i < 100; ++i) + { + int shift = random.Next(64); + BigInteger a = one.ShiftLeft(shift); + BigInteger b = new BigInteger(64 + random.Next(64), random); + BigInteger bShift = b.ShiftRight(shift); + + string data = "shift=" + shift +", b=" + b.ToString(16); + + Assert.AreEqual(bShift, b.Divide(a), data); + Assert.AreEqual(bShift.Negate(), b.Divide(a.Negate()), data); + Assert.AreEqual(bShift.Negate(), b.Negate().Divide(a), data); + Assert.AreEqual(bShift, b.Negate().Divide(a.Negate()), data); + } + + // Regression + { + int shift = 63; + BigInteger a = one.ShiftLeft(shift); + BigInteger b = new BigInteger(1, Hex.Decode("2504b470dc188499")); + BigInteger bShift = b.ShiftRight(shift); + + string data = "shift=" + shift +", b=" + b.ToString(16); + + Assert.AreEqual(bShift, b.Divide(a), data); + Assert.AreEqual(bShift.Negate(), b.Divide(a.Negate()), data); +// Assert.AreEqual(bShift.Negate(), b.Negate().Divide(a), data); + Assert.AreEqual(bShift, b.Negate().Divide(a.Negate()), data); + } + } + + [Test] + public void TestDivideAndRemainder() + { + // TODO More basic tests + + BigInteger n = new BigInteger(48, random); + BigInteger[] qr = n.DivideAndRemainder(n); + Assert.AreEqual(one, qr[0]); + Assert.AreEqual(zero, qr[1]); + qr = n.DivideAndRemainder(one); + Assert.AreEqual(n, qr[0]); + Assert.AreEqual(zero, qr[1]); + + for (int rep = 0; rep < 10; ++rep) + { + BigInteger a = new BigInteger(100 - rep, 0, random); + BigInteger b = new BigInteger(100 + rep, 0, random); + BigInteger c = new BigInteger(10 + rep, 0, random); + BigInteger d = a.Multiply(b).Add(c); + BigInteger[] es = d.DivideAndRemainder(a); + + Assert.AreEqual(b, es[0]); + Assert.AreEqual(c, es[1]); + } + + // Special tests for power of two since uses different code path internally + for (int i = 0; i < 100; ++i) + { + int shift = random.Next(64); + BigInteger a = one.ShiftLeft(shift); + BigInteger b = new BigInteger(64 + random.Next(64), random); + BigInteger bShift = b.ShiftRight(shift); + BigInteger bMod = b.And(a.Subtract(one)); + + string data = "shift=" + shift +", b=" + b.ToString(16); + + qr = b.DivideAndRemainder(a); + Assert.AreEqual(bShift, qr[0], data); + Assert.AreEqual(bMod, qr[1], data); + + qr = b.DivideAndRemainder(a.Negate()); + Assert.AreEqual(bShift.Negate(), qr[0], data); + Assert.AreEqual(bMod, qr[1], data); + + qr = b.Negate().DivideAndRemainder(a); + Assert.AreEqual(bShift.Negate(), qr[0], data); + Assert.AreEqual(bMod.Negate(), qr[1], data); + + qr = b.Negate().DivideAndRemainder(a.Negate()); + Assert.AreEqual(bShift, qr[0], data); + Assert.AreEqual(bMod.Negate(), qr[1], data); + } + } + + [Test] + public void TestFlipBit() + { + for (int i = 0; i < 10; ++i) + { + BigInteger a = new BigInteger(128, 0, random); + BigInteger b = a; + + for (int x = 0; x < 100; ++x) + { + // Note: Intentionally greater than initial size + int pos = random.Next(256); + + a = a.FlipBit(pos); + b = b.TestBit(pos) ? b.ClearBit(pos) : b.SetBit(pos); + } + + Assert.AreEqual(a, b); + } + + for (int i = 0; i < 100; ++i) + { + BigInteger pow2 = one.ShiftLeft(i); + BigInteger minusPow2 = pow2.Negate(); + + Assert.AreEqual(zero, pow2.FlipBit(i)); + Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.FlipBit(i)); + + BigInteger bigI = BigInteger.ValueOf(i); + BigInteger negI = bigI.Negate(); + + for (int j = 0; j < 10; ++j) + { + string data = "i=" + i + ", j=" + j; + Assert.AreEqual(bigI.Xor(one.ShiftLeft(j)), bigI.FlipBit(j), data); + Assert.AreEqual(negI.Xor(one.ShiftLeft(j)), negI.FlipBit(j), data); + } + } + } + + [Test] + public void TestGcd() + { + for (int i = 0; i < 10; ++i) + { + BigInteger fac = new BigInteger(32, random).Add(two); + BigInteger p1 = BigInteger.ProbablePrime(63, random); + BigInteger p2 = BigInteger.ProbablePrime(64, random); + + BigInteger gcd = fac.Multiply(p1).Gcd(fac.Multiply(p2)); + + Assert.AreEqual(fac, gcd); + } + } + + [Test] + public void TestGetLowestSetBit() + { + for (int i = 1; i <= 100; ++i) + { + BigInteger test = new BigInteger(i + 1, 0, random).Add(one); + int bit1 = test.GetLowestSetBit(); + Assert.AreEqual(test, test.ShiftRight(bit1).ShiftLeft(bit1)); + int bit2 = test.ShiftLeft(i + 1).GetLowestSetBit(); + Assert.AreEqual(i + 1, bit2 - bit1); + int bit3 = test.ShiftLeft(3 * i).GetLowestSetBit(); + Assert.AreEqual(3 * i, bit3 - bit1); + } + } + + [Test] + public void TestIntValue() + { + int[] tests = new int[]{ int.MinValue, -1234, -10, -1, 0, ~0, 1, 10, 5678, int.MaxValue }; + + foreach (int test in tests) + { + Assert.AreEqual(test, val(test).IntValue); + } + + // TODO Tests for large numbers + } + + [Test] + public void TestIsProbablePrime() + { + Assert.IsFalse(zero.IsProbablePrime(100)); + Assert.IsFalse(zero.IsProbablePrime(100)); + Assert.IsTrue(zero.IsProbablePrime(0)); + Assert.IsTrue(zero.IsProbablePrime(-10)); + Assert.IsFalse(minusOne.IsProbablePrime(100)); + Assert.IsTrue(minusTwo.IsProbablePrime(100)); + Assert.IsTrue(val(-17).IsProbablePrime(100)); + Assert.IsTrue(val(67).IsProbablePrime(100)); + Assert.IsTrue(val(773).IsProbablePrime(100)); + + foreach (int p in firstPrimes) + { + Assert.IsTrue(val(p).IsProbablePrime(100)); + Assert.IsTrue(val(-p).IsProbablePrime(100)); + } + + foreach (int c in nonPrimes) + { + Assert.IsFalse(val(c).IsProbablePrime(100)); + Assert.IsFalse(val(-c).IsProbablePrime(100)); + } + + foreach (int e in mersennePrimeExponents) + { + Assert.IsTrue(mersenne(e).IsProbablePrime(100)); + Assert.IsTrue(mersenne(e).Negate().IsProbablePrime(100)); + } + + foreach (int e in nonPrimeExponents) + { + Assert.IsFalse(mersenne(e).IsProbablePrime(100)); + Assert.IsFalse(mersenne(e).Negate().IsProbablePrime(100)); + } + + // TODO Other examples of 'tricky' values? + } + + [Test] + public void TestLongValue() + { + long[] tests = new long[]{ long.MinValue, -1234, -10, -1, 0L, ~0L, 1, 10, 5678, long.MaxValue }; + + foreach (long test in tests) + { + Assert.AreEqual(test, val(test).LongValue); + } + + // TODO Tests for large numbers + } + + [Test] + public void TestMax() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual(val(System.Math.Max(i, j)), val(i).Max(val(j))); + } + } + } + + [Test] + public void TestMin() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual(val(System.Math.Min(i, j)), val(i).Min(val(j))); + } + } + } + + [Test] + public void TestMod() + { + // TODO Basic tests + + for (int rep = 0; rep < 100; ++rep) + { + int diff = random.Next(25); + BigInteger a = new BigInteger(100 - diff, 0, random); + BigInteger b = new BigInteger(100 + diff, 0, random); + BigInteger c = new BigInteger(10 + diff, 0, random); + + BigInteger d = a.Multiply(b).Add(c); + BigInteger e = d.Mod(a); + Assert.AreEqual(c, e); + + BigInteger pow2 = one.ShiftLeft(random.Next(128)); + Assert.AreEqual(b.And(pow2.Subtract(one)), b.Mod(pow2)); + } + } + + [Test] + public void TestModInverse() + { + for (int i = 0; i < 10; ++i) + { + BigInteger p = BigInteger.ProbablePrime(64, random); + BigInteger q = new BigInteger(63, random).Add(one); + BigInteger inv = q.ModInverse(p); + BigInteger inv2 = inv.ModInverse(p); + + Assert.AreEqual(q, inv2); + Assert.AreEqual(one, q.Multiply(inv).Mod(p)); + } + + // ModInverse a power of 2 for a range of powers + for (int i = 1; i <= 128; ++i) + { + BigInteger m = one.ShiftLeft(i); + BigInteger d = new BigInteger(i, random).SetBit(0); + BigInteger x = d.ModInverse(m); + BigInteger check = x.Multiply(d).Mod(m); + + Assert.AreEqual(one, check); + } + } + + [Test] + public void TestModPow() + { + try + { + two.ModPow(one, zero); + Assert.Fail("expected ArithmeticException"); + } + catch (ArithmeticException) {} + + Assert.AreEqual(zero, zero.ModPow(zero, one)); + Assert.AreEqual(one, zero.ModPow(zero, two)); + Assert.AreEqual(zero, two.ModPow(one, one)); + Assert.AreEqual(one, two.ModPow(zero, two)); + + for (int i = 0; i < 100; ++i) + { + BigInteger m = BigInteger.ProbablePrime(10 + i, random); + BigInteger x = new BigInteger(m.BitLength - 1, random); + + Assert.AreEqual(x, x.ModPow(m, m)); + if (x.SignValue != 0) + { + Assert.AreEqual(zero, zero.ModPow(x, m)); + Assert.AreEqual(one, x.ModPow(m.Subtract(one), m)); + } + + BigInteger y = new BigInteger(m.BitLength - 1, random); + BigInteger n = new BigInteger(m.BitLength - 1, random); + BigInteger n3 = n.ModPow(three, m); + + BigInteger resX = n.ModPow(x, m); + BigInteger resY = n.ModPow(y, m); + BigInteger res = resX.Multiply(resY).Mod(m); + BigInteger res3 = res.ModPow(three, m); + + Assert.AreEqual(res3, n3.ModPow(x.Add(y), m)); + + BigInteger a = x.Add(one); // Make sure it's not zero + BigInteger b = y.Add(one); // Make sure it's not zero + + Assert.AreEqual(a.ModPow(b, m).ModInverse(m), a.ModPow(b.Negate(), m)); + } + } + + [Test] + public void TestMultiply() + { + BigInteger one = BigInteger.One; + + Assert.AreEqual(one, one.Negate().Multiply(one.Negate())); + + for (int i = 0; i < 100; ++i) + { + int aLen = 64 + random.Next(64); + int bLen = 64 + random.Next(64); + + BigInteger a = new BigInteger(aLen, random).SetBit(aLen); + BigInteger b = new BigInteger(bLen, random).SetBit(bLen); + BigInteger c = new BigInteger(32, random); + + BigInteger ab = a.Multiply(b); + BigInteger bc = b.Multiply(c); + + Assert.AreEqual(ab.Add(bc), a.Add(c).Multiply(b)); + Assert.AreEqual(ab.Subtract(bc), a.Subtract(c).Multiply(b)); + } + + // Special tests for power of two since uses different code path internally + for (int i = 0; i < 100; ++i) + { + int shift = random.Next(64); + BigInteger a = one.ShiftLeft(shift); + BigInteger b = new BigInteger(64 + random.Next(64), random); + BigInteger bShift = b.ShiftLeft(shift); + + Assert.AreEqual(bShift, a.Multiply(b)); + Assert.AreEqual(bShift.Negate(), a.Multiply(b.Negate())); + Assert.AreEqual(bShift.Negate(), a.Negate().Multiply(b)); + Assert.AreEqual(bShift, a.Negate().Multiply(b.Negate())); + + Assert.AreEqual(bShift, b.Multiply(a)); + Assert.AreEqual(bShift.Negate(), b.Multiply(a.Negate())); + Assert.AreEqual(bShift.Negate(), b.Negate().Multiply(a)); + Assert.AreEqual(bShift, b.Negate().Multiply(a.Negate())); + } + } + + [Test] + public void TestNegate() + { + for (int i = -10; i <= 10; ++i) + { + Assert.AreEqual(val(-i), val(i).Negate()); + } + } + + [Test] + public void TestNextProbablePrime() + { + BigInteger firstPrime = BigInteger.ProbablePrime(32, random); + BigInteger nextPrime = firstPrime.NextProbablePrime(); + + Assert.IsTrue(firstPrime.IsProbablePrime(10)); + Assert.IsTrue(nextPrime.IsProbablePrime(10)); + + BigInteger check = firstPrime.Add(one); + + while (check.CompareTo(nextPrime) < 0) + { + Assert.IsFalse(check.IsProbablePrime(10)); + check = check.Add(one); + } + } + + [Test] + public void TestNot() + { + for (int i = -10; i <= 10; ++i) + { + Assert.AreEqual( + val(~i), + val(i).Not(), + "Problem: ~" + i + " should be " + ~i); + } + } + + [Test] + public void TestOr() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i | j), + val(i).Or(val(j)), + "Problem: " + i + " OR " + j + " should be " + (i | j)); + } + } + } + + [Test] + public void TestPow() + { + Assert.AreEqual(one, zero.Pow(0)); + Assert.AreEqual(zero, zero.Pow(123)); + Assert.AreEqual(one, one.Pow(0)); + Assert.AreEqual(one, one.Pow(123)); + + Assert.AreEqual(two.Pow(147), one.ShiftLeft(147)); + Assert.AreEqual(one.ShiftLeft(7).Pow(11), one.ShiftLeft(77)); + + BigInteger n = new BigInteger("1234567890987654321"); + BigInteger result = one; + + for (int i = 0; i < 10; ++i) + { + try + { + val(i).Pow(-1); + Assert.Fail("expected ArithmeticException"); + } + catch (ArithmeticException) {} + + Assert.AreEqual(result, n.Pow(i)); + + result = result.Multiply(n); + } + } + + [Test] + public void TestRemainder() + { + // TODO Basic tests + + for (int rep = 0; rep < 10; ++rep) + { + BigInteger a = new BigInteger(100 - rep, 0, random); + BigInteger b = new BigInteger(100 + rep, 0, random); + BigInteger c = new BigInteger(10 + rep, 0, random); + BigInteger d = a.Multiply(b).Add(c); + BigInteger e = d.Remainder(a); + + Assert.AreEqual(c, e); + } + } + + [Test] + public void TestSetBit() + { + Assert.AreEqual(one, zero.SetBit(0)); + Assert.AreEqual(one, one.SetBit(0)); + Assert.AreEqual(three, two.SetBit(0)); + + Assert.AreEqual(two, zero.SetBit(1)); + Assert.AreEqual(three, one.SetBit(1)); + Assert.AreEqual(two, two.SetBit(1)); + + // TODO Tests for setting bits in negative numbers + + // TODO Tests for setting extended bits + + for (int i = 0; i < 10; ++i) + { + BigInteger n = new BigInteger(128, random); + + for (int j = 0; j < 10; ++j) + { + int pos = random.Next(128); + BigInteger m = n.SetBit(pos); + bool test = m.ShiftRight(pos).Remainder(two).Equals(one); + + Assert.IsTrue(test); + } + } + + for (int i = 0; i < 100; ++i) + { + BigInteger pow2 = one.ShiftLeft(i); + BigInteger minusPow2 = pow2.Negate(); + + Assert.AreEqual(pow2, pow2.SetBit(i)); + Assert.AreEqual(minusPow2, minusPow2.SetBit(i)); + + BigInteger bigI = BigInteger.ValueOf(i); + BigInteger negI = bigI.Negate(); + + for (int j = 0; j < 10; ++j) + { + string data = "i=" + i + ", j=" + j; + Assert.AreEqual(bigI.Or(one.ShiftLeft(j)), bigI.SetBit(j), data); + Assert.AreEqual(negI.Or(one.ShiftLeft(j)), negI.SetBit(j), data); + } + } + } + + [Test] + public void TestShiftLeft() + { + for (int i = 0; i < 100; ++i) + { + int shift = random.Next(128); + + BigInteger a = new BigInteger(128 + i, random).Add(one); + int bits = a.BitCount; // Make sure nBits is set + + BigInteger negA = a.Negate(); + bits = negA.BitCount; // Make sure nBits is set + + BigInteger b = a.ShiftLeft(shift); + BigInteger c = negA.ShiftLeft(shift); + + Assert.AreEqual(a.BitCount, b.BitCount); + Assert.AreEqual(negA.BitCount + shift, c.BitCount); + Assert.AreEqual(a.BitLength + shift, b.BitLength); + Assert.AreEqual(negA.BitLength + shift, c.BitLength); + + int j = 0; + for (; j < shift; ++j) + { + Assert.IsFalse(b.TestBit(j)); + } + + for (; j < b.BitLength; ++j) + { + Assert.AreEqual(a.TestBit(j - shift), b.TestBit(j)); + } + } + } + + [Test] + public void TestShiftRight() + { + for (int i = 0; i < 10; ++i) + { + int shift = random.Next(128); + BigInteger a = new BigInteger(256 + i, random).SetBit(256 + i); + BigInteger b = a.ShiftRight(shift); + + Assert.AreEqual(a.BitLength - shift, b.BitLength); + + for (int j = 0; j < b.BitLength; ++j) + { + Assert.AreEqual(a.TestBit(j + shift), b.TestBit(j)); + } + } + } + + [Test] + public void TestSignValue() + { + for (int i = -10; i <= 10; ++i) + { + Assert.AreEqual(i < 0 ? -1 : i > 0 ? 1 : 0, val(i).SignValue); + } + } + + [Test] + public void TestSubtract() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i - j), + val(i).Subtract(val(j)), + "Problem: " + i + ".Subtract(" + j + ") should be " + (i - j)); + } + } + } + + [Test] + public void TestTestBit() + { + for (int i = 0; i < 10; ++i) + { + BigInteger n = new BigInteger(128, random); + + Assert.IsFalse(n.TestBit(128)); + Assert.IsTrue(n.Negate().TestBit(128)); + + for (int j = 0; j < 10; ++j) + { + int pos = random.Next(128); + bool test = n.ShiftRight(pos).Remainder(two).Equals(one); + + Assert.AreEqual(test, n.TestBit(pos)); + } + } + } + + [Test] + public void TestToByteArray() + { + byte[] z = BigInteger.Zero.ToByteArray(); + Assert.IsTrue(Arrays.AreEqual(new byte[1], z)); + + for (int i = 16; i <= 48; ++i) + { + BigInteger x = BigInteger.ProbablePrime(i, random); + byte[] b = x.ToByteArray(); + Assert.AreEqual((i / 8 + 1), b.Length); + BigInteger y = new BigInteger(b); + Assert.AreEqual(x, y); + + x = x.Negate(); + b = x.ToByteArray(); + Assert.AreEqual((i / 8 + 1), b.Length); + y = new BigInteger(b); + Assert.AreEqual(x, y); + } + } + + [Test] + public void TestToByteArrayUnsigned() + { + byte[] z = BigInteger.Zero.ToByteArrayUnsigned(); + Assert.IsTrue(Arrays.AreEqual(new byte[0], z)); + + for (int i = 16; i <= 48; ++i) + { + BigInteger x = BigInteger.ProbablePrime(i, random); + byte[] b = x.ToByteArrayUnsigned(); + Assert.AreEqual((i + 7) / 8, b.Length); + BigInteger y = new BigInteger(1, b); + Assert.AreEqual(x, y); + + x = x.Negate(); + b = x.ToByteArrayUnsigned(); + Assert.AreEqual(i / 8 + 1, b.Length); + y = new BigInteger(b); + Assert.AreEqual(x, y); + } + } + + [Test] + public void TestToString() + { + string s = "12345667890987654321"; + + Assert.AreEqual(s, new BigInteger(s).ToString()); + Assert.AreEqual(s, new BigInteger(s, 10).ToString(10)); + Assert.AreEqual(s, new BigInteger(s, 16).ToString(16)); + + for (int i = 0; i < 100; ++i) + { + BigInteger n = new BigInteger(i, random); + + Assert.AreEqual(n, new BigInteger(n.ToString(2), 2)); + Assert.AreEqual(n, new BigInteger(n.ToString(10), 10)); + Assert.AreEqual(n, new BigInteger(n.ToString(16), 16)); + } + + // Radix version + int[] radices = new int[] { 2, 8, 10, 16 }; + int trials = 256; + + BigInteger[] tests = new BigInteger[trials]; + for (int i = 0; i < trials; ++i) + { + int len = random.Next(i + 1); + tests[i] = new BigInteger(len, random); + } + + foreach (int radix in radices) + { + for (int i = 0; i < trials; ++i) + { + BigInteger n1 = tests[i]; + string str = n1.ToString(radix); + BigInteger n2 = new BigInteger(str, radix); + Assert.AreEqual(n1, n2); + } + } + } + + [Test] + public void TestValueOf() + { + Assert.AreEqual(-1, BigInteger.ValueOf(-1).SignValue); + Assert.AreEqual(0, BigInteger.ValueOf(0).SignValue); + Assert.AreEqual(1, BigInteger.ValueOf(1).SignValue); + + for (long i = -5; i < 5; ++i) + { + Assert.AreEqual(i, BigInteger.ValueOf(i).IntValue); + } + } + + [Test] + public void TestXor() + { + for (int i = -10; i <= 10; ++i) + { + for (int j = -10; j <= 10; ++j) + { + Assert.AreEqual( + val(i ^ j), + val(i).Xor(val(j)), + "Problem: " + i + " XOR " + j + " should be " + (i ^ j)); + } + } + } + + private static BigInteger val(long n) + { + return BigInteger.ValueOf(n); + } + + private static BigInteger mersenne(int e) + { + return two.Pow(e).Subtract(one); + } + + private static readonly BigInteger minusTwo = BigInteger.Two.Negate(); + private static readonly BigInteger minusOne = BigInteger.One.Negate(); + private static readonly BigInteger zero = BigInteger.Zero; + private static readonly BigInteger one = BigInteger.One; + private static readonly BigInteger two = BigInteger.Two; + private static readonly BigInteger three = BigInteger.Three; + + private static int[] firstPrimes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; + private static int[] nonPrimes = { 0, 1, 4, 10, 20, 21, 22, 25, 26, 27 }; + + private static int[] mersennePrimeExponents = { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89 }; + private static int[] nonPrimeExponents = { 1, 4, 6, 9, 11, 15, 23, 29, 37, 41 }; + } +} diff --git a/crypto/test/src/ocsp/test/AllTests.cs b/crypto/test/src/ocsp/test/AllTests.cs new file mode 100644 index 000000000..2b30e3ad4 --- /dev/null +++ b/crypto/test/src/ocsp/test/AllTests.cs @@ -0,0 +1,29 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Ocsp.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("OCSP Tests"); + + suite.Add(new OcspTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/ocsp/test/OCSPTest.cs b/crypto/test/src/ocsp/test/OCSPTest.cs new file mode 100644 index 000000000..823de90f9 --- /dev/null +++ b/crypto/test/src/ocsp/test/OCSPTest.cs @@ -0,0 +1,852 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Ocsp.Tests +{ + [TestFixture] + public class OcspTest + : SimpleTest + { + private static readonly byte[] testResp1 = 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 static readonly byte[] testResp2 = Base64.Decode( + "MIII1QoBAKCCCM4wggjKBgkrBgEFBQcwAQEEggi7MIIItzCBjqADAgEAoSMw" + + "ITEfMB0GA1UEAxMWT0NTUCBjZXJ0LVFBLUNMSUVOVC04NxgPMjAwMzA1MTky" + + "MDI2MzBaMFEwTzA6MAkGBSsOAwIaBQAEFJniwiUuyrhKIEF2TjVdVdCAOw0z" + + "BBR2olPKrPOJUVyGZ7BXOC4L2BmAqgIBL4AAGA8yMDAzMDUxOTIwMjYzMFow" + + "DQYJKoZIhvcNAQEEBQADggEBALImFU3kUtpNVf4tIFKg/1sDHvGpk5Pk0uhH" + + "TiNp6vdPfWjOgPkVXskx9nOTabVOBE8RusgwEcK1xeBXSHODb6mnjt9pkfv3" + + "ZdbFLFvH/PYjOb6zQOgdIOXhquCs5XbcaSFCX63hqnSaEqvc9w9ctmQwds5X" + + "tCuyCB1fWu/ie8xfuXR5XZKTBf5c6dO82qFE65gTYbGOxJBYiRieIPW1XutZ" + + "A76qla4m+WdxubV6SPG8PVbzmAseqjsJRn4jkSKOGenqSOqbPbZn9oBsU0Ku" + + "hul3pwsNJvcBvw2qxnWybqSzV+n4OvYXk+xFmtTjw8H9ChV3FYYDs8NuUAKf" + + "jw1IjWegggcOMIIHCjCCAzMwggIboAMCAQICAQIwDQYJKoZIhvcNAQEEBQAw" + + "bzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMRAwDgYDVQQHEwdXYWx0aGFt" + + "MRYwFAYDVQQKEw1Gb3J1bSBTeXN0ZW1zMQswCQYDVQQLEwJRQTEcMBoGA1UE" + + "AxMTQ2VydGlmaWNhdGUgTWFuYWdlcjAeFw0wMzAzMjEwNTAwMDBaFw0yNTAz" + + "MjEwNTAwMDBaMCExHzAdBgNVBAMTFk9DU1AgY2VydC1RQS1DTElFTlQtODcw" + + "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVuxRCZgJAYAftYuRy" + + "9axdtsHrkIJyVVRorLCTWOoLmx2tlrGqKbHOGKmvqEPEpeCDYQk+0WIlWMuM" + + "2pgiYAolwqSFBwCjkjQN3fCIHXiby0JBgCCLoe7wa0pZffE+8XZH0JdSjoT3" + + "2OYD19wWZeY2VB0JWJFWYAnIL+R5Eg7LwJ5QZSdvghnOWKTv60m/O1rC0see" + + "9lbPO+3jRuaDyCUKYy/YIKBYC9rtC4hS47jg70dTfmE2nccjn7rFCPBrVr4M" + + "5szqdRzwu3riL9W+IE99LTKXOH/24JX0S4woeGXMS6me7SyZE6x7P2tYkNXM" + + "OfXk28b3SJF75K7vX6T6ecWjAgMBAAGjKDAmMBMGA1UdJQQMMAoGCCsGAQUF" + + "BwMJMA8GCSsGAQUFBzABBQQCBQAwDQYJKoZIhvcNAQEEBQADggEBAKNSn7pp" + + "UEC1VTN/Iqk8Sc2cAYM7KSmeB++tuyes1iXY4xSQaEgOxRa5AvPAKnXKSzfY" + + "vqi9WLdzdkpTo4AzlHl5nqU/NCUv3yOKI9lECVMgMxLAvZgMALS5YXNZsqrs" + + "hP3ASPQU99+5CiBGGYa0PzWLstXLa6SvQYoHG2M8Bb2lHwgYKsyrUawcfc/s" + + "jE3jFJeyCyNwzH0eDJUVvW1/I3AhLNWcPaT9/VfyIWu5qqZU+ukV/yQXrKiB" + + "glY8v4QDRD4aWQlOuiV2r9sDRldOPJe2QSFDBe4NtBbynQ+MRvF2oQs/ocu+" + + "OAHX7uiskg9GU+9cdCWPwJf9cP/Zem6MemgwggPPMIICt6ADAgECAgEBMA0G" + + "CSqGSIb3DQEBBQUAMG8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTEQMA4G" + + "A1UEBxMHV2FsdGhhbTEWMBQGA1UEChMNRm9ydW0gU3lzdGVtczELMAkGA1UE" + + "CxMCUUExHDAaBgNVBAMTE0NlcnRpZmljYXRlIE1hbmFnZXIwHhcNMDMwMzIx" + + "MDUwMDAwWhcNMjUwMzIxMDUwMDAwWjBvMQswCQYDVQQGEwJVUzELMAkGA1UE" + + "CBMCTUExEDAOBgNVBAcTB1dhbHRoYW0xFjAUBgNVBAoTDUZvcnVtIFN5c3Rl" + + "bXMxCzAJBgNVBAsTAlFBMRwwGgYDVQQDExNDZXJ0aWZpY2F0ZSBNYW5hZ2Vy" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4VeU+48VBjI0mGRt" + + "9qlD+WAhx3vv4KCOD5f3HWLj8D2DcoszVTVDqtRK+HS1eSpO/xWumyXhjV55" + + "FhG2eYi4e0clv0WyswWkGLqo7IxYn3ZhVmw04ohdTjdhVv8oS+96MUqPmvVW" + + "+MkVRyqm75HdgWhKRr/lEpDNm+RJe85xMCipkyesJG58p5tRmAZAAyRs3jYw" + + "5YIFwDOnt6PCme7ui4xdas2zolqOlynMuq0ctDrUPKGLlR4mVBzgAVPeatcu" + + "ivEQdB3rR6UN4+nv2jx9kmQNNb95R1M3J9xHfOWX176UWFOZHJwVq8eBGF9N" + + "pav4ZGBAyqagW7HMlo7Hw0FzUwIDAQABo3YwdDARBglghkgBhvhCAQEEBAMC" + + "AJcwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU64zBxl1yKES8tjU3/rBA" + + "NaeBpjkwHwYDVR0jBBgwFoAU64zBxl1yKES8tjU3/rBANaeBpjkwDgYDVR0P" + + "AQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQAzHnf+Z+UgxDVOpCu0DHF+" + + "qYZf8IaUQxLhUD7wjwnt3lJ0QV1z4oyc6Vs9J5xa8Mvf7u1WMmOxvN8r8Kb0" + + "k8DlFszLd0Qwr+NVu5NQO4Vn01UAzCtH4oX2bgrVzotqDnzZ4TcIr11EX3Nb" + + "tO8yWWl+xWIuxKoAO8a0Rh97TyYfAj4++GIm43b2zIvRXEWAytjz7rXUMwRC" + + "1ipRQwSA9gyw2y0s8emV/VwJQXsTe9xtDqlEC67b90V/BgL/jxck5E8yrY9Z" + + "gNxlOgcqscObisAkB5I6GV+dfa+BmZrhSJ/bvFMUrnFzjLFvZp/9qiK11r5K" + + "A5oyOoNv0w+8bbtMNEc1" +// + "===="); + + ""); + + /** + * extra version number encoding. + */ + private static readonly byte[] irregReq = Base64.Decode( + "MIIQpTBUoAMCAQAwTTBLMEkwCQYFKw4DAhoFAAQUIcFvFFVjPem15pKox4cfcnzF" + + "Kf4EFJf8OQzmVmyJ/hc4EhitQbXcqAzDAhB9ePsP19SuP6CsAgFwQuEAoIIQSzCC" + + "EEcwDQYJKoZIhvcNAQEFBQADgYEAlq/Tjl8OtFM8Tib1JYTiaPy9vFDr8UZhqXJI" + + "FyrdgtUyyDt0EcrgnBGacAeRZzF5sokIC6DjXweU7EItGqrpw/RaCUPUWFpPxR6y" + + "HjuzrLmICocTI9MH7dRUXm0qpxoY987sx1PtWB4pSR99ixBtq3OPNdsI0uJ+Qkei" + + "LbEZyvWggg+wMIIPrDCCA5owggKCoAMCAQICEEAxXx/eFe7gm/NX7AkcS68wDQYJ" + + "KoZIhvcNAQEFBQAwgZoxCzAJBgNVBAYTAlNFMTMwMQYDVQQKDCpMw6Ruc2bDtnJz" + + "w6RrcmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkxFTATBgNVBAUTDDExMTEx" + + "MTExMTExMTE/MD0GA1UEAww2TMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIFB1cmNo" + + "YXNlciBDQTEgZm9yIEJhbmtJRCBURVNUMB4XDTA4MTAwNjIyMDAwMFoXDTEwMTAx" + + "MDIxNTk1OVowgZExCzAJBgNVBAYTAlNFMTMwMQYDVQQKDCpMw6Ruc2bDtnJzw6Rr" + + "cmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkxFTATBgNVBAUTDDExMTExMTEx" + + "MTExMTE2MDQGA1UEAwwtTMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIE9DU1AgZm9y" + + "IEJhbmtJRCBURVNUMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5e/h6aL2m" + + "DVpWeu5e5p1Ps9kbvuuGeAp9zJDYLbZz7uzT67X+s59HaViroD2+2my/gg7rX7tK" + + "H9VXpJad1W9O19SjfNyxgeAMwVMkrbb4IlrQwu0v/Ub8JPxSWwZZXYiODq5abeXA" + + "abMYIHxSaSkhrsUj1dpSAohHLJRlq707swIDAQABo2cwZTAfBgNVHSMEGDAWgBTR" + + "vcp2QyNdNGZ+q7TjKSrrHZqxmDATBgNVHSAEDDAKMAgGBiqFcDwBBjAOBgNVHQ8B" + + "Af8EBAMCBkAwHQYDVR0OBBYEFF/3557FEvkA8iiPv2XcBclxKnTdMA0GCSqGSIb3" + + "DQEBBQUAA4IBAQAOxRvHO89XJ0v83BZdPFzEBA4B2Tqc1oABUn13S6fAkcGWvOmG" + + "eY61MK16aMnLPNDadZrAqJc6PEtVY57uaywE9acwv9XpHO0bcS94tLwvZZJ2KBt0" + + "Oq96gaI6gnJViUjyWjm+qBZvod0QPOLGv6wUPoiNcCpSid/COTjKpLYpCJj3ZWUV" + + "nsTRWSRVXsdY/xI0gs/A8/c5P1PuTxoi99RTmcruoFxvV4MmhWyX7IGqG4OAtLdo" + + "yefz/90FPGOrmqY9OgEb+gNuTM26YDvSs1dfarPl89d8jjwxHgNbZjh2VHFqKolJ" + + "8TB8ZS5aNvhHPumOOE47y95rTBxrxSmGvKb8MIIENDCCAxygAwIBAgIRAJAFaeOw" + + "7XbxH/DN/Vvhjx8wDQYJKoZIhvcNAQEFBQAwgZUxCzAJBgNVBAYTAlNFMTMwMQYD" + + "VQQKDCpMw6Ruc2bDtnJzw6RrcmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkx" + + "FTATBgNVBAUTDDExMTExMTExMTExMTE6MDgGA1UEAwwxTMOkbnNmw7Zyc8Oka3Jp" + + "bmdhciBCYW5rIFJvb3QgQ0ExIGZvciBCYW5rSUQgVEVTVDAeFw0wNzEwMDExMjAw" + + "MzdaFw0yOTA3MDExMjAwMzdaMIGaMQswCQYDVQQGEwJTRTEzMDEGA1UECgwqTMOk" + + "bnNmw7Zyc8Oka3JpbmdhciBCYW5rIEFrdGllYm9sYWcgKHB1YmwpMRUwEwYDVQQF" + + "EwwxMTExMTExMTExMTExPzA9BgNVBAMMNkzDpG5zZsO2cnPDpGtyaW5nYXIgQmFu" + + "ayBQdXJjaGFzZXIgQ0ExIGZvciBCYW5rSUQgVEVTVDCCASIwDQYJKoZIhvcNAQEB" + + "BQADggEPADCCAQoCggEBAMK5WbYojYRX1ZKrbxJBgbd4x503LfMWgr67sVD5L0NY" + + "1RPhZVFJRKJWvawE5/eXJ4oNQwc831h2jiOgINXuKyGXqdAVGBcpFwIxTfzxwT4l" + + "fvztr8pE6wk7mLLwKUvIjbM3EF1IL3zUI3UU/U5ioyGmcb/o4GGN71kMmvV/vrkU" + + "02/s7xicXNxYej4ExLiCkS5+j/+3sR47Uq5cL9e8Yg7t5/6FyLGQjKoS8HU/abYN" + + "4kpx/oyrxzrXMhnMVDiI8QX9NYGJwI8KZ/LU6GDq/NnZ3gG5v4l4UU1GhgUbrk4I" + + "AZPDu99zvwCtkdj9lJN0eDv8jdyEPZ6g1qPBE0pCNqcCAwEAAaN4MHYwDwYDVR0T" + + "AQH/BAUwAwEB/zATBgNVHSAEDDAKMAgGBiqFcDwBBjAOBgNVHQ8BAf8EBAMCAQYw" + + "HwYDVR0jBBgwFoAUnkjp1bkQUOrkRiLgxpxwAe2GQFYwHQYDVR0OBBYEFNG9ynZD" + + "I100Zn6rtOMpKusdmrGYMA0GCSqGSIb3DQEBBQUAA4IBAQAPVSC4HEd+yCtSgL0j" + + "NI19U2hJeP28lAD7OA37bcLP7eNrvfU/2tuqY7rEn1m44fUbifewdgR8x2DzhM0m" + + "fJcA5Z12PYUb85L9z8ewGQdyHLNlMpKSTP+0lebSc/obFbteC4jjuvux60y5KVOp" + + "osXbGw2qyrS6uhZJrTDP1B+bYg/XBttG+i7Qzx0S5Tq//VU9OfAQZWpvejadKAk9" + + "WCcXq6zALiJcxsUwOHZRvvHDxkHuf5eZpPvm1gaqa+G9CtV+oysZMU1eTRasBHsB" + + "NRWYfOSXggsyqRHfIAVieB4VSsB8WhZYm8UgYoLhAQfSJ5Xq5cwBOHkVj33MxAyP" + + "c7Y5MIID/zCCAuegAwIBAgIRAOXEoBcV4gV3Z92gk5AuRgwwDQYJKoZIhvcNAQEF" + + "BQAwZjEkMCIGA1UECgwbRmluYW5zaWVsbCBJRC1UZWtuaWsgQklEIEFCMR8wHQYD" + + "VQQLDBZCYW5rSUQgTWVtYmVyIEJhbmtzIENBMR0wGwYDVQQDDBRCYW5rSUQgUm9v" + + "dCBDQSBURVNUMjAeFw0wNzEwMDExMTQ1NDlaFw0yOTA4MDExMTU4MjVaMIGVMQsw" + + "CQYDVQQGEwJTRTEzMDEGA1UECgwqTMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIEFr" + + "dGllYm9sYWcgKHB1YmwpMRUwEwYDVQQFEwwxMTExMTExMTExMTExOjA4BgNVBAMM" + + "MUzDpG5zZsO2cnPDpGtyaW5nYXIgQmFuayBSb290IENBMSBmb3IgQmFua0lEIFRF" + + "U1QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBzn7IXIpyOGCCTuzL" + + "DKE/T+pFRTgFh3QgKtifZ4zxdvB2Sd5+90vUEGcGExUhzpgb9gOUrT1eE0XhdiUR" + + "YuYYpJI/nzPQWTsRtEaql7NHBPKnEauoA9oAhCT4pE5gLlqpTfkB8nAsRTI2XqpI" + + "hQ7vTvnTRx20xog21NIbz1GztV8H1kBH2eDvRX7cXGiugp6CXV/le9cB+/4TBNUN" + + "Xqupt79dM49KCoDuYr72W7Hv4BSWw3IInEN2m8T2X6UBpBGkCiGwLQy/+KOmYRK7" + + "1PSFC0rXDwOJ0HJ/8fHwx6vLMxHAQ6s/9vOW10MjgjSQlbVqH/4Pa+TlpWumSV4E" + + "l0z9AgMBAAGjeDB2MA8GA1UdEwEB/wQFMAMBAf8wEwYDVR0gBAwwCjAIBgYqhXA8" + + "AQYwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQYMBaAFJuTMPljHcYdrRO9sEi1amb4" + + "tE3VMB0GA1UdDgQWBBSeSOnVuRBQ6uRGIuDGnHAB7YZAVjANBgkqhkiG9w0BAQUF" + + "AAOCAQEArnW/9n+G+84JOgv1Wn4tsBBS7QgJp1rdCoiNrZPx2du/7Wz3wQVNKBjL" + + "eMCyLjg0OVHuq4hpCv9MZpUqdcUW8gpp4dLDAAd1uE7xqVuG8g4Ir5qocxbZHQew" + + "fnqSJJDlEZgDeZIzod92OO+htv0MWqKWbr3Mo2Hqhn+t0+UVWsW4k44e7rUw3xQq" + + "r2VdMJv/C68BXUgqh3pplUDjWyXfreiACTT0q3HT6v6WaihKCa2WY9Kd1IkDcLHb" + + "TZk8FqMmGn72SgJw3H5Dvu7AiZijjNAUulMnMpxBEKyFTU2xRBlZZVcp50VJ2F7+" + + "siisxbcYOAX4GztLMlcyq921Ov/ipDCCA88wggK3oAMCAQICEQCmaX+5+m5bF5us" + + "CtyMq41SMA0GCSqGSIb3DQEBBQUAMGYxJDAiBgNVBAoMG0ZpbmFuc2llbGwgSUQt" + + "VGVrbmlrIEJJRCBBQjEfMB0GA1UECwwWQmFua0lEIE1lbWJlciBCYW5rcyBDQTEd" + + "MBsGA1UEAwwUQmFua0lEIFJvb3QgQ0EgVEVTVDIwHhcNMDQwODEzMDcyMDEwWhcN" + + "MjkwODEyMTIwMjQ2WjBmMSQwIgYDVQQKDBtGaW5hbnNpZWxsIElELVRla25payBC" + + "SUQgQUIxHzAdBgNVBAsMFkJhbmtJRCBNZW1iZXIgQmFua3MgQ0ExHTAbBgNVBAMM" + + "FEJhbmtJRCBSb290IENBIFRFU1QyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB" + + "CgKCAQEA25D0f1gipbACk4Bg3t6ODUlCWOU0TWeTkzAHR7IRB5T++yvsVosedMMW" + + "6KYYTbPONeJSt5kydX+wZi9nVNdlhkNULLbDKWfRY7x+B9MR1Q0Kq/e4VR0uRsak" + + "Bv5iwEYZ7cSR63HfBaPTqQsGobq+wtGH5JeTBrmCt4A3kN1UWgX32Dv/I3m7v8bK" + + "iwh4cnvAD9PIOtq6pOmAkSvLvp8jCy3qFLe9KAxm8M/ZAmnxYaRV8DVEg57FGoG6" + + "oiG3Ixx8PSVVdzpFY4kuUFLi4ueMPwjnXFiBhhWJJeOtFG3Lc2aW3zvcDbD/MsDm" + + "rSZNTmtbOOou8xuMKjlNY9PU5MHIaQIDAQABo3gwdjAPBgNVHRMBAf8EBTADAQH/" + + "MBMGA1UdIAQMMAowCAYGKoVwPAEGMA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAW" + + "gBSbkzD5Yx3GHa0TvbBItWpm+LRN1TAdBgNVHQ4EFgQUm5Mw+WMdxh2tE72wSLVq" + + "Zvi0TdUwDQYJKoZIhvcNAQEFBQADggEBAIQ4ZBHWssA38pfNzH5A+H3SXpAlI8Jc" + + "LuoMVOIwwbfd1Up0xopCs+Ay41v8FZtcTMFqCVTih2nzVusTgnFBPMPJ2cnTlRue" + + "kAtVRNsiWn2/Ool/OXoYf5YnpgYu8t9jLCBCoDS5YJg714r9V9hCwfey8TCWBU80" + + "vL7EIfjK13nUxf8d49GzZlFMNqGDMjfMp1FYrHBGLZBr8br/G/7em1Cprw7iR8cw" + + "pddz+QXXFIrIz5Y9D/x1RrwoLibPw0kMrSwI2G4aCvoBySfbD6cpnJf6YHRctdSb" + + "755zhdBW7XWTl6ReUVuEt0hTFms4F60kFAi5hIbDRSN1Slv5yP2b0EA="); + + public override string Name + { + get { return "OCSP"; } + } + + private void doTestECDsa() + { + string signDN = "O=Bouncy Castle, C=AU"; + AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeECKeyPair(); + X509Certificate testCert = OcspTestUtil.MakeECDsaCertificate(signKP, signDN, signKP, signDN); + + string origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; + GeneralName origName = new GeneralName(new X509Name(origDN)); + + // + // general id value for our test issuer cert and a serial number. + // + CertificateID id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One); + + // + // basic request generation + // + OcspReqGenerator gen = new OcspReqGenerator(); + + gen.AddRequest(id); + + OcspReq req = gen.Generate(); + + if (req.IsSigned) + { + Fail("signed but shouldn't be"); + } + + X509Certificate[] certs = req.GetCerts(); + + if (certs != null) + { + Fail("null certs expected, but not found"); + } + + Req[] requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // request generation with signing + // + X509Certificate[] chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + gen.AddRequest(new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withECDSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + certs = req.GetCerts(); + + if (certs == null) + { + Fail("null certs found"); + } + + if (certs.Length != 1 || !certs[0].Equals(testCert)) + { + Fail("incorrect certs found in request"); + } + + // + // encoding test + // + byte[] reqEnc = req.GetEncoded(); + + OcspReq newReq = new OcspReq(reqEnc); + + if (!newReq.Verify(signKP.Public)) + { + Fail("newReq signature failed to Verify"); + } + + // + // request generation with signing and nonce + // + chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + IList oids = new ArrayList(); + IList values = new ArrayList(); + byte[] sampleNonce = new byte[16]; + Random rand = new Random(); + + rand.NextBytes(sampleNonce); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + oids.Add(OcspObjectIdentifiers.PkixOcspNonce); + values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce)))); + + gen.SetRequestExtensions(new X509Extensions(oids, values)); + + gen.AddRequest(new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withECDSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + // + // extension check. + // + ISet extOids = req.GetCriticalExtensionOids(); + + if (extOids.Count != 0) + { + Fail("wrong number of critical extensions in OCSP request."); + } + + extOids = req.GetNonCriticalExtensionOids(); + + if (extOids.Count != 1) + { + Fail("wrong number of non-critical extensions in OCSP request."); + } + + Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce); + + Asn1Encodable extObj = X509ExtensionUtilities.FromExtensionValue(extValue); + + if (!(extObj is Asn1OctetString)) + { + Fail("wrong extension type found."); + } + + if (!AreEqual(((Asn1OctetString)extObj).GetOctets(), sampleNonce)) + { + Fail("wrong extension value found."); + } + + // + // request list check + // + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // response generation + // + BasicOcspRespGenerator respGen = new BasicOcspRespGenerator(signKP.Public); + + respGen.AddResponse(id, CertificateStatus.Good); + + respGen.Generate("SHA1withECDSA", signKP.Private, chain, DateTime.UtcNow); + } + + private void doTestRsa() + { + string signDN = "O=Bouncy Castle, C=AU"; + AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeKeyPair(); + X509Certificate testCert = OcspTestUtil.MakeCertificate(signKP, signDN, signKP, signDN); + + string origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; + GeneralName origName = new GeneralName(new X509Name(origDN)); + + // + // general id value for our test issuer cert and a serial number. + // + CertificateID id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One); + + // + // basic request generation + // + OcspReqGenerator gen = new OcspReqGenerator(); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + OcspReq req = gen.Generate(); + + if (req.IsSigned) + { + Fail("signed but shouldn't be"); + } + + X509Certificate[] certs = req.GetCerts(); + + if (certs != null) + { + Fail("null certs expected, but not found"); + } + + Req[] requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // request generation with signing + // + X509Certificate[] chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withRSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + certs = req.GetCerts(); + + if (certs == null) + { + Fail("null certs found"); + } + + if (certs.Length != 1 || !certs[0].Equals(testCert)) + { + Fail("incorrect certs found in request"); + } + + // + // encoding test + // + byte[] reqEnc = req.GetEncoded(); + + OcspReq newReq = new OcspReq(reqEnc); + + if (!newReq.Verify(signKP.Public)) + { + Fail("newReq signature failed to Verify"); + } + + // + // request generation with signing and nonce + // + chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + IList oids = new ArrayList(); + IList values = new ArrayList(); + byte[] sampleNonce = new byte[16]; + Random rand = new Random(); + + rand.NextBytes(sampleNonce); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + oids.Add(OcspObjectIdentifiers.PkixOcspNonce); + values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce)))); + + gen.SetRequestExtensions(new X509Extensions(oids, values)); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withRSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + // + // extension check. + // + ISet extOids = req.GetCriticalExtensionOids(); + + if (extOids.Count != 0) + { + Fail("wrong number of critical extensions in OCSP request."); + } + + extOids = req.GetNonCriticalExtensionOids(); + + if (extOids.Count != 1) + { + Fail("wrong number of non-critical extensions in OCSP request."); + } + + Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce); + + Asn1Object extObj = X509ExtensionUtilities.FromExtensionValue(extValue); + + if (!(extObj is Asn1OctetString)) + { + Fail("wrong extension type found."); + } + + if (!AreEqual(((Asn1OctetString)extObj).GetOctets(), sampleNonce)) + { + Fail("wrong extension value found."); + } + + // + // request list check + // + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // response generation + // + BasicOcspRespGenerator respGen = new BasicOcspRespGenerator(signKP.Public); + + respGen.AddResponse(id, CertificateStatus.Good); + + BasicOcspResp resp = respGen.Generate("SHA1withRSA", signKP.Private, chain, DateTime.UtcNow); + OCSPRespGenerator rGen = new OCSPRespGenerator(); + + byte[] enc = rGen.Generate(OCSPRespGenerator.Successful, resp).GetEncoded(); + } + + private void doTestIrregularVersionReq() + { + OcspReq ocspRequest = new OcspReq(irregReq); + X509Certificate cert = ocspRequest.GetCerts()[0]; + if (!ocspRequest.Verify(cert.GetPublicKey())) + { + Fail("extra version encoding test failed"); + } + } + + public override void PerformTest() + { + string signDN = "O=Bouncy Castle, C=AU"; + AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeKeyPair(); + X509Certificate testCert = OcspTestUtil.MakeCertificate(signKP, signDN, signKP, signDN); + + string origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; + GeneralName origName = new GeneralName(new X509Name(origDN)); + + // + // general id value for our test issuer cert and a serial number. + // + CertificateID id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One); + + // + // basic request generation + // + OcspReqGenerator gen = new OcspReqGenerator(); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + OcspReq req = gen.Generate(); + + if (req.IsSigned) + { + Fail("signed but shouldn't be"); + } + + X509Certificate[] certs = req.GetCerts(); + + if (certs != null) + { + Fail("null certs expected, but not found"); + } + + Req[] requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // request generation with signing + // + X509Certificate[] chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withRSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + certs = req.GetCerts(); + + if (certs == null) + { + Fail("null certs found"); + } + + if (certs.Length != 1 || !testCert.Equals(certs[0])) + { + Fail("incorrect certs found in request"); + } + + // + // encoding test + // + byte[] reqEnc = req.GetEncoded(); + + OcspReq newReq = new OcspReq(reqEnc); + + if (!newReq.Verify(signKP.Public)) + { + Fail("newReq signature failed to Verify"); + } + + // + // request generation with signing and nonce + // + chain = new X509Certificate[1]; + + gen = new OcspReqGenerator(); + + IList oids = new ArrayList(); + IList values = new ArrayList(); + byte[] sampleNonce = new byte[16]; + Random rand = new Random(); + + rand.NextBytes(sampleNonce); + + gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred"))); + + oids.Add(OcspObjectIdentifiers.PkixOcspNonce); + values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce)))); + + gen.SetRequestExtensions(new X509Extensions(oids, values)); + + gen.AddRequest( + new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One)); + + chain[0] = testCert; + + req = gen.Generate("SHA1withRSA", signKP.Private, chain); + + if (!req.IsSigned) + { + Fail("not signed but should be"); + } + + if (!req.Verify(signKP.Public)) + { + Fail("signature failed to Verify"); + } + + // + // extension check. + // + ISet extOids = req.GetCriticalExtensionOids(); + + if (extOids.Count != 0) + { + Fail("wrong number of critical extensions in OCSP request."); + } + + extOids = req.GetNonCriticalExtensionOids(); + + if (extOids.Count != 1) + { + Fail("wrong number of non-critical extensions in OCSP request."); + } + + Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce); + Asn1Object extObj = X509ExtensionUtilities.FromExtensionValue(extValue); + + if (!(extObj is Asn1OctetString)) + { + Fail("wrong extension type found."); + } + + byte[] compareNonce = ((Asn1OctetString) extObj).GetOctets(); + + if (!AreEqual(compareNonce, sampleNonce)) + { + Fail("wrong extension value found."); + } + + // + // request list check + // + requests = req.GetRequestList(); + + if (!requests[0].GetCertID().Equals(id)) + { + Fail("Failed isFor test"); + } + + // + // response parsing - test 1 + // + OcspResp response = new OcspResp(testResp1); + + if (response.Status != 0) + { + Fail("response status not zero."); + } + + BasicOcspResp brep = (BasicOcspResp) response.GetResponseObject(); + chain = brep.GetCerts(); + + if (!brep.Verify(chain[0].GetPublicKey())) + { + Fail("response 1 failed to Verify."); + } + + // + // test 2 + // + SingleResp[] singleResp = brep.Responses; + + response = new OcspResp(testResp2); + + if (response.Status != 0) + { + Fail("response status not zero."); + } + + brep = (BasicOcspResp)response.GetResponseObject(); + chain = brep.GetCerts(); + + if (!brep.Verify(chain[0].GetPublicKey())) + { + Fail("response 2 failed to Verify."); + } + + singleResp = brep.Responses; + + // + // simple response generation + // + OCSPRespGenerator respGen = new OCSPRespGenerator(); + OcspResp resp = respGen.Generate(OCSPRespGenerator.Successful, response.GetResponseObject()); + + if (!resp.GetResponseObject().Equals(response.GetResponseObject())) + { + Fail("response fails to match"); + } + + doTestECDsa(); + doTestRsa(); + doTestIrregularVersionReq(); + } + + public static void Main( + string[] args) + { + RunTest(new OcspTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/ocsp/test/OCSPTestUtil.cs b/crypto/test/src/ocsp/test/OCSPTestUtil.cs new file mode 100644 index 000000000..53b8f5bb9 --- /dev/null +++ b/crypto/test/src/ocsp/test/OCSPTestUtil.cs @@ -0,0 +1,147 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Ocsp.Tests +{ + public class OcspTestUtil + { + public static SecureRandom rand; + public static IAsymmetricCipherKeyPairGenerator kpg, ecKpg; + public static CipherKeyGenerator desede128kg; + public static CipherKeyGenerator desede192kg; + public static CipherKeyGenerator rc240kg; + public static CipherKeyGenerator rc264kg; + public static CipherKeyGenerator rc2128kg; + public static BigInteger serialNumber; + + public static readonly bool Debug = true; + + static OcspTestUtil() + { + rand = new SecureRandom(); + +// kpg = KeyPairGenerator.GetInstance("RSA"); +// kpg.initialize(1024, rand); + kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpg.Init(new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), rand, 1024, 25)); + + serialNumber = BigInteger.One; + + ecKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + ecKpg.Init(new KeyGenerationParameters(rand, 192)); + } + + public static AsymmetricCipherKeyPair MakeKeyPair() + { + return kpg.GenerateKeyPair(); + } + + public static AsymmetricCipherKeyPair MakeECKeyPair() + { + return ecKpg.GenerateKeyPair(); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate MakeECDsaCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeECDsaCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca) + { + return MakeCertificate(_subKP,_subDN, _issKP, _issDN, "MD5withRSA", _ca); + } + + public static X509Certificate MakeECDsaCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca) + { + return MakeCertificate(_subKP,_subDN, _issKP, _issDN, "SHA1WithECDSA", _ca); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, string algorithm, bool _ca) + { + AsymmetricKeyParameter _subPub = _subKP.Public; + AsymmetricKeyParameter _issPriv = _issKP.Private; + AsymmetricKeyParameter _issPub = _issKP.Public; + + X509V3CertificateGenerator _v3CertGen = new X509V3CertificateGenerator(); + + _v3CertGen.Reset(); + _v3CertGen.SetSerialNumber(allocateSerialNumber()); + _v3CertGen.SetIssuerDN(new X509Name(_issDN)); + _v3CertGen.SetNotBefore(DateTime.UtcNow); + _v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100)); + _v3CertGen.SetSubjectDN(new X509Name(_subDN)); + _v3CertGen.SetPublicKey(_subPub); + _v3CertGen.SetSignatureAlgorithm(algorithm); + + _v3CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, + createSubjectKeyId(_subPub)); + + _v3CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, + createAuthorityKeyId(_issPub)); + + _v3CertGen.AddExtension(X509Extensions.BasicConstraints, false, + new BasicConstraints(_ca)); + + X509Certificate _cert = _v3CertGen.Generate(_issPriv); + + _cert.CheckValidity(DateTime.UtcNow); + _cert.Verify(_issPub); + + return _cert; + } + + /* + * + * INTERNAL METHODS + * + */ + + private static AuthorityKeyIdentifier createAuthorityKeyId( + AsymmetricKeyParameter _pubKey) + { + SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey); + return new AuthorityKeyIdentifier(_info); + } + + private static SubjectKeyIdentifier createSubjectKeyId( + AsymmetricKeyParameter _pubKey) + { + SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey); + return new SubjectKeyIdentifier(_info); + } + + private static BigInteger allocateSerialNumber() + { + BigInteger _tmp = serialNumber; + serialNumber = serialNumber.Add(BigInteger.One); + return _tmp; + } + } +} diff --git a/crypto/test/src/openpgp/examples/ByteArrayHandler.cs b/crypto/test/src/openpgp/examples/ByteArrayHandler.cs new file mode 100644 index 000000000..676db8766 --- /dev/null +++ b/crypto/test/src/openpgp/examples/ByteArrayHandler.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * Simple routine to encrypt and decrypt using a passphrase. + * This service routine provides the basic PGP services between + * byte arrays. + * + * Note: this code plays no attention to -Console in the file name + * the specification of "_CONSOLE" in the filename. + * It also expects that a single pass phrase will have been used. + * + */ + public sealed class ByteArrayHandler + { + private ByteArrayHandler() + { + } + + /** + * decrypt the passed in message stream + * + * @param encrypted The message to be decrypted. + * @param passPhrase Pass phrase (key) + * + * @return Clear text as a byte array. I18N considerations are + * not handled by this routine + * @exception IOException + * @exception PgpException + */ + public static byte[] Decrypt( + byte[] encrypted, + char[] passPhrase) + { + Stream inputStream = new MemoryStream(encrypted); + + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); + PgpEncryptedDataList enc = null; + PgpObject o = pgpF.NextPgpObject(); + + // + // the first object might be a PGP marker packet. + // + if (o is PgpEncryptedDataList) + { + enc = (PgpEncryptedDataList) o; + } + else + { + enc = (PgpEncryptedDataList) pgpF.NextPgpObject(); + } + + PgpPbeEncryptedData pbe = (PgpPbeEncryptedData)enc[0]; + + Stream clear = pbe.GetDataStream(passPhrase); + + PgpObjectFactory pgpFact = new PgpObjectFactory(clear); + + PgpCompressedData cData = (PgpCompressedData) pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(cData.GetDataStream()); + + PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject(); + + Stream unc = ld.GetInputStream(); + + return Streams.ReadAll(unc); + } + + /** + * Simple PGP encryptor between byte[]. + * + * @param clearData The test to be encrypted + * @param passPhrase The pass phrase (key). This method assumes that the + * key is a simple pass phrase, and does not yet support + * RSA or more sophisiticated keying. + * @param fileName File name. This is used in the Literal Data Packet (tag 11) + * which is really inly important if the data is to be + * related to a file to be recovered later. Because this + * routine does not know the source of the information, the + * caller can set something here for file name use that + * will be carried. If this routine is being used to + * encrypt SOAP MIME bodies, for example, use the file name from the + * MIME type, if applicable. Or anything else appropriate. + * + * @param armor + * + * @return encrypted data. + * @exception IOException + * @exception PgpException + */ + public static byte[] Encrypt( + byte[] clearData, + char[] passPhrase, + string fileName, + SymmetricKeyAlgorithmTag algorithm, + bool armor) + { + if (fileName == null) + { + fileName = PgpLiteralData.Console; + } + + byte[] compressedData = Compress(clearData, fileName, CompressionAlgorithmTag.Zip); + + MemoryStream bOut = new MemoryStream(); + + Stream output = bOut; + if (armor) + { + output = new ArmoredOutputStream(output); + } + + PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(algorithm, new SecureRandom()); + encGen.AddMethod(passPhrase); + + Stream encOut = encGen.Open(output, compressedData.Length); + + encOut.Write(compressedData, 0, compressedData.Length); + encOut.Close(); + + if (armor) + { + output.Close(); + } + + return bOut.ToArray(); + } + + private static byte[] Compress(byte[] clearData, string fileName, CompressionAlgorithmTag algorithm) + { + MemoryStream bOut = new MemoryStream(); + + PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm); + Stream cos = comData.Open(bOut); // open it with the final destination + PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); + + // we want to Generate compressed data. This might be a user option later, + // in which case we would pass in bOut. + Stream pOut = lData.Open( + cos, // the compressed output stream + PgpLiteralData.Binary, + fileName, // "filename" to store + clearData.Length, // length of clear data + DateTime.UtcNow // current time + ); + + pOut.Write(clearData, 0, clearData.Length); + pOut.Close(); + + comData.Close(); + + return bOut.ToArray(); + } + + private static string GetAsciiString(byte[] bs) + { + return Encoding.ASCII.GetString(bs, 0, bs.Length); + } + + public static void Main( + string[] args) + { + string passPhrase = "Dick Beck"; + char[] passArray = passPhrase.ToCharArray(); + + byte[] original = Encoding.ASCII.GetBytes("Hello world"); + Console.WriteLine("Starting PGP test"); + byte[] encrypted = Encrypt(original, passArray, "iway", SymmetricKeyAlgorithmTag.Cast5, true); + + Console.WriteLine("\nencrypted data = '"+Hex.ToHexString(encrypted)+"'"); + byte[] decrypted= Decrypt(encrypted,passArray); + + Console.WriteLine("\ndecrypted data = '"+GetAsciiString(decrypted)+"'"); + + encrypted = Encrypt(original, passArray, "iway", SymmetricKeyAlgorithmTag.Aes256, false); + + Console.WriteLine("\nencrypted data = '"+Hex.ToHexString(encrypted)+"'"); + decrypted= Decrypt(encrypted, passArray); + + Console.WriteLine("\ndecrypted data = '"+GetAsciiString(decrypted)+"'"); + } + } +} diff --git a/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs b/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs new file mode 100644 index 000000000..14fa37269 --- /dev/null +++ b/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs @@ -0,0 +1,375 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that creates clear signed files and verifies them. + *

    + * To sign a file: ClearSignedFileProcessor -s fileName secretKey passPhrase. + *

    + *

    + * To decrypt: ClearSignedFileProcessor -v fileName signatureFile publicKeyFile. + *

    + */ + public sealed class ClearSignedFileProcessor + { + private ClearSignedFileProcessor() + { + } + + private static int ReadInputLine( + MemoryStream bOut, + Stream fIn) + { + bOut.SetLength(0); + + int lookAhead = -1; + int ch; + + while ((ch = fIn.ReadByte()) >= 0) + { + bOut.WriteByte((byte) ch); + if (ch == '\r' || ch == '\n') + { + lookAhead = ReadPassedEol(bOut, ch, fIn); + break; + } + } + + return lookAhead; + } + + private static int ReadInputLine( + MemoryStream bOut, + int lookAhead, + Stream fIn) + { + bOut.SetLength(0); + + int ch = lookAhead; + + do + { + bOut.WriteByte((byte) ch); + if (ch == '\r' || ch == '\n') + { + lookAhead = ReadPassedEol(bOut, ch, fIn); + break; + } + } + while ((ch = fIn.ReadByte()) >= 0); + + if (ch < 0) + { + lookAhead = -1; + } + + return lookAhead; + } + + private static int ReadPassedEol( + MemoryStream bOut, + int lastCh, + Stream fIn) + { + int lookAhead = fIn.ReadByte(); + + if (lastCh == '\r' && lookAhead == '\n') + { + bOut.WriteByte((byte) lookAhead); + lookAhead = fIn.ReadByte(); + } + + return lookAhead; + } + + /* + * verify a clear text signed file + */ + private static void VerifyFile( + Stream inputStream, + Stream keyIn, + string resultName) + { + ArmoredInputStream aIn = new ArmoredInputStream(inputStream); + Stream outStr = File.Create(resultName); + + // + // write out signed section using the local line separator. + // note: trailing white space needs to be removed from the end of + // each line RFC 4880 Section 7.1 + // + MemoryStream lineOut = new MemoryStream(); + int lookAhead = ReadInputLine(lineOut, aIn); + byte[] lineSep = LineSeparator; + + if (lookAhead != -1 && aIn.IsClearText()) + { + byte[] line = lineOut.ToArray(); + outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line)); + outStr.Write(lineSep, 0, lineSep.Length); + + while (lookAhead != -1 && aIn.IsClearText()) + { + lookAhead = ReadInputLine(lineOut, lookAhead, aIn); + + line = lineOut.ToArray(); + outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line)); + outStr.Write(lineSep, 0, lineSep.Length); + } + } + + outStr.Close(); + + PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(keyIn); + + PgpObjectFactory pgpFact = new PgpObjectFactory(aIn); + PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject(); + PgpSignature sig = p3[0]; + + sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId)); + + // + // read the input, making sure we ignore the last newline. + // + Stream sigIn = File.OpenRead(resultName); + + lookAhead = ReadInputLine(lineOut, sigIn); + + ProcessLine(sig, lineOut.ToArray()); + + if (lookAhead != -1) + { + do + { + lookAhead = ReadInputLine(lineOut, lookAhead, sigIn); + + sig.Update((byte) '\r'); + sig.Update((byte) '\n'); + + ProcessLine(sig, lineOut.ToArray()); + } + while (lookAhead != -1); + } + + sigIn.Close(); + + if (sig.Verify()) + { + Console.WriteLine("signature verified."); + } + else + { + Console.WriteLine("signature verification failed."); + } + } + + private static byte[] LineSeparator + { + get { return Encoding.ASCII.GetBytes(SimpleTest.NewLine); } + } + + /* + * create a clear text signed file. + */ + private static void SignFile( + string fileName, + Stream keyIn, + Stream outputStream, + char[] pass, + string digestName) + { + HashAlgorithmTag digest; + + if (digestName.Equals("SHA256")) + { + digest = HashAlgorithmTag.Sha256; + } + else if (digestName.Equals("SHA384")) + { + digest = HashAlgorithmTag.Sha384; + } + else if (digestName.Equals("SHA512")) + { + digest = HashAlgorithmTag.Sha512; + } + else if (digestName.Equals("MD5")) + { + digest = HashAlgorithmTag.MD5; + } + else if (digestName.Equals("RIPEMD160")) + { + digest = HashAlgorithmTag.RipeMD160; + } + else + { + digest = HashAlgorithmTag.Sha1; + } + + PgpSecretKey pgpSecKey = PgpExampleUtilities.ReadSecretKey(keyIn); + PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey(pass); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, digest); + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); + + sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey); + + IEnumerator enumerator = pgpSecKey.PublicKey.GetUserIds().GetEnumerator(); + if (enumerator.MoveNext()) + { + spGen.SetSignerUserId(false, (string) enumerator.Current); + sGen.SetHashedSubpackets(spGen.Generate()); + } + + Stream fIn = File.OpenRead(fileName); + ArmoredOutputStream aOut = new ArmoredOutputStream(outputStream); + + aOut.BeginClearText(digest); + + // + // note the last \n/\r/\r\n in the file is ignored + // + MemoryStream lineOut = new MemoryStream(); + int lookAhead = ReadInputLine(lineOut, fIn); + + ProcessLine(aOut, sGen, lineOut.ToArray()); + + if (lookAhead != -1) + { + do + { + lookAhead = ReadInputLine(lineOut, lookAhead, fIn); + + sGen.Update((byte) '\r'); + sGen.Update((byte) '\n'); + + ProcessLine(aOut, sGen, lineOut.ToArray()); + } + while (lookAhead != -1); + } + + fIn.Close(); + + aOut.EndClearText(); + + BcpgOutputStream bOut = new BcpgOutputStream(aOut); + + sGen.Generate().Encode(bOut); + + aOut.Close(); + } + + private static void ProcessLine( + PgpSignature sig, + byte[] line) + { + // note: trailing white space needs to be removed from the end of + // each line for signature calculation RFC 4880 Section 7.1 + int length = GetLengthWithoutWhiteSpace(line); + if (length > 0) + { + sig.Update(line, 0, length); + } + } + + private static void ProcessLine( + Stream aOut, + PgpSignatureGenerator sGen, + byte[] line) + { + int length = GetLengthWithoutWhiteSpace(line); + if (length > 0) + { + sGen.Update(line, 0, length); + } + + aOut.Write(line, 0, line.Length); + } + + private static int GetLengthWithoutSeparatorOrTrailingWhitespace(byte[] line) + { + int end = line.Length - 1; + + while (end >= 0 && IsWhiteSpace(line[end])) + { + end--; + } + + return end + 1; + } + + private static bool IsLineEnding( + byte b) + { + return b == '\r' || b == '\n'; + } + + private static int GetLengthWithoutWhiteSpace( + byte[] line) + { + int end = line.Length - 1; + + while (end >= 0 && IsWhiteSpace(line[end])) + { + end--; + } + + return end + 1; + } + + private static bool IsWhiteSpace( + byte b) + { + return IsLineEnding(b) || b == '\t' || b == ' '; + } + + public static int Main( + string[] args) + { + if (args[0].Equals("-s")) + { + Stream fis = File.OpenRead(args[2]); + Stream fos = File.Create(args[1] + ".asc"); + + Stream keyIn = PgpUtilities.GetDecoderStream(fis); + + string digestName = (args.Length == 4) + ? "SHA1" + : args[4]; + + SignFile(args[1], keyIn, fos, args[3].ToCharArray(), digestName); + + fis.Close(); + fos.Close(); + } + else if (args[0].Equals("-v")) + { + if (args[1].IndexOf(".asc") < 0) + { + Console.Error.WriteLine("file needs to end in \".asc\""); + return 1; + } + + Stream fin = File.OpenRead(args[1]); + Stream fis = File.OpenRead(args[2]); + + Stream keyIn = PgpUtilities.GetDecoderStream(fis); + + VerifyFile(fin, keyIn, args[1].Substring(0, args[1].Length - 4)); + + fin.Close(); + fis.Close(); + } + else + { + Console.Error.WriteLine("usage: ClearSignedFileProcessor [-s file keyfile passPhrase]|[-v sigFile keyFile]"); + } + return 0; + } + } +} diff --git a/crypto/test/src/openpgp/examples/DetachedSignatureProcessor.cs b/crypto/test/src/openpgp/examples/DetachedSignatureProcessor.cs new file mode 100644 index 000000000..c4959844d --- /dev/null +++ b/crypto/test/src/openpgp/examples/DetachedSignatureProcessor.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections; +using System.IO; + + +using Org.BouncyCastle.Bcpg.OpenPgp; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that creates seperate signatures for files and verifies them. + *

    + * To sign a file: DetachedSignatureProcessor -s [-a] fileName secretKey passPhrase.
    + * If -a is specified the output file will be "ascii-armored".

    + *

    + * To decrypt: DetachedSignatureProcessor -v fileName signatureFile publicKeyFile.

    + *

    + * Note: this example will silently overwrite files. + * It also expects that a single pass phrase + * will have been used.

    + */ + public sealed class DetachedSignatureProcessor + { + private DetachedSignatureProcessor() + { + } + + private static void VerifySignature( + string fileName, + string inputFileName, + string keyFileName) + { + using (Stream input = File.OpenRead(inputFileName), + keyIn = File.OpenRead(keyFileName)) + { + VerifySignature(fileName, input, keyIn); + } + } + + /** + * verify the signature in in against the file fileName. + */ + private static void VerifySignature( + string fileName, + Stream inputStream, + Stream keyIn) + { + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream); + PgpSignatureList p3 = null; + PgpObject o = pgpFact.NextPgpObject(); + if (o is PgpCompressedData) + { + PgpCompressedData c1 = (PgpCompressedData)o; + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + } + else + { + p3 = (PgpSignatureList)o; + } + + PgpPublicKeyRingBundle pgpPubRingCollection = new PgpPublicKeyRingBundle( + PgpUtilities.GetDecoderStream(keyIn)); + Stream dIn = File.OpenRead(fileName); + PgpSignature sig = p3[0]; + PgpPublicKey key = pgpPubRingCollection.GetPublicKey(sig.KeyId); + sig.InitVerify(key); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + sig.Update((byte)ch); + } + + dIn.Close(); + + if (sig.Verify()) + { + Console.WriteLine("signature verified."); + } + else + { + Console.WriteLine("signature verification failed."); + } + } + + private static void CreateSignature( + string inputFileName, + string keyFileName, + string outputFileName, + char[] pass, + bool armor) + { + using (Stream keyIn = File.OpenRead(keyFileName), + output = File.OpenRead(outputFileName)) + { + CreateSignature(inputFileName, keyIn, output, pass, armor); + } + } + + private static void CreateSignature( + string fileName, + Stream keyIn, + Stream outputStream, + char[] pass, + bool armor) + { + if (armor) + { + outputStream = new ArmoredOutputStream(outputStream); + } + + PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn); + PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass); + PgpSignatureGenerator sGen = new PgpSignatureGenerator( + pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + + BcpgOutputStream bOut = new BcpgOutputStream(outputStream); + + Stream fIn = File.OpenRead(fileName); + + int ch; + while ((ch = fIn.ReadByte()) >= 0) + { + sGen.Update((byte)ch); + } + + fIn.Close(); + + sGen.Generate().Encode(bOut); + + if (armor) + { + outputStream.Close(); + } + } + + public static void Main( + string[] args) + { + if (args[0].Equals("-s")) + { + if (args[1].Equals("-a")) + { + CreateSignature(args[2], args[3], args[2] + ".asc", args[4].ToCharArray(), true); + } + else + { + CreateSignature(args[1], args[2], args[1] + ".bpg", args[3].ToCharArray(), false); + } + } + else if (args[0].Equals("-v")) + { + VerifySignature(args[1], args[2], args[3]); + } + else + { + Console.Error.WriteLine("usage: DetachedSignatureProcessor [-s [-a] file keyfile passPhrase]|[-v file sigFile keyFile]"); + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/DirectKeySignature.cs b/crypto/test/src/openpgp/examples/DirectKeySignature.cs new file mode 100644 index 000000000..a6bf8e755 --- /dev/null +++ b/crypto/test/src/openpgp/examples/DirectKeySignature.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Bcpg; +using Org.BouncyCastle.Bcpg.Sig; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that directly signs a public key and writes the signed key to "SignedKey.asc" in + * the current working directory. + *

    + * To sign a key: DirectKeySignature secretKeyFile secretKeyPass publicKeyFile(key to be signed) NotationName NotationValue.
    + *

    + * To display a NotationData packet from a publicKey previously signed: DirectKeySignature signedPublicKeyFile.
    + *

    + * Note: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used. + *

    + */ + public class DirectKeySignature + { + public static void Main( + string[] args) + { + if (args.Length == 1) + { + Stream fis = File.OpenRead(args[0]); + + PgpPublicKeyRing ring = new PgpPublicKeyRing( + PgpUtilities.GetDecoderStream(fis)); + PgpPublicKey key = ring.GetPublicKey(); + + // iterate through all direct key signautures and look for NotationData subpackets + foreach (PgpSignature sig in key.GetSignaturesOfType(PgpSignature.DirectKey)) + { + Console.WriteLine("Signature date is: " + + sig.GetHashedSubPackets().GetSignatureCreationTime()); + + NotationData[] data = sig.GetHashedSubPackets().GetNotationDataOccurences(); + + for (int i = 0; i < data.Length; i++) + { + Console.WriteLine("Found Notaion named '" + data[i].GetNotationName() + +"' with content '" + data[i].GetNotationValue() + "'."); + } + } + + fis.Close(); + } + else if (args.Length == 5) + { + Stream secFis = File.OpenRead(args[0]); + Stream pubFis = File.OpenRead(args[2]); + + // gather command line arguments + PgpSecretKeyRing secRing = new PgpSecretKeyRing( + PgpUtilities.GetDecoderStream(secFis)); + String secretKeyPass = args[1]; + PgpPublicKeyRing ring = new PgpPublicKeyRing( + PgpUtilities.GetDecoderStream(pubFis)); + String notationName = args[3]; + String notationValue = args[4]; + + // create the signed keyRing + PgpPublicKeyRing sRing = null; + sRing = new PgpPublicKeyRing( + new MemoryStream( + SignPublicKey(secRing.GetSecretKey(), secretKeyPass, + ring.GetPublicKey(), notationName, notationValue, true), + false)); + ring = sRing; + + secFis.Close(); + pubFis.Close(); + + Stream fos = File.Create("SignedKey.asc"); + + // write the created keyRing to file + ArmoredOutputStream aOut = new ArmoredOutputStream(fos); + sRing.Encode(aOut); + aOut.Close(); + + // Note: ArmoredOutputStream.Close() leaves underlying stream open + fos.Close(); + } + else + { + Console.Error.WriteLine("usage: DirectKeySignature secretKeyFile secretKeyPass publicKeyFile(key to be signed) NotationName NotationValue"); + Console.Error.WriteLine("or: DirectKeySignature signedPublicKeyFile"); + } + } + + private static byte[] SignPublicKey( + PgpSecretKey secretKey, + string secretKeyPass, + PgpPublicKey keyToBeSigned, + string notationName, + string notationValue, + bool armor) + { + Stream os = new MemoryStream(); + if (armor) + { + os = new ArmoredOutputStream(os); + } + + PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey( + secretKeyPass.ToCharArray()); + + PgpSignatureGenerator sGen = new PgpSignatureGenerator( + secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.DirectKey, pgpPrivKey); + + BcpgOutputStream bOut = new BcpgOutputStream(os); + + sGen.GenerateOnePassVersion(false).Encode(bOut); + + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); + + bool isHumanReadable = true; + + spGen.SetNotationData(true, isHumanReadable, notationName, notationValue); + + PgpSignatureSubpacketVector packetVector = spGen.Generate(); + sGen.SetHashedSubpackets(packetVector); + + bOut.Flush(); + + if (armor) + { + os.Close(); + } + + return PgpPublicKey.AddCertification(keyToBeSigned, sGen.Generate()).GetEncoded(); + } + } +} diff --git a/crypto/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs b/crypto/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs new file mode 100644 index 000000000..6040351a3 --- /dev/null +++ b/crypto/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs @@ -0,0 +1,134 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that Generates a public/secret keyring containing a DSA signing + * key and an El Gamal key for encryption. + *

    + * usage: DSAElGamalKeyRingGenerator [-a] identity passPhrase

    + *

    + * Where identity is the name to be associated with the public key. The keys are placed + * in the files pub.[asc|bpg] and secret.[asc|bpg].

    + *

    + * Note: this example encrypts the secret key using AES_256, many PGP products still + * do not support this, if you are having problems importing keys try changing the algorithm + * id to PgpEncryptedData.Cast5. CAST5 is more widelysupported.

    + */ + public sealed class DsaElGamalKeyRingGenerator + { + private DsaElGamalKeyRingGenerator() + { + } + + private static void ExportKeyPair( + Stream secretOut, + Stream publicOut, + AsymmetricCipherKeyPair dsaKp, + AsymmetricCipherKeyPair elgKp, + string identity, + char[] passPhrase, + bool armor) + { + if (armor) + { + secretOut = new ArmoredOutputStream(secretOut); + } + + PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow); + PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow); + + PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair, + identity, SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, new SecureRandom()); + + keyRingGen.AddSubKey(elgKeyPair); + + keyRingGen.GenerateSecretKeyRing().Encode(secretOut); + + if (armor) + { + secretOut.Close(); + publicOut = new ArmoredOutputStream(publicOut); + } + + keyRingGen.GeneratePublicKeyRing().Encode(publicOut); + + if (armor) + { + publicOut.Close(); + } + } + + public static int Main( + string[] args) + { + if (args.Length < 2) + { + Console.WriteLine("DsaElGamalKeyRingGenerator [-a] identity passPhrase"); + return 0; + } + + IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(1024, 80, new SecureRandom()); + DsaParameters dsaParams = pGen.GenerateParameters(); + DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams); + dsaKpg.Init(kgp); + + + // + // this takes a while as the key generator has to Generate some DSA parameters + // before it Generates the key. + // + AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair(); + + + IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL"); + + BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + ElGamalParameters elParams = new ElGamalParameters(p, g); + ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams); + elgKpg.Init(elKgp); + + // + // this is quicker because we are using preGenerated parameters. + // + AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair(); + + Stream out1, out2; + if (args[0].Equals("-a")) + { + if (args.Length < 3) + { + Console.WriteLine("DSAElGamalKeyRingGenerator [-a] identity passPhrase"); + return 0; + } + + out1 = File.Create("secret.asc"); + out2 = File.Create("pub.asc"); + + ExportKeyPair(out1, out2, dsaKp, elgKp, args[1], args[2].ToCharArray(), true); + } + else + { + out1 = File.Create("secret.bpg"); + out2 = File.Create("pub.bpg"); + + ExportKeyPair(out1, out2, dsaKp, elgKp, args[0], args[1].ToCharArray(), false); + } + out1.Close(); + out2.Close(); + return 0; + } + } +} diff --git a/crypto/test/src/openpgp/examples/KeyBasedFileProcessor.cs b/crypto/test/src/openpgp/examples/KeyBasedFileProcessor.cs new file mode 100644 index 000000000..c77408b1f --- /dev/null +++ b/crypto/test/src/openpgp/examples/KeyBasedFileProcessor.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that encrypts/decrypts public key based + * encryption files. + *

    + * To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.
    + * If -a is specified the output file will be "ascii-armored". + * If -i is specified the output file will be have integrity checking added.

    + *

    + * To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.

    + *

    + * Note 1: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used.

    + *

    + * Note 2: if an empty file name has been specified in the literal data object contained in the + * encrypted packet a file with the name filename.out will be generated in the current working directory.

    + */ + public sealed class KeyBasedFileProcessor + { + private KeyBasedFileProcessor() + { + } + + private static void DecryptFile( + string inputFileName, + string keyFileName, + char[] passwd, + string defaultFileName) + { + using (Stream input = File.OpenRead(inputFileName), + keyIn = File.OpenRead(keyFileName)) + { + DecryptFile(input, keyIn, passwd, defaultFileName); + } + } + + /** + * decrypt the passed in message stream + */ + private static void DecryptFile( + Stream inputStream, + Stream keyIn, + char[] passwd, + string defaultFileName) + { + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + try + { + PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); + PgpEncryptedDataList enc; + + PgpObject o = pgpF.NextPgpObject(); + // + // the first object might be a PGP marker packet. + // + if (o is PgpEncryptedDataList) + { + enc = (PgpEncryptedDataList)o; + } + else + { + enc = (PgpEncryptedDataList)pgpF.NextPgpObject(); + } + + // + // find the secret key + // + PgpPrivateKey sKey = null; + PgpPublicKeyEncryptedData pbe = null; + PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle( + PgpUtilities.GetDecoderStream(keyIn)); + + foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects()) + { + sKey = PgpExampleUtilities.FindSecretKey(pgpSec, pked.KeyId, passwd); + + if (sKey != null) + { + pbe = pked; + break; + } + } + + if (sKey == null) + { + throw new ArgumentException("secret key for message not found."); + } + + Stream clear = pbe.GetDataStream(sKey); + + PgpObjectFactory plainFact = new PgpObjectFactory(clear); + + PgpObject message = plainFact.NextPgpObject(); + + if (message is PgpCompressedData) + { + PgpCompressedData cData = (PgpCompressedData)message; + PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream()); + + message = pgpFact.NextPgpObject(); + } + + if (message is PgpLiteralData) + { + PgpLiteralData ld = (PgpLiteralData)message; + + string outFileName = ld.FileName; + if (outFileName.Length == 0) + { + outFileName = defaultFileName; + } + + Stream fOut = File.Create(outFileName); + Stream unc = ld.GetInputStream(); + Streams.PipeAll(unc, fOut); + fOut.Close(); + } + else if (message is PgpOnePassSignatureList) + { + throw new PgpException("encrypted message contains a signed message - not literal data."); + } + else + { + throw new PgpException("message is not a simple encrypted file - type unknown."); + } + + if (pbe.IsIntegrityProtected()) + { + if (!pbe.Verify()) + { + Console.Error.WriteLine("message failed integrity check"); + } + else + { + Console.Error.WriteLine("message integrity check passed"); + } + } + else + { + Console.Error.WriteLine("no message integrity check"); + } + } + catch (PgpException e) + { + Console.Error.WriteLine(e); + + Exception underlyingException = e.InnerException; + if (underlyingException != null) + { + Console.Error.WriteLine(underlyingException.Message); + Console.Error.WriteLine(underlyingException.StackTrace); + } + } + } + + private static void EncryptFile( + string outputFileName, + string inputFileName, + string encKeyFileName, + bool armor, + bool withIntegrityCheck) + { + PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName); + + using (Stream output = File.Create(outputFileName)) + { + EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck); + } + } + + private static void EncryptFile( + Stream outputStream, + string fileName, + PgpPublicKey encKey, + bool armor, + bool withIntegrityCheck) + { + if (armor) + { + outputStream = new ArmoredOutputStream(outputStream); + } + + try + { + byte[] bytes = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip); + + PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); + encGen.AddMethod(encKey); + + Stream cOut = encGen.Open(outputStream, bytes.Length); + + cOut.Write(bytes, 0, bytes.Length); + cOut.Close(); + + if (armor) + { + outputStream.Close(); + } + } + catch (PgpException e) + { + Console.Error.WriteLine(e); + + Exception underlyingException = e.InnerException; + if (underlyingException != null) + { + Console.Error.WriteLine(underlyingException.Message); + Console.Error.WriteLine(underlyingException.StackTrace); + } + } + } + + public static void Main( + string[] args) + { + if (args.Length == 0) + { + Console.Error.WriteLine("usage: KeyBasedFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + return; + } + + if (args[0].Equals("-e")) + { + if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia")) + { + EncryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].IndexOf('i') > 0)); + } + else if (args[1].Equals("-i")) + { + EncryptFile(args[2] + ".bpg", args[2], args[3], false, true); + } + else + { + EncryptFile(args[1] + ".bpg", args[1], args[2], false, false); + } + } + else if (args[0].Equals("-d")) + { + DecryptFile(args[1], args[2], args[3].ToCharArray(), new FileInfo(args[1]).Name + ".out"); + } + else + { + Console.Error.WriteLine("usage: KeyBasedFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs b/crypto/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs new file mode 100644 index 000000000..7fb00a3b7 --- /dev/null +++ b/crypto/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that encrypts/decrypts public key based + * encryption large files. + *

    + * To encrypt a file: KeyBasedLargeFileProcessor -e [-a|-ai] fileName publicKeyFile.
    + * If -a is specified the output file will be "ascii-armored". + * If -i is specified the output file will be have integrity checking added.

    + *

    + * To decrypt: KeyBasedLargeFileProcessor -d fileName secretKeyFile passPhrase.

    + *

    + * Note 1: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used.

    + *

    + * Note 2: this example Generates partial packets to encode the file, the output it Generates + * will not be readable by older PGP products or products that don't support partial packet + * encoding.

    + *

    + * Note 3: if an empty file name has been specified in the literal data object contained in the + * encrypted packet a file with the name filename.out will be generated in the current working directory.

    + */ + public sealed class KeyBasedLargeFileProcessor + { + private KeyBasedLargeFileProcessor() + { + } + + private static void DecryptFile( + string inputFileName, + string keyFileName, + char[] passwd, + string defaultFileName) + { + using (Stream input = File.OpenRead(inputFileName), + keyIn = File.OpenRead(keyFileName)) + { + DecryptFile(input, keyIn, passwd, defaultFileName); + } + } + + /** + * decrypt the passed in message stream + */ + private static void DecryptFile( + Stream inputStream, + Stream keyIn, + char[] passwd, + string defaultFileName) + { + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + try + { + PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); + PgpEncryptedDataList enc; + + PgpObject o = pgpF.NextPgpObject(); + // + // the first object might be a PGP marker packet. + // + if (o is PgpEncryptedDataList) + { + enc = (PgpEncryptedDataList)o; + } + else + { + enc = (PgpEncryptedDataList)pgpF.NextPgpObject(); + } + + // + // find the secret key + // + PgpPrivateKey sKey = null; + PgpPublicKeyEncryptedData pbe = null; + PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle( + PgpUtilities.GetDecoderStream(keyIn)); + + foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects()) + { + sKey = PgpExampleUtilities.FindSecretKey(pgpSec, pked.KeyId, passwd); + + if (sKey != null) + { + pbe = pked; + break; + } + } + + if (sKey == null) + { + throw new ArgumentException("secret key for message not found."); + } + + Stream clear = pbe.GetDataStream(sKey); + + PgpObjectFactory plainFact = new PgpObjectFactory(clear); + + PgpCompressedData cData = (PgpCompressedData) plainFact.NextPgpObject(); + + PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream()); + + PgpObject message = pgpFact.NextPgpObject(); + + if (message is PgpLiteralData) + { + PgpLiteralData ld = (PgpLiteralData)message; + + string outFileName = ld.FileName; + if (outFileName.Length == 0) + { + outFileName = defaultFileName; + } + + Stream fOut = File.Create(outFileName); + Stream unc = ld.GetInputStream(); + Streams.PipeAll(unc, fOut); + fOut.Close(); + } + else if (message is PgpOnePassSignatureList) + { + throw new PgpException("encrypted message contains a signed message - not literal data."); + } + else + { + throw new PgpException("message is not a simple encrypted file - type unknown."); + } + + if (pbe.IsIntegrityProtected()) + { + if (!pbe.Verify()) + { + Console.Error.WriteLine("message failed integrity check"); + } + else + { + Console.Error.WriteLine("message integrity check passed"); + } + } + else + { + Console.Error.WriteLine("no message integrity check"); + } + } + catch (PgpException e) + { + Console.Error.WriteLine(e); + + Exception underlyingException = e.InnerException; + if (underlyingException != null) + { + Console.Error.WriteLine(underlyingException.Message); + Console.Error.WriteLine(underlyingException.StackTrace); + } + } + } + + private static void EncryptFile( + string outputFileName, + string inputFileName, + string encKeyFileName, + bool armor, + bool withIntegrityCheck) + { + PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName); + + using (Stream output = File.Create(outputFileName)) + { + EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck); + } + } + + private static void EncryptFile( + Stream outputStream, + string fileName, + PgpPublicKey encKey, + bool armor, + bool withIntegrityCheck) + { + if (armor) + { + outputStream = new ArmoredOutputStream(outputStream); + } + + try + { + PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); + + cPk.AddMethod(encKey); + + Stream cOut = cPk.Open(outputStream, new byte[1 << 16]); + + PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + PgpUtilities.WriteFileToLiteralData( + comData.Open(cOut), + PgpLiteralData.Binary, + new FileInfo(fileName), + new byte[1 << 16]); + + comData.Close(); + + cOut.Close(); + + if (armor) + { + outputStream.Close(); + } + } + catch (PgpException e) + { + Console.Error.WriteLine(e); + + Exception underlyingException = e.InnerException; + if (underlyingException != null) + { + Console.Error.WriteLine(underlyingException.Message); + Console.Error.WriteLine(underlyingException.StackTrace); + } + } + } + + public static void Main( + string[] args) + { + if (args.Length == 0) + { + Console.Error.WriteLine("usage: KeyBasedLargeFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + return; + } + + if (args[0].Equals("-e")) + { + if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia")) + { + EncryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].IndexOf('i') > 0)); + } + else if (args[1].Equals("-i")) + { + EncryptFile(args[2] + ".bpg", args[2], args[3], false, true); + } + else + { + EncryptFile(args[1] + ".bpg", args[1], args[2], false, false); + } + } + else if (args[0].Equals("-d")) + { + DecryptFile(args[1], args[2], args[3].ToCharArray(), new FileInfo(args[1]).Name + ".out"); + } + else + { + Console.Error.WriteLine("usage: KeyBasedLargeFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/PbeFileProcessor.cs b/crypto/test/src/openpgp/examples/PbeFileProcessor.cs new file mode 100644 index 000000000..66b1cc4ed --- /dev/null +++ b/crypto/test/src/openpgp/examples/PbeFileProcessor.cs @@ -0,0 +1,183 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that encrypts/decrypts password based + * encryption files. + *

    + * To encrypt a file: PBEFileProcessor -e [-ai] fileName passPhrase.
    + * If -a is specified the output file will be "ascii-armored".
    + * If -i is specified the output file will be "integrity protected".

    + *

    + * To decrypt: PBEFileProcessor -d fileName passPhrase.

    + *

    + * Note: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used.

    + */ + public sealed class PbeFileProcessor + { + private PbeFileProcessor() {} + + private static void DecryptFile(string inputFileName, char[] passPhrase) + { + using (Stream input = File.OpenRead(inputFileName)) + { + DecryptFile(input, passPhrase); + } + } + + /** + * decrypt the passed in message stream + */ + private static void DecryptFile( + Stream inputStream, + char[] passPhrase) + { + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); + PgpObject o = pgpF.NextPgpObject(); + + // + // the first object might be a PGP marker packet. + // + PgpEncryptedDataList enc = o as PgpEncryptedDataList; + if (enc == null) + { + enc = (PgpEncryptedDataList)pgpF.NextPgpObject(); + } + + PgpPbeEncryptedData pbe = (PgpPbeEncryptedData)enc[0]; + + Stream clear = pbe.GetDataStream(passPhrase); + + PgpObjectFactory pgpFact = new PgpObjectFactory(clear); + + // + // if we're trying to read a file generated by someone other than us + // the data might not be compressed, so we check the return type from + // the factory and behave accordingly. + // + o = pgpFact.NextPgpObject(); + if (o is PgpCompressedData) + { + PgpCompressedData cData = (PgpCompressedData) o; + pgpFact = new PgpObjectFactory(cData.GetDataStream()); + o = pgpFact.NextPgpObject(); + } + + PgpLiteralData ld = (PgpLiteralData) o; + Stream unc = ld.GetInputStream(); + Stream fOut = File.Create(ld.FileName); + Streams.PipeAll(unc, fOut); + fOut.Close(); + + if (pbe.IsIntegrityProtected()) + { + if (!pbe.Verify()) + { + Console.Error.WriteLine("message failed integrity check"); + } + else + { + Console.Error.WriteLine("message integrity check passed"); + } + } + else + { + Console.Error.WriteLine("no message integrity check"); + } + } + + private static void EncryptFile( + string outputFileName, + string inputFileName, + char[] passPhrase, + bool armor, + bool withIntegrityCheck) + { + using (Stream output = File.Create(outputFileName)) + { + EncryptFile(output, inputFileName, passPhrase, armor, withIntegrityCheck); + } + } + + private static void EncryptFile( + Stream outputStream, + string fileName, + char[] passPhrase, + bool armor, + bool withIntegrityCheck) + { + if (armor) + { + outputStream = new ArmoredOutputStream(outputStream); + } + + try + { + byte[] compressedData = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip); + + PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); + encGen.AddMethod(passPhrase); + + Stream encOut = encGen.Open(outputStream, compressedData.Length); + + encOut.Write(compressedData, 0, compressedData.Length); + encOut.Close(); + + if (armor) + { + outputStream.Close(); + } + } + catch (PgpException e) + { + Console.Error.WriteLine(e); + + Exception underlyingException = e.InnerException; + if (underlyingException != null) + { + Console.Error.WriteLine(underlyingException.Message); + Console.Error.WriteLine(underlyingException.StackTrace); + } + } + } + + public static void Main( + string[] args) + { + if (args[0].Equals("-e")) + { + if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia")) + { + EncryptFile(args[2] + ".asc", args[2], args[3].ToCharArray(), true, (args[1].IndexOf('i') > 0)); + } + else if (args[1].Equals("-i")) + { + EncryptFile(args[2] + ".bpg", args[2], args[3].ToCharArray(), false, true); + } + else + { + EncryptFile(args[1] + ".bpg", args[1], args[2].ToCharArray(), false, false); + } + } + else if (args[0].Equals("-d")) + { + DecryptFile(args[1], args[2].ToCharArray()); + } + else + { + Console.Error.WriteLine("usage: PbeFileProcessor -e [-ai]|-d file passPhrase"); + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/PgpExampleUtilities.cs b/crypto/test/src/openpgp/examples/PgpExampleUtilities.cs new file mode 100644 index 000000000..fd371d7af --- /dev/null +++ b/crypto/test/src/openpgp/examples/PgpExampleUtilities.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + internal class PgpExampleUtilities + { + internal static byte[] CompressFile(string fileName, CompressionAlgorithmTag algorithm) + { + MemoryStream bOut = new MemoryStream(); + PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm); + PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary, + new FileInfo(fileName)); + comData.Close(); + return bOut.ToArray(); + } + + /** + * Search a secret key ring collection for a secret key corresponding to keyID if it + * exists. + * + * @param pgpSec a secret key ring collection. + * @param keyID keyID we want. + * @param pass passphrase to decrypt secret key with. + * @return + * @throws PGPException + * @throws NoSuchProviderException + */ + internal static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyID, char[] pass) + { + PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyID); + + if (pgpSecKey == null) + { + return null; + } + + return pgpSecKey.ExtractPrivateKey(pass); + } + + internal static PgpPublicKey ReadPublicKey(string fileName) + { + using (Stream keyIn = File.OpenRead(fileName)) + { + return ReadPublicKey(keyIn); + } + } + + /** + * A simple routine that opens a key ring file and loads the first available key + * suitable for encryption. + * + * @param input + * @return + * @throws IOException + * @throws PGPException + */ + internal static PgpPublicKey ReadPublicKey(Stream input) + { + PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle( + PgpUtilities.GetDecoderStream(input)); + + // + // we just loop through the collection till we find a key suitable for encryption, in the real + // world you would probably want to be a bit smarter about this. + // + + foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings()) + { + foreach (PgpPublicKey key in keyRing.GetPublicKeys()) + { + if (key.IsEncryptionKey) + { + return key; + } + } + } + + throw new ArgumentException("Can't find encryption key in key ring."); + } + + internal static PgpSecretKey ReadSecretKey(string fileName) + { + using (Stream keyIn = File.OpenRead(fileName)) + { + return ReadSecretKey(keyIn); + } + } + + /** + * A simple routine that opens a key ring file and loads the first available key + * suitable for signature generation. + * + * @param input stream to read the secret key ring collection from. + * @return a secret key. + * @throws IOException on a problem with using the input stream. + * @throws PGPException if there is an issue parsing the input stream. + */ + internal static PgpSecretKey ReadSecretKey(Stream input) + { + PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle( + PgpUtilities.GetDecoderStream(input)); + + // + // we just loop through the collection till we find a key suitable for encryption, in the real + // world you would probably want to be a bit smarter about this. + // + + foreach (PgpSecretKeyRing keyRing in pgpSec.GetKeyRings()) + { + foreach (PgpSecretKey key in keyRing.GetSecretKeys()) + { + if (key.IsSigningKey) + { + return key; + } + } + } + + throw new ArgumentException("Can't find signing key in key ring."); + } + } +} diff --git a/crypto/test/src/openpgp/examples/PublicKeyRingDump.cs b/crypto/test/src/openpgp/examples/PublicKeyRingDump.cs new file mode 100644 index 000000000..bb6108f2d --- /dev/null +++ b/crypto/test/src/openpgp/examples/PublicKeyRingDump.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; + +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * Basic class which just lists the contents of the public key file passed + * as an argument. If the file contains more than one "key ring" they are + * listed in the order found. + */ + public sealed class PublicKeyRingDump + { + private PublicKeyRingDump() + { + } + + public static string GetAlgorithm( + PublicKeyAlgorithmTag algId) + { + switch (algId) + { + case PublicKeyAlgorithmTag.RsaGeneral: + return "RsaGeneral"; + case PublicKeyAlgorithmTag.RsaEncrypt: + return "RsaEncrypt"; + case PublicKeyAlgorithmTag.RsaSign: + return "RsaSign"; + case PublicKeyAlgorithmTag.ElGamalEncrypt: + return "ElGamalEncrypt"; + case PublicKeyAlgorithmTag.Dsa: + return "DSA"; + case PublicKeyAlgorithmTag.EC: + return "EC"; + case PublicKeyAlgorithmTag.ECDsa: + return "ECDSA"; + case PublicKeyAlgorithmTag.ElGamalGeneral: + return "ElGamalGeneral"; + case PublicKeyAlgorithmTag.DiffieHellman: + return "DiffieHellman"; + } + + return "unknown"; + } + + public static void Main( + string[] args) + { + Stream fs = File.OpenRead(args[0]); + + // + // Read the public key rings + // + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle( + PgpUtilities.GetDecoderStream(fs)); + + fs.Close(); + + foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings()) + { + try + { + //PgpPublicKey pubKey = + pgpPub.GetPublicKey(); + } + catch (Exception e) + { + Console.Error.WriteLine(e.Message); + Console.Error.WriteLine(e.StackTrace); + continue; + } + + bool first = true; + + foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys()) + { + if (first) + { + Console.WriteLine("Key ID: " + pgpKey.KeyId.ToString("X")); + first = false; + } + else + { + Console.WriteLine("Key ID: " + pgpKey.KeyId.ToString("X") + " (subkey)"); + } + + Console.WriteLine(" Algorithm: " + GetAlgorithm(pgpKey.Algorithm)); + Console.WriteLine(" Fingerprint: " + Hex.ToHexString(pgpKey.GetFingerprint())); + } + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/RsaKeyRingGenerator.cs b/crypto/test/src/openpgp/examples/RsaKeyRingGenerator.cs new file mode 100644 index 000000000..284118b99 --- /dev/null +++ b/crypto/test/src/openpgp/examples/RsaKeyRingGenerator.cs @@ -0,0 +1,115 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Bcpg.OpenPgp; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that Generates a RSA PgpPublicKey/PgpSecretKey pair. + *

    + * usage: RsaKeyRingGenerator [-a] identity passPhrase

    + *

    + * Where identity is the name to be associated with the public key. The keys are placed + * in the files pub.[asc|bpg] and secret.[asc|bpg].

    + */ + public sealed class RsaKeyRingGenerator + { + private RsaKeyRingGenerator() + { + } + + private static void ExportKeyPair( + Stream secretOut, + Stream publicOut, + AsymmetricKeyParameter publicKey, + AsymmetricKeyParameter privateKey, + string identity, + char[] passPhrase, + bool armor) + { + if (armor) + { + secretOut = new ArmoredOutputStream(secretOut); + } + + PgpSecretKey secretKey = new PgpSecretKey( + PgpSignature.DefaultCertification, + PublicKeyAlgorithmTag.RsaGeneral, + publicKey, + privateKey, + DateTime.UtcNow, + identity, + SymmetricKeyAlgorithmTag.Cast5, + passPhrase, + null, + null, + new SecureRandom() + ); + + secretKey.Encode(secretOut); + + if (armor) + { + secretOut.Close(); + publicOut = new ArmoredOutputStream(publicOut); + } + + PgpPublicKey key = secretKey.PublicKey; + + key.Encode(publicOut); + + if (armor) + { + publicOut.Close(); + } + } + + public static int Main( + string[] args) + { + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + + kpg.Init(new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 1024, 25)); + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + + if (args.Length < 2) + { + Console.WriteLine("RsaKeyPairGenerator [-a] identity passPhrase"); + return 0; + } + + Stream out1, out2; + if (args[0].Equals("-a")) + { + if (args.Length < 3) + { + Console.WriteLine("RsaKeyPairGenerator [-a] identity passPhrase"); + return 0; + } + + out1 = File.Create("secret.asc"); + out2 = File.Create("pub.asc"); + + ExportKeyPair(out1, out2, kp.Public, kp.Private, args[1], args[2].ToCharArray(), true); + } + else + { + out1 = File.Create("secret.bpg"); + out2 = File.Create("pub.bpg"); + + ExportKeyPair(out1, out2, kp.Public, kp.Private, args[0], args[1].ToCharArray(), false); + } + out1.Close(); + out2.Close(); + return 0; + } + } +} diff --git a/crypto/test/src/openpgp/examples/SignedFileProcessor.cs b/crypto/test/src/openpgp/examples/SignedFileProcessor.cs new file mode 100644 index 000000000..1ad0d102b --- /dev/null +++ b/crypto/test/src/openpgp/examples/SignedFileProcessor.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections; +using System.IO; + + +using Org.BouncyCastle.Bcpg.OpenPgp; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples +{ + /** + * A simple utility class that signs and verifies files. + *

    + * To sign a file: SignedFileProcessor -s [-a] fileName secretKey passPhrase.
    + * If -a is specified the output file will be "ascii-armored".

    + *

    + * To decrypt: SignedFileProcessor -v fileName publicKeyFile.

    + *

    + * Note: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used.

    + *

    + * Note: the example also makes use of PGP compression. If you are having difficulty Getting it + * to interoperate with other PGP programs try removing the use of compression first.

    + */ + public sealed class SignedFileProcessor + { + private SignedFileProcessor() {} + + /** + * verify the passed in file as being correctly signed. + */ + private static void VerifyFile( + Stream inputStream, + Stream keyIn) + { + inputStream = PgpUtilities.GetDecoderStream(inputStream); + + PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream); + PgpCompressedData c1 = (PgpCompressedData) pgpFact.NextPgpObject(); + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList) pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData) pgpFact.NextPgpObject(); + Stream dIn = p2.GetInputStream(); + PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn)); + PgpPublicKey key = pgpRing.GetPublicKey(ops.KeyId); + Stream fos = File.Create(p2.FileName); + + ops.InitVerify(key); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + fos.WriteByte((byte) ch); + } + fos.Close(); + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + PgpSignature firstSig = p3[0]; + if (ops.Verify(firstSig)) + { + Console.Out.WriteLine("signature verified."); + } + else + { + Console.Out.WriteLine("signature verification failed."); + } + } + + /** + * Generate an encapsulated signed file. + * + * @param fileName + * @param keyIn + * @param outputStream + * @param pass + * @param armor + */ + private static void SignFile( + string fileName, + Stream keyIn, + Stream outputStream, + char[] pass, + bool armor, + bool compress) + { + if (armor) + { + outputStream = new ArmoredOutputStream(outputStream); + } + + PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn); + PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + foreach (string userId in pgpSec.PublicKey.GetUserIds()) + { + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); + spGen.SetSignerUserId(false, userId); + sGen.SetHashedSubpackets(spGen.Generate()); + // Just the first one! + break; + } + + Stream cOut = outputStream; + PgpCompressedDataGenerator cGen = null; + if (compress) + { + cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib); + + cOut = cGen.Open(cOut); + } + + BcpgOutputStream bOut = new BcpgOutputStream(cOut); + + sGen.GenerateOnePassVersion(false).Encode(bOut); + + FileInfo file = new FileInfo(fileName); + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open(bOut, PgpLiteralData.Binary, file); + FileStream fIn = file.OpenRead(); + int ch = 0; + + while ((ch = fIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte) ch); + sGen.Update((byte)ch); + } + + fIn.Close(); + lGen.Close(); + + sGen.Generate().Encode(bOut); + + if (cGen != null) + { + cGen.Close(); + } + + if (armor) + { + outputStream.Close(); + } + } + + public static void Main( + string[] args) + { + // TODO provide command-line option to determine whether to use compression in SignFile + if (args[0].Equals("-s")) + { + Stream keyIn, fos; + if (args[1].Equals("-a")) + { + keyIn = File.OpenRead(args[3]); + fos = File.Create(args[2] + ".asc"); + + SignFile(args[2], keyIn, fos, args[4].ToCharArray(), true, true); + } + else + { + keyIn = File.OpenRead(args[2]); + fos = File.Create(args[1] + ".bpg"); + + SignFile(args[1], keyIn, fos, args[3].ToCharArray(), false, true); + } + keyIn.Close(); + fos.Close(); + } + else if (args[0].Equals("-v")) + { + using (Stream fis = File.OpenRead(args[1]), + keyIn = File.OpenRead(args[2])) + { + VerifyFile(fis, keyIn); + } + } + else + { + Console.Error.WriteLine("usage: SignedFileProcessor -v|-s [-a] file keyfile [passPhrase]"); + } + } + } +} diff --git a/crypto/test/src/openpgp/examples/test/AllTests.cs b/crypto/test/src/openpgp/examples/test/AllTests.cs new file mode 100644 index 000000000..180d2fa80 --- /dev/null +++ b/crypto/test/src/openpgp/examples/test/AllTests.cs @@ -0,0 +1,403 @@ +using System; +using System.IO; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests +{ + [TestFixture] + public class AllTests + { + private static readonly byte[] clearSignedPublicKey = Base64.Decode( + "mQELBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+" + + "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1" + + "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO" + + "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7" + + "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4" + + "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp" + + "tBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2BBMBAgAgBQJEIdvsAhsDBgsJCAcD" + + "AgQVAggDBBYCAwECHgECF4AACgkQ4M/Ier3f9xagdAf/fbKWBjLQM8xR7JkR" + + "P4ri8YKOQPhK+VrddGUD59/wzVnvaGyl9MZE7TXFUeniQq5iXKnm22EQbYch" + + "v2Jcxyt2H9yptpzyh4tP6tEHl1C887p2J4qe7F2ATua9CzVGwXQSUbKtj2fg" + + "UZP5SsNp25guhPiZdtkf2sHMeiotmykFErzqGMrvOAUThrO63GiYsRk4hF6r" + + "cQ01d+EUVpY/sBcCxgNyOiB7a84sDtrxnX5BTEZDTEj8LvuEyEV3TMUuAjx1" + + "7Eyd+9JtKzwV4v3hlTaWOvGro9nPS7YaPuG+RtufzXCUJPbPfTjTvtGOqvEz" + + "oztls8tuWA0OGHba9XfX9rfgorACAAM="); + + private static readonly string crOnlyMessage = + "\r" + + " hello world!\r" + + "\r" + + "- dash\r"; + + private static readonly string nlOnlyMessage = + "\n" + + " hello world!\n" + + "\n" + + "- dash\n"; + + private static readonly string crNlMessage = + "\r\n" + + " hello world!\r\n" + + "\r\n" + + "- dash\r\n"; + + private static readonly string crNlMessageTrailingWhiteSpace = + "\r\n" + + " hello world! \t\r\n" + + "\r\n" + + "\r\n"; + + private static readonly string crOnlySignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\r" + + "Hash: SHA256\r" + + "\r" + + "\r" + + " hello world!\r" + + "\r" + + "- - dash\r" + + "-----BEGIN PGP SIGNATURE-----\r" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r" + + "\r" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r"; + + private static readonly string nlOnlySignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\n" + + "Hash: SHA256\n" + + "\n" + + "\n" + + " hello world!\n" + + "\n" + + "- - dash\n" + + "-----BEGIN PGP SIGNATURE-----\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\n" + + "\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\n" + + "=84Nd\n" + + "-----END PGP SIGNATURE-----\n"; + + private static readonly string crNlSignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\r\n" + + "Hash: SHA256\r\n" + + "\r\n" + + "\r\n" + + " hello world!\r\n" + + "\r\n" + + "- - dash\r\n" + + "-----BEGIN PGP SIGNATURE-----\r\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n" + + "\r\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r\n"; + + private static readonly string crNlSignedMessageTrailingWhiteSpace = + "-----BEGIN PGP SIGNED MESSAGE-----\r\n" + + "Hash: SHA256\r\n" + + "\r\n" + + "\r\n" + + " hello world! \t\r\n" + + "\r\n" + + "- - dash\r\n" + + "-----BEGIN PGP SIGNATURE-----\r\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n" + + "\r\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r\n"; + + private TextWriter _oldOut; + private TextWriter _oldErr; + + private MemoryStream _currentOut; + private MemoryStream _currentErr; + + [SetUp] + public void SetUp() + { + _oldOut = Console.Out; + _oldErr = Console.Error; + _currentOut = new MemoryStream(); + _currentErr = new MemoryStream(); + + Console.SetOut(new StreamWriter(_currentOut)); + Console.SetError(new StreamWriter(_currentErr)); + } + + [TearDown] + public void TearDown() + { + Console.SetOut(_oldOut); + Console.SetError(_oldErr); + } + + [Test] + public void TestRsaKeyGeneration() + { + RsaKeyRingGenerator.Main(new string[] { "test", "password" }); + + CreateSmallTestInput(); + CreateLargeTestInput(); + + CheckSigning("bpg"); + CheckKeyBasedEncryption("bpg"); + CheckLargeKeyBasedEncryption("bpg"); + + RsaKeyRingGenerator.Main(new string[] { "-a", "test", "password" }); + + CheckSigning("asc"); + CheckKeyBasedEncryption("asc"); + CheckLargeKeyBasedEncryption("asc"); + } + + [Test] + public void TestDsaElGamalKeyGeneration() + { + DsaElGamalKeyRingGenerator.Main(new string[] { "test", "password" }); + + CreateSmallTestInput(); + CreateLargeTestInput(); + + CheckSigning("bpg"); + CheckKeyBasedEncryption("bpg"); + CheckLargeKeyBasedEncryption("bpg"); + + DsaElGamalKeyRingGenerator.Main(new string[] { "-a", "test", "password" }); + + CheckSigning("asc"); + CheckKeyBasedEncryption("asc"); + CheckLargeKeyBasedEncryption("asc"); + } + + [Test] + public void TestPbeEncryption() + { + Console.Error.Flush(); + _currentErr.SetLength(0); + + PbeFileProcessor.Main(new string[] { "-e", "test.txt", "password" }); + + PbeFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "password" }); + + Console.Error.Flush(); + Assert.AreEqual("no message integrity check", GetLine(_currentErr)); + + PbeFileProcessor.Main(new string[] { "-e", "-i", "test.txt", "password" }); + + PbeFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + + PbeFileProcessor.Main(new string[] { "-e", "-ai", "test.txt", "password" }); + + PbeFileProcessor.Main(new string[] { "-d", "test.txt.asc", "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + } + + [Test] + public void TestClearSigned() + { + CreateTestFile(clearSignedPublicKey, "pub.bpg"); + + CheckClearSignedVerify(nlOnlySignedMessage); + CheckClearSignedVerify(crOnlySignedMessage); + CheckClearSignedVerify(crNlSignedMessage); + CheckClearSignedVerify(crNlSignedMessageTrailingWhiteSpace); + + ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" }); + + RsaKeyRingGenerator.Main(new string[] { "test", "password" }); + + CheckClearSigned(crOnlyMessage); + CheckClearSigned(nlOnlyMessage); + CheckClearSigned(crNlMessage); + CheckClearSigned(crNlMessageTrailingWhiteSpace); + } + + [Test] + public void TestClearSignedBogusInput() + { + CreateTestFile(clearSignedPublicKey, "test.txt"); + + ClearSignedFileProcessor.Main(new String[] { "-s", "test.txt", "secret.bpg", "password" }); + } + + private void CheckClearSignedVerify( + string message) + { + CreateTestData(message, "test.txt.asc"); + + ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" }); + } + + private void CheckClearSigned( + string message) + { + CreateTestData(message, "test.txt"); + + ClearSignedFileProcessor.Main(new string[] { "-s", "test.txt", "secret.bpg", "password" }); + ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" }); + } + + private void CheckSigning( + string type) + { + Console.Out.Flush(); + _currentOut.SetLength(0); + + SignedFileProcessor.Main(new string[] { "-s", "test.txt", "secret." + type, "password" }); + SignedFileProcessor.Main(new string[] { "-v", "test.txt.bpg", "pub." + type }); + + Console.Out.Flush(); + Assert.AreEqual("signature verified.", GetLine(_currentOut)); + + SignedFileProcessor.Main(new string[] { "-s", "-a", "test.txt", "secret." + type, "password" }); + SignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub." + type }); + + Console.Out.Flush(); + Assert.AreEqual("signature verified.", GetLine(_currentOut)); + } + + private void CheckKeyBasedEncryption( + string type) + { + Console.Error.Flush(); + _currentErr.SetLength(0); + + KeyBasedFileProcessor.Main(new string[] { "-e", "test.txt", "pub." + type }); + KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("no message integrity check", GetLine(_currentErr)); + + KeyBasedFileProcessor.Main(new string[] { "-e", "-i", "test.txt", "pub." + type }); + KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + + KeyBasedFileProcessor.Main(new string[] { "-e", "-ai", "test.txt", "pub." + type }); + KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.asc", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + } + + private void CheckLargeKeyBasedEncryption( + string type) + { + Console.Error.Flush(); + _currentErr.SetLength(0); + + KeyBasedLargeFileProcessor.Main(new string[] { "-e", "large.txt", "pub." + type }); + KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.bpg", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("no message integrity check", GetLine(_currentErr)); + + KeyBasedLargeFileProcessor.Main(new string[] { "-e", "-i", "large.txt", "pub." + type }); + KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.bpg", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + + KeyBasedLargeFileProcessor.Main(new string[] { "-e", "-ai", "large.txt", "pub." + type }); + KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.asc", "secret." + type, "password" }); + + Console.Error.Flush(); + Assert.AreEqual("message integrity check passed", GetLine(_currentErr)); + } + + private void CreateSmallTestInput() + { + TextWriter bfOut = new StreamWriter(File.Create("test.txt")); + bfOut.WriteLine("hello world!"); + bfOut.Close(); + } + + private void CreateLargeTestInput() + { + TextWriter bfOut = new StreamWriter(File.Create("large.txt")); + + for (int i = 1; i <= 2000; i++) + { + bfOut.WriteLine("hello to planet " + i + "!"); + } + + bfOut.Close(); + } + + private void CreateTestData( + string testData, + string name) + { + TextWriter bfOut = new StreamWriter(File.Create(name)); + bfOut.Write(testData); + bfOut.Close(); + } + + private void CreateTestFile( + byte[] keyData, + string name) + { + FileStream fOut = File.Create(name); + fOut.Write(keyData, 0, keyData.Length); + fOut.Close(); + } + + private string GetLine( + MemoryStream outStr) + { + byte[] b = outStr.ToArray(); + TextReader bRd = new StreamReader(new MemoryStream(b, false)); + outStr.SetLength(0); + return bRd.ReadLine(); + } + + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("OpenPGP Example Tests"); + + suite.Add(new AllTests()); + + return suite; + } + + } +} diff --git a/crypto/test/src/openpgp/test/DSA2Test.cs b/crypto/test/src/openpgp/test/DSA2Test.cs new file mode 100644 index 000000000..883ae317f --- /dev/null +++ b/crypto/test/src/openpgp/test/DSA2Test.cs @@ -0,0 +1,237 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + /** + * GPG compatability test vectors + */ + [TestFixture] + public class Dsa2Test + //extends TestCase + { + [Test] + public void TestK1024H160() + { + doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-160-sign.gpg"); + } + + [Test] + public void TestK1024H224() + { + doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-224-sign.gpg"); + } + + [Test] + public void TestK1024H256() + { + doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-256-sign.gpg"); + } + + [Test] + public void TestK1024H384() + { + doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-384-sign.gpg"); + } + + [Test] + public void TestK1024H512() + { + doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-512-sign.gpg"); + } + + [Test] + public void TestK2048H224() + { + doSigVerifyTest("DSA-2048-224.pub", "dsa-2048-224-sign.gpg"); + } + + [Test] + public void TestK3072H256() + { + doSigVerifyTest("DSA-3072-256.pub", "dsa-3072-256-sign.gpg"); + } + + [Test] + public void TestK7680H384() + { + doSigVerifyTest("DSA-7680-384.pub", "dsa-7680-384-sign.gpg"); + } + + [Test] + public void TestK15360H512() + { + doSigVerifyTest("DSA-15360-512.pub", "dsa-15360-512-sign.gpg"); + } + + [Test] + public void TestGenerateK1024H224() + { + doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha224); + } + + [Test] + public void TestGenerateK1024H256() + { + doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha256); + } + + [Test] + public void TestGenerateK1024H384() + { + doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha384); + } + + [Test] + public void TestGenerateK1024H512() + { + doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha512); + } + + [Test] + public void TestGenerateK2048H256() + { + doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha256); + } + + [Test] + public void TestGenerateK2048H512() + { + doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha512); + } + + private void doSigGenerateTest( + string privateKeyFile, + string publicKeyFile, + HashAlgorithmTag digest) + { + PgpSecretKeyRing secRing = loadSecretKey(privateKeyFile); + PgpPublicKeyRing pubRing = loadPublicKey(publicKeyFile); + string data = "hello world!"; + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(dataBytes, false); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, digest); + + sGen.InitSign(PgpSignature.BinaryDocument, secRing.GetSecretKey().ExtractPrivateKey("test".ToCharArray())); + + BcpgOutputStream bcOut = new BcpgOutputStream(bOut); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + +// Date testDate = new Date((System.currentTimeMillis() / 1000) * 1000); + DateTime testDate = new DateTime( + (DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond); + + Stream lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Binary, + "_CONSOLE", + dataBytes.Length, + testDate); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lGen.Close(); + + sGen.Generate().Encode(bcOut); + + PgpObjectFactory pgpFact = new PgpObjectFactory(bOut.ToArray()); + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + + Assert.AreEqual(digest, ops.HashAlgorithm); + Assert.AreEqual(PublicKeyAlgorithmTag.Dsa, ops.KeyAlgorithm); + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDate)) + { + Assert.Fail("Modification time not preserved"); + } + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pubRing.GetPublicKey()); + + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + PgpSignature sig = p3[0]; + + Assert.AreEqual(digest, sig.HashAlgorithm); + Assert.AreEqual(PublicKeyAlgorithmTag.Dsa, sig.KeyAlgorithm); + + Assert.IsTrue(ops.Verify(sig)); + } + + private void doSigVerifyTest( + string publicKeyFile, + string sigFile) + { + PgpPublicKeyRing publicKey = loadPublicKey(publicKeyFile); + PgpObjectFactory pgpFact = loadSig(sigFile); + + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(publicKey.GetPublicKey()); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + Assert.IsTrue(ops.Verify(p3[0])); + } + + private PgpObjectFactory loadSig( + string sigName) + { + Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.sigs." + sigName); + + return new PgpObjectFactory(fIn); + } + + private PgpPublicKeyRing loadPublicKey( + string keyName) + { + Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.keys." + keyName); + + return new PgpPublicKeyRing(fIn); + } + + private PgpSecretKeyRing loadSecretKey( + string keyName) + { + Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.keys." + keyName); + + return new PgpSecretKeyRing(fIn); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPArmoredTest.cs b/crypto/test/src/openpgp/test/PGPArmoredTest.cs new file mode 100644 index 000000000..aa13477ed --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPArmoredTest.cs @@ -0,0 +1,265 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpArmoredTest + : SimpleTest + { + private static readonly byte[] sample = Base64.Decode( + "mQGiBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn" + + "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg" + + "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf" + + "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ" + + "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G" + + "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ" + + "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG" + + "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP" + + "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif" + + "IIeLOTI5Dc4XKeV32a+bWrQidGVzdCAoVGVzdCBrZXkpIDx0ZXN0QHViaWNh" + + "bGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB4TOABgsJCAcDAgMVAgMDFgIB" + + "Ah4BAheAAAoJEJh8Njfhe8KmGDcAoJWr8xgPr75y/Cp1kKn12oCCOb8zAJ4p" + + "xSvk4K6tB2jYbdeSrmoWBZLdMLACAAC5AQ0EQDzfARAEAJeUAPvUzJJbKcc5" + + "5Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj47UPAD/tQxwz8VAwJySx82ggN" + + "LxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j2BVqZAaX3q79a3eMiql1T0oE" + + "AGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOHAAQNBACD0mVMlAUgd7REYy/1" + + "mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWaHz6CN1XptdwpDeSYEOFZ0PSu" + + "qH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85efMBA9jUv/DeBOzRWMFG6sC6y" + + "k8NGG7Swea7EHKeQI40G3jgO/+xANtMyTIhPBBgRAgAPBQJAPN8BAhsMBQkB" + + "4TOAAAoJEJh8Njfhe8KmG7kAn00mTPGJCWqmskmzgdzeky5fWd7rAKCNCp3u" + + "ZJhfg0htdgAfIy8ppm05vLACAAA="); + + private static readonly byte[] marker = Hex.Decode("2d2d2d2d2d454e4420504750205055424c4943204b455920424c4f434b2d2d2d2d2d"); + + // Contains "Hello World!" as an armored message + // The 'blank line' after the headers contains (legal) whitespace - see RFC2440 6.2 + private static readonly string blankLineData = + "-----BEGIN PGP MESSAGE-----\n" + + "Version: BCPG v1.32\n" + + "Comment: A dummy message\n" + + " \t \t\n" + + "SGVsbG8gV29ybGQh\n" + + "=d9Xi\n" + + "-----END PGP MESSAGE-----\n"; + + private int markerCount( + byte[] data) + { + int ind = 0; + int matches = 0; + + while (ind < data.Length) + { + if (data[ind] == 0x2d) + { + int count = 0; + while (count < marker.Length) + { + if (data[ind + count] != marker[count]) + { + break; + } + count++; + } + + if (count == marker.Length) + { + matches++; + } + + // TODO Is this correct? + ind += count; + } + else + { + ind++; + } + } + + return matches; + } + + private void blankLineTest() + { + byte[] blankLineBytes = Encoding.ASCII.GetBytes(blankLineData); + MemoryStream bIn = new MemoryStream(blankLineBytes, false); + ArmoredInputStream aIn = new ArmoredInputStream(bIn, true); + + MemoryStream bOut = new MemoryStream(); + int c; + while ((c = aIn.ReadByte()) >= 0) + { + bOut.WriteByte((byte)c); + } + + byte[] expected = Encoding.ASCII.GetBytes("Hello World!"); + + if (!Arrays.AreEqual(expected, bOut.ToArray())) + { + Fail("Incorrect message retrieved in blank line test."); + } + } + + public override void PerformTest() + { + // + // test immediate close + // + MemoryStream bOut = new MemoryStream(); + ArmoredOutputStream aOut = new ArmoredOutputStream(bOut); + + aOut.Close(); + + byte[] data = bOut.ToArray(); + + if (data.Length != 0) + { + Fail("No data should have been written"); + } + + // + // multiple close + // + bOut = new MemoryStream(); + aOut = new ArmoredOutputStream(bOut); + + aOut.Write(sample, 0, sample.Length); + + aOut.Close(); + aOut.Close(); + + int mc = markerCount(bOut.ToArray()); + + if (mc < 1) + { + Fail("No end marker found"); + } + + if (mc > 1) + { + Fail("More than one end marker found"); + } + + // + // writing and reading single objects + // + bOut = new MemoryStream(); + aOut = new ArmoredOutputStream(bOut); + + aOut.Write(sample, 0, sample.Length); + + aOut.Close(); + + ArmoredInputStream aIn = new ArmoredInputStream( + new MemoryStream(bOut.ToArray(), false)); + + PgpObjectFactory fact = new PgpObjectFactory(aIn); + int count = 0; + + while (fact.NextPgpObject() != null) + { + count++; + } + + if (count != 1) + { + Fail("wrong number of objects found: " + count); + } + + // + // writing and reading multiple objects - in single block + // + bOut = new MemoryStream(); + aOut = new ArmoredOutputStream(bOut); + + aOut.Write(sample, 0, sample.Length); + aOut.Write(sample, 0, sample.Length); + + aOut.Close(); + + aIn = new ArmoredInputStream( + new MemoryStream(bOut.ToArray(), false)); + + fact = new PgpObjectFactory(aIn); + count = 0; + + while (fact.NextPgpObject() != null) + { + count++; + } + + if (count != 2) + { + Fail("wrong number of objects found: " + count); + } + + // + // writing and reading multiple objects - in single block + // + bOut = new MemoryStream(); + aOut = new ArmoredOutputStream(bOut); + + aOut.Write(sample, 0, sample.Length); + + aOut.Close(); // does not close underlying stream + + aOut = new ArmoredOutputStream(bOut); + + aOut.Write(sample, 0, sample.Length); + + aOut.Close(); + + aIn = new ArmoredInputStream( + new MemoryStream(bOut.ToArray(), false)); + + count = 0; + bool atLeastOne; + do + { + atLeastOne = false; + fact = new PgpObjectFactory(aIn); + + while (fact.NextPgpObject() != null) + { + atLeastOne = true; + count++; + } + } + while (atLeastOne); + + if (count != 2) + { + Fail("wrong number of objects found: " + count); + } + + blankLineTest(); + } + + public override string Name + { + get { return "PGPArmoredTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpArmoredTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPClearSignedSignatureTest.cs b/crypto/test/src/openpgp/test/PGPClearSignedSignatureTest.cs new file mode 100644 index 000000000..668f8cce2 --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPClearSignedSignatureTest.cs @@ -0,0 +1,445 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpClearSignedSignatureTest + : SimpleTest + { + private static readonly byte[] publicKey = Base64.Decode( + "mQELBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+" + + "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1" + + "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO" + + "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7" + + "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4" + + "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp" + + "tBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2BBMBAgAgBQJEIdvsAhsDBgsJCAcD" + + "AgQVAggDBBYCAwECHgECF4AACgkQ4M/Ier3f9xagdAf/fbKWBjLQM8xR7JkR" + + "P4ri8YKOQPhK+VrddGUD59/wzVnvaGyl9MZE7TXFUeniQq5iXKnm22EQbYch" + + "v2Jcxyt2H9yptpzyh4tP6tEHl1C887p2J4qe7F2ATua9CzVGwXQSUbKtj2fg" + + "UZP5SsNp25guhPiZdtkf2sHMeiotmykFErzqGMrvOAUThrO63GiYsRk4hF6r" + + "cQ01d+EUVpY/sBcCxgNyOiB7a84sDtrxnX5BTEZDTEj8LvuEyEV3TMUuAjx1" + + "7Eyd+9JtKzwV4v3hlTaWOvGro9nPS7YaPuG+RtufzXCUJPbPfTjTvtGOqvEz" + + "oztls8tuWA0OGHba9XfX9rfgorACAAM="); + + private static readonly byte[] secretKey = Base64.Decode( + "lQOWBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+" + + "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1" + + "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO" + + "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7" + + "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4" + + "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp" + + "AAf+JCJJeAXEcrTVHotsrRR5idzmg6RK/1MSQUijwPmP7ZGy1BmpAmYUfbxn" + + "B56GvXyFV3Pbj9PgyJZGS7cY+l0BF4ZqN9USiQtC9OEpCVT5LVMCFXC/lahC" + + "/O3EkjQy0CYK+GwyIXa+Flxcr460L/Hvw2ZEXJZ6/aPdiR+DU1l5h99Zw8V1" + + "Y625MpfwN6ufJfqE0HLoqIjlqCfi1iwcKAK2oVx2SwnT1W0NwUUXjagGhD2s" + + "VzJVpLqhlwmS0A+RE9Niqrf80/zwE7QNDF2DtHxmMHJ3RY/pfu5u1rrFg9YE" + + "lmS60mzOe31CaD8Li0k5YCJBPnmvM9mN3/DWWprSZZKtmQQA96C2/VJF5EWm" + + "+/Yxi5J06dG6Bkz311Ui4p2zHm9/4GvTPCIKNpGx9Zn47YFD3tIg3fIBVPOE" + + "ktG38pEPx++dSSFF9Ep5UgmYFNOKNUVq3yGpatBtCQBXb1LQLAMBJCJ5TQmk" + + "68hMOEaqjMHSOa18cS63INgA6okb/ueAKIHxYQcEAP9DaXu5n9dZQw7pshbN" + + "Nu/T5IP0/D/wqM+W5r+j4P1N7PgiAnfKA4JjKrUgl8PGnI2qM/Qu+g3qK++c" + + "F1ESHasnJPjvNvY+cfti06xnJVtCB/EBOA2UZkAr//Tqa76xEwYAWRBnO2Y+" + + "KIVOT+nMiBFkjPTrNAD6fSr1O4aOueBhBAC6aA35IfjC2h5MYk8+Z+S4io2o" + + "mRxUZ/dUuS+kITvWph2e4DT28Xpycpl2n1Pa5dCDO1lRqe/5JnaDYDKqxfmF" + + "5tTG8GR4d4nVawwLlifXH5Ll7t5NcukGNMCsGuQAHMy0QHuAaOvMdLs5kGHn" + + "8VxfKEVKhVrXsvJSwyXXSBtMtUcRtBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2" + + "BBMBAgAgBQJEIdvsAhsDBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ4M/I" + + "er3f9xagdAf/fbKWBjLQM8xR7JkRP4ri8YKOQPhK+VrddGUD59/wzVnvaGyl" + + "9MZE7TXFUeniQq5iXKnm22EQbYchv2Jcxyt2H9yptpzyh4tP6tEHl1C887p2" + + "J4qe7F2ATua9CzVGwXQSUbKtj2fgUZP5SsNp25guhPiZdtkf2sHMeiotmykF" + + "ErzqGMrvOAUThrO63GiYsRk4hF6rcQ01d+EUVpY/sBcCxgNyOiB7a84sDtrx" + + "nX5BTEZDTEj8LvuEyEV3TMUuAjx17Eyd+9JtKzwV4v3hlTaWOvGro9nPS7Ya" + + "PuG+RtufzXCUJPbPfTjTvtGOqvEzoztls8tuWA0OGHba9XfX9rfgorACAAA="); + + private static readonly string crOnlyMessage = + "\r" + + " hello world!\r" + + "\r" + + "- dash\r"; + + private static readonly string nlOnlyMessage = + "\n" + + " hello world!\n" + + "\n" + + "- dash\n"; + + private static readonly string crNlMessage = + "\r\n" + + " hello world!\r\n" + + "\r\n" + + "- dash\r\n"; + + private static readonly string crOnlySignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\r" + + "Hash: SHA256\r" + + "\r" + + "\r" + + " hello world!\r" + + "\r" + + "- - dash\r" + + "-----BEGIN PGP SIGNATURE-----\r" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r" + + "\r" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r"; + + private static readonly string nlOnlySignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\n" + + "Hash: SHA256\n" + + "\n" + + "\n" + + " hello world!\n" + + "\n" + + "- - dash\n" + + "-----BEGIN PGP SIGNATURE-----\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\n" + + "\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\n" + + "=84Nd\n" + + "-----END PGP SIGNATURE-----\n"; + + private static readonly string crNlSignedMessage = + "-----BEGIN PGP SIGNED MESSAGE-----\r\n" + + "Hash: SHA256\r\n" + + "\r\n" + + "\r\n" + + " hello world!\r\n" + + "\r\n" + + "- - dash\r\n" + + "-----BEGIN PGP SIGNATURE-----\r\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n" + + "\r\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r\n"; + + private static readonly string crNlSignedMessageTrailingWhiteSpace = + "-----BEGIN PGP SIGNED MESSAGE-----\r\n" + + "Hash: SHA256\r\n" + + "\r\n" + + "\r\n" + + " hello world! \t\r\n" + + "\r\n" + + "- - dash\r\n" + + "-----BEGIN PGP SIGNATURE-----\r\n" + + "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n" + + "\r\n" + + "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n" + + "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n" + + "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n" + + "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n" + + "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n" + + "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n" + + "=84Nd\r" + + "-----END PGP SIGNATURE-----\r\n"; + + public override string Name + { + get { return "PGPClearSignedSignature"; } + } + + private void messageTest( + string message, + string type) + { + ArmoredInputStream aIn = new ArmoredInputStream( + new MemoryStream(Encoding.ASCII.GetBytes(message))); + + string[] headers = aIn.GetArmorHeaders(); + + if (headers == null || headers.Length != 1) + { + Fail("wrong number of headers found"); + } + + if (!"Hash: SHA256".Equals(headers[0])) + { + Fail("header value wrong: " + headers[0]); + } + + // + // read the input, making sure we ingore the last newline. + // + MemoryStream bOut = new MemoryStream(); + int ch; + + while ((ch = aIn.ReadByte()) >= 0 && aIn.IsClearText()) + { + bOut.WriteByte((byte)ch); + } + + PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(publicKey); + + PgpObjectFactory pgpFact = new PgpObjectFactory(aIn); + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + PgpSignature sig = p3[0]; + + sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId)); + + MemoryStream lineOut = new MemoryStream(); + Stream sigIn = new MemoryStream(bOut.ToArray(), false); + int lookAhead = ReadInputLine(lineOut, sigIn); + + ProcessLine(sig, lineOut.ToArray()); + + if (lookAhead != -1) + { + do + { + lookAhead = ReadInputLine(lineOut, lookAhead, sigIn); + + sig.Update((byte) '\r'); + sig.Update((byte) '\n'); + + ProcessLine(sig, lineOut.ToArray()); + } + while (lookAhead != -1); + } + + if (!sig.Verify()) + { + Fail("signature failed to verify m_in " + type); + } + } + + private PgpSecretKey ReadSecretKey( + Stream inputStream) + { + PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(inputStream); + + // + // we just loop through the collection till we find a key suitable for encryption, in the real + // world you would probably want to be a bit smarter about this. + // + // + // iterate through the key rings. + // + foreach (PgpSecretKeyRing kRing in pgpSec.GetKeyRings()) + { + foreach (PgpSecretKey k in kRing.GetSecretKeys()) + { + if (k.IsSigningKey) + { + return k; + } + } + } + + throw new ArgumentException("Can't find signing key in key ring."); + } + + private void generateTest( + string message, + string type) + { + PgpSecretKey pgpSecKey = ReadSecretKey(new MemoryStream(secretKey)); + PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey("".ToCharArray()); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha256); + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); + + sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey); + + IEnumerator it = pgpSecKey.PublicKey.GetUserIds().GetEnumerator(); + if (it.MoveNext()) + { + spGen.SetSignerUserId(false, (string)it.Current); + sGen.SetHashedSubpackets(spGen.Generate()); + } + + MemoryStream bOut = new MemoryStream(); + ArmoredOutputStream aOut = new ArmoredOutputStream(bOut); + MemoryStream bIn = new MemoryStream(Encoding.ASCII.GetBytes(message), false); + + aOut.BeginClearText(HashAlgorithmTag.Sha256); + + // + // note the last \n m_in the file is ignored + // + MemoryStream lineOut = new MemoryStream(); + int lookAhead = ReadInputLine(lineOut, bIn); + + ProcessLine(aOut, sGen, lineOut.ToArray()); + + if (lookAhead != -1) + { + do + { + lookAhead = ReadInputLine(lineOut, lookAhead, bIn); + + sGen.Update((byte) '\r'); + sGen.Update((byte) '\n'); + + ProcessLine(aOut, sGen, lineOut.ToArray()); + } + while (lookAhead != -1); + } + + aOut.EndClearText(); + + BcpgOutputStream bcpgOut = new BcpgOutputStream(aOut); + + sGen.Generate().Encode(bcpgOut); + + aOut.Close(); + + byte[] bs = bOut.ToArray(); + messageTest(Encoding.ASCII.GetString(bs, 0, bs.Length), type); + } + + private static int ReadInputLine( + MemoryStream bOut, + Stream fIn) + { + bOut.SetLength(0); + + int lookAhead = -1; + int ch; + + while ((ch = fIn.ReadByte()) >= 0) + { + bOut.WriteByte((byte) ch); + if (ch == '\r' || ch == '\n') + { + lookAhead = ReadPassedEol(bOut, ch, fIn); + break; + } + } + + return lookAhead; + } + + private static int ReadInputLine( + MemoryStream bOut, + int lookAhead, + Stream fIn) + { + bOut.SetLength(0); + + int ch = lookAhead; + + do + { + bOut.WriteByte((byte) ch); + if (ch == '\r' || ch == '\n') + { + lookAhead = ReadPassedEol(bOut, ch, fIn); + break; + } + } + while ((ch = fIn.ReadByte()) >= 0); + + return lookAhead; + } + + private static int ReadPassedEol( + MemoryStream bOut, + int lastCh, + Stream fIn) + { + int lookAhead = fIn.ReadByte(); + + if (lastCh == '\r' && lookAhead == '\n') + { + bOut.WriteByte((byte) lookAhead); + lookAhead = fIn.ReadByte(); + } + + return lookAhead; + } + + private static void ProcessLine( + PgpSignature sig, + byte[] line) + { + int length = GetLengthWithoutWhiteSpace(line); + if (length > 0) + { + sig.Update(line, 0, length); + } + } + + private static void ProcessLine( + Stream aOut, + PgpSignatureGenerator sGen, + byte[] line) + { + int length = GetLengthWithoutWhiteSpace(line); + if (length > 0) + { + sGen.Update(line, 0, length); + } + + aOut.Write(line, 0, line.Length); + } + + private static int GetLengthWithoutWhiteSpace( + byte[] line) + { + int end = line.Length - 1; + + while (end >= 0 && IsWhiteSpace(line[end])) + { + end--; + } + + return end + 1; + } + + private static bool IsWhiteSpace( + byte b) + { + return b == '\r' || b == '\n' || b == '\t' || b == ' '; + } + + public override void PerformTest() + { + messageTest(crOnlySignedMessage, "\\r"); + messageTest(nlOnlySignedMessage, "\\n"); + messageTest(crNlSignedMessage, "\\r\\n"); + messageTest(crNlSignedMessageTrailingWhiteSpace, "\\r\\n"); + + generateTest(nlOnlyMessage, "\\r"); + generateTest(crOnlyMessage, "\\n"); + generateTest(crNlMessage, "\\r\\n"); + } + + public static void Main( + string[] args) + { + RunTest(new PgpClearSignedSignatureTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPCompressionTest.cs b/crypto/test/src/openpgp/test/PGPCompressionTest.cs new file mode 100644 index 000000000..fdcf7222c --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPCompressionTest.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Utilities; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpCompressionTest + : SimpleTest + { + private static readonly byte[] Data = Encoding.ASCII.GetBytes("hello world! !dlrow olleh"); + + [Test] + public void TestUncompressed() + { + doTestCompression(CompressionAlgorithmTag.Uncompressed); + } + + [Test] + public void TestZip() + { + doTestCompression(CompressionAlgorithmTag.Zip); + } + + [Test] + public void TestZLib() + { + doTestCompression(CompressionAlgorithmTag.ZLib); + } + + [Test] + public void TestBZip2() + { + doTestCompression(CompressionAlgorithmTag.BZip2); + } + + public override void PerformTest() + { + doTestCompression(CompressionAlgorithmTag.Uncompressed); + doTestCompression(CompressionAlgorithmTag.Zip); + doTestCompression(CompressionAlgorithmTag.ZLib); + doTestCompression(CompressionAlgorithmTag.BZip2); + } + + private void doTestCompression( + CompressionAlgorithmTag type) + { + doTestCompression(type, true); + doTestCompression(type, false); + } + + private void doTestCompression( + CompressionAlgorithmTag type, + bool streamClose) + { + MemoryStream bOut = new MemoryStream(); + PgpCompressedDataGenerator cPacket = new PgpCompressedDataGenerator(type); + Stream os = cPacket.Open(new UncloseableStream(bOut), new byte[Data.Length - 1]); + os.Write(Data, 0, Data.Length); + + if (streamClose) + { + os.Close(); + } + else + { + cPacket.Close(); + } + + ValidateData(bOut.ToArray()); + + try + { + os.Close(); + cPacket.Close(); + } + catch (Exception) + { + Fail("Redundant Close() should be ignored"); + } + } + + private void ValidateData( + byte[] compressed) + { + PgpObjectFactory pgpFact = new PgpObjectFactory(compressed); + PgpCompressedData c1 = (PgpCompressedData) pgpFact.NextPgpObject(); + + Stream pIn = c1.GetDataStream(); + byte[] bytes = Streams.ReadAll(pIn); + pIn.Close(); + + if (!AreEqual(bytes, Data)) + { + Fail("compression test failed"); + } + } + + public override string Name + { + get { return "PGPCompressionTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpCompressionTest()); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs b/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs new file mode 100644 index 000000000..b86324954 --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs @@ -0,0 +1,492 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpDsaElGamalTest + : SimpleTest + { + private static readonly byte[] testPubKeyRing = Base64.Decode( + "mQGiBEAR8jYRBADNifuSopd20JOQ5x30ljIaY0M6927+vo09NeNxS3KqItba" + + "nz9o5e2aqdT0W1xgdHYZmdElOHTTsugZxdXTEhghyxoo3KhVcNnTABQyrrvX" + + "qouvmP2fEDEw0Vpyk+90BpyY9YlgeX/dEA8OfooRLCJde/iDTl7r9FT+mts8" + + "g3azjwCgx+pOLD9LPBF5E4FhUOdXISJ0f4EEAKXSOi9nZzajpdhe8W2ZL9gc" + + "BpzZi6AcrRZBHOEMqd69gtUxA4eD8xycUQ42yH89imEcwLz8XdJ98uHUxGJi" + + "qp6hq4oakmw8GQfiL7yQIFgaM0dOAI9Afe3m84cEYZsoAFYpB4/s9pVMpPRH" + + "NsVspU0qd3NHnSZ0QXs8L8DXGO1uBACjDUj+8GsfDCIP2QF3JC+nPUNa0Y5t" + + "wKPKl+T8hX/0FBD7fnNeC6c9j5Ir/Fp/QtdaDAOoBKiyNLh1JaB1NY6US5zc" + + "qFks2seZPjXEiE6OIDXYra494mjNKGUobA4hqT2peKWXt/uBcuL1mjKOy8Qf" + + "JxgEd0MOcGJO+1PFFZWGzLQ3RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSBv" + + "bmx5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPohZBBMRAgAZBQJAEfI2BAsH" + + "AwIDFQIDAxYCAQIeAQIXgAAKCRAOtk6iUOgnkDdnAKC/CfLWikSBdbngY6OK" + + "5UN3+o7q1ACcDRqjT3yjBU3WmRUNlxBg3tSuljmwAgAAuQENBEAR8jgQBAC2" + + "kr57iuOaV7Ga1xcU14MNbKcA0PVembRCjcVjei/3yVfT/fuCVtGHOmYLEBqH" + + "bn5aaJ0P/6vMbLCHKuN61NZlts+LEctfwoya43RtcubqMc7eKw4k0JnnoYgB" + + "ocLXOtloCb7jfubOsnfORvrUkK0+Ne6anRhFBYfaBmGU75cQgwADBQP/XxR2" + + "qGHiwn+0YiMioRDRiIAxp6UiC/JQIri2AKSqAi0zeAMdrRsBN7kyzYVVpWwN" + + "5u13gPdQ2HnJ7d4wLWAuizUdKIQxBG8VoCxkbipnwh2RR4xCXFDhJrJFQUm+" + + "4nKx9JvAmZTBIlI5Wsi5qxst/9p5MgP3flXsNi1tRbTmRhqIRgQYEQIABgUC" + + "QBHyOAAKCRAOtk6iUOgnkBStAJoCZBVM61B1LG2xip294MZecMtCwQCbBbsk" + + "JVCXP0/Szm05GB+WN+MOCT2wAgAA"); + + private static readonly byte[] testPrivKeyRing = Base64.Decode( + "lQHhBEAR8jYRBADNifuSopd20JOQ5x30ljIaY0M6927+vo09NeNxS3KqItba" + + "nz9o5e2aqdT0W1xgdHYZmdElOHTTsugZxdXTEhghyxoo3KhVcNnTABQyrrvX" + + "qouvmP2fEDEw0Vpyk+90BpyY9YlgeX/dEA8OfooRLCJde/iDTl7r9FT+mts8" + + "g3azjwCgx+pOLD9LPBF5E4FhUOdXISJ0f4EEAKXSOi9nZzajpdhe8W2ZL9gc" + + "BpzZi6AcrRZBHOEMqd69gtUxA4eD8xycUQ42yH89imEcwLz8XdJ98uHUxGJi" + + "qp6hq4oakmw8GQfiL7yQIFgaM0dOAI9Afe3m84cEYZsoAFYpB4/s9pVMpPRH" + + "NsVspU0qd3NHnSZ0QXs8L8DXGO1uBACjDUj+8GsfDCIP2QF3JC+nPUNa0Y5t" + + "wKPKl+T8hX/0FBD7fnNeC6c9j5Ir/Fp/QtdaDAOoBKiyNLh1JaB1NY6US5zc" + + "qFks2seZPjXEiE6OIDXYra494mjNKGUobA4hqT2peKWXt/uBcuL1mjKOy8Qf" + + "JxgEd0MOcGJO+1PFFZWGzP4DAwLeUcsVxIC2s2Bb9ab2XD860TQ2BI2rMD/r" + + "7/psx9WQ+Vz/aFAT3rXkEJ97nFeqEACgKmUCAEk9939EwLQ3RXJpYyBILiBF" + + "Y2hpZG5hICh0ZXN0IGtleSBvbmx5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3Jn" + + "PohZBBMRAgAZBQJAEfI2BAsHAwIDFQIDAxYCAQIeAQIXgAAKCRAOtk6iUOgn" + + "kDdnAJ9Ala3OcwEV1DbK906CheYWo4zIQwCfUqUOLMp/zj6QAk02bbJAhV1r" + + "sAewAgAAnQFYBEAR8jgQBAC2kr57iuOaV7Ga1xcU14MNbKcA0PVembRCjcVj" + + "ei/3yVfT/fuCVtGHOmYLEBqHbn5aaJ0P/6vMbLCHKuN61NZlts+LEctfwoya" + + "43RtcubqMc7eKw4k0JnnoYgBocLXOtloCb7jfubOsnfORvrUkK0+Ne6anRhF" + + "BYfaBmGU75cQgwADBQP/XxR2qGHiwn+0YiMioRDRiIAxp6UiC/JQIri2AKSq" + + "Ai0zeAMdrRsBN7kyzYVVpWwN5u13gPdQ2HnJ7d4wLWAuizUdKIQxBG8VoCxk" + + "bipnwh2RR4xCXFDhJrJFQUm+4nKx9JvAmZTBIlI5Wsi5qxst/9p5MgP3flXs" + + "Ni1tRbTmRhr+AwMC3lHLFcSAtrNg/EiWFLAnKNXH27zjwuhje8u2r+9iMTYs" + + "GjbRxaxRY0GKRhttCwqe2BC0lHhzifdlEcc9yjIjuKfepG2fnnSIRgQYEQIA" + + "BgUCQBHyOAAKCRAOtk6iUOgnkBStAJ9HFejVtVJ/A9LM/mDPe0ExhEXt/QCg" + + "m/KM7hJ/JrfnLQl7IaZsdg1F6vCwAgAA"); + + private static readonly byte[] encMessage = Base64.Decode( + "hQEOAynbo4lhNjcHEAP/dgCkMtPB6mIgjFvNiotjaoh4sAXf4vFNkSeehQ2c" + + "r+IMt9CgIYodJI3FoJXxOuTcwesqTp5hRzgUBJS0adLDJwcNubFMy0M2tp5o" + + "KTWpXulIiqyO6f5jI/oEDHPzFoYgBmR4x72l/YpMy8UoYGtNxNvR7LVOfqJv" + + "uDY/71KMtPQEAIadOWpf1P5Td+61Zqn2VH2UV7H8eI6hGa6Lsy4sb9iZNE7f" + + "c+spGJlgkiOt8TrQoq3iOK9UN9nHZLiCSIEGCzsEn3uNuorD++Qs065ij+Oy" + + "36TKeuJ+38CfT7u47dEshHCPqWhBKEYrxZWHUJU/izw2Q1Yxd2XRxN+nafTL" + + "X1fQ0lABQUASa18s0BkkEERIdcKQXVLEswWcGqWNv1ZghC7xO2VDBX4HrPjp" + + "drjL63p2UHzJ7/4gPWGGtnqq1Xita/1mrImn7pzLThDWiT55vjw6Hw=="); + + private static readonly byte[] signedAndEncMessage = Base64.Decode( + "hQEOAynbo4lhNjcHEAP+K20MVhzdX57hf/cU8TH0prP0VePr9mmeBedzqqMn" + + "fp2p8Zb68zmcMlI/WiL5XMNLYRmCgEcXyWbKdP/XV9m9LDBe1CMAGrkCeGBy" + + "je69IQQ5LS9vDPyEMF4iAAv/EqACjqHkizdY/a/FRx/t2ioXYdEC2jA6kS9C" + + "McpsNz16DE8EAIk3uKn4bGo/+15TXkyFYzW5Cf71SfRoHNmU2zAI93zhjN+T" + + "B7mGJwWXzsMkIO6FkMU5TCSrwZS3DBWCIaJ6SYoaawE/C/2j9D7bX1Jv8kum" + + "4cq+eZM7z6JYs6xend+WAwittpUxbEiyC2AJb3fBSXPAbLqWd6J6xbZZ7GDK" + + "r2Ca0pwBxwGhbMDyi2zpHLzw95H7Ah2wMcGU6kMLB+hzBSZ6mSTGFehqFQE3" + + "2BnAj7MtnbghiefogacJ891jj8Y2ggJeKDuRz8j2iICaTOy+Y2rXnnJwfYzm" + + "BMWcd2h1C5+UeBJ9CrrLniCCI8s5u8z36Rno3sfhBnXdRmWSxExXtocbg1Ht" + + "dyiThf6TK3W29Yy/T6x45Ws5zOasaJdsFKM="); + + private static readonly char[] pass = "hello world".ToCharArray(); + + private static readonly SecureRandom random = new SecureRandom(); + + public override void PerformTest() + { + PgpPublicKey pubKey = null; + + // + // Read the public key + // + PgpObjectFactory pgpFact = new PgpObjectFactory(testPubKeyRing); + PgpPublicKeyRing pgpPub = (PgpPublicKeyRing)pgpFact.NextPgpObject(); + + pubKey = pgpPub.GetPublicKey(); + + if (pubKey.BitStrength != 1024) + { + Fail("failed - key strength reported incorrectly."); + } + + // + // Read the private key + // + PgpSecretKeyRing sKey = new PgpSecretKeyRing(testPrivKeyRing); + PgpSecretKey secretKey = sKey.GetSecretKey(); + PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(pass); + + // + // signature generation + // + const string data = "hello world!"; + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(dataBytes, false); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, + HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + + PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + BcpgOutputStream bcOut = new BcpgOutputStream( + cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + + DateTime testDateTime = new DateTime(1973, 7, 27); + Stream lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Binary, + "_CONSOLE", + dataBytes.Length, + testDateTime); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte) ch); + sGen.Update((byte) ch); + } + + lGen.Close(); + + sGen.Generate().Encode(bcOut); + + cGen.Close(); + + // + // verify Generated signature + // + pgpFact = new PgpObjectFactory(bOut.ToArray()); + + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pubKey); + + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed Generated signature check"); + } + + // + // test encryption + // + + // + // find a key sutiable for encryption + // + long pgpKeyID = 0; + AsymmetricKeyParameter pKey = null; + + foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys()) + { + if (pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalEncrypt + || pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalGeneral) + { + pKey = pgpKey.GetKey(); + pgpKeyID = pgpKey.KeyId; + if (pgpKey.BitStrength != 1024) + { + Fail("failed - key strength reported incorrectly."); + } + + // + // verify the key + // + + } + } + + IBufferedCipher c = CipherUtilities.GetCipher("ElGamal/None/PKCS1Padding"); + + c.Init(true, pKey); + + byte[] inBytes = Encoding.ASCII.GetBytes("hello world"); + byte[] outBytes = c.DoFinal(inBytes); + + pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass); + + c.Init(false, pgpPrivKey.Key); + + outBytes = c.DoFinal(outBytes); + + if (!Arrays.AreEqual(inBytes, outBytes)) + { + Fail("decryption failed."); + } + + // + // encrypted message + // + byte[] text = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', + (byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l', (byte)'d', (byte)'!', (byte)'\n' }; + + PgpObjectFactory pgpF = new PgpObjectFactory(encMessage); + + PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0]; + + Stream clear = encP.GetDataStream(pgpPrivKey); + + pgpFact = new PgpObjectFactory(clear); + + c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpLiteralData ld = (PgpLiteralData)pgpFact.NextPgpObject(); + + if (!ld.FileName.Equals("test.txt")) + { + throw new Exception("wrong filename in packet"); + } + + Stream inLd = ld.GetDataStream(); + byte[] bytes = Streams.ReadAll(inLd); + + if (!Arrays.AreEqual(bytes, text)) + { + Fail("wrong plain text in decrypted packet"); + } + + // + // signed and encrypted message + // + pgpF = new PgpObjectFactory(signedAndEncMessage); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + encP = (PgpPublicKeyEncryptedData)encList[0]; + + clear = encP.GetDataStream(pgpPrivKey); + + pgpFact = new PgpObjectFactory(clear); + + c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + ops = p1[0]; + + ld = (PgpLiteralData)pgpFact.NextPgpObject(); + + bOut = new MemoryStream(); + + if (!ld.FileName.Equals("test.txt")) + { + throw new Exception("wrong filename in packet"); + } + + inLd = ld.GetDataStream(); + + // + // note: we use the DSA public key here. + // + ops.InitVerify(pgpPub.GetPublicKey()); + + while ((ch = inLd.ReadByte()) >= 0) + { + ops.Update((byte) ch); + bOut.WriteByte((byte) ch); + } + + p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed signature check"); + } + + if (!Arrays.AreEqual(bOut.ToArray(), text)) + { + Fail("wrong plain text in decrypted packet"); + } + + // + // encrypt + // + MemoryStream cbOut = new MemoryStream(); + PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.TripleDes, random); + PgpPublicKey puK = sKey.GetSecretKey(pgpKeyID).PublicKey; + + cPk.AddMethod(puK); + + Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOut.ToArray().Length); + + cOut.Write(text, 0, text.Length); + + cOut.Close(); + + pgpF = new PgpObjectFactory(cbOut.ToArray()); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + encP = (PgpPublicKeyEncryptedData)encList[0]; + + pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass); + + clear = encP.GetDataStream(pgpPrivKey); + outBytes = Streams.ReadAll(clear); + + if (!Arrays.AreEqual(outBytes, text)) + { + Fail("wrong plain text in Generated packet"); + } + + // + // use of PgpKeyPair + // + BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + ElGamalParameters elParams = new ElGamalParameters(p, g); + + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL"); + kpg.Init(new ElGamalKeyGenerationParameters(random, elParams)); + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + + PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalGeneral , + kp.Public, kp.Private, DateTime.UtcNow); + + PgpPublicKey k1 = pgpKp.PublicKey; + PgpPrivateKey k2 = pgpKp.PrivateKey; + + + + + + // Test bug with ElGamal P size != 0 mod 8 (don't use these sizes at home!) + for (int pSize = 257; pSize < 264; ++pSize) + { + // Generate some parameters of the given size + ElGamalParametersGenerator epg = new ElGamalParametersGenerator(); + epg.Init(pSize, 2, random); + + elParams = epg.GenerateParameters(); + + kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL"); + kpg.Init(new ElGamalKeyGenerationParameters(random, elParams)); + + + // Run a short encrypt/decrypt test with random key for the given parameters + kp = kpg.GenerateKeyPair(); + + PgpKeyPair elGamalKeyPair = new PgpKeyPair( + PublicKeyAlgorithmTag.ElGamalGeneral, kp, DateTime.UtcNow); + + cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, random); + + puK = elGamalKeyPair.PublicKey; + + cPk.AddMethod(puK); + + cbOut = new MemoryStream(); + + cOut = cPk.Open(new UncloseableStream(cbOut), text.Length); + + cOut.Write(text, 0, text.Length); + + cOut.Close(); + + pgpF = new PgpObjectFactory(cbOut.ToArray()); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + encP = (PgpPublicKeyEncryptedData)encList[0]; + + pgpPrivKey = elGamalKeyPair.PrivateKey; + + // Note: This is where an exception would be expected if the P size causes problems + clear = encP.GetDataStream(pgpPrivKey); + byte[] decText = Streams.ReadAll(clear); + + if (!Arrays.AreEqual(text, decText)) + { + Fail("decrypted message incorrect"); + } + } + + + // check sub key encoding + + foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys()) + { + if (!pgpKey.IsMasterKey) + { + byte[] kEnc = pgpKey.GetEncoded(); + + PgpObjectFactory objF = new PgpObjectFactory(kEnc); + + // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing +// PgpPublicKey k = (PgpPublicKey)objF.NextPgpObject(); +// +// pKey = k.GetKey(); +// pgpKeyID = k.KeyId; +// if (k.BitStrength != 1024) +// { +// Fail("failed - key strength reported incorrectly."); +// } +// +// if (objF.NextPgpObject() != null) +// { +// Fail("failed - stream not fully parsed."); +// } + } + } + } + + public override string Name + { + get { return "PGPDSAElGamalTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpDsaElGamalTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPDSATest.cs b/crypto/test/src/openpgp/test/PGPDSATest.cs new file mode 100644 index 000000000..7808ed6cd --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPDSATest.cs @@ -0,0 +1,597 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpDsaTest + : SimpleTest + { + private static readonly byte[] testPubKey = Base64.Decode( + "mQGiBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ" + + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV" + + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/" + + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug" + + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu" + + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ" + + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz" + + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej" + + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbLQzRXJpYyBFY2hp" + + "ZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNhc3RsZS5vcmc+iFkEExEC" + + "ABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j9enEyjRDAlwAn2rrom0s" + + "MhufWK5vIRwg7gj5qsLEAJ4vnT5dPBVblofsG+pDoCVeJXGGng=="); + + private static readonly byte[] testPrivKey = Base64.Decode( + "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ" + + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV" + + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/" + + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug" + + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu" + + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ" + + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz" + + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej" + + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC" + + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu" + + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh" + + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j" + + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD" + + "4nXkHg=="); + + private static readonly byte[] testPrivKey2 = Base64.Decode( + "lQHhBEAnoewRBADRvKgDhbV6pMzqYfUgBsLxSHzmycpuxGbjMrpyKHDOEemj" + + "iQb6TyyBKUoR28/pfshFP9R5urtKIT7wjVrDuOkxYkgRhNm+xmPXW2Lw3D++" + + "MQrC5VWe8ywBltz6T9msmChsaKo2hDhIiRI/mg9Q6rH9pJKtVGi4R7CgGxM2" + + "STQ5fwCgub38qGS1W2O4hUsa+3gva5gaNZUEAItegda4/H4t88XdWxW3D8pv" + + "RnFz26/ADdImVaQlBoumD15VmcgYoT1Djizey7X8vfV+pntudESzLbn3GHlI" + + "6C09seH4e8eYP63t7KU/qbUCDomlSswd1OgQ/RxfN86q765K2t3K1i3wDSxe" + + "EgSRyGKee0VNvOBFOFhuWt+patXaBADE1riNkUxg2P4lBNWwu8tEZRmsl/Ys" + + "DBIzXBshoMzZCvS5PnNXMW4G3SAaC9OC9jvKSx9IEWhKjfjs3QcWzXR28mcm" + + "5na0bTxeOMlaPPhBdkTCmFl0IITWlH/pFlR2ah9WYoWYhZEL2tqB82wByzxH" + + "SkSeD9V5oeSCdCcqiqkEmv4DAwLeNsQ2XGJVRmA4lld+CR5vRxpT/+/2xklp" + + "lxVf/nx0+thrHDpro3u/nINIIObk0gh59+zaEEe3APlHqbQVYWFhIGJiYiA8" + + "Y2NjQGRkZC5lZWU+iFoEExECABoFAkAnoewFCwcDAgEDFQIDAxYCAQIeAQIX" + + "gAAKCRA5nBpCS63az85BAKCbPfU8ATrFvkXhzGNGlc1BJo6DWQCgnK125xVK" + + "lWLpt6ZJJ7TXcx3nkm6wAgAAnQFXBEAnoe0QBACsQxPvaeBcv2TkbgU/5Wc/" + + "tO222dPE1mxFbXjGTKfb+6ge96iyD8kTRLrKCkEEeVBa8AZqMSoXUVN6tV8j" + + "/zD8Bc76o5iJ6wgpg3Mmy2GxInVfsfZN6/G3Y2ukmouz+CDNvQdUw8cTguIb" + + "QoV3XhQ03MLbfVmNcHsku9F4CuKNWwADBQP0DSSe8v5PXF9CSCXOIxBDcQ5x" + + "RKjyYOveqoH/4lbOV0YNUbIDZq4RaUdotpADuPREFmWf0zTB6KV/WIiag8XU" + + "WU9zdDvLKR483Bo6Do5pDBcN+NqfQ+ntGY9WJ7BSFnhQ3+07i1K+NsfFTRfv" + + "hf9X3MP75rCf7MxAIWHTabEmUf4DAwLeNsQ2XGJVRmA8DssBUCghogG9n8T3" + + "qfBeKsplGyCcF+JjPeQXkKQaoYGJ0aJz36qFP9d8DuWtT9soQcqIxVf6mTa8" + + "kN1594hGBBgRAgAGBQJAJ6HtAAoJEDmcGkJLrdrPpMkAnRyjQSKugz0YJqOB" + + "yGasMLQLxd2OAKCEIlhtCarlufVQNGZsuWxHVbU8crACAAA="); + + private static readonly byte[] sig1 = Base64.Decode( + "owGbwMvMwCR4VvnryyOnTJwZ10gncZSkFpfolVSU2Ltz78hIzcnJVyjPL8pJUeTq" + + "sGdmZQCJwpQLMq3ayTA/0Fj3xf4jbwPfK/H3zj55Z9L1n2k/GOapKJrvMZ4tLiCW" + + "GtP/XeDqX4fORDUA"); + + private static readonly byte[] sig1crc = Base64.Decode("OZa/"); + + private static readonly byte[] testPubWithUserAttr = Base64.Decode( + "mQGiBD2Rqv0RBADqKCkhVEtB/lEEr/9CubuHEy2oN/yU5j+2GXSdcNdVnRI/rwFy" + + "fHEQIk3uU7zHSUKFrC59yDm0sODYyjEdE3BVb0xvEJ5LE/OdndcIMXT1DungZ1vB" + + "zIK/3lr33W/PHixYxv9jduH3WrTehBpiKkgMZp8XloSFj2Cnw9LDyfqB7QCg/8K1" + + "o2k75NkOd9ZjnA9ye7Ri3bEEAKyr61Mo7viPWBK1joWAEsxG0OBWM+iSlG7kwh31" + + "8efgC/7Os6x4Y0jzs8mpcbBjeZtZjS9lRbfp7RinhF269xL0TZ3JxIdtaAV/6yDQ" + + "9NXfZY9dskN++HIR/5GCEEgq/qTJZt6ti5k7aV19ZFfO6wiK3NUy08wOrVsdOkVE" + + "w9IcBADaplhpcel3201uU3OCboogJtw81R5MJMZ4Y9cKL/ca2jGISn0nA7KrAw9v" + + "ShheSixGO4BV9JECkLEbtg7i+W/j/De6S+x2GLNcphuTP3UmgtKbhs0ItRqzW561" + + "s6gLkqi6aWmgaFLd8E1pMJcd9DSY95P13EYB9VJIUxFNUopzo7QcUmFsZiBIYXVz" + + "ZXIgPGhhdXNlckBhY20ub3JnPokAWAQQEQIAGAUCPZGq/QgLAwkIBwIBCgIZAQUb" + + "AwAAAAAKCRAqIBiOh4JvOKg4AJ9j14yygOqqzqiLKeaasIzqT8LCIgCggx14WuLO" + + "wOUTUswTaVKMFnU7tseJAJwEEAECAAYFAj2Rqx8ACgkQ9aWTKMpUDFV+9QP/RiWT" + + "5FAF5Rgb7beaApsgXsME+Pw7HEYFtqGa6VcXEpbcUXO6rjaXsgMgY90klWlWCF1T" + + "HOyKITvj2FdhE+0j8NQn4vaGpiTwORW/zMf/BZ0abdSWQybp10Yjs8gXw30UheO+" + + "F1E524MC+s2AeUi2hwHMiS+AVYd4WhxWHmWuBpTRypP/AAALTgEQAAEBAAAAAQAA" + + "AAABAAAA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQ" + + "Dg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/" + + "2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7" + + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCABqAF0DASIAAhEBAxEB/8QAHwAAAQUB" + + "AQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQID" + + "AAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0" + + "NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKT" + + "lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl" + + "5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL" + + "/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHB" + + "CSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpj" + + "ZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3" + + "uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIR" + + "AxEAPwD2aiiq9xcxWsRllcKqjOT06E/0oAsVm6jrmm6VGXvLuOPGflz8x+grzXxV" + + "8U51u5LXRgBGowZHXknnkc9OQcV51caneXdw9xPOXlckl2AJHY4J6cD1oA9J1z4p" + + "TRkrYQhRyQ0hIY5/2QRx7k9ulczN8SvEEshdZkX0UorDrznI759a5Mksckkknqec" + + "mkoA7WD4oavEoEttbTepYEZ+mCMVv6H8SLTULhbe/gFozAYkD5Unp3Ax/kV5XRQB" + + "9EAhgCDkHkEcgilryTwd4zn0m4WzvpTJZSMBuY5MfbueletKyugZWDKwyCOc/j3o" + + "AduyWLDeWB5Ynj8jSUUUAdFXn/xU15dO0RbGGYC5uWwUB6L1Jx+n413F1cJa2stz" + + "J92JC5+gGa+bdfvp9S1q4urmRneQg5Yk4HGAPYZoAzySxySSSep5yaSvQvAPhOHU" + + "rB7u5iLGUlIwQRx7HPr/AJ9LGsfC+dJGngc+X12gc8nvx1/rQB5rRXS3Xg28t9ye" + + "VLvA7Ddj8MDt6Vnx6JKJCsocnBwqqQSOxPH+fWgDKorTl0SaLGXxkZ+ZcZ4z1yfb" + + "P1qg0MqLueN1A6kqRigCOvVPh74mF9YjS7tgLi3GIm6b17c+oOfrXlda3haeW38R" + + "WjxfeMgBOCcD/PHpzQB7nRRRQBqarZjUNLubPJXz4yhI64PFfO3iDRrnRtdm0+cq" + + "0ocEbehzyOv1xX0vXnHxU8Kf2hYf23aRk3VsMTAZO6MZ5x7UAbfga1W00WzjRSF8" + + "kbsg5z744HT/ADmuoysikdQSVP8AI1yPgq6il0axk27V8sDcTg5x7V1qSxOcJIrH" + + "/ZOaAKV5p8JgJSPJGMr97PNcxqOiRXLiRI8nONoIGO55z/8AqyeldhPcQxwyOzoQ" + + "owRkflXH6t4q0nTLjy57mNXfJCA5x+Qx0NAGXd6LD5iiaPYwTAAx07+vXvXOXmiR" + + "Qu6u5VTk/MQQV7cdvxPT866KbxTpt7HGR8p7SMw5HuOP8/Ws/ULlb2No0bKMOGBJ" + + "BHrjHHXn6D8QDzWZQk8iAYVWIA9K6LwDZNeeJ4sEqsaF2YHBHpz2/wA/WsG+V0vZ" + + "kkGGVsEZz9OcntXffC62iiS7vJTsklKxRFuAw6nBP+eKAPRKKKKAOiqOSNJYzHIo" + + "ZGGCD0NSUUAeRajIunwzQG4e3tYZTHGsPzOxJ6ADuQcH8Pw5v+19Q0rVJVgl1JG3" + + "cxykEj13cnHT1r1C38OQ3l063cIkkhmkZDKSeCfx9R/kVLeeGIRKs7hVVDn5OCx9" + + "yeTjqMf0oAo3k1xP4biuJFeKV4w7gDaQcen1/wAjt5gbK81HW41kIiJBZppULe47" + + "eoxx+YzivW9Vh/0FAE+XPIJGCOR0rnbPT7eG+LyxlkAG1wQSPXrjvg9MfjQBycNj" + + "4hMRZgJkUjETQqAy/UAY6DoO/wCNbVlYTNbSNJbmBlBwoUfM30B7j2/lz20VhbKA" + + "wHmZOQWbOfyrO1G3jil8tBhWToOcdu+c/wAvagDzbUdGlu9aRxFiB/vsuBggZOfq" + + "cfWujSIR2dnNZTEeXKgMcb4BUHjofbjNKmI5juiabaGGxVJLcdh/nFWtI0oxagsD" + + "DIkkWXYp4VQDnOemSfyHbigDtgSQMjBI6HqKKKKAOiopoPXjGKdQBnXLiDUI5SMK" + + "VwxHGf8APFUtW1A+YkMKmbnc23njuf6D/ObWquoaNSQCM/rwP1rMYxxTGWR1UsoU" + + "biAcdep+o/KgDG1LxdpracIirCVRjaykHr6cHGQe1cv/AGjNcXBW3sntyT/rHcjj" + + "Hp6Z+nQdAK6PXIdIvcE3Fv5rEfNgP9eRn8c8d/rgzX2i2sqo1y8745CD5WPseOnH" + + "f8aANiz1O9gjiR5FMUhAV1wcH0Ix6jHHSrMsskz7pGy2MZNc8PEEM7xxWsM/lr8r" + + "b4jtI9CcHt7nr7Vqi4JuEjB2qse9y2Ace47dRn/OQDMuRMl8RHw7SgDBPGT6jpwf" + + "yzXa2NmbYF3IMrDB2kkAe3HP5Vwk99u1hdg3ANuOOOB0z6ZwPz6c8eiAhgCDkHkE" + + "cgigBaKKKAOiqJiMEb9mBknjim3LFIGcOU285ArNa8mKIN3QclScn6+/FADL9xOc" + + "K2Tj7xAxnAwQPqOmawdSNpeSJBfQyGNXwQpIAPvjqOPyPT12nYsxYnJIGSeMnHP+" + + "e9UL7TUumEqOYp1GNw6N/vDv/wDXoA5+70vSbFGlhtopUxkBl3EZ45z7/kKwTdpN" + + "cIsOmeSCduUiCnB9cdeg/M/j0v8AbFtY5hu0gjmGSRICT19cdMDt3+lULzxPZGZv" + + "LXcBnCrwB6Y4PX+ZoAptMRbiMDAGSSMksf8A9Q6DuKzJtVYs+BvcPgMTkEdOTnrx" + + "/KoLzVmvZZQjjaT82DyPbqcdx+GKitLf7TNsLYAGWPfH+TQBcsYJDE0rOyu4wjHk" + + "gfQ+p/zzWjpnja5sdSOm6yyK0Z2pMCQjZ+6SM9CCMdhnp3E1hYy393FaW0eXfjAx" + + "gAdT26D+X4Vg/EuFLbxOsCYBitkQkEdsgcADsB+lAHplvqUbsu5vlYA5PIB7468e" + + "nPf8lfUlDkRRrIvqZNn6EV41o3iO/wBFcCJ/MhBP7pjwD6g9ua7G08b6TcRl7h5L" + + "eTPKvGz5+hUH9cUAeo3uFDrt+Y4O7HOOB69Pr/8AXqhUlx/r2/z2qOgBCQoJJwBy" + + "SeABXHeIfHVvbXcemaW4luHlVJJlIKxjODgg8nqKq/Em6uItOhWOeVAx5CuRnrXn" + + "+jf8hyw/6+Y//QhQB6xrmlxzXc0NyuHVyQcdjnBz379D1BGeK5u88LMJGlt2RlX7" + + "qkEsPXn6/pXo/ilVzbttG7DDOOeornqAONbRpI4v3pKOQcAqQD+Y/P6j052NK0p5" + + "HWHy3IBPyqrfN6gZz+P4/hpXoGzOOiP/ACNdH4XRftsp2jIBxx70AX9E0pdMtvMm" + + "VRNt5xyEGOgPf3NeDeLdVOs+J768zlGkKx+yjgfy/WvoPXeNEvMcfujXzJQAUUUU" + + "Af/ZiQBGBBARAgAGBQI9katEAAoJECogGI6Hgm84xz8AoNGz1fJrVPxqkBrUDmWA" + + "GsP6qVGYAJ0ZOftw/GfQHzdGR8pOK85DLUPEErQkUmFsZiBIYXVzZXIgPGhhdXNl" + + "ckBwcml2YXNwaGVyZS5jb20+iQBGBBARAgAGBQI9katmAAoJECogGI6Hgm84m0oA" + + "oJS3CTrgpqRZfhgPtHGtUVjRCJbbAJ9stJgPcbqA2xXEg9yl2TQToWdWxbQkUmFs" + + "ZiBIYXVzZXIgPGhhdXNlckBwcml2YXNwaGVyZS5vcmc+iQBGBBARAgAGBQI9kauJ" + + "AAoJECogGI6Hgm84GfAAnRswktLMzDfIjv6ni76Qp5B850byAJ90I0LEHOLhda7r" + + "kqTwZ8rguNssUrQkUmFsZiBIYXVzZXIgPGhhdXNlckBwcml2YXNwaGVyZS5uZXQ+" + + "iQBGBBARAgAGBQI9kaubAAoJECogGI6Hgm84zi0An16C4s/B9Z0/AtfoN4ealMh3" + + "i3/7AJ9Jg4GOUqGCGRRKUA9Gs5pk8yM8GbQmUmFsZiBDLiBIYXVzZXIgPHJhbGZo" + + "YXVzZXJAYmx1ZXdpbi5jaD6JAEYEEBECAAYFAj2Rq8oACgkQKiAYjoeCbzhPOACg" + + "iiTohKuIa66FNiI24mQ+XR9nTisAoLmh3lJf16/06qLPsRd9shTkLfmHtB9SYWxm" + + "IEhhdXNlciA8cmFsZmhhdXNlckBnbXguY2g+iQBGBBARAgAGBQI9kavvAAoJECog" + + "GI6Hgm84ZE8An0RlgL8mPBa/P08S5e/lD35MlDdgAJ99pjCeY46S9+nVyx7ACyKO" + + "SZ4OcLQmUmFsZiBIYXVzZXIgPGhhdXNlci5yYWxmQG15c3VucmlzZS5jaD6JAEYE" + + "EBECAAYFAj2RrEEACgkQKiAYjoeCbzjz0wCg+q801XrXk+Rf+koSI50MW5OaaKYA" + + "oKOVA8SLxE29qSR/bJeuW0ryzRLqtCVSYWxmIEhhdXNlciA8aGF1c2VyLnJhbGZA" + + "ZnJlZXN1cmYuY2g+iQBGBBARAgAGBQI9kaxXAAoJECogGI6Hgm848zoAnRBtWH6e" + + "fTb3is63s8J2zTfpsyS0AKDxTjl+ZZV0COHLrSCaNLZVcpImFrkEDQQ9kar+EBAA" + + "+RigfloGYXpDkJXcBWyHhuxh7M1FHw7Y4KN5xsncegus5D/jRpS2MEpT13wCFkiA" + + "tRXlKZmpnwd00//jocWWIE6YZbjYDe4QXau2FxxR2FDKIldDKb6V6FYrOHhcC9v4" + + "TE3V46pGzPvOF+gqnRRh44SpT9GDhKh5tu+Pp0NGCMbMHXdXJDhK4sTw6I4TZ5dO" + + "khNh9tvrJQ4X/faY98h8ebByHTh1+/bBc8SDESYrQ2DD4+jWCv2hKCYLrqmus2UP" + + "ogBTAaB81qujEh76DyrOH3SET8rzF/OkQOnX0ne2Qi0CNsEmy2henXyYCQqNfi3t" + + "5F159dSST5sYjvwqp0t8MvZCV7cIfwgXcqK61qlC8wXo+VMROU+28W65Szgg2gGn" + + "VqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09jdvOmeFX" + + "klnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2gpXI61Brwv0YAWCvl" + + "9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPAQ/ClWxiNjrtVjLhd" + + "ONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrKlQzZlp+r" + + "0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVes91hcAAgIQAKD9MGkS8SUD2irI" + + "AiwVHU0WXLBnk2CvvueSmT9YtC34UKkIkDPZ7VoeuXDfqTOlbiE6T16zPvArZfbl" + + "JGdrU7HhsTdu+ADxRt1dPur0G0ICJ3pBD3ydGWpdLI/94x1BvTY4rsR5mS4YWmpf" + + "e2kWc7ZqezhP7Xt9q7m4EK456ddeUZWtkwGU+PKyRAZ+CK82Uhouw+4aW0NjiqmX" + + "hfH9/BUhI1P/8R9VkTfAFGPmZzqoHr4AuO5tLRLD2RFSmQCP8nZTiP9nP+wBBvn7" + + "vuqKRQsj9PwwPD4V5SM+kpW+rUIWr9TZYl3UqSnlXlpEZFd2Bfl6NloeH0cfU69E" + + "gtjcWGvGxYKPS0cg5yhVb4okka6RqIPQiYl6eJgv4tRTKoPRX29o0aUVdqVvDr5u" + + "tnFzcINq7jTo8GiO8Ia3cIFWfo0LyQBd1cf1U+eEOz+DleEFqyljaz9VCbDPE4GP" + + "o+ALESBlOwn5daUSaah9iU8aVPaSjn45hoQqxOKPwJxnCKKQ01iy0Gir+CDU8JJB" + + "7bmbvQN4bke30EGAeED3oi+3VaBHrhjYLv7SHIxP5jtCJKWMJuLRV709HsWJi3kn" + + "fGHwH+yCDF8+PDeROAzpXBaD2EFhKgeUTjP5Rgn6ltRf8TQnfbW4qlwyiXMhPOfC" + + "x6qNmwaFPKQJpIkVq5VGfRXAERfkiQBMBBgRAgAMBQI9kar+BRsMAAAAAAoJECog" + + "GI6Hgm84CDMAoNrNeP4c8XqFJnsLLPcjk5YGLaVIAKCrL5KFuLQVIp7d0Fkscx3/" + + "7DGrzw=="); + + private static readonly byte[] aesSecretKey = Base64.Decode( + "lQHpBEBSdIYRBADpd7MeIxRk4RsvyMnJNIYe4FiVv6i7I7+LPRvnIjDct0bN" + + "1gCV48QFej7g/PsvXRjYSowV3VIvchWX8OERd/5i10cLbcs7X52EP1vwYaLj" + + "uRfNUBg8Q51RQsKR+/rBmnVsi68rjU4yTH6wpo6FOO4pz4wFV+tWwGOwOitA" + + "K31L4wCgqh59eFFBrOlRFAbDvaL7emoCIR8EAOLxDKiLQJYQrKZfXdZnifeo" + + "dhEP0uuV4O5TG6nrqkhWffzC9cSoFD0BhMl979d8IB2Uft4FNvQc2u8hbJL5" + + "7OCGDCUAidlB9jSdu0/J+kfRaTGhYDjBgw7AA42576BBSMNouJg/aOOQENEN" + + "Nn4n7NxR3viBzIsL/OIeU8HSkBgaA/41PsvcgZ3kwpdltJ/FVRWhmMmv/q/X" + + "qp1YOnF8xPU9bv2ofELrxJfRsbS4GW1etzD+nXs/woW4Vfixs01x+cutR4iF" + + "3hw+eU+yLToMPmmo8D2LUvX1SRODJpx5yBBeRIYv6nz9H3sQRDx3kaLASxDV" + + "jTxKmrLYnZz5w5qyVpvRyv4JAwKyWlhdblPudWBFXNkW5ydKn0AV2f51wEtj" + + "Zy0aLIeutVMSJf1ytLqjFqrnFe6pdJrHO3G00TE8OuFhftWosLGLbEGytDtF" + + "cmljIEguIEVjaGlkbmEgKHRlc3Qga2V5IC0gQUVTMjU2KSA8ZXJpY0Bib3Vu" + + "Y3ljYXN0bGUub3JnPohZBBMRAgAZBQJAUnSGBAsHAwIDFQIDAxYCAQIeAQIX" + + "gAAKCRBYt1NnUiCgeFKaAKCiqtOO+NQES1gJW6XuOGmSkXt8bQCfcuW7SXZH" + + "zxK1FfdcG2HEDs3YEVawAgAA"); + + private static readonly byte[] aesPublicKey = Base64.Decode( + "mQGiBEBSdIYRBADpd7MeIxRk4RsvyMnJNIYe4FiVv6i7I7+LPRvnIjDct0bN" + + "1gCV48QFej7g/PsvXRjYSowV3VIvchWX8OERd/5i10cLbcs7X52EP1vwYaLj" + + "uRfNUBg8Q51RQsKR+/rBmnVsi68rjU4yTH6wpo6FOO4pz4wFV+tWwGOwOitA" + + "K31L4wCgqh59eFFBrOlRFAbDvaL7emoCIR8EAOLxDKiLQJYQrKZfXdZnifeo" + + "dhEP0uuV4O5TG6nrqkhWffzC9cSoFD0BhMl979d8IB2Uft4FNvQc2u8hbJL5" + + "7OCGDCUAidlB9jSdu0/J+kfRaTGhYDjBgw7AA42576BBSMNouJg/aOOQENEN" + + "Nn4n7NxR3viBzIsL/OIeU8HSkBgaA/41PsvcgZ3kwpdltJ/FVRWhmMmv/q/X" + + "qp1YOnF8xPU9bv2ofELrxJfRsbS4GW1etzD+nXs/woW4Vfixs01x+cutR4iF" + + "3hw+eU+yLToMPmmo8D2LUvX1SRODJpx5yBBeRIYv6nz9H3sQRDx3kaLASxDV" + + "jTxKmrLYnZz5w5qyVpvRyrQ7RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSAt" + + "IEFFUzI1NikgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IWQQTEQIAGQUCQFJ0" + + "hgQLBwMCAxUCAwMWAgECHgECF4AACgkQWLdTZ1IgoHhSmgCfU83BLBF2nCua" + + "zk2dXB9zO1l6XS8AnA07U4cq5W0GrKM6/kP9HWtPhgOFsAIAAA=="); + + private static readonly byte[] twofishSecretKey = Base64.Decode( + "lQHpBEBSdtIRBACf7WfrqTl8F051+EbaljPf/8/ajFpAfMq/7p3Hri8OCsuc" + + "fJJIufEEOV1/Lt/wkN67MmSyrU0fUCsRbEckRiB4EJ0zGHVFfAnku2lzdgc8" + + "AVounqcHOmqA/gliFDEnhYOx3bOIAOav+yiOqfKVBhWRCpFdOTE+w/XoDM+p" + + "p8bH5wCgmP2FuWpzfSut7GVKp51xNEBRNuED/3t2Q+Mq834FVynmLKEmeXB/" + + "qtIz5reHEQR8eMogsOoJS3bXs6v3Oblj4in1gLyTVfcID5tku6kLP20xMRM2" + + "zx2oRbz7TyOCrs15IpRXyqqJxUWD8ipgJPkPXE7hK8dh4YSTUi4i5a1ug8xG" + + "314twlPzrchpWZiutDvZ+ks1rzOtBACHrEFG2frUu+qVkL43tySE0cV2bnuK" + + "LVhXbpzF3Qdkfxou2nuzsCbl6m87OWocJX8uYcQGlHLKv8Q2cfxZyieLFg6v" + + "06LSFdE9drGBWz7mbrT4OJjxPyvnkffPfLOOqae3PMYIIuscvswuhm4X5aoj" + + "KJs01YT3L6f0iIj03hCeV/4KAwLcGrxT3X0qR2CZyZYSVBdjXeNYKXuGBtOf" + + "ood26WOtwLw4+l9sHVoiXNv0LomkO58ndJRPGCeZWZEDMVrfkS7rcOlktDxF" + + "cmljIEguIEVjaGlkbmEgKHRlc3Qga2V5IC0gdHdvZmlzaCkgPGVyaWNAYm91" + + "bmN5Y2FzdGxlLm9yZz6IWQQTEQIAGQUCQFJ20gQLBwMCAxUCAwMWAgECHgEC" + + "F4AACgkQaCCMaHh9zR2+RQCghcQwlt4B4YmNxp2b3v6rP3E8M0kAn2Gspi4u" + + "A/ynoqnC1O8HNlbjPdlVsAIAAA=="); + + private static readonly byte[] twofishPublicKey = Base64.Decode( + "mQGiBEBSdtIRBACf7WfrqTl8F051+EbaljPf/8/ajFpAfMq/7p3Hri8OCsuc" + + "fJJIufEEOV1/Lt/wkN67MmSyrU0fUCsRbEckRiB4EJ0zGHVFfAnku2lzdgc8" + + "AVounqcHOmqA/gliFDEnhYOx3bOIAOav+yiOqfKVBhWRCpFdOTE+w/XoDM+p" + + "p8bH5wCgmP2FuWpzfSut7GVKp51xNEBRNuED/3t2Q+Mq834FVynmLKEmeXB/" + + "qtIz5reHEQR8eMogsOoJS3bXs6v3Oblj4in1gLyTVfcID5tku6kLP20xMRM2" + + "zx2oRbz7TyOCrs15IpRXyqqJxUWD8ipgJPkPXE7hK8dh4YSTUi4i5a1ug8xG" + + "314twlPzrchpWZiutDvZ+ks1rzOtBACHrEFG2frUu+qVkL43tySE0cV2bnuK" + + "LVhXbpzF3Qdkfxou2nuzsCbl6m87OWocJX8uYcQGlHLKv8Q2cfxZyieLFg6v" + + "06LSFdE9drGBWz7mbrT4OJjxPyvnkffPfLOOqae3PMYIIuscvswuhm4X5aoj" + + "KJs01YT3L6f0iIj03hCeV7Q8RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSAt" + + "IHR3b2Zpc2gpIDxlcmljQGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkFAkBS" + + "dtIECwcDAgMVAgMDFgIBAh4BAheAAAoJEGggjGh4fc0dvkUAn2QGdNk8Wrrd" + + "+DvKECrO5+yoPRx3AJ91DhCMme6uMrQorKSDYxHlgc7iT7ACAAA="); + + private static readonly char[] pass = "hello world".ToCharArray(); + + /** + * Generated signature test + * + * @param sKey + * @param pgpPrivKey + * @return test result + */ + public void GenerateTest( + PgpSecretKeyRing sKey, + PgpPublicKey pgpPubKey, + PgpPrivateKey pgpPrivKey) + { + string data = "hello world!"; + MemoryStream bOut = new MemoryStream(); + + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + MemoryStream testIn = new MemoryStream(dataBytes, false); + + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); + + IEnumerator enumerator = sKey.GetSecretKey().PublicKey.GetUserIds().GetEnumerator(); + enumerator.MoveNext(); + string primaryUserId = (string) enumerator.Current; + + spGen.SetSignerUserId(true, primaryUserId); + + sGen.SetHashedSubpackets(spGen.Generate()); + + PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + + DateTime testDateTime = new DateTime(1973, 7, 27); + Stream lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Binary, + "_CONSOLE", + dataBytes.Length, + testDateTime); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte) ch); + sGen.Update((byte)ch); + } + + lGen.Close(); + + sGen.Generate().Encode(bcOut); + + cGen.Close(); + + PgpObjectFactory pgpFact = new PgpObjectFactory(bOut.ToArray()); + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData) pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pgpPubKey); + + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte) ch); + } + + PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed generated signature check"); + } + } + + public override void PerformTest() + { + PgpPublicKey pubKey = null; + + // + // Read the public key + // + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey); + + pubKey = pgpPub.GetPublicKey(); + + // + // Read the private key + // + PgpSecretKeyRing sKey = new PgpSecretKeyRing(testPrivKey); + PgpSecretKey secretKey = sKey.GetSecretKey(); + PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(pass); + + // + // test signature message + // + PgpObjectFactory pgpFact = new PgpObjectFactory(sig1); + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pubKey); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte) ch); + } + + PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed signature check"); + } + + // + // signature generation + // + GenerateTest(sKey, pubKey, pgpPrivKey); + + // + // signature generation - canonical text + // + const string data = "hello world!"; + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(dataBytes, false); + PgpSignatureGenerator sGen = new PgpSignatureGenerator( + PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey); + + PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + DateTime testDateTime = new DateTime(1973, 7, 27); + Stream lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Text, + "_CONSOLE", + dataBytes.Length, + testDateTime); + + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte) ch); + sGen.Update((byte)ch); + } + + lGen.Close(); + + sGen.Generate().Encode(bcOut); + + cGen.Close(); + + // + // verify Generated signature - canconical text + // + pgpFact = new PgpObjectFactory(bOut.ToArray()); + + c1 = (PgpCompressedData) pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + p1 = (PgpOnePassSignatureList) pgpFact.NextPgpObject(); + + ops = p1[0]; + + p2 = (PgpLiteralData) pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + dIn = p2.GetInputStream(); + + ops.InitVerify(pubKey); + + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + p3 = (PgpSignatureList) pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed generated signature check"); + } + + // + // Read the public key with user attributes + // + pgpPub = new PgpPublicKeyRing(testPubWithUserAttr); + + pubKey = pgpPub.GetPublicKey(); + + int count = 0; + foreach (PgpUserAttributeSubpacketVector attributes in pubKey.GetUserAttributes()) + { + int sigCount = 0; + foreach (object sigs in pubKey.GetSignaturesForUserAttribute(attributes)) + { + if (sigs == null) + Fail("null signature found"); + + sigCount++; + } + + if (sigCount != 1) + { + Fail("Failed user attributes signature check"); + } + + count++; + } + + if (count != 1) + { + Fail("Failed user attributes check"); + } + + byte[] pgpPubBytes = pgpPub.GetEncoded(); + pgpPub = new PgpPublicKeyRing(pgpPubBytes); + pubKey = pgpPub.GetPublicKey(); + count = 0; + + foreach (object ua in pubKey.GetUserAttributes()) + { + if (ua == null) + Fail("null user attribute found"); + + count++; + } + + if (count != 1) + { + Fail("Failed user attributes reread"); + } + + // + // reading test extra data - key with edge condition for DSA key password. + // + char[] passPhrase = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + + sKey = new PgpSecretKeyRing(testPrivKey2); + pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(passPhrase); + + // + // reading test - aes256 encrypted passphrase. + // + sKey = new PgpSecretKeyRing(aesSecretKey); + pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass); + + // + // reading test - twofish encrypted passphrase. + // + sKey = new PgpSecretKeyRing(twofishSecretKey); + pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass); + + // + // use of PgpKeyPair + // + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, new SecureRandom()); // TODO Is the certainty okay? + DsaParameters dsaParams = pGen.GenerateParameters(); + DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams); + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + kpg.Init(kgp); + + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + + PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, + kp.Public, kp.Private, DateTime.UtcNow); + + PgpPublicKey k1 = pgpKp.PublicKey; + PgpPrivateKey k2 = pgpKp.PrivateKey; + } + + public override string Name + { + get { return "PGPDSATest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpDsaTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPPBETest.cs b/crypto/test/src/openpgp/test/PGPPBETest.cs new file mode 100644 index 000000000..621cef684 --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPPBETest.cs @@ -0,0 +1,384 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpPbeTest + : SimpleTest + { + private static readonly DateTime TestDateTime = new DateTime(2003, 8, 29, 23, 35, 11, 0); + + private static readonly byte[] enc1 = Base64.Decode( + "jA0EAwMC5M5wWBP2HBZgySvUwWFAmMRLn7dWiZN6AkQMvpE3b6qwN3SSun7zInw2" + + "hxxdgFzVGfbjuB8w"); +// private static readonly byte[] enc1crc = Base64.Decode("H66L"); + private static readonly char[] pass = "hello world".ToCharArray(); + + /** + * Message with both PBE and symmetric + */ + private static readonly byte[] testPBEAsym = Base64.Decode( + "hQIOA/ZlQEFWB5vuEAf/covEUaBve7NlWWdiO5NZubdtTHGElEXzG9hyBycp9At8" + + "nZGi27xOZtEGFQo7pfz4JySRc3O0s6w7PpjJSonFJyNSxuze2LuqRwFWBYYcbS8/" + + "7YcjB6PqutrT939OWsozfNqivI9/QyZCjBvFU89pp7dtUngiZ6MVv81ds2I+vcvk" + + "GlIFcxcE1XoCIB3EvbqWNaoOotgEPT60unnB2BeDV1KD3lDRouMIYHfZ3SzBwOOI" + + "6aK39sWnY5sAK7JjFvnDAMBdueOiI0Fy+gxbFD/zFDt4cWAVSAGTC4w371iqppmT" + + "25TM7zAtCgpiq5IsELPlUZZnXKmnYQ7OCeysF0eeVwf+OFB9fyvCEv/zVQocJCg8" + + "fWxfCBlIVFNeNQpeGygn/ZmRaILvB7IXDWP0oOw7/F2Ym66IdYYIp2HeEZv+jFwa" + + "l41w5W4BH/gtbwGjFQ6CvF/m+lfUv6ZZdzsMIeEOwhP5g7rXBxrbcnGBaU+PXbho" + + "gjDqaYzAWGlrmAd6aPSj51AGeYXkb2T1T/yoJ++M3GvhH4C4hvitamDkksh/qRnM" + + "M/s8Nku6z1+RXO3M6p5QC1nlAVqieU8esT43945eSoC77K8WyujDNbysDyUCUTzt" + + "p/aoQwe/HgkeOTJNelKR9y2W3xinZLFzep0SqpNI/e468yB/2/LGsykIyQa7JX6r" + + "BYwuBAIDAkOKfv5rK8v0YDfnN+eFqwhTcrfBj5rDH7hER6nW3lNWcMataUiHEaMg" + + "o6Q0OO1vptIGxW8jClTD4N1sCNwNu9vKny8dKYDDHbCjE06DNTv7XYVW3+JqTL5E" + + "BnidvGgOmA=="); + + /** + * decrypt the passed in message stream + */ + private byte[] DecryptMessage( + byte[] message) + { + PgpObjectFactory pgpF = new PgpObjectFactory(message); + PgpEncryptedDataList enc = (PgpEncryptedDataList) pgpF.NextPgpObject(); + PgpPbeEncryptedData pbe = (PgpPbeEncryptedData) enc[0]; + Stream clear = pbe.GetDataStream(pass); + + PgpObjectFactory pgpFact = new PgpObjectFactory(clear); + PgpCompressedData cData = (PgpCompressedData) pgpFact.NextPgpObject(); + pgpFact = new PgpObjectFactory(cData.GetDataStream()); + + PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject(); + + if (!ld.FileName.Equals("test.txt") + && !ld.FileName.Equals("_CONSOLE")) + { + Fail("wrong filename in packet"); + } + + if (!ld.ModificationTime.Equals(TestDateTime)) + { + Fail("wrong modification time in packet: " + ld.ModificationTime + " vs " + TestDateTime); + } + + Stream unc = ld.GetInputStream(); + byte[] bytes = Streams.ReadAll(unc); + + if (pbe.IsIntegrityProtected() && !pbe.Verify()) + { + Fail("integrity check failed"); + } + + return bytes; + } + + private byte[] DecryptMessageBuffered( + byte[] message) + { + PgpObjectFactory pgpF = new PgpObjectFactory(message); + PgpEncryptedDataList enc = (PgpEncryptedDataList) pgpF.NextPgpObject(); + PgpPbeEncryptedData pbe = (PgpPbeEncryptedData) enc[0]; + + Stream clear = pbe.GetDataStream(pass); + + PgpObjectFactory pgpFact = new PgpObjectFactory(clear); + PgpCompressedData cData = (PgpCompressedData) pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(cData.GetDataStream()); + + PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject(); + + MemoryStream bOut = new MemoryStream(); + if (!ld.FileName.Equals("test.txt") + && !ld.FileName.Equals("_CONSOLE")) + { + Fail("wrong filename in packet"); + } + if (!ld.ModificationTime.Equals(TestDateTime)) + { + Fail("wrong modification time in packet: " + ld.ModificationTime.Ticks + " " + TestDateTime.Ticks); + } + + Stream unc = ld.GetInputStream(); + byte[] buf = new byte[1024]; + + int len; + while ((len = unc.Read(buf, 0, buf.Length)) > 0) + { + bOut.Write(buf, 0, len); + } + + if (pbe.IsIntegrityProtected() && !pbe.Verify()) + { + Fail("integrity check failed"); + } + + return bOut.ToArray(); + } + + public override void PerformTest() + { + byte[] data = DecryptMessage(enc1); + if (data[0] != 'h' || data[1] != 'e' || data[2] != 'l') + { + Fail("wrong plain text in packet"); + } + + // + // create a PBE encrypted message and read it back. + // + byte[] text = Encoding.ASCII.GetBytes("hello world!\n"); + + // + // encryption step - convert to literal data, compress, encode. + // + MemoryStream bOut = new UncloseableMemoryStream(); + + PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); + Stream comOut = comData.Open(new UncloseableStream(bOut)); + Stream ldOut = lData.Open( + new UncloseableStream(comOut), + PgpLiteralData.Binary, + PgpLiteralData.Console, + text.Length, + TestDateTime); + + ldOut.Write(text, 0, text.Length); + ldOut.Close(); + + comOut.Close(); + + // + // encrypt - with stream close + // + MemoryStream cbOut = new UncloseableMemoryStream(); + PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, new SecureRandom()); + + cPk.AddMethod(pass); + + byte[] bOutData = bOut.ToArray(); + Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length); + cOut.Write(bOutData, 0, bOutData.Length); + cOut.Close(); + + data = DecryptMessage(cbOut.ToArray()); + if (!Arrays.AreEqual(data, text)) + { + Fail("wrong plain text in generated packet"); + } + + // + // encrypt - with generator close + // + cbOut = new UncloseableMemoryStream(); + cPk = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, new SecureRandom()); + + cPk.AddMethod(pass); + + bOutData = bOut.ToArray(); + cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length); + cOut.Write(bOutData, 0, bOutData.Length); + + cPk.Close(); + + data = DecryptMessage(cbOut.ToArray()); + + if (!AreEqual(data, text)) + { + Fail("wrong plain text in generated packet"); + } + + // + // encrypt - partial packet style. + // + SecureRandom rand = new SecureRandom(); + byte[] test = new byte[1233]; + + rand.NextBytes(test); + + bOut = new UncloseableMemoryStream(); + + comData = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + comOut = comData.Open(new UncloseableStream(bOut)); + + lData = new PgpLiteralDataGenerator(); + ldOut = lData.Open( + new UncloseableStream(comOut), + PgpLiteralData.Binary, + PgpLiteralData.Console, + TestDateTime, + new byte[16]); + + ldOut.Write(test, 0, test.Length); + lData.Close(); + + comData.Close(); + cbOut = new UncloseableMemoryStream(); + cPk = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, rand); + + cPk.AddMethod(pass); + + cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]); + { + byte[] tmp = bOut.ToArray(); + cOut.Write(tmp, 0, tmp.Length); + } + + cPk.Close(); + + data = DecryptMessage(cbOut.ToArray()); + if (!Arrays.AreEqual(data, test)) + { + Fail("wrong plain text in generated packet"); + } + + // + // with integrity packet + // + cbOut = new UncloseableMemoryStream(); + cPk = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Cast5, true, rand); + + cPk.AddMethod(pass); + + cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]); + bOutData = bOut.ToArray(); + cOut.Write(bOutData, 0, bOutData.Length); + cPk.Close(); + + data = DecryptMessage(cbOut.ToArray()); + if (!Arrays.AreEqual(data, test)) + { + Fail("wrong plain text in generated packet"); + } + + // + // decrypt with buffering + // + data = DecryptMessageBuffered(cbOut.ToArray()); + if (!AreEqual(data, test)) + { + Fail("wrong plain text in buffer generated packet"); + } + + // + // sample message + // + PgpObjectFactory pgpFact = new PgpObjectFactory(testPBEAsym); + + PgpEncryptedDataList enc = (PgpEncryptedDataList)pgpFact.NextPgpObject(); + + PgpPbeEncryptedData pbe = (PgpPbeEncryptedData) enc[1]; + + Stream clear = pbe.GetDataStream("password".ToCharArray()); + + pgpFact = new PgpObjectFactory(clear); + + PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject(); + + Stream unc = ld.GetInputStream(); + byte[] bytes = Streams.ReadAll(unc); + + if (!AreEqual(bytes, Hex.Decode("5361742031302e30322e30370d0a"))) + { + Fail("data mismatch on combined PBE"); + } + + // + // with integrity packet - one byte message + // + byte[] msg = new byte[1]; + bOut = new MemoryStream(); + + comData = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + lData = new PgpLiteralDataGenerator(); + comOut = comData.Open(new UncloseableStream(bOut)); + ldOut = lData.Open( + new UncloseableStream(comOut), + PgpLiteralData.Binary, + PgpLiteralData.Console, + msg.Length, + TestDateTime); + + ldOut.Write(msg, 0, msg.Length); + + ldOut.Close(); + + comOut.Close(); + + cbOut = new MemoryStream(); + cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, rand); + + cPk.AddMethod(pass); + + cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]); + + data = bOut.ToArray(); + cOut.Write(data, 0, data.Length); + + cOut.Close(); + + data = DecryptMessage(cbOut.ToArray()); + if (!AreEqual(data, msg)) + { + Fail("wrong plain text in generated packet"); + } + + // + // decrypt with buffering + // + data = DecryptMessageBuffered(cbOut.ToArray()); + if (!AreEqual(data, msg)) + { + Fail("wrong plain text in buffer generated packet"); + } + } + + private class UncloseableMemoryStream + : MemoryStream + { + public override void Close() + { + throw new Exception("Close() called on underlying stream"); + } + } + + public override string Name + { + get { return "PGPPBETest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpPbeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPPacketTest.cs b/crypto/test/src/openpgp/test/PGPPacketTest.cs new file mode 100644 index 000000000..b82f8526f --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPPacketTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpPacketTest + : SimpleTest + { + private static int MAX = 32000; + + private void ReadBackTest( + PgpLiteralDataGenerator generator) + { + Random rand = new Random(); + byte[] buf = new byte[MAX]; + + rand.NextBytes(buf); + + for (int i = 1; i != MAX; i++) + { + MemoryStream bOut = new MemoryStream(); + + Stream outputStream = generator.Open( + new UncloseableStream(bOut), + PgpLiteralData.Binary, + PgpLiteralData.Console, + i, + DateTime.UtcNow); + + outputStream.Write(buf, 0, i); + + generator.Close(); + + PgpObjectFactory fact = new PgpObjectFactory(bOut.ToArray()); + + PgpLiteralData data = (PgpLiteralData)fact.NextPgpObject(); + + Stream inputStream = data.GetInputStream(); + + for (int count = 0; count != i; count++) + { + if (inputStream.ReadByte() != (buf[count] & 0xff)) + { + Fail("failed readback test - length = " + i); + } + } + } + } + + public override void PerformTest() + { + ReadBackTest(new PgpLiteralDataGenerator(true)); + ReadBackTest(new PgpLiteralDataGenerator(false)); + } + + public override string Name + { + get { return "PGPPacketTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpPacketTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPRSATest.cs b/crypto/test/src/openpgp/test/PGPRSATest.cs new file mode 100644 index 000000000..f38aa002f --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPRSATest.cs @@ -0,0 +1,1235 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Bcpg.Attr; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpRsaTest + : SimpleTest + { + private static readonly byte[] testPubKey = Base64.Decode( + "mIsEPz2nJAEEAOTVqWMvqYE693qTgzKv/TJpIj3hI8LlYPC6m1dk0z3bDLwVVk9F" + + "FAB+CWS8RdFOWt/FG3tEv2nzcoNdRvjv9WALyIGNawtae4Ml6oAT06/511yUzXHO" + + "k+9xK3wkXN5jdzUhf4cA2oGpLSV/pZlocsIDL+jCUQtumUPwFodmSHhzAAYptC9F" + + "cmljIEVjaGlkbmEgKHRlc3Qga2V5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPoi4" + + "BBMBAgAiBQI/PackAhsDBQkAg9YABAsHAwIDFQIDAxYCAQIeAQIXgAAKCRA1WGFG" + + "/fPzc8WMA/9BbjuB8E48QAlxoiVf9U8SfNelrz/ONJA/bMvWr/JnOGA9PPmFD5Uc" + + "+kV/q+i94dEMjsC5CQ1moUHWSP2xlQhbOzBP2+oPXw3z2fBs9XJgnTH6QWMAAvLs" + + "3ug9po0loNHLobT/D/XdXvcrb3wvwvPT2FptZqrtonH/OdzT9JdfrA=="); + + private static readonly byte[] testPrivKey = Base64.Decode( + "lQH8BD89pyQBBADk1aljL6mBOvd6k4Myr/0yaSI94SPC5WDwuptXZNM92wy8FVZP" + + "RRQAfglkvEXRTlrfxRt7RL9p83KDXUb47/VgC8iBjWsLWnuDJeqAE9Ov+ddclM1x" + + "zpPvcSt8JFzeY3c1IX+HANqBqS0lf6WZaHLCAy/owlELbplD8BaHZkh4cwAGKf4D" + + "AwKbLeIOVYTEdWD5v/YgW8ERs0pDsSIfBTvsJp2qA798KeFuED6jGsHUzdi1M990" + + "6PRtplQgnoYmYQrzEc6DXAiAtBR4Kuxi4XHx0ZR2wpVlVxm2Ypgz7pbBNWcWqzvw" + + "33inl7tR4IDsRdJOY8cFlN+1tSCf16sDidtKXUVjRjZNYJytH18VfSPlGXMeYgtw" + + "3cSGNTERwKaq5E/SozT2MKTiORO0g0Mtyz+9MEB6XVXFavMun/mXURqbZN/k9BFb" + + "z+TadpkihrLD1xw3Hp+tpe4CwPQ2GdWKI9KNo5gEnbkJgLrSMGgWalPhknlNHRyY" + + "bSq6lbIMJEE3LoOwvYWwweR1+GrV9farJESdunl1mDr5/d6rKru+FFDwZM3na1IF" + + "4Ei4FpqhivZ4zG6pN5XqLy+AK85EiW4XH0yAKX1O4YlbmDU4BjxhiwTdwuVMCjLO" + + "5++jkz5BBQWdFX8CCMA4FJl36G70IbGzuFfOj07ly7QvRXJpYyBFY2hpZG5hICh0" + + "ZXN0IGtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IuAQTAQIAIgUCPz2nJAIb" + + "AwUJAIPWAAQLBwMCAxUCAwMWAgECHgECF4AACgkQNVhhRv3z83PFjAP/QW47gfBO" + + "PEAJcaIlX/VPEnzXpa8/zjSQP2zL1q/yZzhgPTz5hQ+VHPpFf6voveHRDI7AuQkN" + + "ZqFB1kj9sZUIWzswT9vqD18N89nwbPVyYJ0x+kFjAALy7N7oPaaNJaDRy6G0/w/1" + + "3V73K298L8Lz09habWaq7aJx/znc0/SXX6w="); + + private static readonly byte[] testPubKeyV3 = Base64.Decode( + "mQCNAz+zvlEAAAEEAMS22jgXbOZ/D3xWgM2kauSdzrwlU7Ms5hDW05ObqQyO" + + "FfQoKKMhfupyoa7J3x04VVBKu6Eomvr1es+VImH0esoeWFFahNOYq/I+jRRB" + + "woOhAGZ5UB2/hRd7rFmxqp6sCXi8wmLO2tAorlTzAiNNvl7xF4cQZpc0z56F" + + "wdi2fBUJAAURtApGSVhDSVRZX1FBiQCVAwUQP7O+UZ6Fwdi2fBUJAQFMwwQA" + + "qRnFsdg4xQnB8Y5d4cOpXkIn9AZgYS3cxtuSJB84vG2CgC39nfv4c+nlLkWP" + + "4puG+mZuJNgVoE84cuAF4I//1anKjlU7q1M6rFQnt5S4uxPyG3dFXmgyU1b4" + + "PBOnA0tIxjPzlIhJAMsPCGGA5+5M2JP0ad6RnzqzE3EENMX+GqY="); + + private static readonly byte[] testPrivKeyV3 = Base64.Decode( + "lQHfAz+zvlEAAAEEAMS22jgXbOZ/D3xWgM2kauSdzrwlU7Ms5hDW05ObqQyO" + + "FfQoKKMhfupyoa7J3x04VVBKu6Eomvr1es+VImH0esoeWFFahNOYq/I+jRRB" + + "woOhAGZ5UB2/hRd7rFmxqp6sCXi8wmLO2tAorlTzAiNNvl7xF4cQZpc0z56F" + + "wdi2fBUJAAURAXWwRBZQHNikA/f0ScLLjrXi4s0hgQecg+dkpDow94eu5+AR" + + "0DzZnfurpgfUJCNiDi5W/5c3Zj/xyrfMAgkbCgJ1m6FZqAQh7Mq73l7Kfu4/" + + "XIkyDF3tDgRuZNezB+JuElX10tV03xumHepp6M6CfhXqNJ15F33F99TA5hXY" + + "CPYD7SiSOpIhQkCOAgDAA63imxbpuKE2W7Y4I1BUHB7WQi8ZdkZd04njNTv+" + + "rFUuOPapQVfbWG0Vq8ld3YmJB4QWsa2mmqn+qToXbwufAgBpXkjvqK5yPiHF" + + "Px2QbFc1VqoCJB6PO5JRIqEiUZBFGdDlLxt3VSyqz7IZ/zEnxZq+tPCGGGSm" + + "/sAGiMvENcHVAfy0kTXU42TxEAYJyyNyqjXOobDJpEV1mKhFskRXt7tbMfOS" + + "Yf91oX8f6xw6O2Nal+hU8dS0Bmfmk5/enHmvRLHQocO0CkZJWENJVFlfUUE="); + + private static readonly byte[] sig1 = Base64.Decode( + "owGbwMvMwMRoGpHo9vfz52LGNTJJnBmpOTn5eiUVJfb23JvAHIXy/KKcFEWuToap" + + "zKwMIGG4Bqav0SwMy3yParsEKi2LMGI9xhh65sBxb05n5++ZLcWNJ/eLFKdWbm95" + + "tHbDV7GMwj/tUctUpFUXWPYFCLdNsDiVNuXbQvZtdXV/5xzY+9w1nCnijH9JoNiJ" + + "22n2jo0zo30/TZLo+jDl2vTzIvPeLEsPM3ZUE/1Ytqs4SG2TxIQbH7xf3uzcYXq2" + + "5Fw9AA=="); + +// private static readonly byte[] sig1crc = Base64.Decode("+3i0"); + + private static readonly byte[] subKey = Base64.Decode( + "lQH8BD89pyQBBADk1aljL6mBOvd6k4Myr/0yaSI94SPC5WDwuptXZNM92wy8FVZP" + + "RRQAfglkvEXRTlrfxRt7RL9p83KDXUb47/VgC8iBjWsLWnuDJeqAE9Ov+ddclM1x" + + "zpPvcSt8JFzeY3c1IX+HANqBqS0lf6WZaHLCAy/owlELbplD8BaHZkh4cwAGKf4D" + + "AwKt6ZC7iqsQHGDNn2ZAuhS+ZwiFC+BToW9Vq6rwggWjgM/SThv55rfDk7keiXUT" + + "MyUcZVeYBe4Jttb4fAAm83hNztFu6Jvm9ITcm7YvnasBtVQjppaB+oYZgsTtwK99" + + "LGC3mdexnriCLxPN6tDFkGhzdOcYZfK6py4Ska8Dmq9nOZU9Qtv7Pm3qa5tuBvYw" + + "myTxeaJYifZTu/sky3Gj+REb8WonbgAJX/sLNBPUt+vYko+lxU8uqZpVEMU//hGG" + + "Rns2gIHdbSbIe1vGgIRUEd7Z0b7jfVQLUwqHDyfh5DGvAUhvtJogjUyFIXZzpU+E" + + "9ES9t7LZKdwNZSIdNUjM2eaf4g8BpuQobBVkj/GUcotKyeBjwvKxHlRefL4CCw28" + + "DO3SnLRKxd7uBSqeOGUKxqasgdekM/xIFOrJ85k7p89n6ncLQLHCPGVkzmVeRZro" + + "/T7zE91J57qBGZOUAP1vllcYLty1cs9PCc5oWnj3XbQvRXJpYyBFY2hpZG5hICh0" + + "ZXN0IGtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IuAQTAQIAIgUCPz2nJAIb" + + "AwUJAIPWAAQLBwMCAxUCAwMWAgECHgECF4AACgkQNVhhRv3z83PFjAP/QW47gfBO" + + "PEAJcaIlX/VPEnzXpa8/zjSQP2zL1q/yZzhgPTz5hQ+VHPpFf6voveHRDI7AuQkN" + + "ZqFB1kj9sZUIWzswT9vqD18N89nwbPVyYJ0x+kFjAALy7N7oPaaNJaDRy6G0/w/1" + + "3V73K298L8Lz09habWaq7aJx/znc0/SXX6y0JEVyaWMgRWNoaWRuYSA8ZXJpY0Bi" + + "b3VuY3ljYXN0bGUub3JnPoi4BBMBAgAiBQI/RxQNAhsDBQkAg9YABAsHAwIDFQID" + + "AxYCAQIeAQIXgAAKCRA1WGFG/fPzc3O6A/49tXFCiiP8vg77OXvnmbnzPBA1G6jC" + + "RZNP1yIXusOjpHqyLN5K9hw6lq/o4pNiCuiq32osqGRX3lv/nDduJU1kn2Ow+I2V" + + "ci+ojMXdCGdEqPwZfv47jHLwRrIUJ22OOoWsORtgvSeRUd4Izg8jruaFM7ufr5hr" + + "jEl1cuLW1Hr8Lp0B/AQ/RxxQAQQA0J2BIdqb8JtDGKjvYxrju0urJVVzyI1CnCjA" + + "p7CtLoHQJUQU7PajnV4Jd12ukfcoK7MRraYydQEjxh2MqPpuQgJS3dgQVrxOParD" + + "QYBFrZNd2tZxOjYakhErvUmRo6yWFaxChwqMgl8XWugBNg1Dva+/YcoGQ+ly+Jg4" + + "RWZoH88ABin+AwMCldD/2v8TyT1ghK70IuFs4MZBhdm6VgyGR8DQ/Ago6IAjA4BY" + + "Sol3lJb7+IIGsZaXwEuMRUvn6dWfa3r2I0p1t75vZb1Ng1YK32RZ5DNzl4Xb3L8V" + + "D+1Fiz9mHO8wiplAwDudB+RmQMlth3DNi/UsjeCTdEJAT+TTC7D40DiHDb1bR86Y" + + "2O5Y7MQ3SZs3/x0D/Ob6PStjfQ1kiqbruAMROKoavG0zVgxvspkoKN7h7BapnwJM" + + "6yf4qN/aByhAx9sFvADxu6z3SVcxiFw3IgAmabyWYb85LP8AsTYAG/HBoC6yob47" + + "Mt+GEDeyPifzzGXBWYIH4heZbSQivvA0eRwY5VZsMsBkbY5VR0FLVWgplbuO21bS" + + "rPS1T0crC+Zfj7FQBAkTfsg8RZQ8MPaHng01+gnFd243DDFvTAHygvm6a2X2fiRw" + + "5epAST4wWfY/BZNOxmfSKH6QS0oQMRscw79He6vGTB7vunLrKQYD4veInwQYAQIA" + + "CQUCP0ccUAIbDAAKCRA1WGFG/fPzczmFA/wMg5HhN5NkqmjnHUFfeXNXdHzmekyw" + + "38RnuCMKmfc43AiDs+FtJ62gpQ6PEsZF4o9S5fxcjVk3VSg00XMDtQ/0BsKBc5Gx" + + "hJTq7G+/SoeM433WG19uoS0+5Lf/31wNoTnpv6npOaYpcTQ7L9LCnzwAF4H0hJPE" + + "6bhmW2CMcsE/IZUB4QQ/Rwc1EQQAs5MUQlRiYOfi3fQ1OF6Z3eCwioDKu2DmOxot" + + "BICvdoG2muvs0KEBas9bbd0FJqc92FZJv8yxEgQbQtQAiFxoIFHRTFK+SPO/tQm+" + + "r83nwLRrfDeVVdRfzF79YCc+Abuh8sS/53H3u9Y7DYWr9IuMgI39nrVhY+d8yukf" + + "jo4OR+sAoKS/f7V1Xxj/Eqhb8qzf+N+zJRUlBACDd1eo/zFJZcq2YJa7a9vkViME" + + "axvwApqxeoU7oDpeHEMWg2DXJ7V24ZU5SbPTMY0x98cc8pcoqwsqux8xicWc0reh" + + "U3odQxWM4Se0LmEdca0nQOmNJlL9IsQ+QOJzx47qUOUAqhxnkXxQ/6B8w+M6gZya" + + "fwSdy70OumxESZipeQP+Lo9x6FcaW9L78hDX0aijJhgSEsnGODKB+bln29txX37E" + + "/a/Si+pyeLMi82kUdIL3G3I5HPWd3qSO4K94062+HfFj8bA20/1tbb/WxvxB2sKJ" + + "i3IobblFOvFHo+v8GaLdVyartp0JZLue/jP1dl9ctulSrIqaJT342uLsgTjsr2z+" + + "AwMCAyAU8Vo5AhhgFkDto8vQk7yxyRKEzu5qB66dRcTlaUPIiR8kamcy5ZTtujs4" + + "KIW4j2M/LvagrpWfV5+0M0VyaWMgRWNoaWRuYSAoRFNBIFRlc3QgS2V5KSA8ZXJp" + + "Y0Bib3VuY3ljYXN0bGUub3JnPohZBBMRAgAZBQI/Rwc1BAsHAwIDFQIDAxYCAQIe" + + "AQIXgAAKCRDNI/XpxMo0QwJcAJ40447eezSiIMspuzkwsMyFN8YBaQCdFTuZuT30" + + "CphiUYWnsC0mQ+J15B4="); + + private static readonly byte[] enc1 = Base64.Decode( + "hIwDKwfQexPJboABA/4/7prhYYMORTiQ5avQKx0XYpCLujzGefYjnyuWZnx3Iev8" + + "Pmsguumm+OLLvtXhhkXQmkJRXbIg6Otj2ubPYWflRPgpJSgOrNOreOl5jeABOrtw" + + "bV6TJb9OTtZuB7cTQSCq2gmYiSZkluIiDjNs3R3mEanILbYzOQ3zKSggKpzlv9JQ" + + "AZUqTyDyJ6/OUbJF5fI5uiv76DCsw1zyMWotUIu5/X01q+AVP5Ly3STzI7xkWg/J" + + "APz4zUHism7kSYz2viAQaJx9/bNnH3AM6qm1Fuyikl4="); + +// private static readonly byte[] enc1crc = Base64.Decode("lv4o"); + +// private static readonly byte[] enc2 = Base64.Decode( +// "hIwDKwfQexPJboABBAC62jcJH8xKnKb1neDVmiovYON04+7VQ2v4BmeHwJrdag1g" +// + "Ya++6PeBlQ2Q9lSGBwLobVuJmQ7cOnPUJP727JeSGWlMyFtMbBSHekOaTenT5lj7" +// + "Zk7oRHxMp/hByzlMacIDzOn8LPSh515RHM57eDLCOwqnAxGQwk67GRl8f5dFH9JQ" +// + "Aa7xx8rjCqPbiIQW6t5LqCNvPZOiSCmftll6+se1XJhFEuq8WS4nXtPfTiJ3vib4" +// + "3soJdHzGB6AOs+BQ6aKmmNTVAxa5owhtSt1Z/6dfSSk="); + + private static readonly byte[] subPubKey = Base64.Decode( + "mIsEPz2nJAEEAOTVqWMvqYE693qTgzKv/TJpIj3hI8LlYPC6m1dk0z3bDLwVVk9F" + + "FAB+CWS8RdFOWt/FG3tEv2nzcoNdRvjv9WALyIGNawtae4Ml6oAT06/511yUzXHO" + + "k+9xK3wkXN5jdzUhf4cA2oGpLSV/pZlocsIDL+jCUQtumUPwFodmSHhzAAYptC9F" + + "cmljIEVjaGlkbmEgKHRlc3Qga2V5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPoi4" + + "BBMBAgAiBQI/PackAhsDBQkAg9YABAsHAwIDFQIDAxYCAQIeAQIXgAAKCRA1WGFG" + + "/fPzc8WMA/9BbjuB8E48QAlxoiVf9U8SfNelrz/ONJA/bMvWr/JnOGA9PPmFD5Uc" + + "+kV/q+i94dEMjsC5CQ1moUHWSP2xlQhbOzBP2+oPXw3z2fBs9XJgnTH6QWMAAvLs" + + "3ug9po0loNHLobT/D/XdXvcrb3wvwvPT2FptZqrtonH/OdzT9JdfrIhMBBARAgAM" + + "BQI/RxooBYMAemL8AAoJEM0j9enEyjRDiBgAn3RcLK+gq90PvnQFTw2DNqdq7KA0" + + "AKCS0EEIXCzbV1tfTdCUJ3hVh3btF7QkRXJpYyBFY2hpZG5hIDxlcmljQGJvdW5j" + + "eWNhc3RsZS5vcmc+iLgEEwECACIFAj9HFA0CGwMFCQCD1gAECwcDAgMVAgMDFgIB" + + "Ah4BAheAAAoJEDVYYUb98/Nzc7oD/j21cUKKI/y+Dvs5e+eZufM8EDUbqMJFk0/X" + + "Ihe6w6OkerIs3kr2HDqWr+jik2IK6KrfaiyoZFfeW/+cN24lTWSfY7D4jZVyL6iM" + + "xd0IZ0So/Bl+/juMcvBGshQnbY46haw5G2C9J5FR3gjODyOu5oUzu5+vmGuMSXVy" + + "4tbUevwuiEwEEBECAAwFAj9HGigFgwB6YvwACgkQzSP16cTKNEPwBQCdHm0Amwza" + + "NmVmDHm3rmqI7rp2oQ0An2YbiP/H/kmBNnmTeH55kd253QOhuIsEP0ccUAEEANCd" + + "gSHam/CbQxio72Ma47tLqyVVc8iNQpwowKewrS6B0CVEFOz2o51eCXddrpH3KCuz" + + "Ea2mMnUBI8YdjKj6bkICUt3YEFa8Tj2qw0GARa2TXdrWcTo2GpIRK71JkaOslhWs" + + "QocKjIJfF1roATYNQ72vv2HKBkPpcviYOEVmaB/PAAYpiJ8EGAECAAkFAj9HHFAC" + + "GwwACgkQNVhhRv3z83M5hQP8DIOR4TeTZKpo5x1BX3lzV3R85npMsN/EZ7gjCpn3" + + "ONwIg7PhbSetoKUOjxLGReKPUuX8XI1ZN1UoNNFzA7UP9AbCgXORsYSU6uxvv0qH" + + "jON91htfbqEtPuS3/99cDaE56b+p6TmmKXE0Oy/Swp88ABeB9ISTxOm4ZltgjHLB" + + "PyGZAaIEP0cHNREEALOTFEJUYmDn4t30NThemd3gsIqAyrtg5jsaLQSAr3aBtprr" + + "7NChAWrPW23dBSanPdhWSb/MsRIEG0LUAIhcaCBR0UxSvkjzv7UJvq/N58C0a3w3" + + "lVXUX8xe/WAnPgG7ofLEv+dx97vWOw2Fq/SLjICN/Z61YWPnfMrpH46ODkfrAKCk" + + "v3+1dV8Y/xKoW/Ks3/jfsyUVJQQAg3dXqP8xSWXKtmCWu2vb5FYjBGsb8AKasXqF" + + "O6A6XhxDFoNg1ye1duGVOUmz0zGNMffHHPKXKKsLKrsfMYnFnNK3oVN6HUMVjOEn" + + "tC5hHXGtJ0DpjSZS/SLEPkDic8eO6lDlAKocZ5F8UP+gfMPjOoGcmn8Encu9Drps" + + "REmYqXkD/i6PcehXGlvS+/IQ19GooyYYEhLJxjgygfm5Z9vbcV9+xP2v0ovqcniz" + + "IvNpFHSC9xtyORz1nd6kjuCveNOtvh3xY/GwNtP9bW2/1sb8QdrCiYtyKG25RTrx" + + "R6Pr/Bmi3Vcmq7adCWS7nv4z9XZfXLbpUqyKmiU9+Nri7IE47K9stDNFcmljIEVj" + + "aGlkbmEgKERTQSBUZXN0IEtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IWQQT" + + "EQIAGQUCP0cHNQQLBwMCAxUCAwMWAgECHgECF4AACgkQzSP16cTKNEMCXACfauui" + + "bSwyG59Yrm8hHCDuCPmqwsQAni+dPl08FVuWh+wb6kOgJV4lcYae"); + +// private static readonly byte[] subPubCrc = Base64.Decode("rikt"); + + private static readonly byte[] pgp8Key = Base64.Decode( + "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF" + + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd" + + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy" + + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y" + + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7" + + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO" + + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP" + + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY" + + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb" + + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4" + + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj" + + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I" + + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH" + + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt" + + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j" + + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw" + + "AgAA"); + + private static readonly char[] pgp8Pass = "2002 Buffalo Sabres".ToCharArray(); + + private static readonly char[] pass = "hello world".ToCharArray(); + + private static readonly byte[] fingerprintKey = Base64.Decode( + "mQEPA0CiJdUAAAEIAMI+znDlPd2kQoEcnxqxLcRz56Z7ttFKHpnYp0UkljZdquVc" + + "By1jMfXGVV64xN1IvMcyenLXUE0IUeUBCQs6tHunFRAPSeCxJ3FdFe1B5MpqQG8A" + + "BnEpAds/hAUfRDZD5y/lolk1hjvFMrRh6WXckaA/QQ2t00NmTrJ1pYUpkw9tnVQb" + + "LUjWJhfZDBBcN0ADtATzgkugxMtcDxR6I5x8Ndn+IilqIm23kxGIcmMd/BHOec4c" + + "jRwJXXDb7u8tl+2knAf9cwhPHp3+Zy4uGSQPdzQnXOhBlA+4WDa0RROOevWgq8uq" + + "8/9Xp/OlTVL+OoIzjsI6mJP1Joa4qmqAnaHAmXcAEQEAAbQoQk9BM1JTS1kgPEJP" + + "QSBNb25pdG9yaW5nIEAgODg4LTI2OS01MjY2PokBFQMFEECiJdWqaoCdocCZdwEB" + + "0RsH/3HPxoUZ3G3K7T3jgOnJUckTSHWU3XspHzMVgqOxjTrcexi5IsAM5M+BulfW" + + "T2aO+Kqf5w8cKTKgW02DNpHUiPjHx0nzDE+Do95zbIErGeK+Twkc4O/aVsvU9GGO" + + "81VFI6WMvDQ4CUAUnAdk03MRrzI2nAuhn4NJ5LQS+uJrnqUJ4HmFAz6CQZQKd/kS" + + "Xgq+A6i7aI1LG80YxWa9ooQgaCrb9dwY/kPQ+yC22zQ3FExtv+Fv3VtAKTilO3vn" + + "BA4Y9uTHuObHfI+1yxUS2PrlRUX0m48ZjpIX+cEN3QblGBJudI/A1QSd6P0LZeBr" + + "7F1Z1aF7ZDo0KzgiAIBvgXkeTpw="); + +// private static readonly byte[] fingerprintCheck = Base64.Decode("CTv2"); + + private static readonly byte[] jpegImage = Base64.Decode( + "/9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD/2wBDAAUDBAQEAwUE" + + "BAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/" + + "wAALCAA6AFABASIA/8QAHAAAAgMAAwEAAAAAAAAAAAAABQcABAYBAggD/8QAMRAAAgEDBAEDAwME" + + "AQUAAAAAAQIDBAURAAYSITEHIkETFFEjYXEVMkKRCCUzQ4Gh/9oACAEBAAA/APX1TdKCmlaOoqoo" + + "WXzzbiP9nWaS71lXuA2tqrgopBOxpyGyWLAEEd4GAf3+fOjLPXoVaOcNzYAhl8HskADwAPz37f3z" + + "opSvI9Mjypwcr7l/B1XuFwSmoTVooljB9xDYAH51Vor191F9dKGb6Py3yo4huwcHwf8AYP7ZLIyu" + + "gZSGBGQQejrnU1NKn1EqVi3sZJOBCwxxIp9xzksfb5PR+Mdga+ljqIKje1TNBBNToYYgU4477HwQ" + + "Bn9z8/nW6mqxLR0NzpJkMLx8lJUkOGAIx4I/0f41lJ93UkkrRxVKvNKVjZfpSe6RyqhCp7wCSD89" + + "EEDRWppEkgqKdYohGcoZAjAlSMMcZ+PHH/3odsG6VLW2qaoqV+nTyFZpHOFQL0Sc9ADGTnHWtZap" + + "EpoamJm/TgYkfgJ5H/zGuKieVJIGkqCgmfCJFFy64s3Z+Oh58fHyNfGavipIJ2BrZcKXA+mzEd9Y" + + "OCcHI/gDV62SzvBGKhQHaNWzj8jvP750oN/xM3qkshLPEstOhj7IVyvkY+f7Nd7hf9vbc9QbVb7n" + + "dadLldqc00FMCwlmZnCrgL2v/cAySPBPwSD+/wC+3HbWx3rLbaqW81CVHOWnetMZjRm9h7VvClcj" + + "oDB7PymPTvem+a6roxvC10sd3ScmlucdEyUtRADxdice9wY3PQGRgj4OnHU3u5RW+op6imo4q+KA" + + "1UKGQ/bzrnt0biWxkgFOJK9ZyCCVX6f3T1Rh9RawbltdQNv18CGe2wxBDQyvGrowIJd15HEnHvP+" + + "OBjXoGzS0tNTpQipFTIw48Xn5SSBVUMw5e5wMgZ/j86yVNvvZ9TeDR1c9XSV0bl443dmYZXiCSCR" + + "jvxkjR1L1b46iWpStpIRLOWkCqyniP8AJjxPIniBjr+etFdu11DVu321WZiFHRjZcA/gsO+seNYf" + + "fVpq6n1Eo5KNATIYmb5Bx7csP4z/AKz8aX1N6Q7W3FuWWrS1TRzi+tXSutUESQhCGiVAvJVRgfcc" + + "HkeidM6tSmTbps9RHIH4KoqC8j/VC8R0+CSScZLdknPZGgNfYpUUUzfewxxcWpopWbhL715KgBIQ" + + "MCQc4A84+dD963X7ywQ0NIVW60qqzkzIfoszAMGUNyUHORkDrHxo3sSaOhtX2hnp3uNRF9b7hqtO" + + "DxM3Rcj3dMCPHXLGfOkLuPddp9R/ViOa62KppqK3Vctvsz0UylKtWfgXy3+L8WIZFBGRhs407rTT" + + "bcuFDRWmtsNGIZ1MMEU9GPqRorKPcJEzhich8Anz350Wk2zs2OsT7D7RZJpChMEk0MoypJZWVwM9" + + "ZzjWw2lbKaioFjQy/U9shLyu7Esi5JLEnsgnQlaSqhqayWSRZ5JaiSSNPoBCiq54jPuJyA2W+QfA" + + "+FrSXq4bdulZHRpWRzpArPK0SSNUExh14qB4c5X9ipz41Zud0juVouVooHN6rrZKVaoek/VhYgqE" + + "4v7cZPTfPHwT7tZX0e2NVUV5rK2ku9TeY6aFZJ6GuLALKzNnizE4CsqHIyBxJCk4AYFNt2wSUExm" + + "pP1lqgq1zkfXUtIgkiOFHQCsCM/kfOtZU7GsNZU1FFc1lrqCSNSlFOQ8SJk8kC4/tJx1rMwbWt0V" + + "CW21VW+krVoFTCRrPC0bf+NF8ocqMcT/AIg6EVF5/p9U6zPXLVFGpoKlSpMiEkniSCcqVY+eQIPW" + + "NULf/UNxJNS0dhklu8SK9Lco6pUcEr0JOu1HQ7z+R5OndaI5leWV0VQ54kA5KlWIx/Gqd2t6vcqe" + + "FIXNJMs71SoCMsQuG5jsN8AAjyTnrGlt6mVlqswtS0SG71NTXpSiCQFpogckll6Y4wvyD/OToVd7" + + "3tLedda4Nr3iRK2mqJhW1K0qxSSGJf1OTOAwwVADLkA9fPV2W77msVfPTClNRUyJCla0SqS5dR5J" + + "b2kluKlQc5BbHnWu2xTS0G4qmjvSq6RwrPHJUMHkkYDhzJHXIhmBAHnxpaL6j3il3D6g1VLuSz1k" + + "1ht//S6SZQ4KoTI6MyMOb9hR85HedM/0wqn3RsC0bhgq/pQV9J9WELEFaNWGARg+04xkd95xjQTe" + + "df6c7U+ysl3mtMFJe5JYGkkmAVKgKZCZGzlVbBySemA/OgvpZUQxvaqitgoqSsiX6XKh5RwVCBP0" + + "8KCTIoU8VJyDjIA8Bs2e5CprDTR8VXi8pRgyyZMh8qQMDHz850ZOlVv30RsW5blcL5S3a626+1cq" + + "TirFQ0qJIgAQCNjgIMeFKn9wQCMA3o2vprca/ctp29Jv6/3aoZ4IRRx08dC5D8nWQv7FJYHByeuv" + + "zo5SWn1Z2ttahutFZqbcG6JK5ZLu1TNEzzUq5ASNyVw6pxUMc5Oc5znR6KyXffldUVW4rBcbAqos" + + "EUq1qrUzUkwy8bFB+m4ZI2IBbAJAbOdau0+nmybJYqe027atvNHTRlYomhVz+Tln8knyScn50j/+" + + "SOyd3VO2oDtmPcNPYqJgDt23xKtOIiTy6gYO/Z5YOcAHGsJ/x39NgbzuDc+0bNt6/wAySmltbXGv" + + "flaT8ST07xBjIR30RjsL+dex9uwT/wBKo6i5UtPFdHp4/u/pgECTiOQDYBIByB+w0RVEVmZUUM39" + + "xA7P867ampqampqaq09BQwV9RWwUVNFU1AUTTJEoeQLnHJgMnGTjP51a1Nf/2Q=="); + + private static readonly byte[] embeddedJPEGKey = Base64.Decode( + "mI0ER0JXuwEEAKNqsXwLU6gu6P2Q/HJqEJVt3A7Kp1yucn8HWVeJF9JLAKVjVU8jrvz9Bw4NwaRJ" + + "NGYEAgdRq8Hx3WP9FXFCIVfCdi+oQrphcHWzzBFul8sykUGT+LmcBdqQGU9WaWSJyCOmUht4j7t0" + + "zk/IXX0YxGmkqR+no5rTj9LMDG8AQQrFABEBAAG0P0VyaWMgSCBFY2hpZG5hIChpbWFnZSB0ZXN0" + + "IGtleSkgPGVyaWMuZWNoaWRuYUBib3VuY3ljYXN0bGUub3JnPoi2BBMBAgAgBQJHQle7AhsDBgsJ" + + "CAcDAgQVAggDBBYCAwECHgECF4AACgkQ1+RWqFFpjMTKtgP+Okqkn0gVpQyNYXM/hWX6f3UQcyXk" + + "2Sd/fWW0XG+LBjhhBo+lXRWK0uYF8OMdZwsSl9HimpgYD5/kNs0Seh417DioP1diOgxkgezyQgMa" + + "+ODZfNnIvVaBr1pHLPLeqIBxBVMWBfa4wDXnLLGu8018uvI2yBhz5vByB1ntxwgKMXCwAgAD0cf3" + + "x/UBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQEBAEgASAAA/+EAFkV4aWYAAE1NACoAAAAI" + + "AAAAAAAA/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERgh" + + "GBodHR8fHxMXIiQiHiQcHh8e/8AACwgAOgBQAQEiAP/EABwAAAIDAAMBAAAAAAAAAAAAAAUHAAQG" + + "AQIIA//EADEQAAIBAwQBAwMDBAEFAAAAAAECAwQFEQAGEiExByJBExRRI2FxFTJCkQglM0OBof/a" + + "AAgBAQAAPwD19U3SgppWjqKqKFl8824j/Z1mku9ZV7gNraq4KKQTsachsliwBBHeBgH9/nzoyz16" + + "FWjnDc2AIZfB7JAA8AD89+3986KUryPTI8qcHK+5fwdV7hcEpqE1aKJYwfcQ2AB+dVaK9fdRfXSh" + + "m+j8t8qOIbsHB8H/AGD+2SyMroGUhgRkEHo651NTSp9RKlYt7GSTgQsMcSKfcc5LH2+T0fjHYGvp" + + "Y6iCo3tUzQQTU6GGIFOOO+x8EAZ/c/P51upqsS0dDc6SZDC8fJSVJDhgCMeCP9H+NZSfd1JJK0cV" + + "SrzSlY2X6UnukcqoQqe8Akg/PRBA0VqaRJIKinWKIRnKGQIwJUjDHGfjxx/96HbBulS1tqmqKlfp" + + "08hWaRzhUC9EnPQAxk5x1rWWqRKaGpiZv04GJH4CeR/8xrionlSSBpKgoJnwiRRcuuLN2fjoefHx" + + "8jXxmr4qSCdga2XClwPpsxHfWDgnByP4A1etks7wRioUB2jVs4/I7z++dKDf8TN6pLISzxLLToY+" + + "yFcr5GPn+zXe4X/b23PUG1W+53WnS5XanNNBTAsJZmZwq4C9r/3AMkjwT8Eg/v8Avtx21sd6y22q" + + "lvNQlRzlp3rTGY0ZvYe1bwpXI6Awez8pj073pvmuq6MbwtdLHd0nJpbnHRMlLUQA8XYnHvcGNz0B" + + "kYI+Dpx1N7uUVvqKeopqOKvigNVChkP28657dG4lsZIBTiSvWcgglV+n909UYfUWsG5bXUDb9fAh" + + "ntsMQQ0Mrxq6MCCXdeRxJx7z/jgY16Bs0tLTU6UIqRUyMOPF5+UkgVVDMOXucDIGf4/OslTb72fU" + + "3g0dXPV0ldG5eON3ZmGV4gkgkY78ZI0dS9W+OolqUraSESzlpAqsp4j/ACY8TyJ4gY6/nrRXbtdQ" + + "1bt9tVmYhR0Y2XAP4LDvrHjWH31aaup9RKOSjQEyGJm+Qce3LD+M/wCs/Gl9TekO1txbllq0tU0c" + + "4vrV0rrVBEkIQholQLyVUYH3HB5HonTOrUpk26bPURyB+CqKgvI/1QvEdPgkknGS3ZJz2RoDX2KV" + + "FFM33sMcXFqaKVm4S+9eSoASEDAkHOAPOPnQ/et1+8sENDSFVutKqs5MyH6LMwDBlDclBzkZA6x8" + + "aN7EmjobV9oZ6d7jURfW+4arTg8TN0XI93TAjx1yxnzpC7j3XafUf1Yjmutiqaait1XLb7M9FMpS" + + "rVn4F8t/i/FiGRQRkYbONO60023LhQ0VprbDRiGdTDBFPRj6kaKyj3CRM4YnIfAJ89+dFpNs7Njr" + + "E+w+0WSaQoTBJNDKMqSWVlcDPWc41sNpWymoqBY0Mv1PbIS8ruxLIuSSxJ7IJ0JWkqoamslkkWeS" + + "WokkjT6AQoqueIz7icgNlvkHwPha0l6uG3bpWR0aVkc6QKzytEkjVBMYdeKgeHOV/Yqc+NWbndI7" + + "laLlaKBzeq62SlWqHpP1YWIKhOL+3GT03zx8E+7WV9HtjVVFeaytpLvU3mOmhWSehriwCyszZ4sx" + + "OArKhyMgcSQpOAGBTbdsElBMZqT9ZaoKtc5H11LSIJIjhR0ArAjP5HzrWVOxrDWVNRRXNZa6gkjU" + + "pRTkPEiZPJAuP7ScdazMG1rdFQlttVVvpK1aBUwkazwtG3/jRfKHKjHE/wCIOhFRef6fVOsz1y1R" + + "RqaCpUqTIhJJ4kgnKlWPnkCD1jVC3/1DcSTUtHYZJbvEivS3KOqVHBK9CTrtR0O8/keTp3WiOZXl" + + "ldFUOeJAOSpViMfxqndrer3KnhSFzSTLO9UqAjLELhuY7DfAAI8k56xpbeplZarMLUtEhu9TU16U" + + "ogkBaaIHJJZemOML8g/zk6FXe97S3nXWuDa94kStpqiYVtStKsUkhiX9TkzgMMFQAy5APXz1dlu+" + + "5rFXz0wpTUVMiQpWtEqkuXUeSW9pJbipUHOQWx51rtsU0tBuKpo70qukcKzxyVDB5JGA4cyR1yIZ" + + "gQB58aWi+o94pdw+oNVS7ks9ZNYbf/0ukmUOCqEyOjMjDm/YUfOR3nTP9MKp90bAtG4YKv6UFfSf" + + "VhCxBWjVhgEYPtOMZHfecY0E3nX+nO1PsrJd5rTBSXuSWBpJJgFSoCmQmRs5VWwcknpgPzoL6WVE" + + "Mb2qorYKKkrIl+lyoeUcFQgT9PCgkyKFPFScg4yAPAbNnuQqaw00fFV4vKUYMsmTIfKkDAx8/OdG" + + "TpVb99EbFuW5XC+Ut2utuvtXKk4qxUNKiSIAEAjY4CDHhSp/cEAjAN6Nr6a3Gv3LadvSb+v92qGe" + + "CEUcdPHQuQ/J1kL+xSWBwcnrr86OUlp9WdrbWobrRWam3BuiSuWS7tUzRM81KuQEjclcOqcVDHOT" + + "nOc50eisl335XVFVuKwXGwKqLBFKtaq1M1JMMvGxQfpuGSNiAWwCQGznWrtPp5smyWKntNu2rbzR" + + "00ZWKJoVc/k5Z/JJ8knJ+dI//kjsnd1TtqA7Zj3DT2KiYA7dt8SrTiIk8uoGDv2eWDnABxrCf8d/" + + "TYG87g3PtGzbev8AMkppbW1xr35Wk/Ek9O8QYyEd9EY7C/nXsfbsE/8ASqOouVLTxXR6eP7v6YBA" + + "k4jkA2ASAcgfsNEVRFZmVFDN/cQOz/Ou2pqampqamqtPQUMFfUVsFFTRVNQFE0yRKHkC5xyYDJxk" + + "4z+dWtTX/9mItgQTAQIAIAUCR0JYkAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJENfkVqhR" + + "aYzEAPYD/iHdLOAE8r8HHF3F4z28vtIT8iiRB9aPC/YH0xqV1qeEKG8+VosBaQAOCEquONtRWsww" + + "gO3XB0d6VAq2kMOKc2YiB4ZtZcFvvmP9KdmVIZxVjpa9ozjP5j9zFso1HOpFcsn/VDBEqy5TvsNx" + + "Qvmtc8X7lqK/zLRVkSSBItik2IIhsAIAAw=="); + + private void FingerPrintTest() + { + // + // version 3 + // + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(fingerprintKey); + + PgpPublicKey pubKey = pgpPub.GetPublicKey(); + + if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("4FFB9F0884266C715D1CEAC804A3BBFA"))) + { + Fail("version 3 fingerprint test failed"); + } + + // + // version 4 + // + pgpPub = new PgpPublicKeyRing(testPubKey); + + pubKey = pgpPub.GetPublicKey(); + + if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("3062363c1046a01a751946bb35586146fdf3f373"))) + { + Fail("version 4 fingerprint test failed"); + } + } + + private void MixedTest( + PgpPrivateKey pgpPrivKey, + PgpPublicKey pgpPubKey) + { + byte[] text = Encoding.ASCII.GetBytes("hello world!\n"); + + // + // literal data + // + MemoryStream bOut = new MemoryStream(); + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open( + bOut, + PgpLiteralData.Binary, + PgpLiteralData.Console, + text.Length, + DateTime.UtcNow); + + lOut.Write(text, 0, text.Length); + + lGen.Close(); + + byte[] bytes = bOut.ToArray(); + + PgpObjectFactory f = new PgpObjectFactory(bytes); + CheckLiteralData((PgpLiteralData)f.NextPgpObject(), text); + + MemoryStream bcOut = new MemoryStream(); + + PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator( + SymmetricKeyAlgorithmTag.Aes128, + true, + new SecureRandom()); + + encGen.AddMethod(pgpPubKey); + + encGen.AddMethod("password".ToCharArray()); + + Stream cOut = encGen.Open(bcOut, bytes.Length); + + cOut.Write(bytes, 0, bytes.Length); + + cOut.Close(); + + byte[] encData = bcOut.ToArray(); + + // + // asymmetric + // + PgpObjectFactory pgpF = new PgpObjectFactory(encData); + + PgpEncryptedDataList encList = (PgpEncryptedDataList) pgpF.NextPgpObject(); + + PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0]; + + Stream clear = encP.GetDataStream(pgpPrivKey); + + PgpObjectFactory pgpFact = new PgpObjectFactory(clear); + + CheckLiteralData((PgpLiteralData)pgpFact.NextPgpObject(), text); + + // + // PBE + // + pgpF = new PgpObjectFactory(encData); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + PgpPbeEncryptedData encPbe = (PgpPbeEncryptedData) encList[1]; + + clear = encPbe.GetDataStream("password".ToCharArray()); + + pgpF = new PgpObjectFactory(clear); + + CheckLiteralData((PgpLiteralData) pgpF.NextPgpObject(), text); + } + + private void CheckLiteralData( + PgpLiteralData ld, + byte[] data) + { + if (!ld.FileName.Equals(PgpLiteralData.Console)) + throw new Exception("wrong filename in packet"); + + Stream inLd = ld.GetDataStream(); + byte[] bytes = Streams.ReadAll(inLd); + + if (!AreEqual(bytes, data)) + { + Fail("wrong plain text in decrypted packet"); + } + } + + private void ExistingEmbeddedJpegTest() + { + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(embeddedJPEGKey); + + PgpPublicKey pubKey = pgpPub.GetPublicKey(); + + int count = 0; + foreach (PgpUserAttributeSubpacketVector attributes in pubKey.GetUserAttributes()) + { + int sigCount = 0; + foreach (PgpSignature sig in pubKey.GetSignaturesForUserAttribute(attributes)) + { + sig.InitVerify(pubKey); + + if (!sig.VerifyCertification(attributes, pubKey)) + { + Fail("signature failed verification"); + } + + sigCount++; + } + + if (sigCount != 1) + { + Fail("Failed user attributes signature check"); + } + count++; + } + + if (count != 1) + { + Fail("didn't find user attributes"); + } + } + + private void EmbeddedJpegTest() + { + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey); + PgpSecretKeyRing pgpSec = new PgpSecretKeyRing(testPrivKey); + + PgpPublicKey pubKey = pgpPub.GetPublicKey(); + + PgpUserAttributeSubpacketVectorGenerator vGen = new PgpUserAttributeSubpacketVectorGenerator(); + + vGen.SetImageAttribute(ImageAttrib.Format.Jpeg, jpegImage); + + PgpUserAttributeSubpacketVector uVec = vGen.Generate(); + + PgpSignatureGenerator sGen = new PgpSignatureGenerator( + PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.PositiveCertification, pgpSec.GetSecretKey().ExtractPrivateKey(pass)); + + PgpSignature sig = sGen.GenerateCertification(uVec, pubKey); + + PgpPublicKey nKey = PgpPublicKey.AddCertification(pubKey, uVec, sig); + + int count = 0; + foreach (PgpUserAttributeSubpacketVector attributes in nKey.GetUserAttributes()) + { + int sigCount = 0; + foreach (PgpSignature s in nKey.GetSignaturesForUserAttribute(attributes)) + { + s.InitVerify(pubKey); + + if (!s.VerifyCertification(attributes, pubKey)) + { + Fail("added signature failed verification"); + } + + sigCount++; + } + + if (sigCount != 1) + { + Fail("Failed added user attributes signature check"); + } + count++; + } + + if (count != 1) + { + Fail("didn't find added user attributes"); + } + + nKey = PgpPublicKey.RemoveCertification(nKey, uVec); + + if (nKey.GetUserAttributes().GetEnumerator().MoveNext()) + { + Fail("found attributes where none expected"); + } + } + + public override void PerformTest() + { + // + // Read the public key + // + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey); + + AsymmetricKeyParameter pubKey = pgpPub.GetPublicKey().GetKey(); + + IEnumerator enumerator = pgpPub.GetPublicKey().GetUserIds().GetEnumerator(); + enumerator.MoveNext(); + string uid = (string) enumerator.Current; + + + enumerator = pgpPub.GetPublicKey().GetSignaturesForId(uid).GetEnumerator(); + enumerator.MoveNext(); + PgpSignature sig = (PgpSignature) enumerator.Current; + + sig.InitVerify(pgpPub.GetPublicKey()); + + if (!sig.VerifyCertification(uid, pgpPub.GetPublicKey())) + { + Fail("failed to verify certification"); + } + + // + // write a public key + // + MemoryStream bOut = new UncloseableMemoryStream(); + BcpgOutputStream pOut = new BcpgOutputStream(bOut); + + pgpPub.Encode(pOut); + + if (!Arrays.AreEqual(bOut.ToArray(), testPubKey)) + { + Fail("public key rewrite failed"); + } + + // + // Read the public key + // + PgpPublicKeyRing pgpPubV3 = new PgpPublicKeyRing(testPubKeyV3); + AsymmetricKeyParameter pubKeyV3 = pgpPub.GetPublicKey().GetKey(); + + // + // write a V3 public key + // + bOut = new UncloseableMemoryStream(); + pOut = new BcpgOutputStream(bOut); + + pgpPubV3.Encode(pOut); + + // + // Read a v3 private key + // + char[] passP = "FIXCITY_QA".ToCharArray(); + +#if INCLUDE_IDEA + { + PgpSecretKeyRing pgpPriv2 = new PgpSecretKeyRing(testPrivKeyV3); + PgpSecretKey pgpPrivSecretKey = pgpPriv2.GetSecretKey(); + PgpPrivateKey pgpPrivKey2 = pgpPrivSecretKey.ExtractPrivateKey(passP); + + // + // write a v3 private key + // + bOut = new UncloseableMemoryStream(); + pOut = new BcpgOutputStream(bOut); + + pgpPriv2.Encode(pOut); + + byte[] result = bOut.ToArray(); + if (!Arrays.AreEqual(result, testPrivKeyV3)) + { + Fail("private key V3 rewrite failed"); + } + } +#endif + + // + // Read the private key + // + PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(testPrivKey); + PgpPrivateKey pgpPrivKey = pgpPriv.GetSecretKey().ExtractPrivateKey(pass); + + // + // write a private key + // + bOut = new UncloseableMemoryStream(); + pOut = new BcpgOutputStream(bOut); + + pgpPriv.Encode(pOut); + + if (!Arrays.AreEqual(bOut.ToArray(), testPrivKey)) + { + Fail("private key rewrite failed"); + } + + // + // test encryption + // + IBufferedCipher c = CipherUtilities.GetCipher("RSA"); + +// c.Init(Cipher.ENCRYPT_MODE, pubKey); + c.Init(true, pubKey); + + byte[] inBytes = Encoding.ASCII.GetBytes("hello world"); + byte[] outBytes = c.DoFinal(inBytes); + +// c.Init(Cipher.DECRYPT_MODE, pgpPrivKey.GetKey()); + c.Init(false, pgpPrivKey.Key); + + outBytes = c.DoFinal(outBytes); + + if (!Arrays.AreEqual(inBytes, outBytes)) + { + Fail("decryption failed."); + } + + // + // test signature message + // + PgpObjectFactory pgpFact = new PgpObjectFactory(sig1); + + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pgpPub.GetPublicKey(ops.KeyId)); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed signature check"); + } + + // + // encrypted message - read subkey + // + pgpPriv = new PgpSecretKeyRing(subKey); + + // + // encrypted message + // + byte[] text = Encoding.ASCII.GetBytes("hello world!\n"); + + PgpObjectFactory pgpF = new PgpObjectFactory(enc1); + + PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0]; + + pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass); + + Stream clear = encP.GetDataStream(pgpPrivKey); + + pgpFact = new PgpObjectFactory(clear); + + c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpLiteralData ld = (PgpLiteralData)pgpFact.NextPgpObject(); + + if (!ld.FileName.Equals("test.txt")) + { + throw new Exception("wrong filename in packet"); + } + + Stream inLd = ld.GetDataStream(); + byte[] bytes = Streams.ReadAll(inLd); + + if (!Arrays.AreEqual(bytes, text)) + { + Fail("wrong plain text in decrypted packet"); + } + + // + // encrypt - short message + // + byte[] shortText = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o' }; + + MemoryStream cbOut = new UncloseableMemoryStream(); + PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom()); + PgpPublicKey puK = pgpPriv.GetSecretKey(encP.KeyId).PublicKey; + + cPk.AddMethod(puK); + + Stream cOut = cPk.Open(new UncloseableStream(cbOut), shortText.Length); + + cOut.Write(shortText, 0, shortText.Length); + + cOut.Close(); + + pgpF = new PgpObjectFactory(cbOut.ToArray()); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + encP = (PgpPublicKeyEncryptedData)encList[0]; + + pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass); + + if (encP.GetSymmetricAlgorithm(pgpPrivKey) != SymmetricKeyAlgorithmTag.Cast5) + { + Fail("symmetric algorithm mismatch"); + } + + clear = encP.GetDataStream(pgpPrivKey); + outBytes = Streams.ReadAll(clear); + + if (!Arrays.AreEqual(outBytes, shortText)) + { + Fail("wrong plain text in generated short text packet"); + } + + // + // encrypt + // + cbOut = new UncloseableMemoryStream(); + cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom()); + puK = pgpPriv.GetSecretKey(encP.KeyId).PublicKey; + + cPk.AddMethod(puK); + + cOut = cPk.Open(new UncloseableStream(cbOut), text.Length); + + cOut.Write(text, 0, text.Length); + + cOut.Close(); + + pgpF = new PgpObjectFactory(cbOut.ToArray()); + + encList = (PgpEncryptedDataList)pgpF.NextPgpObject(); + + encP = (PgpPublicKeyEncryptedData)encList[0]; + + pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass); + + clear = encP.GetDataStream(pgpPrivKey); + outBytes = Streams.ReadAll(clear); + + if (!Arrays.AreEqual(outBytes, text)) + { + Fail("wrong plain text in generated packet"); + } + + // + // read public key with sub key. + // + pgpF = new PgpObjectFactory(subPubKey); + object o; + while ((o = pgpFact.NextPgpObject()) != null) + { + // TODO Should something be tested here? + // Console.WriteLine(o); + } + + // + // key pair generation - CAST5 encryption + // + char[] passPhrase = "hello".ToCharArray(); + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 1024, 25); + + kpg.Init(genParam); + + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + + PgpSecretKey secretKey = new PgpSecretKey( + PgpSignature.DefaultCertification, + PublicKeyAlgorithmTag.RsaGeneral, + kp.Public, + kp.Private, + DateTime.UtcNow, + "fred", + SymmetricKeyAlgorithmTag.Cast5, + passPhrase, + null, + null, + new SecureRandom() + ); + + PgpPublicKey key = secretKey.PublicKey; + + + enumerator = key.GetUserIds().GetEnumerator(); + enumerator.MoveNext(); + uid = (string) enumerator.Current; + + + enumerator = key.GetSignaturesForId(uid).GetEnumerator(); + enumerator.MoveNext(); + sig = (PgpSignature) enumerator.Current; + + sig.InitVerify(key); + + if (!sig.VerifyCertification(uid, key)) + { + Fail("failed to verify certification"); + } + + pgpPrivKey = secretKey.ExtractPrivateKey(passPhrase); + + key = PgpPublicKey.RemoveCertification(key, uid, sig); + + if (key == null) + { + Fail("failed certification removal"); + } + + byte[] keyEnc = key.GetEncoded(); + + key = PgpPublicKey.AddCertification(key, uid, sig); + + keyEnc = key.GetEncoded(); + + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.KeyRevocation, secretKey.ExtractPrivateKey(passPhrase)); + + sig = sGen.GenerateCertification(key); + + key = PgpPublicKey.AddCertification(key, sig); + + keyEnc = key.GetEncoded(); + + PgpPublicKeyRing tmpRing = new PgpPublicKeyRing(keyEnc); + + key = tmpRing.GetPublicKey(); + + IEnumerator sgEnum = key.GetSignaturesOfType(PgpSignature.KeyRevocation).GetEnumerator(); + sgEnum.MoveNext(); + sig = (PgpSignature) sgEnum.Current; + + sig.InitVerify(key); + + if (!sig.VerifyCertification(key)) + { + Fail("failed to verify revocation certification"); + } + + // + // use of PgpKeyPair + // + PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, + kp.Public, kp.Private, DateTime.UtcNow); + + PgpPublicKey k1 = pgpKp.PublicKey; + PgpPrivateKey k2 = pgpKp.PrivateKey; + + k1.GetEncoded(); + + MixedTest(k2, k1); + + // + // key pair generation - AES_256 encryption. + // + kp = kpg.GenerateKeyPair(); + + secretKey = new PgpSecretKey(PgpSignature.DefaultCertification, PublicKeyAlgorithmTag.RsaGeneral, kp.Public, kp.Private, DateTime.UtcNow, "fred", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, new SecureRandom()); + + secretKey.ExtractPrivateKey(passPhrase); + + secretKey.Encode(new UncloseableMemoryStream()); + + // + // secret key password changing. + // + const string newPass = "newPass"; + + secretKey = PgpSecretKey.CopyWithNewPassword(secretKey, passPhrase, newPass.ToCharArray(), secretKey.KeyEncryptionAlgorithm, new SecureRandom()); + + secretKey.ExtractPrivateKey(newPass.ToCharArray()); + + secretKey.Encode(new UncloseableMemoryStream()); + + key = secretKey.PublicKey; + + key.Encode(new UncloseableMemoryStream()); + + + enumerator = key.GetUserIds().GetEnumerator(); + enumerator.MoveNext(); + uid = (string) enumerator.Current; + + + enumerator = key.GetSignaturesForId(uid).GetEnumerator(); + enumerator.MoveNext(); + sig = (PgpSignature) enumerator.Current; + + sig.InitVerify(key); + + if (!sig.VerifyCertification(uid, key)) + { + Fail("failed to verify certification"); + } + + pgpPrivKey = secretKey.ExtractPrivateKey(newPass.ToCharArray()); + + // + // signature generation + // + const string data = "hello world!"; + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + + bOut = new UncloseableMemoryStream(); + + MemoryStream testIn = new MemoryStream(dataBytes, false); + + sGen = new PgpSignatureGenerator( + PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + + PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator( + CompressionAlgorithmTag.Zip); + + BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + + DateTime testDateTime = new DateTime(1973, 7, 27); + Stream lOut = lGen.Open(new UncloseableStream(bcOut), PgpLiteralData.Binary, "_CONSOLE", + dataBytes.Length, testDateTime); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Close(); + + sGen.Generate().Encode(bcOut); + + bcOut.Close(); + + // + // verify generated signature + // + pgpFact = new PgpObjectFactory(bOut.ToArray()); + + c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + ops = p1[0]; + + p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + dIn = p2.GetInputStream(); + + ops.InitVerify(secretKey.PublicKey); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed generated signature check"); + } + + // + // signature generation - version 3 + // + bOut = new UncloseableMemoryStream(); + + testIn = new MemoryStream(dataBytes); + PgpV3SignatureGenerator sGenV3 = new PgpV3SignatureGenerator( + PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); + + cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); + + bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + lGen = new PgpLiteralDataGenerator(); + lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Binary, + "_CONSOLE", + dataBytes.Length, + testDateTime); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte) ch); + sGen.Update((byte)ch); + } + + lOut.Close(); + + sGen.Generate().Encode(bcOut); + + bcOut.Close(); + + // + // verify generated signature + // + pgpFact = new PgpObjectFactory(bOut.ToArray()); + + c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + ops = p1[0]; + + p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + dIn = p2.GetInputStream(); + + ops.InitVerify(secretKey.PublicKey); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed v3 generated signature check"); + } + + // + // extract PGP 8 private key + // + pgpPriv = new PgpSecretKeyRing(pgp8Key); + + secretKey = pgpPriv.GetSecretKey(); + + pgpPrivKey = secretKey.ExtractPrivateKey(pgp8Pass); + + // + // other sig tests + // + PerformTestSig(HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey); + PerformTestSig(HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey); + PerformTestSig(HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey); + FingerPrintTest(); + ExistingEmbeddedJpegTest(); + EmbeddedJpegTest(); + } + + private void PerformTestSig( + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + PgpPrivateKey privKey) + { + const string data = "hello world!"; + byte[] dataBytes = Encoding.ASCII.GetBytes(data); + + MemoryStream bOut = new UncloseableMemoryStream(); + MemoryStream testIn = new MemoryStream(dataBytes, false); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, hashAlgorithm); + + sGen.InitSign(PgpSignature.BinaryDocument, privKey); + + PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); + + BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut))); + + sGen.GenerateOnePassVersion(false).Encode(bcOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + DateTime testDateTime = new DateTime(1973, 7, 27); + Stream lOut = lGen.Open( + new UncloseableStream(bcOut), + PgpLiteralData.Binary, + "_CONSOLE", + dataBytes.Length, + testDateTime); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Close(); + + sGen.Generate().Encode(bcOut); + + bcOut.Close(); + + // + // verify generated signature + // + PgpObjectFactory pgpFact = new PgpObjectFactory(bOut.ToArray()); + + PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject(); + + pgpFact = new PgpObjectFactory(c1.GetDataStream()); + + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + + PgpOnePassSignature ops = p1[0]; + + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + if (!p2.ModificationTime.Equals(testDateTime)) + { + Fail("Modification time not preserved"); + } + + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pubKey); + + // TODO Need a stream object to automatically call Update? + // (via ISigner implementation of PgpSignatureGenerator) + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + + if (!ops.Verify(p3[0])) + { + Fail("Failed generated signature check - " + hashAlgorithm); + } + } + + private class UncloseableMemoryStream + : MemoryStream + { + public override void Close() + { + throw new Exception("Close() called on underlying stream"); + } + } + + public override string Name + { + get { return "PGPRSATest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpRsaTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PGPSignatureTest.cs b/crypto/test/src/openpgp/test/PGPSignatureTest.cs new file mode 100644 index 000000000..3aba2c302 --- /dev/null +++ b/crypto/test/src/openpgp/test/PGPSignatureTest.cs @@ -0,0 +1,761 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpSignatureTest + : SimpleTest + { + private const int[] NO_PREFERENCES = null; + private static readonly int[] PREFERRED_SYMMETRIC_ALGORITHMS + = new int[] { (int)SymmetricKeyAlgorithmTag.Aes128, (int)SymmetricKeyAlgorithmTag.TripleDes }; + private static readonly int[] PREFERRED_HASH_ALGORITHMS + = new int[] { (int)HashAlgorithmTag.Sha1, (int)HashAlgorithmTag.Sha256 }; + private static readonly int[] PREFERRED_COMPRESSION_ALGORITHMS + = new int[] { (int)CompressionAlgorithmTag.ZLib }; + + private const int TEST_EXPIRATION_TIME = 10000; + private const string TEST_USER_ID = "test user id"; + private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("hello world!\nhello world!\n"); + private static readonly byte[] TEST_DATA_WITH_CRLF = Encoding.ASCII.GetBytes("hello world!\r\nhello world!\r\n"); + + private static readonly byte[] dsaKeyRing = Base64.Decode( + "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ" + + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV" + + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/" + + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug" + + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu" + + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ" + + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz" + + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej" + + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC" + + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu" + + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh" + + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j" + + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD" + + "4nXkHg=="); + + private static readonly char[] dsaPass = "hello world".ToCharArray(); + + private static readonly byte[] rsaKeyRing = Base64.Decode( + "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF" + + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd" + + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy" + + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y" + + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7" + + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO" + + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP" + + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY" + + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb" + + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4" + + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj" + + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I" + + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH" + + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt" + + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j" + + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw" + + "AgAA"); + + private static readonly char[] rsaPass = "2002 Buffalo Sabres".ToCharArray(); + + private static readonly byte[] nullPacketsSubKeyBinding = Base64.Decode( + "iDYEGBECAAAAACp9AJ9PlJCrFpi+INwG7z61eku2Wg1HaQCgl33X5Egj+Kf7F9CXIWj2iFCvQDo="); + + public override void PerformTest() + { + // + // RSA tests + // + PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(rsaKeyRing); + PgpSecretKey secretKey = pgpPriv.GetSecretKey(); + PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(rsaPass); + + try + { + doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + + Fail("RSA wrong key test failed."); + } + catch (PgpException) + { + // expected + } + + try + { + doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + + Fail("RSA V3 wrong key test failed."); + } + catch (PgpException) + { + // expected + } + + // + // certifications + // + PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey); + + PgpSignature sig = sGen.GenerateCertification(secretKey.PublicKey); + + sig.InitVerify(secretKey.PublicKey); + + if (!sig.VerifyCertification(secretKey.PublicKey)) + { + Fail("revocation verification failed."); + } + + PgpSecretKeyRing pgpDSAPriv = new PgpSecretKeyRing(dsaKeyRing); + PgpSecretKey secretDSAKey = pgpDSAPriv.GetSecretKey(); + PgpPrivateKey pgpPrivDSAKey = secretDSAKey.ExtractPrivateKey(dsaPass); + + sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey); + + PgpSignatureSubpacketGenerator unhashedGen = new PgpSignatureSubpacketGenerator(); + PgpSignatureSubpacketGenerator hashedGen = new PgpSignatureSubpacketGenerator(); + + hashedGen.SetSignatureExpirationTime(false, TEST_EXPIRATION_TIME); + hashedGen.SetSignerUserId(true, TEST_USER_ID); + hashedGen.SetPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS); + hashedGen.SetPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS); + hashedGen.SetPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS); + + sGen.SetHashedSubpackets(hashedGen.Generate()); + sGen.SetUnhashedSubpackets(unhashedGen.Generate()); + + sig = sGen.GenerateCertification(secretDSAKey.PublicKey, secretKey.PublicKey); + + byte[] sigBytes = sig.GetEncoded(); + + PgpObjectFactory f = new PgpObjectFactory(sigBytes); + + sig = ((PgpSignatureList) f.NextPgpObject())[0]; + + sig.InitVerify(secretDSAKey.PublicKey); + + if (!sig.VerifyCertification(secretDSAKey.PublicKey, secretKey.PublicKey)) + { + Fail("subkey binding verification failed."); + } + + PgpSignatureSubpacketVector hashedPcks = sig.GetHashedSubPackets(); + PgpSignatureSubpacketVector unhashedPcks = sig.GetUnhashedSubPackets(); + + if (hashedPcks.Count != 6) + { + Fail("wrong number of hashed packets found."); + } + + if (unhashedPcks.Count != 1) + { + Fail("wrong number of unhashed packets found."); + } + + if (!hashedPcks.GetSignerUserId().Equals(TEST_USER_ID)) + { + Fail("test userid not matching"); + } + + if (hashedPcks.GetSignatureExpirationTime() != TEST_EXPIRATION_TIME) + { + Fail("test signature expiration time not matching"); + } + + if (unhashedPcks.GetIssuerKeyId() != secretDSAKey.KeyId) + { + Fail("wrong issuer key ID found in certification"); + } + + int[] prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms(); + preferredAlgorithmCheck("compression", PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs); + + prefAlgs = hashedPcks.GetPreferredHashAlgorithms(); + preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS, prefAlgs); + + prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms(); + preferredAlgorithmCheck("symmetric", PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs); + + SignatureSubpacketTag[] criticalHashed = hashedPcks.GetCriticalTags(); + + if (criticalHashed.Length != 1) + { + Fail("wrong number of critical packets found."); + } + + if (criticalHashed[0] != SignatureSubpacketTag.SignerUserId) + { + Fail("wrong critical packet found in tag list."); + } + + // + // no packets passed + // + sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey); + + sGen.SetHashedSubpackets(null); + sGen.SetUnhashedSubpackets(null); + + sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey); + + sig.InitVerify(secretDSAKey.PublicKey); + + if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey)) + { + Fail("subkey binding verification failed."); + } + + hashedPcks = sig.GetHashedSubPackets(); + + if (hashedPcks.Count != 1) + { + Fail("found wrong number of hashed packets"); + } + + unhashedPcks = sig.GetUnhashedSubPackets(); + + if (unhashedPcks.Count != 1) + { + Fail("found wrong number of unhashed packets"); + } + + try + { + sig.VerifyCertification(secretKey.PublicKey); + + Fail("failed to detect non-key signature."); + } + catch (InvalidOperationException) + { + // expected + } + + // + // override hash packets + // + sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1); + + sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey); + + hashedGen = new PgpSignatureSubpacketGenerator(); + + DateTime creationTime = new DateTime(1973, 7, 27); + hashedGen.SetSignatureCreationTime(false, creationTime); + + sGen.SetHashedSubpackets(hashedGen.Generate()); + + sGen.SetUnhashedSubpackets(null); + + sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey); + + sig.InitVerify(secretDSAKey.PublicKey); + + if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey)) + { + Fail("subkey binding verification failed."); + } + + hashedPcks = sig.GetHashedSubPackets(); + + if (hashedPcks.Count != 1) + { + Fail("found wrong number of hashed packets in override test"); + } + + if (!hashedPcks.HasSubpacket(SignatureSubpacketTag.CreationTime)) + { + Fail("hasSubpacket test for creation time failed"); + } + + DateTime sigCreationTime = hashedPcks.GetSignatureCreationTime(); + if (!sigCreationTime.Equals(creationTime)) + { + Fail("creation of overridden date failed."); + } + + prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms(); + preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs); + + prefAlgs = hashedPcks.GetPreferredHashAlgorithms(); + preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs); + + prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms(); + preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs); + + if (hashedPcks.GetKeyExpirationTime() != 0) + { + Fail("unexpected key expiration time found"); + } + + if (hashedPcks.GetSignatureExpirationTime() != 0) + { + Fail("unexpected signature expiration time found"); + } + + if (hashedPcks.GetSignerUserId() != null) + { + Fail("unexpected signer user ID found"); + } + + criticalHashed = hashedPcks.GetCriticalTags(); + + if (criticalHashed.Length != 0) + { + Fail("critical packets found when none expected"); + } + + unhashedPcks = sig.GetUnhashedSubPackets(); + + if (unhashedPcks.Count != 1) + { + Fail("found wrong number of unhashed packets in override test"); + } + + // + // general signatures + // + doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey); + doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey); + doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey); + doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF); + doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF); + doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF); + doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF); + + // + // DSA Tests + // + pgpPriv = new PgpSecretKeyRing(dsaKeyRing); + secretKey = pgpPriv.GetSecretKey(); + pgpPrivKey = secretKey.ExtractPrivateKey(dsaPass); + + try + { + doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + + Fail("DSA wrong key test failed."); + } + catch (PgpException) + { + // expected + } + + try + { + doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + + Fail("DSA V3 wrong key test failed."); + } + catch (PgpException) + { + // expected + } + + doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey); + doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF); + doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF); + doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF); + doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF); + + // special cases + // + doTestMissingSubpackets(nullPacketsSubKeyBinding); + + doTestMissingSubpackets(generateV3BinarySig(pgpPrivKey, PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1)); + + // keyflags + doTestKeyFlagsValues(); + } + + private void doTestKeyFlagsValues() + { + checkValue(KeyFlags.CertifyOther, 0x01); + checkValue(KeyFlags.SignData, 0x02); + checkValue(KeyFlags.EncryptComms, 0x04); + checkValue(KeyFlags.EncryptStorage, 0x08); + checkValue(KeyFlags.Split, 0x10); + checkValue(KeyFlags.Authentication, 0x20); + checkValue(KeyFlags.Shared, 0x80); + + // yes this actually happens + checkValue(new byte[] { 4, 0, 0, 0 }, 0x04); + checkValue(new byte[] { 4, 0, 0 }, 0x04); + checkValue(new byte[] { 4, 0 }, 0x04); + checkValue(new byte[] { 4 }, 0x04); + } + + private void checkValue(int flag, int val) + { + KeyFlags f = new KeyFlags(true, flag); + + if (f.Flags != val) + { + Fail("flag value mismatch"); + } + } + + private void checkValue(byte[] flag, int val) + { + KeyFlags f = new KeyFlags(true, flag); + + if (f.Flags != val) + { + Fail("flag value mismatch"); + } + } + + private void doTestMissingSubpackets(byte[] signature) + { + PgpObjectFactory f = new PgpObjectFactory(signature); + object obj = f.NextPgpObject(); + + while (!(obj is PgpSignatureList)) + { + obj = f.NextPgpObject(); + if (obj is PgpLiteralData) + { + Stream input = ((PgpLiteralData)obj).GetDataStream(); + Streams.Drain(input); + } + } + + PgpSignature sig = ((PgpSignatureList)obj)[0]; + + if (sig.Version > 3) + { + PgpSignatureSubpacketVector v = sig.GetHashedSubPackets(); + + if (v.GetKeyExpirationTime() != 0) + { + Fail("key expiration time not zero for missing subpackets"); + } + + if (!sig.HasSubpackets) + { + Fail("HasSubpackets property was false with packets"); + } + } + else + { + if (sig.GetHashedSubPackets() != null) + { + Fail("hashed sub packets found when none expected"); + } + + if (sig.GetUnhashedSubPackets() != null) + { + Fail("unhashed sub packets found when none expected"); + } + + if (sig.HasSubpackets) + { + Fail("HasSubpackets property was true with no packets"); + } + } + } + + private void preferredAlgorithmCheck( + string type, + int[] expected, + int[] prefAlgs) + { + if (expected == null) + { + if (prefAlgs != null) + { + Fail("preferences for " + type + " found when none expected"); + } + } + else + { + if (prefAlgs.Length != expected.Length) + { + Fail("wrong number of preferred " + type + " algorithms found"); + } + + for (int i = 0; i != expected.Length; i++) + { + if (expected[i] != prefAlgs[i]) + { + Fail("wrong algorithm found for " + type + ": expected " + expected[i] + " got " + prefAlgs); + } + } + } + } + + private void doTestSig( + PublicKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + PgpPrivateKey privKey) + { + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(TEST_DATA, false); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm); + + sGen.InitSign(PgpSignature.BinaryDocument, privKey); + sGen.GenerateOnePassVersion(false).Encode(bOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open( + new UncloseableStream(bOut), + PgpLiteralData.Binary, + "_CONSOLE", + TEST_DATA.Length * 2, + DateTime.UtcNow); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Write(TEST_DATA, 0, TEST_DATA.Length); + sGen.Update(TEST_DATA); + + lGen.Close(); + + sGen.Generate().Encode(bOut); + + verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA); + } + + private void doTestTextSig( + PublicKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + PgpPrivateKey privKey, + byte[] data, + byte[] canonicalData) + { + PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1); + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(data, false); + DateTime creationTime = DateTime.UtcNow; + + sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey); + sGen.GenerateOnePassVersion(false).Encode(bOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open( + new UncloseableStream(bOut), + PgpLiteralData.Text, + "_CONSOLE", + data.Length * 2, + creationTime); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Write(data, 0, data.Length); + sGen.Update(data); + + lGen.Close(); + + PgpSignature sig = sGen.Generate(); + + if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0)) + { + Fail("creation time not set in v4 signature"); + } + + sig.Encode(bOut); + + verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData); + } + + private void doTestSigV3( + PublicKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + PgpPrivateKey privKey) + { + byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm); + + verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA); + } + + private byte[] generateV3BinarySig( + PgpPrivateKey privKey, + PublicKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm) + { + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(TEST_DATA, false); + PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, hashAlgorithm); + + sGen.InitSign(PgpSignature.BinaryDocument, privKey); + sGen.GenerateOnePassVersion(false).Encode(bOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open( + new UncloseableStream(bOut), + PgpLiteralData.Binary, + "_CONSOLE", + TEST_DATA.Length * 2, + DateTime.UtcNow); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Write(TEST_DATA, 0, TEST_DATA.Length); + sGen.Update(TEST_DATA); + + lGen.Close(); + + sGen.Generate().Encode(bOut); + + return bOut.ToArray(); + } + + private void doTestTextSigV3( + PublicKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + PgpPrivateKey privKey, + byte[] data, + byte[] canonicalData) + { + PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1); + MemoryStream bOut = new MemoryStream(); + MemoryStream testIn = new MemoryStream(data, false); + + sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey); + sGen.GenerateOnePassVersion(false).Encode(bOut); + + PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); + Stream lOut = lGen.Open( + new UncloseableStream(bOut), + PgpLiteralData.Text, + "_CONSOLE", + data.Length * 2, + DateTime.UtcNow); + + int ch; + while ((ch = testIn.ReadByte()) >= 0) + { + lOut.WriteByte((byte)ch); + sGen.Update((byte)ch); + } + + lOut.Write(data, 0, data.Length); + sGen.Update(data); + + lGen.Close(); + + PgpSignature sig = sGen.Generate(); + + if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0)) + { + Fail("creation time not set in v3 signature"); + } + + sig.Encode(bOut); + + verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData); + } + + private void verifySignature( + byte[] encodedSig, + HashAlgorithmTag hashAlgorithm, + PgpPublicKey pubKey, + byte[] original) + { + PgpObjectFactory pgpFact = new PgpObjectFactory(encodedSig); + PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject(); + PgpOnePassSignature ops = p1[0]; + PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject(); + Stream dIn = p2.GetInputStream(); + + ops.InitVerify(pubKey); + + int ch; + while ((ch = dIn.ReadByte()) >= 0) + { + ops.Update((byte)ch); + } + + PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); + PgpSignature sig = p3[0]; + + DateTime creationTime = sig.CreationTime; + + // Check creationTime is recent + if (creationTime.CompareTo(DateTime.UtcNow) > 0 + || creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0) + { + Fail("bad creation time in signature: " + creationTime); + } + + if (sig.KeyId != pubKey.KeyId) + { + Fail("key id mismatch in signature"); + } + + if (!ops.Verify(sig)) + { + Fail("Failed generated signature check - " + hashAlgorithm); + } + + sig.InitVerify(pubKey); + + for (int i = 0; i != original.Length; i++) + { + sig.Update(original[i]); + } + + sig.Update(original); + + if (!sig.Verify()) + { + Fail("Failed generated signature check against original data"); + } + } + + public override string Name + { + get { return "PGPSignatureTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpSignatureTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs new file mode 100644 index 000000000..b776a0d2a --- /dev/null +++ b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs @@ -0,0 +1,2163 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpKeyRingTest + : SimpleTest + { + private static readonly byte[] pub1 = Base64.Decode( + "mQGiBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn" + + "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg" + + "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf" + + "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ" + + "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G" + + "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ" + + "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG" + + "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP" + + "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif" + + "IIeLOTI5Dc4XKeV32a+bWrQidGVzdCAoVGVzdCBrZXkpIDx0ZXN0QHViaWNh" + + "bGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB4TOABgsJCAcDAgMVAgMDFgIB" + + "Ah4BAheAAAoJEJh8Njfhe8KmGDcAoJWr8xgPr75y/Cp1kKn12oCCOb8zAJ4p" + + "xSvk4K6tB2jYbdeSrmoWBZLdMLACAAC5AQ0EQDzfARAEAJeUAPvUzJJbKcc5" + + "5Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj47UPAD/tQxwz8VAwJySx82ggN" + + "LxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j2BVqZAaX3q79a3eMiql1T0oE" + + "AGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOHAAQNBACD0mVMlAUgd7REYy/1" + + "mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWaHz6CN1XptdwpDeSYEOFZ0PSu" + + "qH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85efMBA9jUv/DeBOzRWMFG6sC6y" + + "k8NGG7Swea7EHKeQI40G3jgO/+xANtMyTIhPBBgRAgAPBQJAPN8BAhsMBQkB" + + "4TOAAAoJEJh8Njfhe8KmG7kAn00mTPGJCWqmskmzgdzeky5fWd7rAKCNCp3u" + + "ZJhfg0htdgAfIy8ppm05vLACAAA="); + + private static readonly byte[] sec1 = Base64.Decode( + "lQHhBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn" + + "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg" + + "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf" + + "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ" + + "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G" + + "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ" + + "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG" + + "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP" + + "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif" + + "IIeLOTI5Dc4XKeV32a+bWv4CAwJ5KgazImo+sGBfMhDiBcBTqyDGhKHNgHic" + + "0Pky9FeRvfXTc2AO+jGmFPjcs8BnTWuDD0/jkQnRZpp1TrQidGVzdCAoVGVz" + + "dCBrZXkpIDx0ZXN0QHViaWNhbGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB" + + "4TOABgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEJh8Njfhe8KmGDcAn3XeXDMg" + + "BZgrZzFWU2IKtA/5LG2TAJ0Vf/jjyq0jZNZfGfoqGTvD2MAl0rACAACdAVgE" + + "QDzfARAEAJeUAPvUzJJbKcc55Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj4" + + "7UPAD/tQxwz8VAwJySx82ggNLxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j" + + "2BVqZAaX3q79a3eMiql1T0oEAGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOH" + + "AAQNBACD0mVMlAUgd7REYy/1mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWa" + + "Hz6CN1XptdwpDeSYEOFZ0PSuqH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85e" + + "fMBA9jUv/DeBOzRWMFG6sC6yk8NGG7Swea7EHKeQI40G3jgO/+xANtMyTP4C" + + "AwJ5KgazImo+sGBl2C7CFuI+5KM4ZhbtVie7l+OiTpr5JW2z5VgnV3EX9p04" + + "LcGKfQvD65+ELwli6yh8B2zGcipqTaYk3QoYNIhPBBgRAgAPBQJAPN8BAhsM" + + "BQkB4TOAAAoJEJh8Njfhe8KmG7kAniuRkaFFv1pdCBN8JJXpcorHmyouAJ9L" + + "xxmusffR6OI7WgD3XZ0AL8zUC7ACAAA="); + +// private static readonly char[] pass1 = "qwertzuiop".ToCharArray(); + + private static readonly byte[] pub2 = Base64.Decode( + "mQGiBEBtfW8RBADfWjTxFedIbGBNVgh064D/OCf6ul7x4PGsCl+BkAyheYkr" + + "mVUsChmBKoeXaY+Fb85wwusXzyM/6JFK58Rg+vEb3Z19pue8Ixxq7cRtCtOA" + + "tOP1eKXLNtTRWJutvLkQmeOa19UZ6ziIq23aWuWKSq+KKMWek2GUnGycnx5M" + + "W0pn1QCg/39r9RKhY9cdKYqRcqsr9b2B/AsD/Ru24Q15Jmrsl9zZ6EC47J49" + + "iNW5sLQx1qf/mgfVWQTmU2j6gq4ND1OuK7+0OP/1yMOUpkjjcqxFgTnDAAoM" + + "hHDTzCv/aZzIzmMvgLsYU3aIMfbz+ojpuASMCMh+te01cEMjiPWwDtdWWOdS" + + "OSyX9ylzhO3PiNDks8R83onsacYpA/9WhTcg4bvkjaj66I7wGZkm3BmTxNSb" + + "pE4b5HZDh31rRYhY9tmrryCfFnU4BS2Enjj5KQe9zFv7pUBCBW2oFo8i8Osn" + + "O6fa1wVN4fBHC6wqWmmpnkFerNPkiC9V75KUFIfeWHmT3r2DVSO3dfdHDERA" + + "jFIAioMLjhaX6DnODF5KQrABh7QmU2FpIFB1bGxhYmhvdGxhIDxwc2FpQG15" + + "amF2YXdvcmxkLmNvbT6wAwP//4kAVwQQEQIAFwUCQG19bwcLCQgHAwIKAhkB" + + "BRsDAAAAAAoJEKXQf/RT99uYmfAAoMKxV5g2owIfmy2w7vSLvOQUpvvOAJ4n" + + "jB6xJot523rPAQW9itPoGGekirABZ7kCDQRAbX1vEAgA9kJXtwh/CBdyorrW" + + "qULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9" + + "ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/" + + "Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4" + + "DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEs" + + "tSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1B" + + "n5x8vYlLIhkmuquiXsNV6TILOwACAgf9F7/nJHDayJ3pBVTTVSq2g5WKUXMg" + + "xxGKTvOahiVRcbO03w0pKAkH85COakVfe56sMYpWRl36adjNoKOxaciow74D" + + "1R5snY/hv/kBXPBkzo4UMkbANIVaZ0IcnLp+rkkXcDVbRCibZf8FfCY1zXbq" + + "d680UtEgRbv1D8wFBqfMt7kLsuf9FnIw6vK4DU06z5ZDg25RHGmswaDyY6Mw" + + "NGCrKGbHf9I/T7MMuhGF/in8UU8hv8uREOjseOqklG3/nsI1hD/MdUC7fzXi" + + "MRO4RvahLoeXOuaDkMYALdJk5nmNuCL1YPpbFGttI3XsK7UrP/Fhd8ND6Nro" + + "wCqrN6keduK+uLABh4kATAQYEQIADAUCQG19bwUbDAAAAAAKCRCl0H/0U/fb" + + "mC/0AJ4r1yvyu4qfOXlDgmVuCsvHFWo63gCfRIrCB2Jv/N1cgpmq0L8LGHM7" + + "G/KwAWeZAQ0EQG19owEIAMnavLYqR7ffaDPbbq+lQZvLCK/3uA0QlyngNyTa" + + "sDW0WC1/ryy2dx7ypOOCicjnPYfg3LP5TkYAGoMjxH5+xzM6xfOR+8/EwK1z" + + "N3A5+X/PSBDlYjQ9dEVKrvvc7iMOp+1K1VMf4Ug8Yah22Ot4eLGP0HRCXiv5" + + "vgdBNsAl/uXnBJuDYQmLrEniqq/6UxJHKHxZoS/5p13Cq7NfKB1CJCuJXaCE" + + "TW2do+cDpN6r0ltkF/r+ES+2L7jxyoHcvQ4YorJoDMlAN6xpIZQ8dNaTYP/n" + + "Mx/pDS3shUzbU+UYPQrreJLMF1pD+YWP5MTKaZTo+U/qPjDFGcadInhPxvh3" + + "1ssAEQEAAbABh7QuU2FuZGh5YSBQdWxsYWJob3RsYSA8cHNhbmRoeWFAbXlq" + + "YXZhd29ybGQuY29tPrADA///iQEtBBABAgAXBQJAbX2jBwsJCAcDAgoCGQEF" + + "GwMAAAAACgkQx87DL9gOvoeVUwgAkQXYiF0CxhKbDnuabAssnOEwJrutgCRO" + + "CJRQvIwTe3fe6hQaWn2Yowt8OQtNFiR8GfAY6EYxyFLKzZbAI/qtq5fHmN3e" + + "RSyNWe6d6e17hqZZL7kf2sVkyGTChHj7Jiuo7vWkdqT2MJN6BW5tS9CRH7Me" + + "D839STv+4mAAO9auGvSvicP6UEQikAyCy/ihoJxLQlspfbSNpi0vrUjCPT7N" + + "tWwfP0qF64i9LYkjzLqihnu+UareqOPhXcWnyFKrjmg4ezQkweNU2pdvCLbc" + + "W24FhT92ivHgpLyWTswXcqjhFjVlRr0+2sIz7v1k0budCsJ7PjzOoH0hJxCv" + + "sJQMlZR/e7ABZ7kBDQRAbX2kAQgAm5j+/LO2M4pKm/VUPkYuj3eefHkzjM6n" + + "KbvRZX1Oqyf+6CJTxQskUWKAtkzzKafPdS5Wg0CMqeXov+EFod4bPEYccszn" + + "cKd1U8NRwacbEpCvvvB84Yl2YwdWpDpkryyyLI4PbCHkeuwx9Dc2z7t4XDB6" + + "FyAJTMAkia7nzYa/kbeUO3c2snDb/dU7uyCsyKtTZyTyhTgtl/f9L03Bgh95" + + "y3mOUz0PimJ0Sg4ANczF4d04BpWkjLNVJi489ifWodPlHm1hag5drYekYpWJ" + + "+3g0uxs5AwayV9BcOkPKb1uU3EoYQw+nn0Kn314Nvx2M1tKYunuVNLEm0PhA" + + "/+B8PTq8BQARAQABsAGHiQEiBBgBAgAMBQJAbX2kBRsMAAAAAAoJEMfOwy/Y" + + "Dr6HkLoH/RBY8lvUv1r8IdTs5/fN8e/MnGeThLl+JrlYF/4t3tjXYIf5xUj/" + + "c9NdjreKYgHfMtrbVM08LlxUVQlkjuF3DIk5bVH9Blq8aXmyiwiM5GrCry+z" + + "WiqkpZze1G577C38mMJbHDwbqNCLALMzo+W2q04Avl5sniNnDNGbGz9EjhRg" + + "o7oS16KkkD6Ls4RnHTEZ0vyZOXodDHu+sk/2kzj8K07kKaM8rvR7aDKiI7HH" + + "1GxJz70fn1gkKuV2iAIIiU25bty+S3wr+5h030YBsUZF1qeKCdGOmpK7e9Of" + + "yv9U7rf6Z5l8q+akjqLZvej9RnxeH2Um7W+tGg2me482J+z6WOawAWc="); + + private static readonly byte[] sec2 = Base64.Decode( + "lQHpBEBtfW8RBADfWjTxFedIbGBNVgh064D/OCf6ul7x4PGsCl+BkAyheYkr" + + "mVUsChmBKoeXaY+Fb85wwusXzyM/6JFK58Rg+vEb3Z19pue8Ixxq7cRtCtOA" + + "tOP1eKXLNtTRWJutvLkQmeOa19UZ6ziIq23aWuWKSq+KKMWek2GUnGycnx5M" + + "W0pn1QCg/39r9RKhY9cdKYqRcqsr9b2B/AsD/Ru24Q15Jmrsl9zZ6EC47J49" + + "iNW5sLQx1qf/mgfVWQTmU2j6gq4ND1OuK7+0OP/1yMOUpkjjcqxFgTnDAAoM" + + "hHDTzCv/aZzIzmMvgLsYU3aIMfbz+ojpuASMCMh+te01cEMjiPWwDtdWWOdS" + + "OSyX9ylzhO3PiNDks8R83onsacYpA/9WhTcg4bvkjaj66I7wGZkm3BmTxNSb" + + "pE4b5HZDh31rRYhY9tmrryCfFnU4BS2Enjj5KQe9zFv7pUBCBW2oFo8i8Osn" + + "O6fa1wVN4fBHC6wqWmmpnkFerNPkiC9V75KUFIfeWHmT3r2DVSO3dfdHDERA" + + "jFIAioMLjhaX6DnODF5KQv4JAwIJH6A/rzqmMGAG4e+b8Whdvp8jaTGVT4CG" + + "M1b65rbiDyAuf5KTFymQBOIi9towgFzG9NXAZC07nEYSukN56tUTUDNVsAGH" + + "tCZTYWkgUHVsbGFiaG90bGEgPHBzYWlAbXlqYXZhd29ybGQuY29tPrADA///" + + "iQBXBBARAgAXBQJAbX1vBwsJCAcDAgoCGQEFGwMAAAAACgkQpdB/9FP325iZ" + + "8ACgwrFXmDajAh+bLbDu9Iu85BSm+84AnieMHrEmi3nbes8BBb2K0+gYZ6SK" + + "sAFnnQJqBEBtfW8QCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoB" + + "p1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3b" + + "zpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa" + + "8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPw" + + "pVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obE" + + "AxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7" + + "AAICB/0Xv+ckcNrInekFVNNVKraDlYpRcyDHEYpO85qGJVFxs7TfDSkoCQfz" + + "kI5qRV97nqwxilZGXfpp2M2go7FpyKjDvgPVHmydj+G/+QFc8GTOjhQyRsA0" + + "hVpnQhycun6uSRdwNVtEKJtl/wV8JjXNdup3rzRS0SBFu/UPzAUGp8y3uQuy" + + "5/0WcjDq8rgNTTrPlkODblEcaazBoPJjozA0YKsoZsd/0j9Pswy6EYX+KfxR" + + "TyG/y5EQ6Ox46qSUbf+ewjWEP8x1QLt/NeIxE7hG9qEuh5c65oOQxgAt0mTm" + + "eY24IvVg+lsUa20jdewrtSs/8WF3w0Po2ujAKqs3qR524r64/gkDAmmp39NN" + + "U2pqYHokufIOab2VpD7iQo8UjHZNwR6dpjyky9dVfIe4MA0H+t0ju8UDdWoe" + + "IkRu8guWsI83mjGPbIq8lmsZOXPCA8hPuBmL0iaj8TnuotmsBjIBsAGHiQBM" + + "BBgRAgAMBQJAbX1vBRsMAAAAAAoJEKXQf/RT99uYL/QAnivXK/K7ip85eUOC" + + "ZW4Ky8cVajreAJ9EisIHYm/83VyCmarQvwsYczsb8rABZ5UDqARAbX2jAQgA" + + "ydq8tipHt99oM9tur6VBm8sIr/e4DRCXKeA3JNqwNbRYLX+vLLZ3HvKk44KJ" + + "yOc9h+Dcs/lORgAagyPEfn7HMzrF85H7z8TArXM3cDn5f89IEOViND10RUqu" + + "+9zuIw6n7UrVUx/hSDxhqHbY63h4sY/QdEJeK/m+B0E2wCX+5ecEm4NhCYus" + + "SeKqr/pTEkcofFmhL/mnXcKrs18oHUIkK4ldoIRNbZ2j5wOk3qvSW2QX+v4R" + + "L7YvuPHKgdy9DhiismgMyUA3rGkhlDx01pNg/+czH+kNLeyFTNtT5Rg9Cut4" + + "kswXWkP5hY/kxMpplOj5T+o+MMUZxp0ieE/G+HfWywARAQABCWEWL2cKQKcm" + + "XFTNsWgRoOcOkKyJ/osERh2PzNWvOF6/ir1BMRsg0qhd+hEcoWHaT+7Vt12i" + + "5Y2Ogm2HFrVrS5/DlV/rw0mkALp/3cR6jLOPyhmq7QGwhG27Iy++pLIksXQa" + + "RTboa7ZasEWw8zTqa4w17M5Ebm8dtB9Mwl/kqU9cnIYnFXj38BWeia3iFBNG" + + "PD00hqwhPUCTUAcH9qQPSqKqnFJVPe0KQWpq78zhCh1zPUIa27CE86xRBf45" + + "XbJwN+LmjCuQEnSNlloXJSPTRjEpla+gWAZz90fb0uVIR1dMMRFxsuaO6aCF" + + "QMN2Mu1wR/xzTzNCiQf8cVzq7YkkJD8ChJvu/4BtWp3BlU9dehAz43mbMhaw" + + "Qx3NmhKR/2dv1cJy/5VmRuljuzC+MRtuIjJ+ChoTa9ubNjsT6BF5McRAnVzf" + + "raZK+KVWCGA8VEZwe/K6ouYLsBr6+ekCKIkGZdM29927m9HjdFwEFjnzQlWO" + + "NZCeYgDcK22v7CzobKjdo2wdC7XIOUVCzMWMl+ch1guO/Y4KVuslfeQG5X1i" + + "PJqV+bwJriCx5/j3eE/aezK/vtZU6cchifmvefKvaNL34tY0Myz2bOx44tl8" + + "qNcGZbkYF7xrNCutzI63xa2ruN1p3hNxicZV1FJSOje6+ITXkU5Jmufto7IJ" + + "t/4Q2dQefBQ1x/d0EdX31yK6+1z9dF/k3HpcSMb5cAWa2u2g4duAmREHc3Jz" + + "lHCsNgyzt5mkb6kS43B6og8Mm2SOx78dBIOA8ANzi5B6Sqk3/uN5eQFLY+sQ" + + "qGxXzimyfbMjyq9DdqXThx4vlp3h/GC39KxL5MPeB0oe6P3fSP3C2ZGjsn3+" + + "XcYk0Ti1cBwBOFOZ59WYuc61B0wlkiU/WGeaebABh7QuU2FuZGh5YSBQdWxs" + + "YWJob3RsYSA8cHNhbmRoeWFAbXlqYXZhd29ybGQuY29tPrADA///iQEtBBAB" + + "AgAXBQJAbX2jBwsJCAcDAgoCGQEFGwMAAAAACgkQx87DL9gOvoeVUwgAkQXY" + + "iF0CxhKbDnuabAssnOEwJrutgCROCJRQvIwTe3fe6hQaWn2Yowt8OQtNFiR8" + + "GfAY6EYxyFLKzZbAI/qtq5fHmN3eRSyNWe6d6e17hqZZL7kf2sVkyGTChHj7" + + "Jiuo7vWkdqT2MJN6BW5tS9CRH7MeD839STv+4mAAO9auGvSvicP6UEQikAyC" + + "y/ihoJxLQlspfbSNpi0vrUjCPT7NtWwfP0qF64i9LYkjzLqihnu+UareqOPh" + + "XcWnyFKrjmg4ezQkweNU2pdvCLbcW24FhT92ivHgpLyWTswXcqjhFjVlRr0+" + + "2sIz7v1k0budCsJ7PjzOoH0hJxCvsJQMlZR/e7ABZ50DqARAbX2kAQgAm5j+" + + "/LO2M4pKm/VUPkYuj3eefHkzjM6nKbvRZX1Oqyf+6CJTxQskUWKAtkzzKafP" + + "dS5Wg0CMqeXov+EFod4bPEYccszncKd1U8NRwacbEpCvvvB84Yl2YwdWpDpk" + + "ryyyLI4PbCHkeuwx9Dc2z7t4XDB6FyAJTMAkia7nzYa/kbeUO3c2snDb/dU7" + + "uyCsyKtTZyTyhTgtl/f9L03Bgh95y3mOUz0PimJ0Sg4ANczF4d04BpWkjLNV" + + "Ji489ifWodPlHm1hag5drYekYpWJ+3g0uxs5AwayV9BcOkPKb1uU3EoYQw+n" + + "n0Kn314Nvx2M1tKYunuVNLEm0PhA/+B8PTq8BQARAQABCXo6bD6qi3s4U8Pp" + + "Uf9l3DyGuwiVPGuyb2P+sEmRFysi2AvxMe9CkF+CLCVYfZ32H3Fcr6XQ8+K8" + + "ZGH6bJwijtV4QRnWDZIuhUQDS7dsbGqTh4Aw81Fm0Bz9fpufViM9RPVEysxs" + + "CZRID+9jDrACthVsbq/xKomkKdBfNTK7XzGeZ/CBr9F4EPlnBWClURi9txc0" + + "pz9YP5ZRy4XTFgx+jCbHgKWUIz4yNaWQqpSgkHEDrGZwstXeRaaPftcfQN+s" + + "EO7OGl/Hd9XepGLez4vKSbT35CnqTwMzCK1IwUDUzyB4BYEFZ+p9TI18HQDW" + + "hA0Wmf6E8pjS16m/SDXoiRY43u1jUVZFNFzz25uLFWitfRNHCLl+VfgnetZQ" + + "jMFr36HGVQ65fogs3avkgvpgPwDc0z+VMj6ujTyXXgnCP/FdhzgkRFJqgmdJ" + + "yOlC+wFmZJEs0MX7L/VXEXdpR27XIGYm24CC7BTFKSdlmR1qqenXHmCCg4Wp" + + "00fV8+aAsnesgwPvxhCbZQVp4v4jqhVuB/rvsQu9t0rZnKdDnWeom/F3StYo" + + "A025l1rrt0wRP8YS4XlslwzZBqgdhN4urnzLH0/F3X/MfjP79Efj7Zk07vOH" + + "o/TPjz8lXroPTscOyXWHwtQqcMhnVsj9jvrzhZZSdUuvnT30DR7b8xcHyvAo" + + "WG2cnF/pNSQX11RlyyAOlw9TOEiDJ4aLbFdkUt+qZdRKeC8mEC2xsQ87HqFR" + + "pWKWABWaoUO0nxBEmvNOy97PkIeGVFNHDLlIeL++Ry03+JvuNNg4qAnwacbJ" + + "TwQzWP4vJqre7Gl/9D0tVlD4Yy6Xz3qyosxdoFpeMSKHhgKVt1bk0SQP7eXA" + + "C1c+eDc4gN/ZWpl+QLqdk2T9vr4wRAaK5LABh4kBIgQYAQIADAUCQG19pAUb" + + "DAAAAAAKCRDHzsMv2A6+h5C6B/0QWPJb1L9a/CHU7Of3zfHvzJxnk4S5fia5" + + "WBf+Ld7Y12CH+cVI/3PTXY63imIB3zLa21TNPC5cVFUJZI7hdwyJOW1R/QZa" + + "vGl5sosIjORqwq8vs1oqpKWc3tRue+wt/JjCWxw8G6jQiwCzM6PltqtOAL5e" + + "bJ4jZwzRmxs/RI4UYKO6EteipJA+i7OEZx0xGdL8mTl6HQx7vrJP9pM4/CtO" + + "5CmjPK70e2gyoiOxx9RsSc+9H59YJCrldogCCIlNuW7cvkt8K/uYdN9GAbFG" + + "RdanignRjpqSu3vTn8r/VO63+meZfKvmpI6i2b3o/UZ8Xh9lJu1vrRoNpnuP" + + "Nifs+ljmsAFn"); + + private static readonly char[] sec2pass1 = "sandhya".ToCharArray(); + private static readonly char[] sec2pass2 = "psai".ToCharArray(); + + private static readonly byte[] pub3 = Base64.Decode( + "mQGiBEB9BH0RBACtYQtE7tna6hgGyGLpq+ds3r2cLC0ISn5dNw7tm9vwiNVF" + + "JA2N37RRrifw4PvgelRSvLaX3M3ZBqC9s1Metg3v4FSlIRtSLWCNpHSvNw7i" + + "X8C2Xy9Hdlbh6Y/50o+iscojLRE14upfR1bIkcCZQGSyvGV52V2wBImUUZjV" + + "s2ZngwCg7mu852vK7+euz4WaL7ERVYtq9CMEAJ5swrljerDpz/RQ4Lhp6KER" + + "KyuI0PUttO57xINGshEINgYlZdGaZHRueHe7uKfI19mb0T4N3NJWaZ0wF+Cn" + + "rixsq0VrTUfiwfZeGluNG73aTCeY45fVXMGTTSYXzS8T0LW100Xn/0g9HRyA" + + "xUpuWo8IazxkMqHJis2uwriYKpAfA/9anvj5BS9p5pfPjp9dGM7GTMIYl5f2" + + "fcP57f+AW1TVR6IZiMJAvAdeWuLtwLnJiFpGlnFz273pfl+sAuqm1yNceImR" + + "2SDDP4+vtyycWy8nZhgEuhZx3W3cWMQz5WyNJSY1JJHh9TCQkCoN8E7XpVP4" + + "zEPboB2GzD93mfD8JLHP+7QtVGVzdCBLZXkgKG5vIGNvbW1lbnQpIDx0ZXN0" + + "QGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkFAkB9BH0ECwcDAgMVAgMDFgIB" + + "Ah4BAheAAAoJEKnMV8vjZQOpSRQAnidAQswYkrXQAFcLBzhxQTknI9QMAKDR" + + "ryV3l6xuCCgHST8JlxpbjcXhlLACAAPRwXPBcQEQAAEBAAAAAAAAAAAAAAAA" + + "/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q" + + "/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAi" + + "LCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEcITIy" + + "MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy" + + "MjIy/8AAEQgAFAAUAwEiAAIRAQMRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAE" + + "BQIDBgf/xAAoEAABAgUDBAEFAAAAAAAAAAABAgMABBEhMQUSQQYTIiNhFFGB" + + "kcH/xAAXAQEAAwAAAAAAAAAAAAAAAAAEAgMF/8QAJBEAAQQAAwkAAAAAAAAA" + + "AAAAAQACERIEIfATMTJBUZGx0fH/2gAMAwEAAhEDEQA/APMuotJlJVxstqaP" + + "o22NlAUp+YsNO0qSUtBcMu6n6EtOHcfPAHHFI16++oajQtTA3DapK02HFR8U" + + "pE9pTbQWtKm2WG2rlxVyQTcfGbn7Qm0OIjL77Wrs2NNm9lzTmmSxQ0PX4opS" + + "prk5tmESF6syggzGwOLG6gXgHFbZhBixk8XlIDcOQLRKt+rX+3qC5ZLTQblp" + + "Qlvwvxn9CMpZturVGkJHapQJphRH8hCLXbzrqpYsCx1zC5rtpJNuYQhASc0U" + + "AQv/2YhcBBMRAgAcBQJAfQV+AhsDBAsHAwIDFQIDAxYCAQIeAQIXgAAKCRCp" + + "zFfL42UDqfa2AJ9hjtEeDTbTEAuuSbzhYFxN/qc0FACgsmzysdbBpuN65yK0" + + "1tbEaeIMtqCwAgADuM0EQH0EfhADAKpG5Y6vGbm//xZYG08RRmdi67dZjF59" + + "Eqfo43mRrliangB8qkqoqqf3za2OUbXcZUQ/ajDXUvjJAoY2b5XJURqmbtKk" + + "wPRIeD2+wnKABat8wmcFhZKATX1bqjdyRRGxawADBgMAoMJKJLELdnn885oJ" + + "6HDmIez++ZWTlafzfUtJkQTCRKiE0NsgSvKJr/20VdK3XUA/iy0m1nQwfzv/" + + "okFuIhEPgldzH7N/NyEvtN5zOv/TpAymFKewAQ26luEu6l+lH4FsiEYEGBEC" + + "AAYFAkB9BH4ACgkQqcxXy+NlA6mtMgCgtQMFBaKymktM+DQmCgy2qjW7WY0A" + + "n3FaE6UZE9GMDmCIAjhI+0X9aH6CsAIAAw=="); + + private static readonly byte[] sec3 = Base64.Decode( + "lQHhBEB9BH0RBACtYQtE7tna6hgGyGLpq+ds3r2cLC0ISn5dNw7tm9vwiNVF" + + "JA2N37RRrifw4PvgelRSvLaX3M3ZBqC9s1Metg3v4FSlIRtSLWCNpHSvNw7i" + + "X8C2Xy9Hdlbh6Y/50o+iscojLRE14upfR1bIkcCZQGSyvGV52V2wBImUUZjV" + + "s2ZngwCg7mu852vK7+euz4WaL7ERVYtq9CMEAJ5swrljerDpz/RQ4Lhp6KER" + + "KyuI0PUttO57xINGshEINgYlZdGaZHRueHe7uKfI19mb0T4N3NJWaZ0wF+Cn" + + "rixsq0VrTUfiwfZeGluNG73aTCeY45fVXMGTTSYXzS8T0LW100Xn/0g9HRyA" + + "xUpuWo8IazxkMqHJis2uwriYKpAfA/9anvj5BS9p5pfPjp9dGM7GTMIYl5f2" + + "fcP57f+AW1TVR6IZiMJAvAdeWuLtwLnJiFpGlnFz273pfl+sAuqm1yNceImR" + + "2SDDP4+vtyycWy8nZhgEuhZx3W3cWMQz5WyNJSY1JJHh9TCQkCoN8E7XpVP4" + + "zEPboB2GzD93mfD8JLHP+/4DAwIvYrn+YqRaaGAu19XUj895g/GROyP8WEaU" + + "Bd/JNqWc4kE/0guetGnPzq7G3bLVwiKfFd4X7BrgHAo3mrQtVGVzdCBLZXkg" + + "KG5vIGNvbW1lbnQpIDx0ZXN0QGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkF" + + "AkB9BH0ECwcDAgMVAgMDFgIBAh4BAheAAAoJEKnMV8vjZQOpSRQAoKZy6YS1" + + "irF5/Q3JlWiwbkN6dEuLAJ9lldRLOlXsuQ5JW1+SLEc6K9ho4rACAADRwXPB" + + "cQEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3Jl" + + "YXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZ" + + "EhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sA" + + "QwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy" + + "MjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgAFAAUAwEiAAIRAQMRAf/EABoA" + + "AQACAwEAAAAAAAAAAAAAAAAEBQIDBgf/xAAoEAABAgUDBAEFAAAAAAAAAAAB" + + "AgMABBEhMQUSQQYTIiNhFFGBkcH/xAAXAQEAAwAAAAAAAAAAAAAAAAAEAgMF" + + "/8QAJBEAAQQAAwkAAAAAAAAAAAAAAQACERIEIfATMTJBUZGx0fH/2gAMAwEA" + + "AhEDEQA/APMuotJlJVxstqaPo22NlAUp+YsNO0qSUtBcMu6n6EtOHcfPAHHF" + + "I16++oajQtTA3DapK02HFR8UpE9pTbQWtKm2WG2rlxVyQTcfGbn7Qm0OIjL7" + + "7Wrs2NNm9lzTmmSxQ0PX4opSprk5tmESF6syggzGwOLG6gXgHFbZhBixk8Xl" + + "IDcOQLRKt+rX+3qC5ZLTQblpQlvwvxn9CMpZturVGkJHapQJphRH8hCLXbzr" + + "qpYsCx1zC5rtpJNuYQhASc0UAQv/2YhcBBMRAgAcBQJAfQV+AhsDBAsHAwID" + + "FQIDAxYCAQIeAQIXgAAKCRCpzFfL42UDqfa2AJ9hjtEeDTbTEAuuSbzhYFxN" + + "/qc0FACgsmzysdbBpuN65yK01tbEaeIMtqCwAgAAnQEUBEB9BH4QAwCqRuWO" + + "rxm5v/8WWBtPEUZnYuu3WYxefRKn6ON5ka5Ymp4AfKpKqKqn982tjlG13GVE" + + "P2ow11L4yQKGNm+VyVEapm7SpMD0SHg9vsJygAWrfMJnBYWSgE19W6o3ckUR" + + "sWsAAwYDAKDCSiSxC3Z5/POaCehw5iHs/vmVk5Wn831LSZEEwkSohNDbIEry" + + "ia/9tFXSt11AP4stJtZ0MH87/6JBbiIRD4JXcx+zfzchL7Teczr/06QMphSn" + + "sAENupbhLupfpR+BbP4DAwIvYrn+YqRaaGBjvFK1fbxCt7ZM4I2W/3BC0lCX" + + "m/NypKNspGflec8u96uUlA0fNCnxm6f9nbB0jpvoKi0g4iqAf+P2iEYEGBEC" + + "AAYFAkB9BH4ACgkQqcxXy+NlA6mtMgCgvccZA/Sg7BXVpxli47SYhxSHoM4A" + + "oNCOMplSnYTuh5ikKeBWtz36gC1psAIAAA=="); + + private static readonly char[] sec3pass1 = "123456".ToCharArray(); + + // + // GPG comment packets. + // + private static readonly byte[] sec4 = Base64.Decode( + "lQG7BD0PbK8RBAC0cW4Y2MZXmAmqYp5Txyw0kSQsFvwZKHNMFRv996IsN57URVF5" + + "BGMVPRBi9dNucWbjiSYpiYN13wE9IuLZsvVaQojV4XWGRDc+Rxz9ElsXnsYQ3mZU" + + "7H1bNQEofstChk4z+dlvPBN4GFahrIzn/CeVUn6Ut7dVdYbiTqviANqNXwCglfVA" + + "2OEePvqFnGxs1jhJyPSOnTED/RwRvsLH/k43mk6UEvOyN1RIpBXN+Ieqs7h1gFrQ" + + "kB+WMgeP5ZUsotTffVDSUS9UMxRQggVUW1Xml0geGwQsNfkr/ztWMs/T4xp1v5j+" + + "QyJx6OqNlkGdqOsoqkzJx0SQ1zBxdinFyyC4H95SDAb/RQOu5LQmxFG7quexztMs" + + "infEA/9cVc9+qCo92yRAaXRqKNVVQIQuPxeUsGMyVeJQvJBD4An8KTMCdjpF10Cp" + + "qA3t+n1S0zKr5WRUtvS6y60MOONO+EJWVWBNkx8HJDaIMNkfoqQoz3Krn7w6FE/v" + + "/5uwMd6jY3N3yJZn5nDZT9Yzv9Nx3j+BrY+henRlSU0c6xDc9QAAnjJYg0Z83VJG" + + "6HrBcgc4+4K6lHulCqH9JiM6RFNBX2ZhY3RvcjoAAK9hV206agp99GI6x5qE9+pU" + + "vs6O+Ich/SYjOkRTQV9mYWN0b3I6AACvYAfGn2FGrpBYbjnpTuFOHJMS/T5xg/0m" + + "IzpEU0FfZmFjdG9yOgAAr0dAQz6XxMwxWIn8xIZR/v2iN2L9C6O0EkZvbyBCYXIg" + + "PGJhekBxdXV4PohXBBMRAgAXBQI9D2yvBQsHCgMEAxUDAgMWAgECF4AACgkQUGLI" + + "YCIktfoGogCfZiXMJUKrScqozv5tMwzTTk2AaT8AniM5iRr0Du/Y08SL/NMhtF6H" + + "hJ89nO4EPQ9ssRADAI6Ggxj6ZBfoavuXd/ye99osW8HsNlbqhXObu5mCMNySX2wa" + + "HoWyRUEaUkI9eQw+MlHzIwzA32E7y2mU3OQBKdgLcBg4jxtcWVEg8ESKF9MpFXxl" + + "pExxWrr4DFBfCRcsTwAFEQL9G3OvwJuEZXgx2JSS41D3pG4/qiHYICVa0u3p/14i" + + "cq0kXajIk5ZJ6frCIAHIzuQ3n7jjzr05yR8s/qCrNbBA+nlkVNa/samk+jCzxxxa" + + "cR/Dbh2wkvTFuDFFETwQYLuZAADcDck4YGQAmHivVT2NNDCf/aTz0+CJWl+xRc2l" + + "Qw7D/SQjOkVMR19mYWN0b3I6AACbBnv9m5/bb/pjYAm2PtDp0CysQ9X9JCM6RUxH" + + "X2ZhY3RvcjoAAJsFyHnSmaWguTFf6lJ/j39LtUNtmf0kIzpFTEdfZmFjdG9yOgAA" + + "mwfwMD3LxmWtuCWBE9BptWMNH07Z/SQjOkVMR19mYWN0b3I6AACbBdhBrbSiM4UN" + + "y7khDW2Sk0e4v9mIRgQYEQIABgUCPQ9ssQAKCRBQYshgIiS1+jCMAJ9txwHnb1Kl" + + "6i/fSoDs8SkdM7w48wCdFvPEV0sSxE73073YhBgPZtMWbBo="); + + // + // PGP freeware version 7 + // + private static readonly byte[] pub5 = Base64.Decode( + "mQENBEBrBE4BCACjXVcNIFDQSofaIyZnALb2CRg+WY9uUqgHEEAOlPe03Cs5STM5" + + "HDlNmrh4TdFceJ46rxk1mQOjULES1YfHay8lCIzrD7FX4oj0r4DC14Fs1vXaSar2" + + "1szIpttOw3obL4A1e0p6N4jjsoG7N/pA0fEL0lSw92SoBrMbAheXRg4qNTZvdjOR" + + "grcuOuwgJRvPLtRXlhyLBoyhkd5mmrIDGv8QHJ/UjpeIcRXY9kn9oGXnEYcRbMaU" + + "VwXB4pLzWqz3ZejFI3lOxRWjm760puPOnGYlzSVBxlt2LgzUgSj1Mn+lIpWmAzsa" + + "xEiU4xUwEomQns72yYRZ6D3euNCibcte4SeXABEBAAG0KXBhbGFzaCBrYXNvZGhh" + + "biA8cGthc29kaGFuQHRpYWEtY3JlZi5vcmc+iQEuBBABAgAYBQJAawROCAsBAwkI" + + "BwIKAhkBBRsDAAAAAAoJEOfelumuiOrYqPEH+wYrdP5Tq5j+E5yN1pyCg1rwbSOt" + + "Dka0y0p7Oq/VIGLk692IWPItLEunnBXQtGBcWqklrvogvlhxtf16FgoyScfLJx1e" + + "1cJa+QQnVuH+VOESN6iS9Gp9lUfVOHv74mEMXw0l2Djfy/lnrkAMBatggyGnF9xF" + + "VXOLk1J2WVFm9KUE23o6qdB7RGkf31pN2eA7SWmkdJSkUH7o/QSFBI+UTRZ/IY5P" + + "ZIJpsdiIOqd9YMG/4RoSZuPqNRR6x7BSs8nQVR9bYs4PPlp4GfdRnOcRonoTeJCZ" + + "83RnsraWJnJTg34gRLBcqumhTuFKc8nuCNK98D6zkQESdcHLLTquCOaF5L+5AQ0E" + + "QGsETwEIAOVwNCTaDZvW4dowPbET1bI5UeYY8rAGLYsWSUfgaFv2srMiApyBVltf" + + "i6OLcPjcUCHDBjCv4pwx/C4qcHWb8av4xQIpqQXOpO9NxYE1eZnel/QB7DtH12ZO" + + "nrDNmHtaXlulcKNGe1i1utlFhgzfFx6rWkRL0ENmkTkaQmPY4gTGymJTUhBbsSRq" + + "2ivWqQA1TPwBuda73UgslIAHRd/SUaxjXoLpMbGOTeqzcKGjr5XMPTs7/YgBpWPP" + + "UxMlEQIiU3ia1bxpEhx05k97ceK6TSH2oCPQA7gumjxOSjKT+jEm+8jACVzymEmc" + + "XRy4D5Ztqkw/Z16pvNcu1DI5m6xHwr8AEQEAAYkBIgQYAQIADAUCQGsETwUbDAAA" + + "AAAKCRDn3pbprojq2EynB/4/cEOtKbI5UisUd3vkTzvWOcqWUqGqi5wjjioNtIM5" + + "pur2nFvhQE7SZ+PbAa87HRJU/4WcWMcoLkHD48JrQwHCHOLHSV5muYowb78X4Yh9" + + "epYtSJ0uUahcn4Gp48p4BkhgsPYXkxEImSYzAOWStv21/7WEMqItMYl89BV6Upm8" + + "HyTJx5MPTDbMR7X51hRg3OeQs6po3WTCWRzFIMyGm1rd/VK1L5ZDFPqO3S6YUJ0z" + + "cxecYruvfK0Wp7q834wE8Zkl/PQ3NhfEPL1ZiLr/L00Ty+77/FZqt8SHRCICzOfP" + + "OawcVGI+xHVXW6lijMpB5VaVIH8i2KdBMHXHtduIkPr9"); + + private static readonly byte[] sec5 = Base64.Decode( + "lQOgBEBrBE4BCACjXVcNIFDQSofaIyZnALb2CRg+WY9uUqgHEEAOlPe03Cs5STM5" + + "HDlNmrh4TdFceJ46rxk1mQOjULES1YfHay8lCIzrD7FX4oj0r4DC14Fs1vXaSar2" + + "1szIpttOw3obL4A1e0p6N4jjsoG7N/pA0fEL0lSw92SoBrMbAheXRg4qNTZvdjOR" + + "grcuOuwgJRvPLtRXlhyLBoyhkd5mmrIDGv8QHJ/UjpeIcRXY9kn9oGXnEYcRbMaU" + + "VwXB4pLzWqz3ZejFI3lOxRWjm760puPOnGYlzSVBxlt2LgzUgSj1Mn+lIpWmAzsa" + + "xEiU4xUwEomQns72yYRZ6D3euNCibcte4SeXABEBAAEB8wqP7JkKN6oMNi1xJNqU" + + "vvt0OV4CCnrIFiOPCjebjH/NC4T/9pJ6BYSjYdo3VEPNhPhRS9U3071Kqbdt35J5" + + "kmzMq1yNStC1jkxHRCNTMsb1yIEY1v+fv8/Cy+tBpvAYiJKaox8jW3ppi9vTHZjW" + + "tYYq0kwAVojMovz1O3wW/pEF69UPBmPYsze+AHA1UucYYqdWO8U2tsdFJET/hYpe" + + "o7ppHJJCdqWzeiE1vDUrih9pP3MPpzcRS/gU7HRDb5HbfP7ghSLzByEa+2mvg5eK" + + "eLwNAx2OUtrVg9rJswXX7DOLa1nKPhdGrSV/qwuK4rBdaqJ/OvszVJ0Vln0T/aus" + + "it1PAuVROLUPqTVVN8/zkMenFbf5vtryC3GQYXvvZq+l3a4EXwrR/1pqrTfnfOuD" + + "GwlFhRJAqPfthxZS68/xC8qAmTtkl7j4nscNM9kSoZ3BFwSyD9B/vYHPWGlqnpGF" + + "k/hBXuIgl07KIeNIyEC3f1eRyaiMFqEz5yXbbTfEKirSVpHM/mpeKxG8w96aK3Je" + + "AV0X6ZkC4oLTp6HCG2TITUIeNxCh2rX3fhr9HvBDXBbMHgYlIcLwzNkwDX74cz/7" + + "nIclcubaWjEkDHP20XFicuChFc9zx6kBYuYy170snltTBgTWSuRH15W4NQqrLo37" + + "zyzZQubX7CObgQJu4ahquiOg4SWl6uEI7+36U0SED7sZzw8ns1LxrwOWbXuHie1i" + + "xCvsJ4RpJJ03iEdNdUIb77qf6AriqE92tXzcVXToBv5S2K5LdFYNJ1rWdwaKJRkt" + + "kmjCL67KM9WT/IagsUyU+57ao3COtqw9VWZi6ev+ubM6fIV0ZK46NEggOLph1hi2" + + "gZ9ew9uVuruYg7lG2Ku82N0fjrQpcGFsYXNoIGthc29kaGFuIDxwa2Fzb2RoYW5A" + + "dGlhYS1jcmVmLm9yZz6dA6AEQGsETwEIAOVwNCTaDZvW4dowPbET1bI5UeYY8rAG" + + "LYsWSUfgaFv2srMiApyBVltfi6OLcPjcUCHDBjCv4pwx/C4qcHWb8av4xQIpqQXO" + + "pO9NxYE1eZnel/QB7DtH12ZOnrDNmHtaXlulcKNGe1i1utlFhgzfFx6rWkRL0ENm" + + "kTkaQmPY4gTGymJTUhBbsSRq2ivWqQA1TPwBuda73UgslIAHRd/SUaxjXoLpMbGO" + + "TeqzcKGjr5XMPTs7/YgBpWPPUxMlEQIiU3ia1bxpEhx05k97ceK6TSH2oCPQA7gu" + + "mjxOSjKT+jEm+8jACVzymEmcXRy4D5Ztqkw/Z16pvNcu1DI5m6xHwr8AEQEAAQF7" + + "osMrvQieBAJFYY+x9jKPVclm+pVaMaIcHKwCTv6yUZMqbHNRTfwdCVKTdAzdlh5d" + + "zJNXXRu8eNwOcfnG3WrWAy59cYE389hA0pQPOh7iL2V1nITf1qdLru1HJqqLC+dy" + + "E5GtkNcgvQYbv7ACjQacscvnyBioYC6TATtPnHipMO0S1sXEnmUugNlW88pDln4y" + + "VxCtQXMBjuqMt0bURqmb+RoYhHhoCibo6sexxSnbEAPHBaW1b1Rm7l4UBSW6S5U0" + + "MXURE60IHfP1TBe1l/xOIxOi8qdBQCyaFW2up00EhRBy/WOO6KAYXQrRRpOs9TBq" + + "ic2wquwZePmErTbIttnnBcAKmpodrM/JBkn/we5fVg+FDTP8sM/Ubv0ZuM70aWmF" + + "v0/ZKbkCkh2YORLWl5+HR/RKShdkmmFgZZ5uzbOGxxEGKhw+Q3+QFUF7PmYOnOtv" + + "s9PZE3dV7ovRDoXIjfniD1+8sLUWwW5d+3NHAQnCHJrLnPx4sTHx6C0yWMcyZk6V" + + "fNHpLK4xDTbgoTmxJa/4l+wa0iD69h9K/Nxw/6+X/GEM5w3d/vjlK1Da6urN9myc" + + "GMsfiIll5DNIWdLLxCBPFmhJy653CICQLY5xkycWB7JOZUBTOEVrYr0AbBZSTkuB" + + "fq5p9MfH4N51M5TWnwlJnqEiGnpaK+VDeP8GniwCidTYyiocNPvghvWIzG8QGWMY" + + "PFncRpjFxmcY4XScYYpyRme4qyPbJhbZcgGpfeLvFKBPmNxVKJ2nXTdx6O6EbHDj" + + "XctWqNd1EQas7rUN728u7bk8G7m37MGqQuKCpNvOScH4TnPROBY8get0G3bC4mWz" + + "6emPeENnuyElfWQiHEtCZr1InjnNbb/C97O+vWu9PfsE"); + + private static readonly char[] sec5pass1 = "12345678".ToCharArray(); + + // + // Werner Koch "odd keys" + // + private static readonly byte[] pub6 = Base64.Decode( + "mQGiBDWiHh4RBAD+l0rg5p9rW4M3sKvmeyzhs2mDxhRKDTVVUnTwpMIR2kIA9pT4" + + "3No/coPajDvhZTaDM/vSz25IZDZWJ7gEu86RpoEdtr/eK8GuDcgsWvFs5+YpCDwW" + + "G2dx39ME7DN+SRvEE1xUm4E9G2Nnd2UNtLgg82wgi/ZK4Ih9CYDyo0a9awCgisn3" + + "RvZ/MREJmQq1+SjJgDx+c2sEAOEnxGYisqIKcOTdPOTTie7o7x+nem2uac7uOW68" + + "N+wRWxhGPIxsOdueMIa7U94Wg/Ydn4f2WngJpBvKNaHYmW8j1Q5zvZXXpIWRXSvy" + + "TR641BceGHNdYiR/PiDBJsGQ3ac7n7pwhV4qex3IViRDJWz5Dzr88x+Oju63KtxY" + + "urUIBACi7d1rUlHr4ok7iBRlWHYXU2hpUIQ8C+UOE1XXT+HB7mZLSRONQnWMyXnq" + + "bAAW+EUUX2xpb54CevAg4eOilt0es8GZMmU6c0wdUsnMWWqOKHBFFlDIvyI27aZ9" + + "quf0yvby63kFCanQKc0QnqGXQKzuXbFqBYW2UQrYgjXji8rd8bQnV2VybmVyIEtv" + + "Y2ggKGdudXBnIHNpZykgPGRkOWpuQGdudS5vcmc+iGUEExECAB0FAjZVoKYFCQht" + + "DIgDCwQDBRUDAgYBAxYCAQIXgAASCRBot6uJV1SNzQdlR1BHAAEBLj4AoId15gcy" + + "YpBX2YLtEQTlXPp3mtEGAJ9UxzJE/t3EHCHK2bAIOkBwIW8ItIkBXwMFEDWiHkMD" + + "bxG4/z6qCxADYzIFHR6I9Si9gzPQNRcFs2znrTp5pV5Mk6f1aqRgZxL3E4qUZ3xe" + + "PQhwAo3fSy3kCwLmFGqvzautSMHn8K5V1u+T5CSHqLFYKqj5FGtuB/xwoKDXH6UO" + + "P0+l5IP8H1RTjme3Fhqahec+zPG3NT57vc2Ru2t6PmuAwry2BMuSFMBs7wzXkyC3" + + "DbI54MV+IKPjHMORivK8uI8jmna9hdNVyBifCk1GcxkHBSCFvU8xJePsA/Q//zCe" + + "lvrnrIiMfY4CQTmKzke9MSzbAZQIRddgrGAsiX1tE8Z3YMd8lDpuujHLVEdWZo6s" + + "54OJuynHrtFFObdapu0uIrT+dEXSASMUbEuNCLL3aCnrEtGJCwxB2TPQvCCvR2BK" + + "zol6MGWxA+nmddeQib2r+GXoKXLdnHcpsAjA7lkXk3IFyJ7MLFK6uDrjGbGJs2FK" + + "SduUjS/Ib4hGBBARAgAGBQI1oic8AAoJEGx+4bhiHMATftYAn1fOaKDUOt+dS38r" + + "B+CJ2Q+iElWJAKDRPpp8q5GylbM8DPlMpClWN3TYqYhGBBARAgAGBQI27U5sAAoJ" + + "EF3iSZZbA1iiarYAn35qU3ZOlVECELE/3V6q98Q30eAaAKCtO+lacH0Qq1E6v4BP" + + "/9y6MoLIhohiBBMRAgAiAhsDBAsHAwIDFQIDAxYCAQIeAQIXgAUCP+mCaQUJDDMj" + + "ywAKCRBot6uJV1SNzaLvAJwLsPV1yfc2D+yT+2W11H/ftNMDvwCbBweORhCb/O/E" + + "Okg2UTXJBR4ekoCIXQQTEQIAHQMLBAMFFQMCBgEDFgIBAheABQI/6YJzBQkMMyPL" + + "AAoJEGi3q4lXVI3NgroAn2Z+4KgVo2nzW72TgCJwkAP0cOc2AJ0ZMilsOWmxmEG6" + + "B4sHMLkB4ir4GIhdBBMRAgAdAwsEAwUVAwIGAQMWAgECF4AFAj/pgnMFCQwzI8sA" + + "CgkQaLeriVdUjc2CugCfRrOIfllp3mSmGpHgIxvg5V8vtMcAn0BvKVehOn+12Yvn" + + "9BCHfg34jUZbiF0EExECAB0DCwQDBRUDAgYBAxYCAQIXgAUCP+mCcwUJDDMjywAK" + + "CRBot6uJV1SNzYK6AJ9x7R+daNIjkieNW6lJeVUIoj1UHgCeLZm025uULML/5DFs" + + "4tUvXs8n9XiZAaIENaIg8xEEALYPe0XNsPjx+inTQ+Izz527ZJnoc6BhWik/4a2b" + + "ZYENSOQXAMKTDQMv2lLeI0i6ceB967MNubhHeVdNeOWYHFSM1UGRfhmZERISho3b" + + "p+wVZvVG8GBVwpw34PJjgYU/0tDwnJaJ8BzX6j0ecTSTjQPnaUEtdJ/u/gmG9j02" + + "18TzAKDihdNoKJEU9IKUiSjdGomSuem/VwQArHfaucSiDmY8+zyZbVLLnK6UJMqt" + + "sIv1LvAg20xwXoUk2bY8H3tXL4UZ8YcoSXYozwALq3cIo5UZJ0q9Of71mI8WLK2i" + + "FSYVplpTX0WMClAdkGt3HgVb7xtOhGt1mEKeRQjNZ2LteUQrRDD9MTQ+XxcvEN0I" + + "pAj4kBJe9bR6HzAD/iecCmGwSlHUZZrgqWzv78o79XxDdcuLdl4i2fL7kwEOf9js" + + "De7hGs27yrdJEmAG9QF9TOF9LJFmE1CqkgW+EpKxsY01Wjm0BFJB1R7iPUaUtFRZ" + + "xYqfgXarmPjql2iBi+cVjLzGu+4BSojVAPgP/hhcnIowf4M4edPiICMP1GVjtCFX" + + "ZXJuZXIgS29jaCA8d2VybmVyLmtvY2hAZ3V1Zy5kZT6IYwQTEQIAGwUCNs8JNwUJ" + + "CCCxRAMLCgMDFQMCAxYCAQIXgAASCRBsfuG4YhzAEwdlR1BHAAEBaSAAn3YkpT5h" + + "xgehGFfnX7izd+c8jI0SAJ9qJZ6jJvXnGB07p60aIPYxgJbLmYkAdQMFEDWjdxQd" + + "GfTBDJhXpQEBPfMC/0cxo+4xYVAplFO0nIYyjQgP7D8O0ufzPsIwF3kvb7b5FNNj" + + "fp+DAhN6G0HOIgkL3GsWtCfH5UHali+mtNFIKDpTtr+F/lPpZP3OPzzsLZS4hYTq" + + "mMs1O/ACq8axKgAilYkBXwMFEDWiJw4DbxG4/z6qCxADB9wFH0i6mmn6rWYKFepJ" + + "hXyhE4wWqRPJAnvfoiWUntDp4aIQys6lORigVXIWo4k4SK/FH59YnzF7578qrTZW" + + "/RcA0bIqJqzqaqsOdTYEFa49cCjvLnBW4OebJlLTUs/nnmU0FWKW8OwwL+pCu8d7" + + "fLSSnggBsrUQwbepuw0cJoctFPAz5T1nQJieQKVsHaCNwL2du0XefOgF5ujB1jK1" + + "q3p4UysF9hEcBR9ltE3THr+iv4jtZXmC1P4at9W5LFWsYuwr0U3yJcaKSKp0v/wG" + + "EWe2J/gFQZ0hB1+35RrCZPgiWsEv87CHaG6XtQ+3HhirBCJsYhmOikVKoEan6PhU" + + "VR1qlXEytpAt389TBnvyceAX8hcHOE3diuGvILEgYes3gw3s5ZmM7bUX3jm2BrX8" + + "WchexUFUQIuKW2cL379MFXR8TbxpVxrsRYE/4jHZBYhGBBARAgAGBQI27U4LAAoJ" + + "EF3iSZZbA1iifJoAoLEsGy16hV/CfmDku6D1CBUIxXvpAJ9GBApdC/3OXig7sBrV" + + "CWOb3MQzcLkBjQQ2zwcIEAYA9zWEKm5eZpMMBRsipL0IUeSKEyeKUjABX4vYNurl" + + "44+2h6Y8rHn7rG1l/PNj39UJXBkLFj1jk8Q32v+3BQDjvwv8U5e/kTgGlf7hH3WS" + + "W38RkZw18OXYCvnoWkYneIuDj6/HH2bVNXmTac05RkBUPUv4yhqlaFpkVcswKGuE" + + "NRxujv/UWvVF+/2P8uSQgkmGp/cbwfMTkC8JBVLLBRrJhl1uap2JjZuSVklUUBez" + + "Vf3NJMagVzx47HPqLVl4yr4bAAMGBf9PujlH5I5OUnvZpz+DXbV/WQVfV1tGRCra" + + "kIj3mpN6GnUDF1LAbe6vayUUJ+LxkM1SqQVcmuy/maHXJ+qrvNLlPqUZPmU5cINl" + + "sA7bCo1ljVUp54J1y8PZUx6HxfEl/LzLVkr+ITWnyqeiRikDecUf4kix2teTlx6I" + + "3ecqT5oNqZSRXWwnN4SbkXtAd7rSgEptUYhQXgSEarp1pXJ4J4rgqFa49jKISDJq" + + "rn/ElltHe5Fx1bpfkCIYlYk45Cga9bOIVAQYEQIADAUCNs8HCAUJBvPJAAASCRBs" + + "fuG4YhzAEwdlR1BHAAEBeRUAoIGpCDmMy195TatlloHAJEjZu5KaAJwOvW989hOb" + + "8cg924YIFVA1+4/Ia7kBjQQ1oiE8FAYAkQmAlOXixb8wra83rE1i7LCENLzlvBZW" + + "KBXN4ONelZAnnkOm7IqRjMhtKRJN75zqVyKUaUwDKjpf9J5K2t75mSxBtnbNRqL3" + + "XodjHK93OcAUkz3ci7iuC/b24JI2q4XeQG/v4YR1VodM0zEQ1IC0JCq4Pl39QZyX" + + "JdZCrUFvMcXq5ruNSldztBqTFFUiFbkw1Fug/ZyXJve2FVcbsRXFrB7EEuy+iiU/" + + "kZ/NViKk0L4T6KRHVsEiriNlCiibW19fAAMFBf9Tbv67KFMDrLqQan/0oSSodjDQ" + + "KDGqtoh7KQYIKPXqfqT8ced9yd5MLFwPKf3t7AWG1ucW2x118ANYkPSU122UTndP" + + "sax0cY4XkaHxaNwpNFCotGQ0URShxKNpcqbdfvy+1d8ppEavgOyxnV1JOkLjZJLw" + + "K8bgxFdbPWcsJJnjuuH3Pwz87CzTgOSYQxMPnIwQcx5buZIV5NeELJtcbbd3RVua" + + "K/GQht8QJpuXSji8Nl1FihYDjACR8TaRlAh50GmIRgQoEQIABgUCOCv7gwAKCRBs" + + "fuG4YhzAE9hTAJ9cRHu+7q2hkxpFfnok4mRisofCTgCgzoPjNIuYiiV6+wLB5o11" + + "7MNWPZCIVAQYEQIADAUCNaIhPAUJB4TOAAASCRBsfuG4YhzAEwdlR1BHAAEBDfUA" + + "oLstR8cg5QtHwSQ3nFCOKEREUFIwAKDID3K3hM+b6jW1o+tNX9dnjb+YMZkAbQIw" + + "bYOUAAABAwC7ltmO5vdKssohwzXEZeYvDW2ll3CYD2I+ruiNq0ybxkfFBopq9cxt" + + "a0OvVML4LK/TH+60f/Fqx9wg2yk9APXyaomdLrXfWyfZ91YtNCfj3ElC4XB4qqm0" + + "HRn0wQyYV6UABRG0IVdlcm5lciBLb2NoIDx3ZXJuZXIua29jaEBndXVnLmRlPokA" + + "lQMFEDRfoOmOB31Gi6BmjQEBzwgD/2fHcdDXuRRY+SHvIVESweijstB+2/sVRp+F" + + "CDjR74Kg576sJHfTJCxtSSmzpaVpelb5z4URGJ/Byi5L9AU7hC75S1ZnJ+MjBT6V" + + "ePyk/r0uBrMkU/lMG7lk/y2By3Hll+edjzJsdwn6aoNPiyen4Ch4UGTEguxYsLq0" + + "HES/UvojiQEVAwUTNECE2gnp+QqKck5FAQH+1Af/QMlYPlLG+5E19qP6AilKQUzN" + + "kd1TWMenXTS66hGIVwkLVQDi6RCimhnLMq/F7ENA8bSbyyMuncaBz5dH4kjfiDp1" + + "o64LULcTmN1LW9ctpTAIeLLJZnwxoJLkUbLUYKADKqIBXHMt2B0zRmhFOqEjRN+P" + + "hI7XCcHeHWHiDeUB58QKMyeoJ/QG/7zLwnNgDN2PVqq2E72C3ye5FOkYLcHfWKyB" + + "Rrn6BdUphAB0LxZujSGk8ohZFbia+zxpWdE8xSBhZbjVGlwLurmS2UTjjxByBNih" + + "eUD6IC3u5P6psld0OfqnpriZofP0CBP2oTk65r529f/1lsy2kfWrVPYIFJXEnIkA" + + "lQMFEDQyneGkWMS9SnJfMQEBMBMD/1ADuhhuY9kyN7Oj6DPrDt5SpPQDGS0Jtw3y" + + "uIPoed+xyzlrEuL2HeaOj1O9urpn8XLN7V21ajkzlqsxnGkOuifbE9UT67o2b2vC" + + "ldCcY4nV5n+U1snMDwNv+RkcEgNa8ANiWkm03UItd7/FpHDQP0FIgbPEPwRoBN87" + + "I4gaebfRiQCVAwUQNDUSwxRNm5Suj3z1AQGMTAP/UaXXMhPzcjjLxBW0AccTdHUt" + + "Li+K+rS5PNxxef2nnasEhCdK4GkM9nwJgsP0EZxCG3ZSAIlWIgQ3MK3ZAV1Au5pL" + + "KolRjFyEZF420wAtiE7V+4lw3FCqNoXDJEFC3BW431kx1wAhDk9VaIHHadYcof4d" + + "dmMLQOW2cJ7LDEEBW/WJAJUDBRA0M/VQImbGhU33abUBARcoA/9eerDBZGPCuGyE" + + "mQBcr24KPJHWv/EZIKl5DM/Ynz1YZZbzLcvEFww34mvY0jCfoVcCKIeFFBMKiSKr" + + "OMtoVC6cQMKpmhE9hYRStw4E0bcf0BD/stepdVtpwRnG8SDP2ZbmtgyjYT/7T4Yt" + + "6/0f6N/0NC7E9qfq4ZlpU3uCGGu/44kAlQMFEDQz8kp2sPVxuCQEdQEBc5YD/Rix" + + "vFcLTO1HznbblrO0WMzQc+R4qQ50CmCpWcFMwvVeQHo/bxoxGggNMmuVT0bqf7Mo" + + "lZDSJNS96IAN32uf25tYHgERnQaMhmi1aSHvRDh4jxFu8gGVgL6lWit/vBDW/BiF" + + "BCH6sZJJrGSuSdpecTtaWC8OJGDoKTO9PqAA/HQRiQB1AwUQNDJSx011eFs7VOAZ" + + "AQGdKQL/ea3qD2OP3wVTzXvfjQL1CosX4wyKusBBhdt9u2vOT+KWkiRk1o35nIOG" + + "uZLHtSFQDY8CVDOkqg6g4sVbOcTl8QUwHA+A4AVDInwTm1m4Bk4oeCIwk4Bp6mDd" + + "W11g28k/iQEVAgUSNDIWPm/Y4wPDeaMxAQGvBQgAqGhzA/21K7oL/L5S5Xz//eO7" + + "J8hgvqqGXWd13drNy3bHbKPn7TxilkA3ca24st+6YPZDdSUHLMCqg16YOMyQF8gE" + + "kX7ZHWPacVoUpCmSz1uQ3p6W3+u5UCkRpgQN8wBbJx5ZpBBqeq5q/31okaoNjzA2" + + "ghEWyR5Ll+U0C87MY7pc7PlNHGCr0ZNOhhtf1jU+H9ag5UyT6exIYim3QqWYruiC" + + "LSUcim0l3wK7LMW1w/7Q6cWfAFQvl3rGjt3rg6OWg9J4H2h5ukf5JNiRybkupmat" + + "UM+OVMRkf93jzU62kbyZpJBHiQZuxxJaLkhpv2RgWib9pbkftwEy/ZnmjkxlIIkA" + + "lQMFEDQvWjh4313xYR8/NQEB37QEAIi9vR9h9ennz8Vi7RNU413h1ZoZjxfEbOpk" + + "QAjE/LrZ/L5WiWdoStSiyqCLPoyPpQafiU8nTOr1KmY4RgceJNgxIW4OiSMoSvrh" + + "c2kqP+skb8A2B4+47Aqjr5fSAVfVfrDMqDGireOguhQ/hf9BOYsM0gs+ROdtyLWP" + + "tMjRnFlviD8DBRAz8qQSj6lRT5YOKXIRAntSAJ9StSEMBoFvk8iRWpXb6+LDNLUW" + + "zACfT8iY3IxwvMF6jjCHrbuxQkL7chSJARUDBRA0MMO7569NIyeqD3EBATIAB/4t" + + "CPZ1sLWO07g2ZCpiP1HlYpf5PENaXtaasFvhWch7eUe3DksuMEPzB5GnauoQZAku" + + "hEGkoEfrfL3AXtXH+WMm2t7dIcTBD4p3XkeZ+PgJpKiASXDyul9rumXXvMxSL4KV" + + "7ar+F1ZJ0ycCx2r2au0prPao70hDAzLTy16hrWgvdHSK7+wwaYO5TPCL5JDmcB+d" + + "HKW72qNUOD0pxbe0uCkkb+gDxeVX28pZEkIIOMMV/eAs5bs/smV+eJqWT/EyfVBD" + + "o7heF2aeyJj5ecxNOODr88xKF7qEpqazCQ4xhvFY+Yn6+vNCcYfkoZbOn0XQAvqf" + + "a2Vab9woVIVSaDji/mlPiQB1AwUQNDC233FfeD4HYGBJAQFh6QL/XCgm5O3q9kWp" + + "gts1MHKoHoh7vxSSQGSP2k7flNP1UB2nv4sKvyGM8eJKApuROIodcTkccM4qXaBu" + + "XunMr5kJlvDJPm+NLzKyhtQP2fWI7xGYwiCiB29gm1GFMjdur4amiQEVAwUQNDBR" + + "9fjDdqGixRdJAQE+mAf+JyqJZEVFwNwZ2hSIMewekC1r7N97p924nqfZKnzn6weF" + + "pE80KIJSWtEVzI0XvHlVCOnS+WRxn7zxwrOTbrcEOy0goVbNgUsP5ypZa2/EM546" + + "uyyJTvgD0nwA45Q4bP5sGhjh0G63r9Vwov7itFe4RDBGM8ibGnZTr9hHo469jpom" + + "HSNeavcaUYyEqcr4GbpQmdpJTnn/H0A+fMl7ZHRoaclNx9ZksxihuCRrkQvUOb3u" + + "RD9lFIhCvNwEardN62dKOKJXmn1TOtyanZvnmWigU5AmGuk6FpsClm3p5vvlid64" + + "i49fZt9vW5krs2XfUevR4oL0IyUl+qW2HN0DIlDiAYkAlQMFEDQvbv2wcgJwUPMh" + + "JQEBVBID/iOtS8CQfMxtG0EmrfaeVUU8R/pegBmVWDBULAp8CLTtdfxjVzs/6DXw" + + "0RogXMRRl2aFfu1Yp0xhBYjII6Kque/FzAFXY9VNF1peqnPt7ADdeptYMppZa8sG" + + "n9BBRu9Fsw69z6JkyqvMiVxGcKy3XEpVGr0JHx8Xt6BYdrULiKr2iQB1AwUQNC68" + + "n6jZR/ntlUftAQFaYgL+NUYEj/sX9M5xq1ORX0SsVPMpNamHO3JBSmZSIzjiox5M" + + "AqoFOCigAkonuzk5aBy/bRHy1cmDBOxf4mNhzrH8N6IkGvPE70cimDnbFvr+hoZS" + + "jIqxtELNZsLuLVavLPAXiQCVAwUQNC6vWocCuHlnLQXBAQHb1gQAugp62aVzDCuz" + + "4ntfXsmlGbLY7o5oZXYIKdPP4riOj4imcJh6cSgYFL6OMzeIp9VW/PHo2mk8kkdk" + + "z5uif5LqOkEuIxgra7p1Yq/LL4YVhWGQeD8hwpmu+ulYoPOw40dVYS36PwrHIH9a" + + "fNhl8Or5O2VIHIWnoQ++9r6gwngFQOyJAJUDBRAzHnkh1sNKtX1rroUBAWphBACd" + + "huqm7GHoiXptQ/Y5F6BivCjxr9ch+gPSjaLMhq0kBHVO+TbXyVefVVGVgCYvFPjo" + + "zM8PEVykQAtY//eJ475aGXjF+BOAhl2z0IMkQKCJMExoEDHbcj0jIIMZ2/+ptgtb" + + "FSyJ2DQ3vvCdbw/1kyPHTPfP+L2u40GWMIYVBbyouokAlQMFEDMe7+UZsymln7HG" + + "2QEBzMED/3L0DyPK/u6PyAd1AdpjUODTkWTZjZ6XA2ubc6IXXsZWpmCgB/24v8js" + + "J3DIsvUD3Ke55kTr6xV+au+mAkwOQqWUTUWfQCkSrSDlbUJ1VPBzhyTpuzjBopte" + + "7o3R6XXfcLiC5jY6eCX0QtLGhKpLjTr5uRhf1fYODGsAGXmCByDviQB1AgUQMy6U" + + "MB0Z9MEMmFelAQHV4AMAjdFUIyFtpTr5jkyZSd3y//0JGO0z9U9hLVxeBBCwvdEQ" + + "xsrpeTtVdqpeKZxHN1GhPCYvgLFZAQlcPh/Gc8u9uO7wVSgJc3zYKFThKpQevdF/" + + "rzjTCHfgigf5Iui0qiqBiQCVAwUQMx22bAtzgG/ED06dAQFi0gQAkosqTMWy+1eU" + + "Xbi2azFK3RX5ERf9wlN7mqh7TvwcPXvVWzUARnwRv+4kk3uOWI18q5UPis7KH3KY" + + "OVeRrPd8bbp6SjhBh82ourTEQUXLBDQiI1V1cZZmwwEdlnAnhFnkXgMBNM2q7oBe" + + "fRHADfYDfGo90wXyrVVL+GihDNpzUwOJAJUDBRAzHUFnOWvfULwOR3EBAbOYA/90" + + "JIrKmxhwP6quaheFOjjPoxDGEZpGJEOwejEByYj+AgONCRmQS3BydtubA+nm/32D" + + "FeG8pe/dnFvGc+QgNW560hK21C2KJj72mhjRlg/na7jz4/MmBAv5k61Q7roWi0rw" + + "x+R9NSHxpshC8A92zmvo8w/XzVSogC8pJ04jcnY6YokAlQMFEDMdPtta9LwlvuSC" + + "3QEBvPMD/3TJGroHhHYjHhiEpDZZVszeRQ0cvVI/uLLi5yq3W4F6Jy47DF8VckA7" + + "mw0bXrOMNACN7Je7uyaU85qvJC2wgoQpFGdFlkjmkAwDAjR+koEysiE8FomiOHhv" + + "EpEY/SjSS4jj4IPmgV8Vq66XjPw+i7Z0RsPLOIf67yZHxypNiBiYiQCVAwUQMxxw" + + "pKrq6G7/78D5AQHo2QQAjnp6KxOl6Vvv5rLQ/4rj3OemvF7IUUq34xb25i/BSvGB" + + "UpDQVUmhv/qIfWvDqWGZedyM+AlNSfUWPWnP41S8OH+lcERH2g2dGKGl7kH1F2Bx" + + "ByZlqREHm2q624wPPA35RLXtXIx06yYjLtJ7b+FCAX6PUgZktZYk5gwjdoAGrC2J" + + "AJUDBRAzGvcCKC6c7f53PGUBAUozA/9l/qKmcqbi8RtLsKQSh3vHds9d22zcbkuJ" + + "PBSoOv2D7i2VLshaQFjq+62uYZGE6nU1WP5sZcBDuWjoX4t4NrffnOG/1R9D0t1t" + + "9F47D77HJzjvo+J52SN520YHcbT8VoHdPRoEOXPN4tzhvn2GapVVdaAlWM0MLloh" + + "NH3I9jap9okAdQMFEDMZlUAnyXglSykrxQEBnuwC/jXbFL+jzs2HQCuo4gyVrPlU" + + "ksQCLYZjNnZtw1ca697GV3NhBhSXR9WHLQH+ZWnpTzg2iL3WYSdi9tbPs78iY1FS" + + "d4EG8H9V700oQG8dlICF5W2VjzR7fByNosKM70WSXYkBFQMFEDMWBsGCy1t9eckW" + + "HQEBHzMH/jmrsHwSPrA5R055VCTuDzdS0AJ+tuWkqIyqQQpqbost89Hxper3MmjL" + + "Jas/VJv8EheuU3vQ9a8sG2SnlWKLtzFqpk7TCkyq/H3blub0agREbNnYhHHTGQFC" + + "YJb4lWjWvMjfP+N5jvlLcnDqQPloXfAOgy7W90POoqFrsvhxdpnXgoLrzyNNja1O" + + "1NRj+Cdv/GmJYNi6sQe43zmXWeA7syLKMw6058joDqEJFKndgSp3Zy/yXmObOZ/H" + + "C2OJwA3gzEaAu8Pqd1svwGIGznqtTNCn9k1+rMvJPaxglg7PXIJS282hmBl9AcJl" + + "wmh2GUCswl9/sj+REWTb8SgJUbkFcp6JAJUDBRAwdboVMPfsgxioXMEBAQ/LA/9B" + + "FTZ9T95P/TtsxeC7lm9imk2mpNQCBEvXk286FQnGFtDodGfBfcH5SeKHaUNxFaXr" + + "39rDGUtoTE98iAX3qgCElf4V2rzgoHLpuQzCg3U35dfs1rIxlpcSDk5ivaHpPV3S" + + "v+mlqWL049y+3bGaZeAnwM6kvGMP2uccS9U6cbhpw4hGBBARAgAGBQI3GtRfAAoJ" + + "EF3iSZZbA1iikWUAoIpSuXzuN/CI63dZtT7RL7c/KtWUAJ929SAtTr9SlpSgxMC8" + + "Vk1T1i5/SYkBFQMFEzccnFnSJilEzmrGwQEBJxwH/2oauG+JlUC3zBUsoWhRQwqo" + + "7DdqaPl7sH5oCGDKS4x4CRA23U15NicDI7ox6EizkwCjk0dRr1EeRK+RqL1b/2T4" + + "2B6nynOLhRG2A0BPHRRJLcoL4nKfoPSo/6dIC+3iVliGEl90KZZD5bnONrVJQkRj" + + "ZL8Ao+9IpmoYh8XjS5xMLEF9oAQqAkA93nVBm56lKmaL1kl+M3dJFtNKtVB8de1Z" + + "XifDs8HykD42qYVtcseCKxZXhC3UTG5YLNhPvgZKH8WBCr3zcR13hFDxuecUmu0M" + + "VhvEzoKyBYYt0rrqnyWrxwbv4gSTUWH5ZbgsTjc1SYKZxz6hrPQnfYWzNkznlFWJ" + + "ARUDBRM0xL43CdxwOTnzf10BATOCB/0Q6WrpzwPMofjHj54MiGLKVP++Yfwzdvns" + + "HxVpTZLZ5Ux8ErDsnLmvUGphnLVELZwEkEGRjln7a19h9oL8UYZaV+IcR6tQ06Fb" + + "1ldR+q+3nXtBYzGhleXdgJQSKLJkzPF72tvY0DHUB//GUV9IBLQMvfG8If/AFsih" + + "4iXi96DOtUAbeuIhnMlWwLJFeGjLLsX1u6HSX33xy4bGX6v/UcHbTSSYaxzb92GR" + + "/xpP2Xt332hOFRkDZL52g27HS0UrEJWdAVZbh25KbZEl7C6zX/82OZ5nTEziHo20" + + "eOS6Nrt2+gLSeA9X5h/+qUx30kTPz2LUPBQyIqLCJkHM8+0q5j9ciQCiAwUTNMS+" + + "HZFeTizbCJMJAQFrGgRlEAkG1FYU4ufTxsaxhFZy7xv18527Yxpls6mSCi1HL55n" + + "Joce6TI+Z34MrLOaiZljeQP3EUgzA+cs1sFRago4qz2wS8McmQ9w0FNQQMz4vVg9" + + "CVi1JUVd4EWYvJpA8swDd5b9+AodYFEsfxt9Z3aP+AcWFb10RlVVsNw9EhObc6IM" + + "nwAOHCEI9vp5FzzFiQCVAwUQNxyr6UyjTSyISdw9AQHf+wP+K+q6hIQ09tkgaYaD" + + "LlWKLbuxePXqM4oO72qi70Gkg0PV5nU4l368R6W5xgR8ZkxlQlg85sJ0bL6wW/Sj" + + "Mz7pP9hkhNwk0x3IFkGMTYG8i6Gt8Nm7x70dzJoiC+A496PryYC0rvGVf+Om8j5u" + + "TexBBjb/jpJhAQ/SGqeDeCHheOC0Lldlcm5lciBLb2NoIChtZWluIGFsdGVyIGtl" + + "eSkgPHdrQGNvbXB1dGVyLm9yZz6JAHUDBRM2G2MyHRn0wQyYV6UBASKKAv4wzmK7" + + "a9Z+g0KH+6W8ffIhzrQo8wDAU9X1WJKzJjS205tx4mmdnAt58yReBc/+5HXTI8IK" + + "R8IgF+LVXKWAGv5P5AqGhnPMeQSCs1JYdf9MPvbe34jD8wA1LTWFXn9e/cWIRgQQ" + + "EQIABgUCNxrUaQAKCRBd4kmWWwNYovRiAJ9dJBVfjx9lGARoFXmAieYrMGDrmwCZ" + + "AQyO4Wo0ntQ+iq4do9M3/FTFjiCZAaIENu1I6REEAJRGEqcYgXJch5frUYBj2EkD" + + "kWAbhRqVXnmiF3PjCEGAPMMYsTddiU7wcKfiCAqKWWXow7BjTJl6Do8RT1jdKpPO" + + "lBJXqqPYzsyBxLzE6mLps0K7SLJlSKTQqSVRcx0jx78JWYGlAlP0Kh9sPV2w/rPh" + + "0LrPeOKXT7lZt/DrIhfPAKDL/sVqCrmY3QfvrT8kSKJcgtLWfQP/cfbqVNrGjW8a" + + "m631N3UVA3tWfpgM/T9OjmKmw44NE5XfPJTAXlCV5j7zNMUkDeoPkrFF8DvbpYQs" + + "4XWYHozDjhR2Q+eI6gZ0wfmhLHqqc2eVVkEG7dT57Wp9DAtCMe7RZfhnarTQMqlY" + + "tOEa/suiHk0qLo59NsyF8eh68IDNCeYD/Apzonwaq2EQ1OEpfFlp6LcSnS34+UGZ" + + "tTO4BgJdmEjr/QrIPp6bJDstgho+/2oR8yQwuHGJwbS/8ADA4IFEpLduSpzrABho" + + "7RuNQcm96bceRY+7Hza3zf7pg/JGdWOb+bC3S4TIpK+3sx3YNWs7eURwpGREeJi5" + + "/Seic+GXlGzltBpXZXJuZXIgS29jaCA8d2tAZ251cGcub3JnPohjBBMRAgAbBQI3" + + "Gs+QBQkMyXyAAwsKAwMVAwIDFgIBAheAABIJEF3iSZZbA1iiB2VHUEcAAQFdwgCe" + + "O/s43kCLDMIsHCb2H3LC59clC5UAn1EyrqWk+qcOXLpQIrP6Qa3QSmXIiEYEEBEC" + + "AAYFAjca0T0ACgkQbH7huGIcwBOF9ACeNwO8G2G0ei03z0g/n3QZIpjbzvEAnRaE" + + "qX2PuBbClWoIP6h9yrRlAEbUiQB1AwUQNxrRYx0Z9MEMmFelAQHRrgL/QDNKPV5J" + + "gWziyzbHvEKfTIw/Ewv6El2MadVvQI8kbPN4qkPr2mZWwPzuc9rneCPQ1eL8AOdC" + + "8+ZyxWzx2vsrk/FcU5donMObva2ct4kqJN6xl8xjsxDTJhBSFRaiBJjxiEYEEBEC" + + "AAYFAjca0aMACgkQaLeriVdUjc0t+ACghK37H2vTYeXXieNJ8aZkiPJSte4An0WH" + + "FOotQdTW4NmZJK+Uqk5wbWlgiEYEEBECAAYFAjdPH10ACgkQ9u7fIBhLxNktvgCe" + + "LnQ5eOxAJz+Cvkb7FnL/Ko6qc5YAnjhWWW5c1o3onvKEH2Je2wQa8T6iiEYEEBEC" + + "AAYFAjenJv4ACgkQmDRl2yFDlCJ+yQCfSy1zLftEfLuIHZsUHis9U0MlqLMAn2EI" + + "f7TI1M5OKysQcuFLRC58CfcfiEUEEBECAAYFAjfhQTMACgkQNmdg8X0u14h55wCf" + + "d5OZCV3L8Ahi4QW/JoXUU+ZB0M0AmPe2uw7WYDLOzv48H76tm6cy956IRgQQEQIA" + + "BgUCOCpiDwAKCRDj8lhUEo8OeRsdAJ9FHupRibBPG2t/4XDqF+xiMLL/8ACfV5F2" + + "SR0ITE4k/C+scS1nJ1KZUDW0C1dlcm5lciBLb2NoiGMEExECABsFAjbtSOoFCQzJ" + + "fIADCwoDAxUDAgMWAgECF4AAEgkQXeJJllsDWKIHZUdQRwABAbXWAJ9SCW0ieOpL" + + "7AY6vF+OIaMmw2ZW1gCgkto0eWfgpjAuVg6jXqR1wHt2pQOJAh4EEBQDAAYFAjcv" + + "WdQACgkQbEwxpbHVFWcNxQf/bg14WGJ0GWMNSuuOOR0WYzUaNtzYpiLSVyLrreXt" + + "o8LBNwzbgzj2ramW7Ri+tYJAHLhtua8ZgSeibmgBuZasF8db1m5NN1ZcHBXGTysA" + + "jp+KnicTZ9Orj75D9o3oSmMyRcisEhr+gkj0tVhGfOAOC6eKbufVuyYFDVIyOyUB" + + "GlW7ApemzAzYemfs3DdjHn87lkjHMVESO4fM5rtLuSc7cBfL/e6ljaWQc5W8S0gI" + + "Dv0VtL39pMW4BlpKa25r14oJywuUpvWCZusvDm7ZJnqZ/WmgOHQUsyYudTROpGIb" + + "lsNg8iqC6huWpGSBRdu3oRQRhkqpfVdszz6BB/nAx01q2wf/Q+U9XId1jyzxUL1S" + + "GgaYMf6QdyjHQ1oxuFLNxzM6C/M069twbNgXJ71RsDDXVxFZfSTjSiH100AP9+9h" + + "b5mycaXLUOXYDvOSFzHBd/LsjFNVrrFbDs5Xw+cLGVHOIgR5IWAfgu5d1PAZU9uQ" + + "VgdGnQfmZg383RSPxvR3fnZz1rHNUGmS6w7x6FVbxa1QU2t38gNacIwHATAPcBpy" + + "JLfXoznbpg3ADbgCGyDjBwnuPQEQkYwRakbczRrge8IaPZbt2HYPoUsduXMZyJI8" + + "z5tvu7pUDws51nV1EX15BcN3++aY5pUyA1ItaaDymQVmoFbQC0BNMzMO53dMnFko" + + "4i42kohGBBARAgAGBQI3OvmjAAoJEHUPZJXInZM+hosAnRntCkj/70shGTPxgpUF" + + "74zA+EbzAKCcMkyHXIz2W0Isw3gDt27Z9ggsE4hGBBARAgAGBQI3NyPFAAoJEPbu" + + "3yAYS8TZh2UAoJVmzw85yHJzsXQ1vpO2IAPfv59NAJ9WY0oiYqb3q1MSxBRwG0gV" + + "iNCJ7YkBFQMFEDdD3tNSgFdEdlNAHQEByHEH/2JMfg71GgiyGJTKxCAymdyf2j2y" + + "fH6wI782JK4BWV4c0E/V38q+jpIYslihV9t8s8w1XK5niMaLwlCOyBWOkDP3ech6" + + "+GPPtfB3cmlL2hS896PWZ1adQHgCeQpB837n56yj0aTs4L1xarbSVT22lUwMiU6P" + + "wYdH2Rh8nh8FvN0IZsbln2nOj73qANQzNflmseUKF1Xh4ck8yLrRd4r6amhxAVAf" + + "cYFRJN4zdLL3cmhgkt0ADZlzAwXnEjwdHHy7SvAJk1ecNOA9pFsOJbvnzufd1afs" + + "/CbG78I+0JDhg75Z2Nwq8eKjsKqiO0zz/vG5yWSndZvWkTWz3D3b1xr1Id2IRgQQ" + + "EQIABgUCOCpiHgAKCRDj8lhUEo8OeQ+QAKCbOTscyUnWHSrDo4fIy0MThEjhOgCe" + + "L4Kb7TWkd/OHQScVBO8sTUz0+2g="); + +// private static readonly byte[] pub6check = Base64.Decode("62O9"); + + // + // revoked sub key + // + private static readonly byte[] pub7 = Base64.Decode( + "mQGiBEFOsIwRBADcjRx7nAs4RaWsQU6p8/ECLZD9sSeYc6CN6UDI96RKj0/hCzMs" + + "qlA0+9fzGZ7ZEJ34nuvDKlhKGC7co5eOiE0a9EijxgcrZU/LClZWa4YfyNg/ri6I" + + "yTyfOfrPQ33GNQt2iImDf3FKp7XKuY9nIxicGQEaW0kkuAmbV3oh0+9q8QCg/+fS" + + "epDEqEE/+nKONULGizKUjMED/RtL6RThRftZ9DOSdBytGYd48z35pca/qZ6HA36K" + + "PVQwi7V77VKQyKFLTOXPLnVyO85hyYB/Nv4DFHN+vcC7/49lfoyYMZlN+LarckHi" + + "NL154wmmzygB/KKysvWBLgkErEBCD0xBDd89iTQNlDtVQAWGORVffl6WWjOAkliG" + + "3dL6A/9A288HfFRnywqi3xddriV6wCPmStC3dkCS4vHk2ofS8uw4ZNoRlp1iEPna" + + "ai2Xa9DX1tkhaGk2k96MqqbBdGpbW8sMA9otJ9xdMjWEm/CgJUFUFQf3zaVy3mkM" + + "S2Lvb6P4Wc2l/diEEIyK8+PqJItSh0OVU3K9oM7ngHwVcalKILQVUkV2b2tlZCA8" + + "UmV2b2tlZEB0ZWQ+iQBOBBARAgAOBQJBTrCMBAsDAgECGQEACgkQvglkcFA/c63+" + + "QgCguh8rsJbPTtbhZcrqBi5Mo1bntLEAoPZQ0Kjmu2knRUpHBeUemHDB6zQeuQIN" + + "BEFOsIwQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz" + + "0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRP" + + "xfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvN" + + "ILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dD" + + "ox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMI" + + "PWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/93zriSvSHqsi1FeEmUBo431Jkh" + + "VerIzb6Plb1j6FIq+s3vyvx9K+dMvjotZqylWZj4GXpH+2xLJTjWkrGSfUZVI2Nk" + + "nyOFxUCKLLqaqVBFAQIjULfvQfGEWiGQKk9aRLkdG+D+8Y2N9zYoBXoQ9arvvS/t" + + "4mlOsiuaTe+BZ4x+BXTpF4b9sKZl7V8QP/TkoJWUdydkvxciHdWp7ssqyiKOFRhG" + + "818knDfFQ3cn2w/RnOb+7AF9wDncXDPYLfpPv9b2qZoLrXcyvlLffGDUdWs553ut" + + "1F5AprMURs8BGmY9BnjggfVubHdhTUoA4gVvrdaf+D9NwZAl0xK/5Y/oPuMZiQBG" + + "BBgRAgAGBQJBTrCMAAoJEL4JZHBQP3Ot09gAoMmLKloVDP+WhDXnsM5VikxysZ4+" + + "AKCrJAUO+lYAyPYwEwgK+bKmUGeKrIkARgQoEQIABgUCQU6wpQAKCRC+CWRwUD9z" + + "rQK4AJ98kKFxGU6yhHPr6jYBJPWemTNOXgCfeGB3ox4PXeS4DJDuLy9yllytOjo="); + +// private static readonly byte[] pub7check = Base64.Decode("f/YQ"); + + private static readonly byte[] pub8 = Base64.Decode( + "mQGiBEEcraYRBADFYj+uFOhHz5SdECvJ3Z03P47gzmWLQ5HH8fPYC9rrv7AgqFFX" + + "aWlJJVMLua9e6xoCiDWJs/n4BbZ/weL/11ELg6XqUnzFhYyz0H2KFsPgQ/b9lWLY" + + "MtcPMFy5jE33hv/ixHgYLFqoNaAIbg0lzYEW/otQ9IhRl16fO1Q/CQZZrQCg/9M2" + + "V2BTmm9RYog86CXJtjawRBcD/RIqU0zulxZ2Zt4javKVxrGIwW3iBU935ebmJEIK" + + "Y5EVkGKBOCvsApZ+RGzpYeR2uMsTnQi8RJgiAnjaoVPCdsVJE7uQ0h8XuJ5n5mJ2" + + "kLCFlF2hj5ViicZzse+crC12CGtgRe8z23ubLRcd6IUGhVutK8/b5knZ22vE14JD" + + "ykKdA/96ObzJQdiuuPsEWN799nUUCaYWPAoLAmiXuICSP4GEnxLbYHWo8zhMrVMT" + + "9Q5x3h8cszUz7Acu2BXjP1m96msUNoxPOZtt88NlaFz1Q/JSbQTsVOMd9b/IRN6S" + + "A/uU0BiKEMHXuT8HUHVPK49oCKhZrGFP3RT8HZxDKLmR/qrgZ7ABh7QhSmlhIFlp" + + "eXUgPHl5amlhQG5vd21lZGlhdGVjaC5jb20+sAMD//+JAF0EEBECAB0FAkEcraYH" + + "CwkIBwMCCgIZAQUbAwAAAAUeAQAAAAAKCRD0/lb4K/9iFJlhAKCRMifQewiX5o8F" + + "U099FG3QnLVUZgCfWpMOsHulGHfNrxdBSkE5Urqh1ymwAWe5Ag0EQRytphAIAPZC" + + "V7cIfwgXcqK61qlC8wXo+VMROU+28W65Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdM" + + "ZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09jdvOmeFXklnN/biudE/F/Ha8g8VHMGHO" + + "fMlm/xX5u/2RXscBqtNbno2gpXI61Brwv0YAWCvl9Ij9WE5J280gtJ3kkQc2azNs" + + "OA1FHQ98iLMcfFstjvbzySPAQ/ClWxiNjrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq" + + "/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrKlQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2J" + + "SyIZJrqrol7DVekyCzsAAgIH/3K2wKRSzkIpDfZR25+tnQ8brv3TYoDZo3/wN3F/" + + "r6PGjx0150Q8g8EAC0bqm4rXWzOqdSxYxvIPOAGm5P4y+884yS6j3vKcXitT7vj+" + + "ODc2pVwGDLDjrMRrosSK89ycPCK6R/5pD7Rv4l9DWi2fgLvXqJHS2/ujUf2uda9q" + + "i9xNMnBXIietR82Sih4undFUOwh6Mws/o3eed9DIdaqv2Y2Aw43z/rJ6cjSGV3C7" + + "Rkf9x85AajYA3LwpS8d99tgFig2u6V/A16oi6/M51oT0aR/ZAk50qUc4WBk9uRUX" + + "L3Y+P6v6FCBE/06fgVltwcQHO1oKYKhH532tDL+9mW5/dYGwAYeJAEwEGBECAAwF" + + "AkEcraYFGwwAAAAACgkQ9P5W+Cv/YhShrgCg+JW8m5nF3R/oZGuG87bXQBszkjMA" + + "oLhGPncuGKowJXMRVc70/8qwXQJLsAFnmQGiBD2K5rYRBADD6kznWZA9nH/pMlk0" + + "bsG4nI3ELgyI7KpgRSS+Dr17+CCNExxCetT+fRFpiEvUcSxeW4pOe55h0bQWSqLo" + + "MNErXVJEXrm1VPkC08W8D/gZuPIsdtKJu4nowvdoA+WrI473pbeONGjaEDbuIJak" + + "yeKM1VMSGhsImdKtxqhndq2/6QCg/xARUIzPRvKr2TJ52K393895X1kEAMCdjSs+" + + "vABnhaeNNR5+NNkkIOCCjCS8qZRZ4ZnIayvn9ueG3KrhZeBIHoajUHrlTXBVj7XO" + + "wXVfGpW17jCDiqhU8Pu6VwEwX1iFbuUwqBffiRLXKg0zfcN+MyFKToi+VsJi4jiZ" + + "zcwUFMb8jE8tvR/muXti7zKPRPCbNBExoCt4A/0TgkzAosG/W4dUkkbc6XoHrjob" + + "iYuy6Xbs/JYlV0vf2CyuKCZC6UoznO5x2GkvOyVtAgyG4HSh1WybdrutZ8k0ysks" + + "mOthE7n7iczdj9Uwg2h+TfgDUnxcCAwxnOsX5UaBqGdkX1PjCWs+O3ZhUDg6UsZc" + + "7O5a3kstf16lHpf4q7ABAIkAYQQfEQIAIQUCPYrmtgIHABcMgBHRi/xlIgI+Q6LT" + + "kNJ7zKvTd87NHAAKCRDJM3gHb/sRj7bxAJ9f6mdlXQH7gMaYiY5tBe/FRtPr1gCf" + + "UhDJQG0ARvORFWHjwhhBMLxW7j2wAWC0KkRlc21vbmQgS2VlIDxkZXNtb25kLmtl" + + "ZUBub3dtZWRpYXRlY2guY29tPrADAQD9iQBYBBARAgAYBQI9iua2CAsDCQgHAgEK" + + "AhkBBRsDAAAAAAoJEMkzeAdv+xGP7v4An19iqadBCCgDIe2DTpspOMidwQYPAJ4/" + + "5QXbcn4ClhOKTO3ZEZefQvvL27ABYLkCDQQ9iua2EAgA9kJXtwh/CBdyorrWqULz" + + "Bej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHT" + + "UPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq" + + "01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O" + + "9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcK" + + "ctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TIL" + + "OwACAgf/SO+bbg+owbFKVN5HgOjOElQZVnCsegwCLqTeQzPPzsWmkGX2qZJPDIRN" + + "RZfJzti6+oLJwaRA/3krjviUty4VKhZ3lKg8fd9U0jEdnw+ePA7yJ6gZmBHL15U5" + + "OKH4Zo+OVgDhO0c+oetFpend+eKcvtoUcRoQoi8VqzYUNG0b/nmZGDlxQe1/ZNbP" + + "HpNf1BAtJXivCEKMD6PVzsLPg2L4tFIvD9faeeuKYQ4jcWtTkBLuIaZba3i3a4wG" + + "xTN20j9HpISVuLW/EfZAK1ef4DNjLmHEU9dMzDqfi+hPmMbGlFqcKr+VjcYIDuje" + + "o+92xm/EWAmlti88r2hZ3MySamHDrLABAIkATAQYEQIADAUCPYrmtgUbDAAAAAAK" + + "CRDJM3gHb/sRjzVTAKDVS+OJLMeS9VLAmT8atVCB42MwIQCgoh1j3ccWnhc/h6B7" + + "9Uqz3fUvGoewAWA="); + + private static readonly byte[] sec8 = Base64.Decode( + "lQHpBEEcraYRBADFYj+uFOhHz5SdECvJ3Z03P47gzmWLQ5HH8fPYC9rrv7AgqFFX" + + "aWlJJVMLua9e6xoCiDWJs/n4BbZ/weL/11ELg6XqUnzFhYyz0H2KFsPgQ/b9lWLY" + + "MtcPMFy5jE33hv/ixHgYLFqoNaAIbg0lzYEW/otQ9IhRl16fO1Q/CQZZrQCg/9M2" + + "V2BTmm9RYog86CXJtjawRBcD/RIqU0zulxZ2Zt4javKVxrGIwW3iBU935ebmJEIK" + + "Y5EVkGKBOCvsApZ+RGzpYeR2uMsTnQi8RJgiAnjaoVPCdsVJE7uQ0h8XuJ5n5mJ2" + + "kLCFlF2hj5ViicZzse+crC12CGtgRe8z23ubLRcd6IUGhVutK8/b5knZ22vE14JD" + + "ykKdA/96ObzJQdiuuPsEWN799nUUCaYWPAoLAmiXuICSP4GEnxLbYHWo8zhMrVMT" + + "9Q5x3h8cszUz7Acu2BXjP1m96msUNoxPOZtt88NlaFz1Q/JSbQTsVOMd9b/IRN6S" + + "A/uU0BiKEMHXuT8HUHVPK49oCKhZrGFP3RT8HZxDKLmR/qrgZ/4JAwLXyWhb4pf4" + + "nmCmD0lDwoYvatLiR7UQVM2MamxClIiT0lCPN9C2AYIFgRWAJNS215Tjx7P/dh7e" + + "8sYfh5XEHErT3dMbsAGHtCFKaWEgWWl5dSA8eXlqaWFAbm93bWVkaWF0ZWNoLmNv" + + "bT6wAwP//4kAXQQQEQIAHQUCQRytpgcLCQgHAwIKAhkBBRsDAAAABR4BAAAAAAoJ" + + "EPT+Vvgr/2IUmWEAoJEyJ9B7CJfmjwVTT30UbdCctVRmAJ9akw6we6UYd82vF0FK" + + "QTlSuqHXKbABZ50CawRBHK2mEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlL" + + "OCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N" + + "286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/" + + "RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2O" + + "u1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqV" + + "DNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAgf/crbApFLO" + + "QikN9lHbn62dDxuu/dNigNmjf/A3cX+vo8aPHTXnRDyDwQALRuqbitdbM6p1LFjG" + + "8g84Aabk/jL7zzjJLqPe8pxeK1Pu+P44NzalXAYMsOOsxGuixIrz3Jw8IrpH/mkP" + + "tG/iX0NaLZ+Au9eokdLb+6NR/a51r2qL3E0ycFciJ61HzZKKHi6d0VQ7CHozCz+j" + + "d5530Mh1qq/ZjYDDjfP+snpyNIZXcLtGR/3HzkBqNgDcvClLx3322AWKDa7pX8DX" + + "qiLr8znWhPRpH9kCTnSpRzhYGT25FRcvdj4/q/oUIET/Tp+BWW3BxAc7WgpgqEfn" + + "fa0Mv72Zbn91gf4JAwITijME9IlFBGAwH6YmBtWIlnDiRbsq/Pxozuhbnes831il" + + "KmdpUKXkiIfHY0MqrEWl3Dfn6PMJGTnhgqXMrDxx3uHrq0Jl2swRnAWIIO8gID7j" + + "uPetUqEviPiwAYeJAEwEGBECAAwFAkEcraYFGwwAAAAACgkQ9P5W+Cv/YhShrgCg" + + "+JW8m5nF3R/oZGuG87bXQBszkjMAoLhGPncuGKowJXMRVc70/8qwXQJLsAFn"); + + private static readonly char[] sec8pass = "qwertyui".ToCharArray(); + + private static readonly byte[] sec9 = Base64.Decode( + "lQGqBEHCokERBAC9rh5SzC1sX1y1zoFuBB/v0SGhoKMEvLYf8Qv/j4deAMrc" + + "w5dxasYoD9oxivIUfTbZKo8cqr+dKLgu8tycigTM5b/T2ms69SUAxSBtj2uR" + + "LZrh4vjC/93kF+vzYJ4fNaBs9DGfCnsTouKjXqmfN3SlPMKNcGutO7FaUC3d" + + "zcpYfwCg7qyONHvXPhS0Iw4QL3mJ/6wMl0UD/0PaonqW0lfGeSjJSM9Jx5Bt" + + "fTSlwl6GmvYmI8HKvOBXAUSTZSbEkMsMVcIgf577iupzgWCgNF6WsNqQpKaq" + + "QIq1Kjdd0Y00xU1AKflOkhl6eufTigjviM+RdDlRYsOO5rzgwDTRTu9giErs" + + "XIyJAIZIdu2iaBHX1zHTfJ1r7nlAA/9H4T8JIhppUk/fLGsoPNZzypzVip8O" + + "mFb9PgvLn5GmuIC2maiocT7ibbPa7XuXTO6+k+323v7PoOUaKD3uD93zHViY" + + "Ma4Q5pL5Ajc7isnLXJgJb/hvvB1oo+wSDo9vJX8OCSq1eUPUERs4jm90/oqy" + + "3UG2QVqs5gcKKR4o48jTiv4DZQJHTlUBtB1mb28ga2V5IDxmb28ua2V5QGlu" + + "dmFsaWQuY29tPoheBBMRAgAeBQJBwqJCAhsDBgsJCAcDAgMVAgMDFgIBAh4B" + + "AheAAAoJEOKcXvehtw4ajJMAoK9nLfsrRY6peq56l/KzmjzuaLacAKCXnmiU" + + "waI7+uITZ0dihJ3puJgUz50BWARBwqJDEAQA0DPcNIn1BQ4CDEzIiQkegNPY" + + "mkYyYWDQjb6QFUXkuk1WEB73TzMoemsA0UKXwNuwrUgVhdpkB1+K0OR/e5ik" + + "GhlFdrDCqyT+mw6dRWbJ2i4AmFXZaRKO8AozZeWojsfP1/AMxQoIiBEteMFv" + + "iuXnZ3pGxSfZYm2+33IuPAV8KKMAAwUD/0C2xZQXgVWTiVz70HUviOmeTQ+f" + + "b1Hj0U9NMXWB383oQRBZCvQDM12cqGsvPZuZZ0fkGehGAIoyXtIjJ9lejzZN" + + "1TE9fnXZ9okXI4yCl7XLSE26OAbNsis4EtKTNScNaU9Dk3CS5XD/pkRjrkPN" + + "2hdUFtshuGmYkqhb9BIlrwE7/gMDAglbVSwecr9mYJcDYCH62U9TScWDTzsQ" + + "NFEfhMez3hGnNHNfHe+7yN3+Q9/LIhbba3IJEN5LsE5BFvudLbArp56EusIn" + + "JCxgiEkEGBECAAkFAkHCokMCGwwACgkQ4pxe96G3Dho2UQCeN3VPwx3dROZ+" + + "4Od8Qj+cLrBndGEAn0vaQdy6eIGeDw2I9u3Quwy6JnROnQHhBEHCozMRBADH" + + "ZBlB6xsAnqFYtYQOHr4pX6Q8TrqXCiHHc/q56G2iGbI9IlbfykQzaPHgWqZw" + + "9P0QGgF/QZh8TitiED+imLlGDqj3nhzpazqDh5S6sg6LYkQPqhwG/wT5sZQQ" + + "fzdeupxupjI5YN8RdIqkWF+ILOjk0+awZ4z0TSY/f6OSWpOXlwCgjIquR3KR" + + "tlCLk+fBlPnOXaOjX+kEAJw7umykNIHNaoY/2sxNhQhjqHVxKyN44y6FCSv9" + + "jRyW8Q/Qc8YhqBIHdmlcXoNWkDtlvErjdYMvOKFqKB1e2bGpjvhtIhNVQWdk" + + "oHap9ZuM1nV0+fD/7g/NM6D9rOOVCahBG2fEEeIwxa2CQ7zHZYfg9Umn3vbh" + + "TYi68R3AmgLOA/wKIVkfFKioI7iX4crQviQHJK3/A90SkrjdMQwLoiUjdgtk" + + "s7hJsTP1OPb2RggS1wCsh4sv9nOyDULj0T0ySGv7cpyv5Nq0FY8gw2oogHs5" + + "fjUnG4VeYW0zcIzI8KCaJT4UhR9An0A1jF6COrYCcjuzkflFbQLtQb9uNj8a" + + "hCpU4/4DAwIUxXlRMYE8uWCranzPo83FnBPRnGJ2aC9SqZWJYVUKIn4Vf2nu" + + "pVvCGFja0usl1WfV72hqlNKEONq7lohJBBgRAgAJBQJBwqMzAhsCAAoJEOKc" + + "Xvehtw4afisAoME/t8xz/rj/N7QRN9p8Ji8VPGSqAJ9K8eFJ+V0mxR+octJr" + + "6neEEX/i1Q=="); + + public char[] sec9pass = "foo".ToCharArray(); + + // version 4 keys with expiry dates + private static readonly byte[] pub10 = Base64.Decode( + "mQGiBEKqia0RBACc3hkufmscRSC4UvPZqMDsHm4+d/GXIr+3iNMSSEySJu8yk+k0" + + "Xs11C/K+n+v1rnn2jGGknv+1lDY6w75TIcTE6o6HGKeIDxsAm8P3MhoGU1GNPamA" + + "eTDeNybtrN/g6C65fCY9uI11hsUboYgQZ8ND22PB0VtvdOgq9D85qNUzxwCg1BbJ" + + "ycAKd4VqEvQ2Zglp3dCSrFMD/Ambq1kZqYa69sp3b9BPKuAgUgUPoytOArEej3Bk" + + "easAgAxNhWJy4GxigES3vk50rVi7w8XBuqbD1mQCzldF0HX0/A7PxLBv6od5uqqF" + + "HFxIyxg/KBZLd9ZOrsSaoUWH58jZq98X/sFtJtRi5VuJagMxCIJD4mLgtMv7Unlb" + + "/GrsA/9DEnObA/fNTgK70T+ZmPIS5tSt+bio30Aw4YGpPCGqpnm1u73b5kqX3U3B" + + "P+vGDvFuqZYpqQA8byAueH0MbaDHI4CFugvShXvgysJxN7ov7/8qsZZUMfK1t2Nr" + + "SAsPuKRbcY4gNKXIElKeXbyaET7vX7uAEKuxEwdYGFp/lNTkHLQgdGVzdCBrZXkg" + + "KHRlc3QpIDx0ZXN0QHRlc3QudGVzdD6IZAQTEQIAJAUCQqqJrQIbAwUJACTqAAYL" + + "CQgHAwIDFQIDAxYCAQIeAQIXgAAKCRDjDROQZRqIzDzLAJ42AeCRIBBjv8r8qw9y" + + "laNj2GZ1sACgiWYHVXMA6B1H9I1kS3YsCd3Oq7qwAgAAuM0EQqqJrhADAKWkix8l" + + "pJN7MMTXob4xFF1TvGll0UD1bDGOMMbes6aeXSbT9QXee/fH3GnijLY7wB+qTPv9" + + "ohubrSpnv3yen3CEBW6Q2YK+NlCskma42Py8YMV2idmYjtJi1ckvHFWt5wADBQL/" + + "fkB5Q5xSGgspMaTZmtmX3zG7ZDeZ0avP8e8mRL8UszCTpqs6vMZrXwyQLZPbtMYv" + + "PQpuRGEeKj0ysimwYRA5rrLQjnRER3nyuuEUUgc4j+aeRxPf9WVsJ/a1FCHtaAP1" + + "iE8EGBECAA8FAkKqia4CGwwFCQAk6gAACgkQ4w0TkGUaiMzdqgCfd66H7DL7kFGd" + + "IoS+NIp8JO+noxAAn25si4QAF7og8+4T5YQUuhIhx/NesAIAAA=="); + + private static readonly byte[] sec10 = Base64.Decode( + "lQHhBEKqia0RBACc3hkufmscRSC4UvPZqMDsHm4+d/GXIr+3iNMSSEySJu8yk+k0" + + "Xs11C/K+n+v1rnn2jGGknv+1lDY6w75TIcTE6o6HGKeIDxsAm8P3MhoGU1GNPamA" + + "eTDeNybtrN/g6C65fCY9uI11hsUboYgQZ8ND22PB0VtvdOgq9D85qNUzxwCg1BbJ" + + "ycAKd4VqEvQ2Zglp3dCSrFMD/Ambq1kZqYa69sp3b9BPKuAgUgUPoytOArEej3Bk" + + "easAgAxNhWJy4GxigES3vk50rVi7w8XBuqbD1mQCzldF0HX0/A7PxLBv6od5uqqF" + + "HFxIyxg/KBZLd9ZOrsSaoUWH58jZq98X/sFtJtRi5VuJagMxCIJD4mLgtMv7Unlb" + + "/GrsA/9DEnObA/fNTgK70T+ZmPIS5tSt+bio30Aw4YGpPCGqpnm1u73b5kqX3U3B" + + "P+vGDvFuqZYpqQA8byAueH0MbaDHI4CFugvShXvgysJxN7ov7/8qsZZUMfK1t2Nr" + + "SAsPuKRbcY4gNKXIElKeXbyaET7vX7uAEKuxEwdYGFp/lNTkHP4DAwLssmOjVC+d" + + "mWB783Lpzjb9evKzsxisTdx8/jHpUSS+r//6/Guyx3aA/zUw5bbftItW57mhuNNb" + + "JTu7WrQgdGVzdCBrZXkgKHRlc3QpIDx0ZXN0QHRlc3QudGVzdD6IZAQTEQIAJAUC" + + "QqqJrQIbAwUJACTqAAYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRDjDROQZRqIzDzL" + + "AJ0cYPwKeoSReY14LqJtAjnkX7URHACgsRZWfpbalrSyDnq3TtZeGPUqGX+wAgAA" + + "nQEUBEKqia4QAwClpIsfJaSTezDE16G+MRRdU7xpZdFA9WwxjjDG3rOmnl0m0/UF" + + "3nv3x9xp4oy2O8Afqkz7/aIbm60qZ798np9whAVukNmCvjZQrJJmuNj8vGDFdonZ" + + "mI7SYtXJLxxVrecAAwUC/35AeUOcUhoLKTGk2ZrZl98xu2Q3mdGrz/HvJkS/FLMw" + + "k6arOrzGa18MkC2T27TGLz0KbkRhHio9MrIpsGEQOa6y0I50REd58rrhFFIHOI/m" + + "nkcT3/VlbCf2tRQh7WgD9f4DAwLssmOjVC+dmWDXVLRopzxbBGOvodp/LZoSDb56" + + "gNJjDMJ1aXqWW9qTAg1CFjBq73J3oFpVzInXZ8+Q8inxv7bnWiHbiE8EGBECAA8F" + + "AkKqia4CGwwFCQAk6gAACgkQ4w0TkGUaiMzdqgCgl2jw5hfk/JsyjulQqe1Nps1q" + + "Lx0AoMdnFMZmTMLHn8scUW2j9XO312tmsAIAAA=="); + +// private static readonly char[] sec10pass = "test".ToCharArray(); + + private static readonly byte[] subKeyBindingKey = Base64.Decode( + "mQGiBDWagYwRBAD7UcH4TAIp7tmUoHBNxVxCVz2ZrNo79M6fV63riOiH2uDxfIpr" + + "IrL0cM4ehEKoqlhngjDhX60eJrOw1nC5BpYZRnDnyDYT4wTWRguxObzGq9pqA1dM" + + "oPTJhkFZVIBgFY99/ULRqaUYIhFGgBtnwS70J8/L/PGVc3DmWRLMkTDjSQCg/5Nh" + + "MCjMK++MdYMcMl/ziaKRT6EEAOtw6PnU9afdohbpx9CK4UvCCEagfbnUtkSCQKSk" + + "6cUp6VsqyzY0pai/BwJ3h4apFMMMpVrtBAtchVgqo4xTr0Sve2j0k+ase6FSImiB" + + "g+AR7hvTUTcBjwtIExBc8TuCTqmn4GG8F7UMdl5Z0AZYj/FfAQYaRVZYP/pRVFNx" + + "Lw65BAC/Fi3qgiGCJFvXnHIckTfcAmZnKSEXWY9NJ4YQb4+/nH7Vsw0wR/ZObUHR" + + "bWgTc9Vw1uZIMe0XVj6Yk1dhGRehUnrm3mE7UJxu7pgkBCbFECFSlSSqP4MEJwZV" + + "09YP/msu50kjoxyoTpt+16uX/8B4at24GF1aTHBxwDLd8X0QWrQsTWVycmlsbCBM" + + "eW5jaCBDTEVBUiBzeXN0ZW0gREggPGNsZWFyQG1sLmNvbT6JAEsEEBECAAsFAjWa" + + "gYwECwMBAgAKCRDyAGjiP47/XanfAKCs6BPURWVQlGh635VgL+pdkUVNUwCdFcNa" + + "1isw+eAcopXPMj6ACOapepu5Ag0ENZqBlBAIAPZCV7cIfwgXcqK61qlC8wXo+VMR" + + "OU+28W65Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf" + + "3HZSTz09jdvOmeFXklnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2g" + + "pXI61Brwv0YAWCvl9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPA" + + "Q/ClWxiNjrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQD" + + "GcgHKXrKlQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVekyCzsAAgIH" + + "/RYtVo+HROZ6jrNjrATEwQm1fUQrk6n5+2dniN881lF0CNkB4NkHw1Xxz4Ejnu/0" + + "iLg8fkOAsmanOsKpOkRtqUnVpsVL5mLJpFEyCY5jbcfj+KY9/25bs0ga7kLHNZia" + + "zbCxJdF+W179z3nudQxRaXG/0XISIH7ziZbSVni69sKc1osk1+OoOMbSuZ86z535" + + "Pln4fXclkFE927HxfbWoO+60hkOLKh7x+8fC82b3x9vCETujEaxrscO2xS7/MYXP" + + "8t1ffriTDmhuIuQS2q4fLgeWdqrODrMhrD8Dq7e558gzp30ZCqpiS7EmKGczL7B8" + + "gXxbBCVSTxYMJheXt2xMXsuJAD8DBRg1moGU8gBo4j+O/10RAgWdAKCPhaFIXuC8" + + "/cdiNMxTDw9ug3De5QCfYXmDzRSFUu/nrCi8yz/l09wsnxo="); + +// private static readonly byte[] subKeyBindingCheckSum = Base64.Decode("3HU+"); + + // + // PGP8 with SHA1 checksum. + // + private static readonly byte[] rewrapKey = Base64.Decode( + "lQOWBEUPOQgBCADdjPTtl8oOwqJFA5WU8p7oDK5KRWfmXeXUZr+ZJipemY5RSvAM" + + "rxqsM47LKYbmXOJznXCQ8+PPa+VxXAsI1CXFHIFqrXSwvB/DUmb4Ec9EuvNd18Zl" + + "hJAybzmV2KMkaUp9oG/DUvxZJqkpUddNfwqZu0KKKZWF5gwW5Oy05VCpaJxQVXFS" + + "whdbRfwEENJiNx4RB3OlWhIjY2p+TgZfgQjiGB9i15R+37sV7TqzBUZF4WWcnIRQ" + + "DnpUfxHgxQ0wO/h/aooyRHSpIx5i4oNpMYq9FNIyakEx/Bomdbs5hW9dFxhrE8Es" + + "UViAYITgTsyROxmgGatGG09dcmVDJVYF4i7JAAYpAAf/VnVyUDs8HrxYTOIt4rYY" + + "jIHToBsV0IiLpA8fEA7k078L1MwSwERVVe6oHVTjeR4A9OxE52Vroh2eOLnF3ftf" + + "6QThVVZr+gr5qeG3yvQ36N7PXNEVOlkyBzGmFQNe4oCA+NR2iqnAIspnekVmwJV6" + + "xVvPCjWw/A7ZArDARpfthspwNcJAp4SWfoa2eKzvUTznTyqFu2PSS5fwQZUgOB0P" + + "Y2FNaKeqV8vEZu4SUWwLOqXBQIZXiaLvdKNgwFvUe3kSHdCNsrVzW7SYxFwaEog2" + + "o6YLKPVPqjlGX1cMOponGp+7n9nDYkQjtEsGSSMQkQRDAcBdSVJmLO07kFOQSOhL" + + "WQQA49BcgTZyhyH6TnDBMBHsGCYj43FnBigypGT9FrQHoWybfX47yZaZFROAaaMa" + + "U6man50YcYZPwzDzXHrK2MoGALY+DzB3mGeXVB45D/KYtlMHPLgntV9T5b14Scbc" + + "w1ES2OUtsSIUs0zelkoXqjLuKnSIYK3mMb67Au7AEp6LXM8EAPj2NypvC86VEnn+" + + "FH0QHvUwBpmDw0EZe25xQs0brvAG00uIbiZnTH66qsIfRhXV/gbKK9J5DTGIqQ15" + + "DuPpz7lcxg/n2+SmjQLNfXCnG8hmtBjhTe+udXAUrmIcfafXyu68SAtebgm1ga56" + + "zUfqsgN3FFuMUffLl3myjyGsg5DnA/oCFWL4WCNClOgL6A5VkNIUait8QtSdCACT" + + "Y7jdSOguSNXfln0QT5lTv+q1AjU7zjRl/LsFNmIJ5g2qdDyK937FOXM44FEEjZty" + + "/4P2dzYpThUI4QUohIj8Qi9f2pZQueC5ztH6rpqANv9geZKcciAeAbZ8Md0K2TEU" + + "RD3Lh+RSBzILtBtUZXN0IEtleSA8dGVzdEBleGFtcGxlLmNvbT6JATYEEwECACAF" + + "AkUPOQgCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRDYpknHeQaskD9NB/9W" + + "EbFuLaqZAl3yjLU5+vb75BdvcfL1lUs44LZVwobNp3/0XbZdY76xVPNZURtU4u3L" + + "sJfGlaF+EqZDE0Mqc+vs5SIb0OnCzNJ00KaUFraUtkByRV32T5ECHK0gMBjCs5RT" + + "I0vVv+Qmzl4+X1Y2bJ2mlpBejHIrOzrBD5NTJimTAzyfnNfipmbqL8p/cxXKKzS+" + + "OM++ZFNACj6lRM1W9GioXnivBRC88gFSQ4/GXc8yjcrMlKA27JxV+SZ9kRWwKH2f" + + "6o6mojUQxnHr+ZFKUpo6ocvTgBDlC57d8IpwJeZ2TvqD6EdA8rZ0YriVjxGMDrX1" + + "8esfw+iLchfEwXtBIRwS"); + + private static readonly char[] rewrapPass = "voltage123".ToCharArray(); + + private static readonly byte[] pubWithX509 = Base64.Decode( + "mQENBERabjABCACtmfyo6Nph9MQjv4nmCWjZrRYnhXbivomAdIwYkLZUj1bjqE+j" + + "uaLzjZV8xSI59odZvrmOiqlzOc4txitQ1OX7nRgbOJ7qku0dvwjtIn46+HQ+cAFn" + + "2mTi81RyXEpO2uiZXfsNTxUtMi+ZuFLufiMc2kdk27GZYWEuasdAPOaPJnA+wW6i" + + "ZHlt0NfXIGNz864gRwhD07fmBIr1dMFfATWxCbgMd/rH7Z/j4rvceHD2n9yrhPze" + + "YN7W4Nuhsr2w/Ft5Cm9xO7vXT/cpto45uxn8f7jERep6bnUwNOhH8G+6xLQgTLD0" + + "qFBGVSIneK3lobs6+xn6VaGN8W0tH3UOaxA1ABEBAAG0D0NOPXFhLWRlZXBzaWdo" + + "dIkFDgQQZAIFAQUCRFpuMAUDCWdU0gMF/3gCGwPELGQBAQQwggTkMIIDzKADAgEC" + + "AhBVUMV/M6rIiE+IzmnPheQWMA0GCSqGSIb3DQEBBQUAMG4xEzARBgoJkiaJk/Is" + + "ZAEZFgNjb20xEjAQBgoJkiaJk/IsZAEZFgJxYTEVMBMGCgmSJomT8ixkARkWBXRt" + + "czAxMRUwEwYKCZImiZPyLGQBGRYFV2ViZmUxFTATBgNVBAMTDHFhLWRlZXBzaWdo" + + "dDAeFw0wNjA1MDQyMTEyMTZaFw0xMTA1MDQyMTIwMDJaMG4xEzARBgoJkiaJk/Is" + + "ZAEZFgNjb20xEjAQBgoJkiaJk/IsZAEZFgJxYTEVMBMGCgmSJomT8ixkARkWBXRt" + + "czAxMRUwEwYKCZImiZPyLGQBGRYFV2ViZmUxFTATBgNVBAMTDHFhLWRlZXBzaWdo" + + "dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2Z/Kjo2mH0xCO/ieYJ" + + "aNmtFieFduK+iYB0jBiQtlSPVuOoT6O5ovONlXzFIjn2h1m+uY6KqXM5zi3GK1DU" + + "5fudGBs4nuqS7R2/CO0ifjr4dD5wAWfaZOLzVHJcSk7a6Jld+w1PFS0yL5m4Uu5+" + + "IxzaR2TbsZlhYS5qx0A85o8mcD7BbqJkeW3Q19cgY3PzriBHCEPTt+YEivV0wV8B" + + "NbEJuAx3+sftn+Piu9x4cPaf3KuE/N5g3tbg26GyvbD8W3kKb3E7u9dP9ym2jjm7" + + "Gfx/uMRF6npudTA06Efwb7rEtCBMsPSoUEZVIid4reWhuzr7GfpVoY3xbS0fdQ5r" + + "EDUCAwEAAaOCAXwwggF4MAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G" + + "A1UdDgQWBBSmFTRv5y65DHtTYae48zl0ExNWZzCCASUGA1UdHwSCARwwggEYMIIB" + + "FKCCARCgggEMhoHFbGRhcDovLy9DTj1xYS1kZWVwc2lnaHQsQ049cWEtd3VtYW4x" + + "LWRjLENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNl" + + "cyxDTj1Db25maWd1cmF0aW9uLERDPVdlYmZlLERDPXRtczAxLERDPXFhLERDPWNv" + + "bT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JM" + + "RGlzdHJpYnV0aW9uUG9pbnSGQmh0dHA6Ly9xYS13dW1hbjEtZGMud2ViZmUudG1z" + + "MDEucWEuY29tL0NlcnRFbnJvbGwvcWEtZGVlcHNpZ2h0LmNybDAQBgkrBgEEAYI3" + + "FQEEAwIBADANBgkqhkiG9w0BAQUFAAOCAQEAfuZCW3XlB7Eok35zQbvYt9rhAndT" + + "DNw3wPNI4ZzD1nXoYWnwhNNvWRpsOt4ExOSNdaHErfgDXAMyyg66Sro0TkAx8eAj" + + "fPQsyRAh0nm0glzFmJN6TdOZbj7hqGZjc4opQ6nZo8h/ULnaEwMIUW4gcSkZt0ww" + + "CuErl5NUrN3DpkREeCG/fVvQZ8ays3ibQ5ZCZnYBkLYq/i0r3NLW34WfYhjDY48J" + + "oQWtvFSAxvRfz2NGmqnrCHPQZxqlfdta97kDa4VQ0zSeBaC70gZkLmD1GJMxWoXW" + + "6tmEcgPY5SghInUf+L2u52V55MjyAFzVp7kTK2KY+p7qw35vzckrWkwu8AAAAAAA" + + "AQE="); + + private static readonly byte[] secWithPersonalCertificate = Base64.Decode( + "lQOYBEjGLGsBCACp1I1dZKsK4N/I0/4g02hDVNLdQkDZfefduJgyJUyBGo/I" + + "/ZBpc4vT1YwVIdic4ADjtGB4+7WohN4v8siGzwRSeXardSdZVIw2va0JDsQC" + + "yeoTnwVkUgn+w/MDgpL0BBhTpr9o3QYoo28/qKMni3eA8JevloZqlAbQ/sYq" + + "rToMAqn0EIdeVVh6n2lRQhUJaNkH/kA5qWBpI+eI8ot/Gm9kAy3i4e0Xqr3J" + + "Ff1lkGlZuV5H5p/ItZui9BDIRn4IDaeR511NQnKlxFalM/gP9R9yDVI1aXfy" + + "STcp3ZcsTOTGNzACtpvMvl6LZyL42DyhlOKlJQJS81wp4dg0LNrhMFOtABEB" + + "AAEAB/0QIH5UEg0pTqAG4r/3v1uKmUbKJVJ3KhJB5xeSG3dKWIqy3AaXR5ZN" + + "mrJfXK7EfC5ZcSAqx5br1mzVl3PHVBKQVQxvIlmG4r/LKvPVhQYZUFyJWckZ" + + "9QMR+EA0Dcran9Ds5fa4hH84jgcwalkj64XWRAKDdVh098g17HDw+IYnQanl" + + "7IXbYvh+1Lr2HyPo//vHX8DxXIJBv+E4skvqGoNfCIfwcMeLsrI5EKo+D2pu" + + "kAuBYI0VBiZkrJHFXWmQLW71Mc/Bj7wTG8Q1pCpu7YQ7acFSv+/IOCsB9l9S" + + "vdB7pNhB3lEjYFGoTgr03VfeixA7/x8uDuSXjnBdTZqmGqkZBADNwCqlzdaQ" + + "X6CjS5jc3vzwDSPgM7ovieypEL6NU3QDEUhuP6fVvD2NYOgVnAEbJzgOleZS" + + "W2AFXKAf5NDxfqHnBmo/jlYb5yZV5Y+8/poLLj/m8t7sAfAmcZqGXfYMbSbe" + + "tr6TGTUXcXgbRyU5oH1e4iq691LOwZ39QjL8lNQQywQA006XYEr/PS9uJkyM" + + "Cg+M+nmm40goW4hU/HboFh9Ru6ataHj+CLF42O9sfMAV02UcD3Agj6w4kb5L" + + "VswuwfmY+17IryT81d+dSmDLhpo6ufKoAp4qrdP+bzdlbfIim4Rdrw5vF/Yk" + + "rC/Nfm3CLJxTimHJhqFx4MG7yEC89lxgdmcD/iJ3m41fwS+bPN2rrCAf7j1u" + + "JNr/V/8GAnoXR8VV9150BcOneijftIIYKKyKkV5TGwcTfjaxRKp87LTeC3MV" + + "szFDw04MhlIKRA6nBdU0Ay8Yu+EjXHK2VSpLG/Ny+KGuNiFzhqgBxM8KJwYA" + + "ISa1UEqWjXoLU3qu1aD7cCvANPVCOASwAYe0GlBHUCBEZXNrdG9wIDxpbmZv" + + "QHBncC5jb20+sAMD//+JAW4EEAECAFgFAkjGLGswFIAAAAAAIAAHcHJlZmVy" + + "cmVkLWVtYWlsLWVuY29kaW5nQHBncC5jb21wZ3BtaW1lBwsJCAcDAgoCGQEF" + + "GwMAAAADFgECBR4BAAAABRUCCAkKAAoJEHHHqp2m1tlWsx8H/icpHl1Nw17A" + + "D6MJN6zJm+aGja+5BOFxOsntW+IV6JI+l5WwiIVE8xTDhoXW4zdH3IZTqoyY" + + "frtkqLGpvsPtAQmV6eiPgE3+25ahL+MmjXKsceyhbZeCPDtM2M382VCHYCZK" + + "DZ4vrHVgK/BpyTeP/mqoWra9+F5xErhody71/cLyIdImLqXgoAny6YywjuAD" + + "2TrFnzPEBmZrkISHVEso+V9sge/8HsuDqSI03BAVWnxcg6aipHtxm907sdVo" + + "jzl2yFbxCCCaDIKR7XVbmdX7VZgCYDvNSxX3WEOgFq9CYl4ZlXhyik6Vr4XP" + + "7EgqadtfwfMcf4XrYoImSQs0gPOd4QqwAWedA5gESMYsawEIALiazFREqBfi" + + "WouTjIdLuY09Ks7PCkn0eo/i40/8lEj1R6JKFQ5RlHNnabh+TLvjvb3nOSU0" + + "sDg+IKK/JUc8/Fo7TBdZvARX6BmltEGakqToDC3eaF9EQgHLEhyE/4xXiE4H" + + "EeIQeCHdC7k0pggEuWUn5lt6oeeiPUWhqdlUOvzjG+jqMPJL0bk9STbImHUR" + + "EiugCPTekC0X0Zn0yrwyqlJQMWnh7wbSl/uo4q45K7qOhxcijo+hNNrkRAMi" + + "fdNqD4s5qDERqqHdAAgpWqydo7zV5tx0YSz5fjh59Z7FxkUXpcu1WltT6uVn" + + "hubiMTWpXzXOQI8wZL2fb12JmRY47BEAEQEAAQAH+wZBeanj4zne+fBHrWAS" + + "2vx8LYiRV9EKg8I/PzKBVdGUnUs0vTqtXU1dXGXsAsPtu2r1bFh0TQH06gR1" + + "24iq2obgwkr6x54yj+sZlE6SU0SbF/mQc0NCNAXtSKV2hNXvy+7P+sVJR1bn" + + "b5ukuvkj1tgEln/0W4r20qJ60F+M5QxXg6kGh8GAlo2tetKEv1NunAyWY6iv" + + "FTnSaIJ/YaKQNcudNvOJjeIakkIzfzBL+trUiI5n1LTBB6+u3CF/BdZBTxOy" + + "QwjAh6epZr+GnQqeaomFxBc3mU00sjrsB1Loso84UIs6OKfjMkPoZWkQrQQW" + + "+xvQ78D33YwqNfXk/5zQAxkEANZxJGNKaAeDpN2GST/tFZg0R5GPC7uWYC7T" + + "pG100mir9ugRpdeIFvfAa7IX2jujxo9AJWo/b8hq0q0koUBdNAX3xxUaWy+q" + + "KVCRxBifpYVBfEViD3lsbMy+vLYUrXde9087YD0c0/XUrj+oowWJavblmZtS" + + "V9OjkQW9zoCigpf5BADcYV+6bkmJtstxJopJG4kD/lr1o35vOEgLkNsMLayc" + + "NuzES084qP+8yXPehkzSsDB83kc7rKfQCQMZ54V7KCCz+Rr4wVG7FCrFAw4e" + + "4YghfGVU/5whvbJohl/sXXCYGtVljvY/BSQrojRdP+/iZxFbeD4IKiTjV+XL" + + "WKSS56Fq2QQAzeoKBJFUq8nqc8/OCmc52WHSOLnB4AuHL5tNfdE9tjqfzZAE" + + "tx3QB7YGGP57tPQxPFDFJVRJDqw0YxI2tG9Pum8iriKGjHg+oEfFhxvCmPxf" + + "zDKaGibkLeD7I6ATpXq9If+Nqb5QjzPjFbXBIz/q2nGjamZmp4pujKt/aZxF" + + "+YRCebABh4kCQQQYAQIBKwUCSMYsbAUbDAAAAMBdIAQZAQgABgUCSMYsawAK" + + "CRCrkqZshpdZSNAiB/9+5nAny2O9/lp2K2z5KVXqlNAHUmd4S/dpqtsZCbAo" + + "8Lcr/VYayrNojga1U7cyhsvFky3N9wczzPHq3r9Z+R4WnRM1gpRWl+9+xxtd" + + "ZxGfGzMRlxX1n5rCqltKKk6IKuBAr2DtTnxThaQiISO2hEw+P1MT2HnSzMXt" + + "zse5CZ5OiOd/bm/rdvTRD/JmLqhXmOFaIwzdVP0dR9Ld4Dug2onOlIelIntC" + + "cywY6AmnL0DThaTy5J8MiMSPamSmATl4Bicm8YRbHHz58gCYxI5UMLwtwR1+" + + "rSEmrB6GwVHZt0/BzOpuGpvFZI5ZmC5yO/waR1hV+VYj025cIz+SNuDPyjy4" + + "AAoJEHHHqp2m1tlW/w0H/3w38SkB5n9D9JL3chp+8fex03t7CQowVMdsBYNY" + + "qI4QoVQkakkxzCz5eF7rijXt5eC3NE/quWhlMigT8LARiwBROBWgDRFW4WuX" + + "6MwYtjKKUkZSkBKxP3lmaqZrJpF6jfhPEN76zr/NxWPC/nHRNldUdqkzSu/r" + + "PeJyePMofJevzMkUzw7EVtbtWhZavCz+EZXRTZXub9M4mDMj64BG6JHMbVZI" + + "1iDF2yka5RmhXz9tOhYgq80m7UQUb1ttNn86v1zVbe5lmB8NG4Ndv+JaaSuq" + + "SBZOYQ0ZxtMAB3vVVLZCWxma1P5HdXloegh+hosqeu/bl0Wh90z5Bspt6eI4" + + "imqwAWeVAdgESMYtmwEEAM9ZeMFxor7oSoXnhQAXD9lXLLfBky6IcIWISY4F" + + "JWc8sK8+XiVzpOrefKro0QvmEGSYcDFQMHdScBLOTsiVJiqenA7fg1bkBr/M" + + "bnD7vTKMJe0DARlU27tE5hsWCDYTluxIFjGcAcecY2UqHkqpctYKY0WY9EIm" + + "dBA5TYaw3c0PABEBAAEAA/0Zg6318nC57cWLIp5dZiO/dRhTPZD0hI+BWZrg" + + "zJtPT8rXVY+qK3Jwquig8z29/r+nppEE+xQWVWDlv4M28BDJAbGE+qWKAZqT" + + "67lyKgc0c50W/lfbGvvs+F7ldCcNpFvlk79GODKxcEeTGDQKb9R6FnHFee/K" + + "cZum71O3Ku3vUQIA3B3PNM+tKocIUNDHnInuLyqLORwQBNGfjU/pLMM0MkpP" + + "lWeIfgUmn2zL/e0JrRoO0LQqX1LN/TlfcurDM0SEtwIA8Sba9OpDq99Yz360" + + "FiePJiGNNlbj9EZsuGJyMVXL1mTLA6WHnz5XZOfYqJXHlmKvaKDbARW4+0U7" + + "0/vPdYWSaQIAwYeo2Ce+b7M5ifbGMDWYBisEvGISg5xfvbe6qApmHS4QVQzE" + + "Ym81rdJJ8OfvgSbHcgn37S3OBXIQvNdejF4BWqM9sAGHtCBIeW5lay1JbnRy" + + "YW5ldCA8aHluZWtAYWxzb2Z0LmN6PrADA///iQDrBBABAgBVBQJIxi2bBQkB" + + "mgKAMBSAAAAAACAAB3ByZWZlcnJlZC1lbWFpbC1lbmNvZGluZ0BwZ3AuY29t" + + "cGdwbWltZQULBwgJAgIZAQUbAQAAAAUeAQAAAAIVAgAKCRDlTa3BE84gWVKW" + + "BACcoCFKvph9r9QiHT1Z3N4wZH36Uxqu/059EFALnBkEdVudX/p6S9mynGRk" + + "EfhmWFC1O6dMpnt+ZBEed/4XyFWVSLPwirML+6dxfXogdUsdFF1NCRHc3QGc" + + "txnNUT/zcZ9IRIQjUhp6RkIvJPHcyfTXKSbLviI+PxzHU2Padq8pV7ABZ7kA" + + "jQRIfg8tAQQAutJR/aRnfZYwlVv+KlUDYjG8YQUfHpTxpnmVu7W6N0tNg/Xr" + + "5dg50wq3I4HOamRxUwHpdPkXyNF1szpDSRZmlM+VmiIvJDBnyH5YVlxT6+zO" + + "8LUJ2VTbfPxoLFp539SQ0oJOm7IGMAGO7c0n/QV0N3hKUfWgCyJ+sENDa0Ft" + + "JycAEQEAAbABj4kEzQQYAQIENwUCSMYtnAUJAeEzgMLFFAAAAAAAFwNleDUw" + + "OWNlcnRpZmljYXRlQHBncC5jb20wggNhMIICyqADAgECAgkA1AoCoRKJCgsw" + + "DQYJKoZIhvcNAQEFBQAwgakxCzAJBgNVBAYTAkNaMRcwFQYDVQQIEw5DemVj" + + "aCBSZXB1YmxpYzESMBAGA1UEChQJQSYmTCBzb2Z0MSAwHgYDVQQLExdJbnRl" + + "cm5hbCBEZXZlbG9wbWVudCBDQTEqMCgGA1UEAxQhQSYmTCBzb2Z0IEludGVy" + + "bmFsIERldmVsb3BtZW50IENBMR8wHQYJKoZIhvcNAQkBFhBrYWRsZWNAYWxz" + + "b2Z0LmN6MB4XDTA4MDcxNjE1MDkzM1oXDTA5MDcxNjE1MDkzM1owaTELMAkG" + + "A1UEBhMCQ1oxFzAVBgNVBAgTDkN6ZWNoIFJlcHVibGljMRIwEAYDVQQKFAlB" + + "JiZMIHNvZnQxFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5IeW5l" + + "ay1JbnRyYW5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAutJR/aRn" + + "fZYwlVv+KlUDYjG8YQUfHpTxpnmVu7W6N0tNg/Xr5dg50wq3I4HOamRxUwHp" + + "dPkXyNF1szpDSRZmlM+VmiIvJDBnyH5YVlxT6+zO8LUJ2VTbfPxoLFp539SQ" + + "0oJOm7IGMAGO7c0n/QV0N3hKUfWgCyJ+sENDa0FtJycCAwEAAaOBzzCBzDAJ" + + "BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD" + + "ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNaw7A6r10PtYZzAvr9CrSKeRYJgwHwYD" + + "VR0jBBgwFoAUmqSRM8rN3+T1+tkGiqef8S5suYgwGgYDVR0RBBMwEYEPaHlu" + + "ZWtAYWxzb2Z0LmN6MCgGA1UdHwQhMB8wHaAboBmGF2h0dHA6Ly9wZXRyazIv" + + "Y2EvY2EuY3JsMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQCUdOWd" + + "7mBLWj1/GSiYgfwgdTrgk/VZOJvMKBiiFyy1iFEzldz6Xx+mAexnFJKfZXZb" + + "EMEGWHfWPmgJzAtuTT0Jz6tUwDmeLH3MP4m8uOZtmyUJ2aq41kciV3rGxF0G" + + "BVlZ/bWTaOzHdm6cjylt6xxLt6MJzpPBA/9ZfybSBh1DaAUbDgAAAJ0gBBkB" + + "AgAGBQJIxi2bAAoJEAdYkEWLb2R2fJED/RK+JErZ98uGo3Z81cHkdP3rk8is" + + "DUL/PR3odBPFH2SIA5wrzklteLK/ZXmBUzcvxqHEgI1F7goXbsBgeTuGgZdx" + + "pINErxkNpcMl9FTldWKGiapKrhkZ+G8knDizF/Y7Lg6uGd2nKVxzutLXdHJZ" + + "pU89Q5nzq6aJFAZo5TBIcchQAAoJEOVNrcETziBZXvQD/1mvFqBfWqwXxoj3" + + "8fHUuFrE2pcp32y3ciO2i+uNVEkNDoaVVNw5eHQaXXWpllI/Pe6LnBl4vkyc" + + "n3pjONa4PKrePkEsCUhRbIySqXIHuNwZumDOlKzZHDpCUw72LaC6S6zwuoEf" + + "ucOcxTeGIUViANWXyTIKkHfo7HfigixJIL8nsAFn"); + + [Test] + public void PerformTest1() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub1); + + int count = 0; + + foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + byte[] bytes = pgpPub1.GetEncoded(); + + PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes); + + foreach (PgpPublicKey pubKey in pgpPub2.GetPublicKeys()) + { + keyCount++; + + foreach (PgpSignature sig in pubKey.GetSignatures()) + { + if (sig == null) + Fail("null signature found"); + } + } + + if (keyCount != 2) + { + Fail("wrong number of public keys"); + } + } + + if (count != 1) + { + Fail("wrong number of public keyrings"); + } + + // + // exact match + // + count = 0; + foreach (PgpPublicKeyRing pgpPub3 in pubRings.GetKeyRings("test (Test key) ")) + { + if (pgpPub3 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of public keyrings on exact match"); + } + + // + // partial match 1 expected + // + count = 0; + foreach (PgpPublicKeyRing pgpPub4 in pubRings.GetKeyRings("test", true)) + { + if (pgpPub4 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of public keyrings on partial match 1"); + } + + // + // partial match 0 expected + // + count = 0; + foreach (PgpPublicKeyRing pgpPub5 in pubRings.GetKeyRings("XXX", true)) + { + if (pgpPub5 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 0) + { + Fail("wrong number of public keyrings on partial match 0"); + } + + // + // case-insensitive partial match + // + count = 0; + foreach (PgpPublicKeyRing pgpPub6 in pubRings.GetKeyRings("TEST@ubicall.com", true, true)) + { + if (pgpPub6 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of public keyrings on case-insensitive partial match"); + } + + PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(sec1); + count = 0; + + foreach (PgpSecretKeyRing pgpSec1 in secretRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + PgpPublicKey pk = k.PublicKey; + + pk.GetSignatures(); + + byte[] pkBytes = pk.GetEncoded(); + + PgpPublicKeyRing pkR = new PgpPublicKeyRing(pkBytes); + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } + + // + // exact match + // + count = 0; + foreach (PgpSecretKeyRing o1 in secretRings.GetKeyRings("test (Test key) ")) + { + if (o1 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of secret keyrings on exact match"); + } + + // + // partial match 1 expected + // + count = 0; + foreach (PgpSecretKeyRing o2 in secretRings.GetKeyRings("test", true)) + { + if (o2 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of secret keyrings on partial match 1"); + } + + // + // exact match 0 expected + // + count = 0; + foreach (PgpSecretKeyRing o3 in secretRings.GetKeyRings("test", false)) + { + if (o3 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 0) + { + Fail("wrong number of secret keyrings on partial match 0"); + } + + // + // case-insensitive partial match + // + count = 0; + foreach (PgpSecretKeyRing o4 in secretRings.GetKeyRings("TEST@ubicall.com", true, true)) + { + if (o4 == null) + Fail("null keyring found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of secret keyrings on case-insensitive partial match"); + } + } + + [Test] + public void PerformTest2() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub2); + + int count = 0; + + byte[] encRing = pubRings.GetEncoded(); + + pubRings = new PgpPublicKeyRingBundle(encRing); + + foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpPub1.GetEncoded(); + + PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes); + + foreach (PgpPublicKey pk in pgpPub2.GetPublicKeys()) + { + byte[] pkBytes = pk.GetEncoded(); + + PgpPublicKeyRing pkR = new PgpPublicKeyRing(pkBytes); + + keyCount++; + } + + if (keyCount != 2) + { + Fail("wrong number of public keys"); + } + } + + if (count != 2) + { + Fail("wrong number of public keyrings"); + } + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(sec2); + + count = 0; + + + encRing = secretRings2.GetEncoded(); + PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings2.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + PgpPublicKey pk = k.PublicKey; + + if (pk.KeyId == -1413891222336124627L) + { + int sCount = 0; + + foreach (PgpSignature pgpSignature in pk.GetSignaturesOfType(PgpSignature.SubkeyBinding)) + { + int type = pgpSignature.SignatureType; + if (type != PgpSignature.SubkeyBinding) + { + Fail("failed to return correct signature type"); + } + sCount++; + } + + if (sCount != 1) + { + Fail("failed to find binding signature"); + } + } + + pk.GetSignatures(); + + if (k.KeyId == -4049084404703773049L + || k.KeyId == -1413891222336124627L) + { + k.ExtractPrivateKey(sec2pass1); + } + else if (k.KeyId == -6498553574938125416L + || k.KeyId == 59034765524361024L) + { + k.ExtractPrivateKey(sec2pass2); + } + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 2) + { + Fail("wrong number of secret keyrings"); + } + } + + [Test] + public void PerformTest3() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub3); + + int count = 0; + + byte[] encRing = pubRings.GetEncoded(); + + pubRings = new PgpPublicKeyRingBundle(encRing); + + foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpPub1.GetEncoded(); + + PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes); + + foreach (PgpPublicKey pubK in pgpPub2.GetPublicKeys()) + { + keyCount++; + pubK.GetSignatures(); + } + + if (keyCount != 2) + { + Fail("wrong number of public keys"); + } + } + + if (count != 1) + { + Fail("wrong number of public keyrings"); + } + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(sec3); + + count = 0; + + encRing = secretRings2.GetEncoded(); + + PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings2.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + k.ExtractPrivateKey(sec3pass1); + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } + } + + [Test] + public void PerformTest4() + { + PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec4); + int count = 0; + + + byte[] encRing = secretRings1.GetEncoded(); + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + k.ExtractPrivateKey(sec3pass1); + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } + } + + [Test] + public void PerformTest5() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub5); + + int count = 0; + + byte[] encRing = pubRings.GetEncoded(); + + pubRings = new PgpPublicKeyRingBundle(encRing); + + foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpPub1.GetEncoded(); + + PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes); + + foreach (PgpPublicKey o in pgpPub2.GetPublicKeys()) + { + if (o == null) + Fail("null keyring found"); + + keyCount++; + } + + if (keyCount != 2) + { + Fail("wrong number of public keys"); + } + } + + if (count != 1) + { + Fail("wrong number of public keyrings"); + } + +#if INCLUDE_IDEA + PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec5); + + count = 0; + + encRing = secretRings1.GetEncoded(); + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + k.ExtractPrivateKey(sec5pass1); + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } +#endif + } + + [Test] + public void PerformTest6() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub6); + + foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings()) + { + foreach (PgpPublicKey k in pgpPub.GetPublicKeys()) + { + if (k.KeyId == 0x5ce086b5b5a18ff4L) + { + int count = 0; + + foreach (PgpSignature sig in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation)) + { + if (sig == null) + Fail("null signature found"); + + count++; + } + + if (count != 1) + { + Fail("wrong number of revocations in test6."); + } + } + } + } + + byte[] encRing = pubRings.GetEncoded(); + } + + [Test, Explicit] + public void PerformTest7() + { + PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(pub7); + PgpPublicKey masterKey = null; + + foreach (PgpPublicKey k in pgpPub.GetPublicKeys()) + { + if (k.IsMasterKey) + { + masterKey = k; + continue; + } + + int count = 0; + PgpSignature sig = null; + + foreach (PgpSignature sigTemp in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation)) + { + sig = sigTemp; + count++; + } + + if (count != 1) + { + Fail("wrong number of revocations in test7."); + } + + sig.InitVerify(masterKey); + + if (!sig.VerifyCertification(k)) + { + Fail("failed to verify revocation certification"); + } + } + } + + [Test] + public void PerformTest8() + { + PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub8); + + int count = 0; + + byte[] encRing = pubRings.GetEncoded(); + + pubRings = new PgpPublicKeyRingBundle(encRing); + + foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpPub1.GetEncoded(); + + PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes); + + foreach (PgpPublicKey o in pgpPub2.GetPublicKeys()) + { + if (o == null) + Fail("null key found"); + + keyCount++; + } + + if (keyCount != 2) + { + Fail("wrong number of public keys"); + } + } + + if (count != 2) + { + Fail("wrong number of public keyrings"); + } + + PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec8); + + count = 0; + + encRing = secretRings1.GetEncoded(); + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + k.ExtractPrivateKey(sec8pass); + } + + if (keyCount != 2) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } + } + + [Test] + public void PerformTest9() + { + PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec9); + + int count = 0; + + byte[] encRing = secretRings1.GetEncoded(); + + PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing); + + foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings()) + { + count++; + + int keyCount = 0; + + byte[] bytes = pgpSec1.GetEncoded(); + + PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes); + + foreach (PgpSecretKey k in pgpSec2.GetSecretKeys()) + { + keyCount++; + + PgpPrivateKey pKey = k.ExtractPrivateKey(sec9pass); + if (keyCount == 1 && pKey != null) + { + Fail("primary secret key found, null expected"); + } + } + + if (keyCount != 3) + { + Fail("wrong number of secret keys"); + } + } + + if (count != 1) + { + Fail("wrong number of secret keyrings"); + } + } + + [Test] + public void PerformTest10() + { + PgpSecretKeyRing secretRing = new PgpSecretKeyRing(sec10); + + foreach (PgpSecretKey secretKey in secretRing.GetSecretKeys()) + { + PgpPublicKey pubKey = secretKey.PublicKey; + + if (pubKey.ValidDays != 28) + { + Fail("days wrong on secret key ring"); + } + + if (pubKey.GetValidSeconds() != 28 * 24 * 60 * 60) + { + Fail("seconds wrong on secret key ring"); + } + } + + PgpPublicKeyRing publicRing = new PgpPublicKeyRing(pub10); + + foreach (PgpPublicKey pubKey in publicRing.GetPublicKeys()) + { + if (pubKey.ValidDays != 28) + { + Fail("days wrong on public key ring"); + } + + if (pubKey.GetValidSeconds() != 28 * 24 * 60 * 60) + { + Fail("seconds wrong on public key ring"); + } + } + } + + [Test] + public void PerformTest11() + { + PgpPublicKeyRing pubRing = new PgpPublicKeyRing(subKeyBindingKey); + + foreach (PgpPublicKey key in pubRing.GetPublicKeys()) + { + if (key.GetValidSeconds() != 0) + { + Fail("expiration time non-zero"); + } + } + } + + [Test] + public void GenerateTest() + { + char[] passPhrase = "hello".ToCharArray(); + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, new SecureRandom()); + DsaParameters dsaParams = pGen.GenerateParameters(); + DsaKeyGenerationParameters dsaKgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams); + IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + dsaKpg.Init(dsaKgp); + + + // + // this takes a while as the key generator has to Generate some DSA parameters + // before it Generates the key. + // + AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair(); + IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL"); + + BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + ElGamalParameters elParams = new ElGamalParameters(p, g); + ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams); + elgKpg.Init(elKgp); + + // + // this is quicker because we are using preGenerated parameters. + // + AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair(); + PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow); + PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow); + + PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair, + "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, new SecureRandom()); + + keyRingGen.AddSubKey(elgKeyPair); + + PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing(); + + keyRing.GetSecretKey().ExtractPrivateKey(passPhrase); + + PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing(); + + PgpPublicKey vKey = null; + PgpPublicKey sKey = null; + + foreach (PgpPublicKey pk in pubRing.GetPublicKeys()) + { + if (pk.IsMasterKey) + { + vKey = pk; + } + else + { + sKey = pk; + } + } + + foreach (PgpSignature sig in sKey.GetSignatures()) + { + if (sig.KeyId == vKey.KeyId + && sig.SignatureType == PgpSignature.SubkeyBinding) + { + sig.InitVerify(vKey); + + if (!sig.VerifyCertification(vKey, sKey)) + { + Fail("failed to verify sub-key signature."); + } + } + } + } + + [Test] + public void InsertMasterTest() + { + SecureRandom random = new SecureRandom(); + + char[] passPhrase = "hello".ToCharArray(); + IAsymmetricCipherKeyPairGenerator rsaKpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + + rsaKpg.Init(new KeyGenerationParameters(random, 512)); + + // + // this is quicker because we are using pregenerated parameters. + // + AsymmetricCipherKeyPair rsaKp = rsaKpg.GenerateKeyPair(); + PgpKeyPair rsaKeyPair1 = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, rsaKp, DateTime.UtcNow); + + rsaKp = rsaKpg.GenerateKeyPair(); + PgpKeyPair rsaKeyPair2 = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, rsaKp, DateTime.UtcNow); + + PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, + rsaKeyPair1, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random); + PgpSecretKeyRing secRing1 = keyRingGen.GenerateSecretKeyRing(); + PgpPublicKeyRing pubRing1 = keyRingGen.GeneratePublicKeyRing(); + + keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, + rsaKeyPair2, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random); + PgpSecretKeyRing secRing2 = keyRingGen.GenerateSecretKeyRing(); + PgpPublicKeyRing pubRing2 = keyRingGen.GeneratePublicKeyRing(); + + try + { + PgpPublicKeyRing.InsertPublicKey(pubRing1, pubRing2.GetPublicKey()); + Fail("adding second master key (public) should throw an ArgumentException"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("cannot add a master key to a ring that already has one")) + { + Fail("wrong message in public test"); + } + } + + try + { + PgpSecretKeyRing.InsertSecretKey(secRing1, secRing2.GetSecretKey()); + Fail("adding second master key (secret) should throw an ArgumentException"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("cannot add a master key to a ring that already has one")) + { + Fail("wrong message in secret test"); + } + } + } + + [Test] + public void GenerateSha1Test() + { + char[] passPhrase = "hello".ToCharArray(); + + IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, new SecureRandom()); + DsaParameters dsaParams = pGen.GenerateParameters(); + DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams); + dsaKpg.Init(kgp); + + // + // this takes a while as the key generator has to generate some DSA params + // before it generates the key. + // + AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair(); + + + IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL"); + + BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + ElGamalParameters elParams = new ElGamalParameters(p, g); + ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams); + elgKpg.Init(elKgp); + + // + // this is quicker because we are using preGenerated parameters. + // + AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair(); + + + PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow); + PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow); + + PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair, + "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, new SecureRandom()); + + keyRingGen.AddSubKey(elgKeyPair); + + PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing(); + + keyRing.GetSecretKey().ExtractPrivateKey(passPhrase); + + PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing(); + + PgpPublicKey vKey = null; + PgpPublicKey sKey = null; + + foreach (PgpPublicKey pk in pubRing.GetPublicKeys()) + { + if (pk.IsMasterKey) + { + vKey = pk; + } + else + { + sKey = pk; + } + } + + foreach (PgpSignature sig in sKey.GetSignatures()) + { + if (sig.KeyId == vKey.KeyId + && sig.SignatureType == PgpSignature.SubkeyBinding) + { + sig.InitVerify(vKey); + + if (!sig.VerifyCertification(vKey, sKey)) + { + Fail("failed to verify sub-key signature."); + } + } + } + } + + [Test] + public void RewrapTest() + { + SecureRandom rand = new SecureRandom(); + + // Read the secret key rings + PgpSecretKeyRingBundle privRings = new PgpSecretKeyRingBundle( + new MemoryStream(rewrapKey, false)); + + foreach (PgpSecretKeyRing pgpPrivEnum in privRings.GetKeyRings()) + { + foreach (PgpSecretKey pgpKeyEnum in pgpPrivEnum.GetSecretKeys()) + { + // re-encrypt the key with an empty password + PgpSecretKeyRing pgpPriv = PgpSecretKeyRing.RemoveSecretKey(pgpPrivEnum, pgpKeyEnum); + PgpSecretKey pgpKey = PgpSecretKey.CopyWithNewPassword( + pgpKeyEnum, + rewrapPass, + null, + SymmetricKeyAlgorithmTag.Null, + rand); + pgpPriv = PgpSecretKeyRing.InsertSecretKey(pgpPriv, pgpKey); + + // this should succeed + PgpPrivateKey privTmp = pgpKey.ExtractPrivateKey(null); + } + } + } + + [Test] + public void PublicKeyRingWithX509Test() + { + checkPublicKeyRingWithX509(pubWithX509); + + PgpPublicKeyRing pubRing = new PgpPublicKeyRing(pubWithX509); + + checkPublicKeyRingWithX509(pubRing.GetEncoded()); + } + + [Test] + public void SecretKeyRingWithPersonalCertificateTest() + { + checkSecretKeyRingWithPersonalCertificate(secWithPersonalCertificate); + PgpSecretKeyRingBundle secRing = new PgpSecretKeyRingBundle(secWithPersonalCertificate); + checkSecretKeyRingWithPersonalCertificate(secRing.GetEncoded()); + } + + private void checkSecretKeyRingWithPersonalCertificate( + byte[] keyRing) + { + PgpSecretKeyRingBundle secCol = new PgpSecretKeyRingBundle(keyRing); + + int count = 0; + + foreach (PgpSecretKeyRing ring in secCol.GetKeyRings()) + { + IEnumerator e = ring.GetExtraPublicKeys().GetEnumerator(); + while (e.MoveNext()) + { + ++count; + } + } + + if (count != 1) + { + Fail("personal certificate data subkey not found - count = " + count); + } + } + + private void checkPublicKeyRingWithX509( + byte[] keyRing) + { + PgpPublicKeyRing pubRing = new PgpPublicKeyRing(keyRing); + IEnumerator en = pubRing.GetPublicKeys().GetEnumerator(); + + if (en.MoveNext()) + { + PgpPublicKey key = (PgpPublicKey) en.Current; + + IEnumerator sEn = key.GetSignatures().GetEnumerator(); + + if (sEn.MoveNext()) + { + PgpSignature sig = (PgpSignature) sEn.Current; + if (sig.KeyAlgorithm != PublicKeyAlgorithmTag.Experimental_1) + { + Fail("experimental signature not found"); + } + if (!AreEqual(sig.GetSignature(), Hex.Decode("000101"))) + { + Fail("experimental encoding check failed"); + } + } + else + { + Fail("no signature found"); + } + } + else + { + Fail("no key found"); + } + } + + public override void PerformTest() + { + PerformTest1(); + PerformTest2(); + PerformTest3(); + PerformTest4(); + PerformTest5(); + PerformTest6(); + + // NB: This was commented out in the original Java source + //PerformTest7(); + + PerformTest8(); + PerformTest9(); + PerformTest10(); + PerformTest11(); + + GenerateTest(); + GenerateSha1Test(); + RewrapTest(); + PublicKeyRingWithX509Test(); + SecretKeyRingWithPersonalCertificateTest(); + InsertMasterTest(); + } + + public override string Name + { + get { return "PgpKeyRingTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpKeyRingTest()); + } + } +} diff --git a/crypto/test/src/openpgp/test/PgpMarkerTest.cs b/crypto/test/src/openpgp/test/PgpMarkerTest.cs new file mode 100644 index 000000000..89be7cd52 --- /dev/null +++ b/crypto/test/src/openpgp/test/PgpMarkerTest.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + [TestFixture] + public class PgpMarkerTest + : SimpleTest + { + private static readonly byte[] message1 = Base64.Decode( + "qANQR1DBwU4DdrlXatQSHgoQCADWlhY3bWWaOTm4t2espRWPFQmETeinnieHce64" + + "lmEIFzaryEWeSdQc8XGfDzcb7sxq7b5b9Hm6OrACcCbSp2KGEJNG5kJmo2A16UPq" + + "JdK4xNelpJRh3KcJPv+N/9VJrMdj4C+DRnGNFg1hTQf3RKsX+ms2V0OBC5vGlOZY" + + "zX+XZz/7hl1PXVLN23u4npZI/1xETI2VtRoM76S6oykGXxMtT3+sGU1fAVEKVS45" + + "pyQHWbBqApkWrURq0xBqpVfDwOgGw09dJxt2igW9hjvNAd9tJiMGrMF5o2OLlub7" + + "c7FiK+dWLLcw+nx7Hl6FQmo9E8qyW8x1Cb78HjR/JXMgH/ngB/4gba6xX+s5TJkW" + + "H2Wpp5ePTw39EqHosUMrm05R+C0ha3EyyaJIvKj2WWmImKu5PWo1t37Pi6KHFNC3" + + "wsYJMRKnnNtd34luMTOgLpDcdgClzfp2p6EqHMoB7Uj3etlLmbN+vpGgz9qkLBRV" + + "7MpR1yE9qrZNeGgbkry6N31w5E7HoAHu5JNcwxgzbJoj2lI8uvs6Gf7fEoQOuAPE" + + "W/SGlfR2BdBPiJ1yErMElc2O8LVS0wTwwifHpEsMV+1ntl1EC5d052lo+6q7zNqD" + + "uYt1/2if6h9W9fe+S9mzr0ZAtxIN2ZGOFJJRnqzjDQ4siB9nnwr6YgvUVRSr/lQB" + + "hDTd0bmjyWacCt0PPMJWchO6A5tzqKUpTWSYibpdks80kLQogQHsJTZd/kpS0I6f" + + "gD0HYYlMssZwhg2J2TWwXDpDTgQ6mzFKbGSdOSk/deTJj2+EubzxaZcxZEocCJA8" + + "bppCj4kLBnCj1LjYx7A="); + + private static readonly byte[] message2 = Base64.Decode( + "qANQR1DBwU4DZlTzKj+E4aMQCADruFAojUIlHGcnswLIekvhbVnaHnbCt6Kp" + + "IL2zppmEIYJ9n1xCO1k+3Y5j9vNATbqCVWs1HD0aAL3PRI1eZ1l8GkIBCd2z" + + "tcZpSI/uyI/JCzVW2stCH0gpP2V7zcjk8HaIuBz4ZsyU9m7v6LwCDPB4CTrb" + + "Z5nn5Jm3eowonQsRL/3TpJtG+IjTaw29NbCBNNX8quM5LwfIsfWovqNv28r1" + + "aX8FsqoTRsWEfQ7dMV/swVGqv0PgKxqErdnZVJ2yOJqjLk+lBJT6zhqPijGV" + + "10pc68hdZxxLU1KZq25DAjS12xcAgagjRkOmYE/H1oEjGZlXfS4y/xQ7skHa" + + "HI+b04vECACTpQPwCXhxYiNWnf4XhJPONIGyrsXVtsTNwzOShFPmeUvpipP4" + + "HknakBkBuUY49xcffQogW/NlGCZnQOulDLE6fCH/krkSmI8WVP5Vhf6bM1Qm" + + "92dHZFoTrrcQ9NVGaCNHHWf7KXkNfKdTkE23LdggoVrVAzO4WcdqVc6s/or7" + + "jQYP9zXLeu8+GGFMxe/9FCtoIWbujGQHsdDEkCK4h+D44EVDPzbvWj39ZB4w" + + "hHoab8RLHd7njcrPeoCPdYkFVCKOSuLdxxYZDbbmgpISaafrafwefkkESeGu" + + "JzbNhmyS8zfOiejWzndaLYWUSE/sqISK9Pg+xKundnFPk04+AhIRyYEoUjG3" + + "LgGVyM49mrM8E7QwAGU0m/VCJLoOu+N74Z1rp1wFdA5yCllFlONNM4Czhd1D" + + "ZMyLFqGXiKlyVCPlUTN2uVisYQGr6iNGYSPxpKjwiAzdeeQBPOETG0vd3nTO" + + "MN4BMKcG+kRJd5FU72SRfmbGwPPjd1gts9xFvtj4Tvpkam8="); + + public override void PerformTest() + { + // + // test encrypted message + // + PgpObjectFactory pgpFact = new PgpObjectFactory(message1); + + if (pgpFact.NextPgpObject() is PgpMarker) + { + if (pgpFact.NextPgpObject() is PgpEncryptedDataList) + { + return; + } + else + { + Fail("error processing after marker."); + } + } + + // TODO Does this even get called? + pgpFact = new PgpObjectFactory(message2); + + if (pgpFact.NextPgpObject() is PgpMarker) + { + if (!(pgpFact.NextPgpObject() is PgpEncryptedDataList)) + { + return; + } + else + { + Fail("error processing after marker."); + } + } + } + + public override string Name + { + get { return "PgpMarkerTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PgpMarkerTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openpgp/test/RegressionTest.cs b/crypto/test/src/openpgp/test/RegressionTest.cs new file mode 100644 index 000000000..d74c5d483 --- /dev/null +++ b/crypto/test/src/openpgp/test/RegressionTest.cs @@ -0,0 +1,34 @@ +using System; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests +{ + public class RegressionTest + { + public static ITest[] tests = + { + new PgpKeyRingTest(), + new PgpRsaTest(), + new PgpDsaTest(), + new PgpDsaElGamalTest(), + new PgpPbeTest(), + new PgpMarkerTest(), + new PgpPacketTest(), + new PgpArmoredTest(), + new PgpSignatureTest(), + new PgpClearSignedSignatureTest(), + new PgpCompressionTest() + }; + + public static void Main( + string[] args) + { + foreach (ITest test in tests) + { + ITestResult result = test.Perform(); + Console.WriteLine(result); + } + } + } +} diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs new file mode 100644 index 000000000..921208179 --- /dev/null +++ b/crypto/test/src/openssl/test/AllTests.cs @@ -0,0 +1,133 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.OpenSsl.Tests +{ + [TestFixture] + public class AllTests + { + private class Password + : IPasswordFinder + { + private readonly char[] password; + + public Password( + char[] word) + { + this.password = (char[]) word.Clone(); + } + + public char[] GetPassword() + { + return (char[]) password.Clone(); + } + } + + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OpenSSL Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] + public void TestOpenSsl() + { + Org.BouncyCastle.Utilities.Test.ITest[] tests = new Org.BouncyCastle.Utilities.Test.ITest[]{ + new ReaderTest(), + new WriterTest() + }; + + foreach (Org.BouncyCastle.Utilities.Test.ITest test in tests) + { + SimpleTestResult result = (SimpleTestResult)test.Perform(); + + if (!result.IsSuccessful()) + { + Assert.Fail(result.ToString()); + } + } + } + + [Test] + public void TestPkcs8Encrypted() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); + + AsymmetricKeyParameter privKey = kpGen.GenerateKeyPair().Private; + + // FIXME see PbeUtilities and Pkcs8Generator +// EncryptedTest(privKey, Pkcs8Generator.Aes256Cbc); +// EncryptedTest(privKey, Pkcs8Generator.Des3Cbc); + EncryptedTest(privKey, Pkcs8Generator.PbeSha1_3DES); + } + + private void EncryptedTest(AsymmetricKeyParameter privKey, string algorithm) + { + StringWriter sw = new StringWriter(); + PemWriter pWrt = new PemWriter(sw); + Pkcs8Generator pkcs8 = new Pkcs8Generator(privKey, algorithm); + pkcs8.Password = "hello".ToCharArray(); + + pWrt.WriteObject(pkcs8); + pWrt.Writer.Close(); + + String result = sw.ToString(); + + PemReader pRd = new PemReader(new StringReader(result), new Password("hello".ToCharArray())); + + AsymmetricKeyParameter rdKey = (AsymmetricKeyParameter)pRd.ReadObject(); + pRd.Reader.Close(); + + Assert.AreEqual(privKey, rdKey); + } + + [Test] + public void TestPkcs8Plain() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); + + AsymmetricKeyParameter privKey = kpGen.GenerateKeyPair().Private; + + StringWriter sw = new StringWriter(); + PemWriter pWrt = new PemWriter(sw); + + Pkcs8Generator pkcs8 = new Pkcs8Generator(privKey); + pWrt.WriteObject(pkcs8); + pWrt.Writer.Close(); + + string result = sw.ToString(); + + PemReader pRd = new PemReader(new StringReader(result), new Password("hello".ToCharArray())); + + AsymmetricKeyParameter rdKey = (AsymmetricKeyParameter)pRd.ReadObject(); + pRd.Reader.Close(); + + Assert.AreEqual(privKey, rdKey); + } + + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + Suite.Run(el); + } + } +} diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs new file mode 100644 index 000000000..d27ed742f --- /dev/null +++ b/crypto/test/src/openssl/test/ReaderTest.cs @@ -0,0 +1,380 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.OpenSsl.Tests +{ + /** + * basic class for reading test.pem - the password is "secret" + */ + [TestFixture] + public class ReaderTest + : SimpleTest + { + private class Password + : IPasswordFinder + { + private readonly char[] password; + + public Password( + char[] word) + { + this.password = (char[]) word.Clone(); + } + + public char[] GetPassword() + { + return (char[]) password.Clone(); + } + } + + public override string Name + { + get { return "PEMReaderTest"; } + } + + public override void PerformTest() + { + IPasswordFinder pGet = new Password("secret".ToCharArray()); + PemReader pemRd = OpenPemResource("test.pem", pGet); + AsymmetricCipherKeyPair pair; + + object o; + while ((o = pemRd.ReadObject()) != null) + { +// if (o is AsymmetricCipherKeyPair) +// { +// ackp = (AsymmetricCipherKeyPair)o; +// +// Console.WriteLine(ackp.Public); +// Console.WriteLine(ackp.Private); +// } +// else +// { +// Console.WriteLine(o.ToString()); +// } + } + + // + // pkcs 7 data + // + pemRd = OpenPemResource("pkcs7.pem", null); + + ContentInfo d = (ContentInfo)pemRd.ReadObject(); + + if (!d.ContentType.Equals(CmsObjectIdentifiers.EnvelopedData)) + { + Fail("failed envelopedData check"); + } + + /* + { + // + // ECKey + // + pemRd = OpenPemResource("eckey.pem", null); + + // TODO Resolve return type issue with EC keys and fix PemReader to return parameters +// ECNamedCurveParameterSpec spec = (ECNamedCurveParameterSpec)pemRd.ReadObject(); + + pair = (AsymmetricCipherKeyPair)pemRd.ReadObject(); + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); + + sgr.Init(true, pair.Private); + + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, pair.Public); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("EC verification failed"); + } + + // TODO Resolve this issue with the algorithm name, study Java version +// if (!((ECPublicKeyParameters) pair.Public).AlgorithmName.Equals("ECDSA")) +// { +// Fail("wrong algorithm name on public got: " + ((ECPublicKeyParameters) pair.Public).AlgorithmName); +// } +// +// if (!((ECPrivateKeyParameters) pair.Private).AlgorithmName.Equals("ECDSA")) +// { +// Fail("wrong algorithm name on private got: " + ((ECPrivateKeyParameters) pair.Private).AlgorithmName); +// } + } + */ + + // + // writer/parser test + // + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), + new SecureRandom(), + 768, + 25)); + + pair = kpGen.GenerateKeyPair(); + + keyPairTest("RSA", pair); + +// kpGen = KeyPairGenerator.getInstance("DSA"); +// kpGen.initialize(512, new SecureRandom()); + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, new SecureRandom()); + + kpGen = GeneratorUtilities.GetKeyPairGenerator("DSA"); + kpGen.Init( + new DsaKeyGenerationParameters( + new SecureRandom(), + pGen.GenerateParameters())); + + pair = kpGen.GenerateKeyPair(); + + keyPairTest("DSA", pair); + + // + // PKCS7 + // + MemoryStream bOut = new MemoryStream(); + PemWriter pWrt = new PemWriter(new StreamWriter(bOut)); + + pWrt.WriteObject(d); + pWrt.Writer.Close(); + + pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false))); + d = (ContentInfo)pemRd.ReadObject(); + + if (!d.ContentType.Equals(CmsObjectIdentifiers.EnvelopedData)) + { + Fail("failed envelopedData recode check"); + } + + + // OpenSSL test cases (as embedded resources) + doOpenSslDsaTest("unencrypted"); + doOpenSslRsaTest("unencrypted"); + + doOpenSslTests("aes128"); + doOpenSslTests("aes192"); + doOpenSslTests("aes256"); + doOpenSslTests("blowfish"); + doOpenSslTests("des1"); + doOpenSslTests("des2"); + doOpenSslTests("des3"); + doOpenSslTests("rc2_128"); + + doOpenSslDsaTest("rc2_40_cbc"); + doOpenSslRsaTest("rc2_40_cbc"); + doOpenSslDsaTest("rc2_64_cbc"); + doOpenSslRsaTest("rc2_64_cbc"); + + // TODO Figure out why exceptions differ for commented out cases + doDudPasswordTest("7fd98", 0, "Corrupted stream - out of bounds length found"); + doDudPasswordTest("ef677", 1, "Corrupted stream - out of bounds length found"); +// doDudPasswordTest("800ce", 2, "cannot recognise object in stream"); + doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56"); + doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28"); + doDudPasswordTest("2ac3b9", 5, "DER length more than 4 bytes: 11"); + doDudPasswordTest("2cba96", 6, "DEF length 100 object truncated by 35"); + doDudPasswordTest("2e3354", 7, "DEF length 42 object truncated by 9"); + doDudPasswordTest("2f4142", 8, "DER length more than 4 bytes: 14"); + doDudPasswordTest("2fe9bb", 9, "DER length more than 4 bytes: 65"); + doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57"); + doDudPasswordTest("41af75", 11, "malformed sequence in DSA private key"); + doDudPasswordTest("1704a5", 12, "corrupted stream detected"); +// doDudPasswordTest("1c5822", 13, "corrupted stream detected"); +// doDudPasswordTest("5a3d16", 14, "corrupted stream detected"); + doDudPasswordTest("8d0c97", 15, "corrupted stream detected"); + doDudPasswordTest("bc0daf", 16, "corrupted stream detected"); + doDudPasswordTest("aaf9c4d",17, "Corrupted stream - out of bounds length found"); + + // encrypted private key test + pGet = new Password("password".ToCharArray()); + pemRd = OpenPemResource("enckey.pem", pGet); + + RsaPrivateCrtKeyParameters privKey = (RsaPrivateCrtKeyParameters)pemRd.ReadObject(); + + if (!privKey.PublicExponent.Equals(new BigInteger("10001", 16))) + { + Fail("decryption of private key data check failed"); + } + + // general PKCS8 test + pGet = new Password("password".ToCharArray()); + pemRd = OpenPemResource("pkcs8test.pem", pGet); + + while ((privKey = (RsaPrivateCrtKeyParameters)pemRd.ReadObject()) != null) + { + if (!privKey.PublicExponent.Equals(new BigInteger("10001", 16))) + { + Fail("decryption of private key data check failed"); + } + } + } + + private void keyPairTest( + string name, + AsymmetricCipherKeyPair pair) + { + MemoryStream bOut = new MemoryStream(); + PemWriter pWrt = new PemWriter(new StreamWriter(bOut)); + + pWrt.WriteObject(pair.Public); + pWrt.Writer.Close(); + + PemReader pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false))); + + AsymmetricKeyParameter pubK = (AsymmetricKeyParameter) pemRd.ReadObject(); + if (!pubK.Equals(pair.Public)) + { + Fail("Failed public key read: " + name); + } + + bOut = new MemoryStream(); + pWrt = new PemWriter(new StreamWriter(bOut)); + + pWrt.WriteObject(pair.Private); + pWrt.Writer.Close(); + + pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false))); + + AsymmetricCipherKeyPair kPair = (AsymmetricCipherKeyPair) pemRd.ReadObject(); + if (!kPair.Private.Equals(pair.Private)) + { + Fail("Failed private key read: " + name); + } + + if (!kPair.Public.Equals(pair.Public)) + { + Fail("Failed private key public read: " + name); + } + } + + private void doOpenSslTests( + string baseName) + { + doOpenSslDsaModesTest(baseName); + doOpenSslRsaModesTest(baseName); + } + + private void doOpenSslDsaModesTest( + string baseName) + { + doOpenSslDsaTest(baseName + "_cbc"); + doOpenSslDsaTest(baseName + "_cfb"); + doOpenSslDsaTest(baseName + "_ecb"); + doOpenSslDsaTest(baseName + "_ofb"); + } + + private void doOpenSslRsaModesTest( + string baseName) + { + doOpenSslRsaTest(baseName + "_cbc"); + doOpenSslRsaTest(baseName + "_cfb"); + doOpenSslRsaTest(baseName + "_ecb"); + doOpenSslRsaTest(baseName + "_ofb"); + } + + private void doOpenSslDsaTest( + string name) + { + string fileName = "dsa.openssl_dsa_" + name + ".pem"; + + doOpenSslTestFile(fileName, typeof(DsaPrivateKeyParameters)); + } + + private void doOpenSslRsaTest( + string name) + { + string fileName = "rsa.openssl_rsa_" + name + ".pem"; + + doOpenSslTestFile(fileName, typeof(RsaPrivateCrtKeyParameters)); + } + + private void doOpenSslTestFile( + string fileName, + Type expectedPrivKeyType) + { + PemReader pr = OpenPemResource(fileName, new Password("changeit".ToCharArray())); + AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair; + pr.Reader.Close(); + + if (kp == null) + { + Fail("Didn't find OpenSSL key"); + } + + if (!expectedPrivKeyType.IsInstanceOfType(kp.Private)) + { + Fail("Returned key not of correct type"); + } + } + + private void doDudPasswordTest(string password, int index, string message) + { + // illegal state exception check - in this case the wrong password will + // cause an underlying class cast exception. + try + { + IPasswordFinder pGet = new Password(password.ToCharArray()); + PemReader pemRd = OpenPemResource("test.pem", pGet); + + Object o; + while ((o = pemRd.ReadObject()) != null) + { + } + + Fail("issue not detected: " + index); + } + catch (IOException e) + { + if (e.Message.IndexOf(message) < 0) + { + Console.Error.WriteLine(message); + Console.Error.WriteLine(e.Message); + Fail("issue " + index + " exception thrown, but wrong message"); + } + } + } + + private static PemReader OpenPemResource( + string fileName, + IPasswordFinder pGet) + { + Stream data = GetTestDataAsStream("openssl." + fileName); + TextReader tr = new StreamReader(data); + return new PemReader(tr, pGet); + } + + public static void Main( + string[] args) + { + RunTest(new ReaderTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/openssl/test/WriterTest.cs b/crypto/test/src/openssl/test/WriterTest.cs new file mode 100644 index 000000000..41f371708 --- /dev/null +++ b/crypto/test/src/openssl/test/WriterTest.cs @@ -0,0 +1,185 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.IO.Pem; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.OpenSsl.Tests +{ + [TestFixture] + public class WriterTest + : SimpleTest + { + private static readonly SecureRandom random = new SecureRandom(); + + // TODO Replace with a randomly generated key each test run? + private static readonly RsaPrivateCrtKeyParameters testRsaKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + private static readonly DsaParameters testDsaParams = new DsaParameters( + new BigInteger("7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673"), + new BigInteger("1138656671590261728308283492178581223478058193247"), + new BigInteger("4182906737723181805517018315469082619513954319976782448649747742951189003482834321192692620856488639629011570381138542789803819092529658402611668375788410")); + +// private static readonly PKCS8EncodedKeySpec testEcDsaKeySpec = new PKCS8EncodedKeySpec( +// Base64.Decode("MIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMr" + +// "jAwPp9R+KMUEhB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus+w2sY8OIPQQWGb5i5LdAyi" + +// "/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2dno1GMols5497in5gL5+zn0yMsRtyv5o=") +// ); + private static readonly byte[] testEcDsaKeyBytes = Base64.Decode( + "MIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMr" + + "jAwPp9R+KMUEhB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus+w2sY8OIPQQWGb5i5LdAyi" + + "/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2dno1GMols5497in5gL5+zn0yMsRtyv5o="); + + private static readonly char[] testPassword = "bouncy".ToCharArray(); + + private static readonly string[] algorithms = new string[] + { + "AES-128-CBC", "AES-128-CFB", "AES-128-ECB", "AES-128-OFB", + "AES-192-CBC", "AES-192-CFB", "AES-192-ECB", "AES-192-OFB", + "AES-256-CBC", "AES-256-CFB", "AES-256-ECB", "AES-256-OFB", + "BF-CBC", "BF-CFB", "BF-ECB", "BF-OFB", + "DES-CBC", "DES-CFB", "DES-ECB", "DES-OFB", + "DES-EDE", "DES-EDE-CBC", "DES-EDE-CFB", "DES-EDE-ECB", "DES-EDE-OFB", + "DES-EDE3", "DES-EDE3-CBC", "DES-EDE3-CFB", "DES-EDE3-ECB", "DES-EDE3-OFB", + "RC2-CBC", "RC2-CFB", "RC2-ECB", "RC2-OFB", + "RC2-40-CBC", + "RC2-64-CBC", + }; + + private class Password + : IPasswordFinder + { + private readonly char[] password; + + public Password( + char[] word) + { + this.password = (char[]) word.Clone(); + } + + public char[] GetPassword() + { + return (char[]) password.Clone(); + } + } + + public override string Name + { + get { return "PEMWriterTest"; } + } + + public override void PerformTest() + { + IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA"); + dsaKpg.Init(new DsaKeyGenerationParameters(random, testDsaParams)); + AsymmetricCipherKeyPair testDsaKp = dsaKpg.GenerateKeyPair(); + AsymmetricKeyParameter testDsaKey = testDsaKp.Private; + + doWriteReadTest(testDsaKey); + doWriteReadTests(testDsaKey, algorithms); + + doWriteReadTest(testRsaKey); + doWriteReadTests(testRsaKey, algorithms); + + AsymmetricKeyParameter ecPriv = PrivateKeyFactory.CreateKey(testEcDsaKeyBytes); + doWriteReadTest(ecPriv); + doWriteReadTests(ecPriv, algorithms); + + IAsymmetricCipherKeyPairGenerator ecKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + ecKpg.Init(new KeyGenerationParameters(random, 239)); + ecPriv = ecKpg.GenerateKeyPair().Private; + doWriteReadTest(ecPriv); + doWriteReadTests(ecPriv, algorithms); + + // override test + PemWriter pWrt = new PemWriter(new StringWriter()); + + object o = new PemObject("FRED", new byte[100]); + pWrt.WriteObject(o); + + pWrt.Writer.Close(); + } + + private void doWriteReadTests( + AsymmetricKeyParameter akp, + string[] algorithms) + { + foreach (string algorithm in algorithms) + { + doWriteReadTest(akp, algorithm); + } + } + + private void doWriteReadTest( + AsymmetricKeyParameter akp) + { + StringWriter sw = new StringWriter(); + PemWriter pw = new PemWriter(sw); + + pw.WriteObject(akp); + pw.Writer.Close(); + + string data = sw.ToString(); + + PemReader pr = new PemReader(new StringReader(data)); + + AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair; + + if (kp == null || !kp.Private.Equals(akp)) + { + Fail("Failed to read back test key"); + } + } + + private void doWriteReadTest( + AsymmetricKeyParameter akp, + string algorithm) + { + StringWriter sw = new StringWriter(); + PemWriter pw = new PemWriter(sw); + + pw.WriteObject(akp, algorithm, testPassword, random); + pw.Writer.Close(); + + string data = sw.ToString(); + + PemReader pr = new PemReader(new StringReader(data), new Password(testPassword)); + + AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair; + + if (kp == null || !kp.Private.Equals(akp)) + { + Fail("Failed to read back test key encoded with: " + algorithm); + } + } + + public static void Main( + string[] args) + { + RunTest(new WriterTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/pkcs/examples/PKCS12Example.cs b/crypto/test/src/pkcs/examples/PKCS12Example.cs new file mode 100644 index 000000000..002e14c38 --- /dev/null +++ b/crypto/test/src/pkcs/examples/PKCS12Example.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Pkcs.Examples +{ + /** + * Example of how to set up a certificate chain and a PKCS 12 store for + * a private individual - obviously you'll need to generate your own keys, + * and you may need to add a NetscapeCertType extension or add a key + * usage extension depending on your application, but you should get the + * idea! As always this is just an example... + */ + public class Pkcs12Example + { + private static readonly char[] passwd = "hello world".ToCharArray(); + + private static readonly X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator(); + private static readonly X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + /** + * we generate the CA's certificate + */ + public static X509CertificateEntry CreateMasterCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey) + { + // + // signers name + // + string issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; + + // + // subjects name - the same as we are self signed. + // + string subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; + + // + // create the certificate - version 1 + // + + v1CertGen.SetSerialNumber(BigInteger.One); + v1CertGen.SetIssuerDN(new X509Name(issuer)); + v1CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1)); + v1CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1)); + v1CertGen.SetSubjectDN(new X509Name(subject)); + v1CertGen.SetPublicKey(pubKey); + v1CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + X509Certificate cert = v1CertGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + +// PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; + IDictionary bagAttr = new Hashtable(); + + // + // this is actually optional - but if you want to have control + // over setting the friendly name this is the way to do it... + // +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_friendlyName, +// new DERBMPString("Bouncy Primary Certificate")); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id, + new DerBmpString("Bouncy Primary Certificate")); + + return new X509CertificateEntry(cert, bagAttr); + } + + /** + * we generate an intermediate certificate signed by our CA + */ + public static X509CertificateEntry CreateIntermediateCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter caPrivKey, + X509Certificate caCert) + { + // + // subject name table. + // + IDictionary attrs = new Hashtable(); + IList order = new ArrayList(); + + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.OU, "Bouncy Intermediate Certificate"); + attrs.Add(X509Name.EmailAddress, "feedback-crypto@bouncycastle.org"); + + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.OU); + order.Add(X509Name.EmailAddress); + + // + // create the certificate - version 3 + // + v3CertGen.Reset(); + + v3CertGen.SetSerialNumber(BigInteger.Two); + v3CertGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert)); + v3CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1)); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1)); + v3CertGen.SetSubjectDN(new X509Name(order, attrs)); + v3CertGen.SetPublicKey(pubKey); + v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + // + // extensions + // + v3CertGen.AddExtension( + X509Extensions.SubjectKeyIdentifier, + false, + new SubjectKeyIdentifierStructure(pubKey)); + + v3CertGen.AddExtension( + X509Extensions.AuthorityKeyIdentifier, + false, + new AuthorityKeyIdentifierStructure(caCert)); + + v3CertGen.AddExtension( + X509Extensions.BasicConstraints, + true, + new BasicConstraints(0)); + + X509Certificate cert = v3CertGen.Generate(caPrivKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(caCert.GetPublicKey()); + +// PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; + IDictionary bagAttr = new Hashtable(); + + // + // this is actually optional - but if you want to have control + // over setting the friendly name this is the way to do it... + // +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_friendlyName, +// new DERBMPString("Bouncy Intermediate Certificate")); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id, + new DerBmpString("Bouncy Intermediate Certificate")); + + return new X509CertificateEntry(cert, bagAttr); + } + + /** + * we generate a certificate signed by our CA's intermediate certficate + */ + public static X509CertificateEntry CreateCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter caPrivKey, + AsymmetricKeyParameter caPubKey) + { + // + // signers name table. + // + IDictionary sAttrs = new Hashtable(); + IList sOrder = new ArrayList(); + + sAttrs.Add(X509Name.C, "AU"); + sAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + sAttrs.Add(X509Name.OU, "Bouncy Intermediate Certificate"); + sAttrs.Add(X509Name.EmailAddress, "feedback-crypto@bouncycastle.org"); + + sOrder.Add(X509Name.C); + sOrder.Add(X509Name.O); + sOrder.Add(X509Name.OU); + sOrder.Add(X509Name.EmailAddress); + + // + // subjects name table. + // + IDictionary attrs = new Hashtable(); + IList order = new ArrayList(); + + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.CN, "Eric H. Echidna"); + attrs.Add(X509Name.EmailAddress, "feedback-crypto@bouncycastle.org"); + + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.CN); + order.Add(X509Name.EmailAddress); + + // + // create the certificate - version 3 + // + v3CertGen.Reset(); + + v3CertGen.SetSerialNumber(BigInteger.Three); + v3CertGen.SetIssuerDN(new X509Name(sOrder, sAttrs)); + v3CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1)); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1)); + v3CertGen.SetSubjectDN(new X509Name(order, attrs)); + v3CertGen.SetPublicKey(pubKey); + v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + // + // add the extensions + // + v3CertGen.AddExtension( + X509Extensions.SubjectKeyIdentifier, + false, + new SubjectKeyIdentifierStructure(pubKey)); + + v3CertGen.AddExtension( + X509Extensions.AuthorityKeyIdentifier, + false, + new AuthorityKeyIdentifierStructure(caPubKey)); + + X509Certificate cert = v3CertGen.Generate(caPrivKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(caPubKey); + +// PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; + IDictionary bagAttr = new Hashtable(); + + // + // this is also optional - in the sense that if you leave this + // out the keystore will add it automatically, note though that + // for the browser to recognise the associated private key this + // you should at least use the pkcs_9_localKeyId OID and set it + // to the same as you do for the private key's localKeyId. + // +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_friendlyName, +// new DERBMPString("Eric's Key")); +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_localKeyId, +// new SubjectKeyIdentifierStructure(pubKey)); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id, + new DerBmpString("Eric's Key")); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id, + new SubjectKeyIdentifierStructure(pubKey)); + + return new X509CertificateEntry(cert, bagAttr); + } + + public static void Main( + string[] args) + { +// Security.addProvider(new BouncyCastleProvider()); + + // + // personal keys + // +// RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( + RsaKeyParameters pubKey = new RsaKeyParameters(false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + +// RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( + RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + // + // intermediate keys. + // +// RSAPublicKeySpec intPubKeySpec = new RSAPublicKeySpec( + RsaKeyParameters intPubKey = new RsaKeyParameters(false, + new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), + new BigInteger("ffff", 16)); + + +// RSAPrivateCrtKeySpec intPrivKeySpec = new RSAPrivateCrtKeySpec( + RsaPrivateCrtKeyParameters intPrivKey = new RsaPrivateCrtKeyParameters( + new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), + new BigInteger("ffff", 16), + new BigInteger("7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff", 16), + new BigInteger("ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649", 16), + new BigInteger("97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721", 16), + new BigInteger("6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f", 16), + new BigInteger("70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f", 16), + new BigInteger("e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d", 16)); + + // + // ca keys + // +// RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec( + RsaKeyParameters caPubKey = new RsaKeyParameters(false, + new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), + new BigInteger("11", 16)); + +// RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec( + RsaPrivateCrtKeyParameters caPrivKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), + new BigInteger("11", 16), + new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16), + new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16), + new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16), + new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16), + new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16), + new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16)); + + + + // + // set up the keys + // +// KeyFactory fact = KeyFactory.getInstance("RSA", "BC"); +// PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec); +// PublicKey caPubKey = fact.generatePublic(caPubKeySpec); +// PrivateKey intPrivKey = fact.generatePrivate(intPrivKeySpec); +// PublicKey intPubKey = fact.generatePublic(intPubKeySpec); +// PrivateKey privKey = fact.generatePrivate(privKeySpec); +// PublicKey pubKey = fact.generatePublic(pubKeySpec); + + X509CertificateEntry[] chain = new X509CertificateEntry[3]; + + chain[2] = CreateMasterCert(caPubKey, caPrivKey); + chain[1] = CreateIntermediateCert(intPubKey, caPrivKey, chain[2].Certificate); + chain[0] = CreateCert(pubKey, intPrivKey, intPubKey); + + // + // add the friendly name for the private key + // +// PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; + IDictionary bagAttr = new Hashtable(); + + // + // this is also optional - in the sense that if you leave this + // out the keystore will add it automatically, note though that + // for the browser to recognise which certificate the private key + // is associated with you should at least use the pkcs_9_localKeyId + // OID and set it to the same as you do for the private key's + // corresponding certificate. + // +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_friendlyName, +// new DERBMPString("Eric's Key")); +// bagAttr.setBagAttribute( +// PKCSObjectIdentifiers.pkcs_9_at_localKeyId, +// new SubjectKeyIdentifierStructure(pubKey)); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id, + new DerBmpString("Eric's Key")); + bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id, + new SubjectKeyIdentifierStructure(pubKey)); + + // + // store the key and the certificate chain + // +// KeyStore store = KeyStore.getInstance("PKCS12", "BC"); +// store.load(null, null); + Pkcs12Store store = new Pkcs12StoreBuilder().Build(); + + // + // if you haven't set the friendly name and local key id above + // the name below will be the name of the key + // + store.SetKeyEntry("Eric's Key", new AsymmetricKeyEntry(privKey, bagAttr), chain); + +// FileOutputStream fOut = new FileOutputStream("id.p12"); +// +// store.store(fOut, passwd); + FileStream fOut = File.Create("id.p12"); + store.Save(fOut, passwd, new SecureRandom()); + fOut.Close(); + } + } +} diff --git a/crypto/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs b/crypto/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs new file mode 100644 index 000000000..a41c99266 --- /dev/null +++ b/crypto/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs @@ -0,0 +1,92 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Pkcs.Tests +{ + [TestFixture] + public class EncryptedPrivateKeyInfoTest + : SimpleTest + { + private readonly string alg = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id; // 3 key triple DES with SHA-1 + + public override string Name + { + get { return "EncryptedPrivateKeyInfoTest"; } + } + + public override void PerformTest() + { + IAsymmetricCipherKeyPairGenerator pGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + // + // set up the parameters + // + byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int iterationCount = 100; + + // + // set up the key + // + char[] password1 = { 'h', 'e', 'l', 'l', 'o' }; + + EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(alg, password1, salt, iterationCount, PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private)); + + PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password1, encInfo); + + AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(info); + + if (!key.Equals(pair.Private)) + { + Fail("Key corrupted"); + } + + doOpensslTestKeys(); + } + + private void doOpensslTestKeys() + { + string[] names = GetTestDataEntries("keys"); + foreach (string name in names) + { +// Console.Write(name + " => "); + Stream data = GetTestDataAsStream(name); + AsymmetricKeyParameter key = PrivateKeyFactory.DecryptKey("12345678a".ToCharArray(), data); +// Console.WriteLine(key.GetType().Name); + if (!(key is RsaPrivateCrtKeyParameters)) + { + Fail("Sample key could not be decrypted: " + name); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new EncryptedPrivateKeyInfoTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/pkcs/test/PKCS10Test.cs b/crypto/test/src/pkcs/test/PKCS10Test.cs new file mode 100644 index 000000000..d0227b9de --- /dev/null +++ b/crypto/test/src/pkcs/test/PKCS10Test.cs @@ -0,0 +1,88 @@ +#region Using directives + +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Security; + +#endregion + +namespace Org.BouncyCastle.Pkcs.Tests +{ + [TestFixture] + public class Pkcs10Test + : SimpleTest + { + public override string Name + { + get { return "Pkcs10"; } + } + + public override void PerformTest() + { + IAsymmetricCipherKeyPairGenerator pGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25); + + pGen.Init(genParam); + + AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair(); + + IDictionary attrs = new Hashtable(); + + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.EmailAddress, "feedback-crypto@bouncycastle.org"); + + X509Name subject = new X509Name(new ArrayList(attrs.Keys), attrs); + + Pkcs10CertificationRequest req1 = new Pkcs10CertificationRequest( + "SHA1withRSA", + subject, + pair.Public, + null, + pair.Private); + + byte[] bytes = req1.GetEncoded(); + + Pkcs10CertificationRequest req2 = new Pkcs10CertificationRequest(bytes); + + if (!req2.Verify()) + { + Fail("Failed verify check."); + } + + if (!req2.GetPublicKey().Equals(req1.GetPublicKey())) + { + Fail("Failed public key check."); + } + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs10Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs new file mode 100644 index 000000000..c6b39135e --- /dev/null +++ b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs @@ -0,0 +1,921 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkcs.Tests +{ + /** + * Exercise the various key stores, making sure we at least get back what we put in! + *

    This tests both the PKCS12 key store.

    + */ + [TestFixture] + public class Pkcs12StoreTest + : SimpleTest + { + private static readonly char[] passwd = "hello world".ToCharArray(); + + // + // pkcs-12 pfx-pdu + // + private static readonly byte[] pkcs12 = Base64.Decode( + "MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZI" + + "hvcNAQcBBAGgBAGABAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCAzQEAQQEAQEE" + + "ATAEAQQEAQMEA4IDMAQBBAQBAQQBBgQBBAQBAQQBCwQBBAQBCwQLKoZIhvcN" + + "AQwKAQIEAQQEAQEEAaAEAQQEAQMEA4ICpQQBBAQBAQQBMAQBBAQBAwQDggKh" + + "BAEEBAEBBAEwBAEEBAEBBAEbBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoq" + + "hkiG9w0BDAEDBAEEBAEPBA8wDQQIoagiwNZPJR4CAQEEAQQEAQEEAQQEAQQE" + + "AQMEA4ICgAQBBAQDggKABIICgEPG0XlhMFyrs4ZWDrvEzl51ICfXd6K2ql2l" + + "nnxhszUbigtSj6x49VEx4PfOB9fQFeidc5L5An+nKp646NBMIY0UwXGs8BLQ" + + "au59jtOs987+l7QYIvl6fdGUIuLPhVSnZZDyqD+HQjU/0/ccKFHRif4tlEQq" + + "aErvZbFeH0pg4ijf1HfgX6gBJGRKdO+msa4qKGnZdHCSLZehyyxvxAmURetg" + + "yhtEl7RmedTB+4TDs7atekqxkNlD9tfwDUX6sb0IH6qbEA6P/DlVMdaD54Cl" + + "QDxRzOfIIjklZhv5OMFWtPK0aYPcqyxzLpw1qRAyoTVXpidkj/hpIpgCVBP/" + + "k5s2+WdGbLgA/4/zSrF6feRCE5llzM2IGxiHVq4oPzzngl3R+Fi5VCPDMcuW" + + "NRuIOzJA+RNV2NPOE/P3knThDnwiImq+rfxmvZ1u6T06s20RmWK6cxp7fTEw" + + "lQ9BOsv+mmyV8dr6cYJq4IlRzHdFOyEUBDwfHThyribNKKobO50xh2f93xYj" + + "Rn5UMOQBJIe3b7OKZt5HOIMrJSZO02IZgvImi9yQWi96PnWa419D1cAsLWvM" + + "xiN0HqZMbDFfxVM2BZmsxiexLhkHWKwLqfQDzRjJfmVww8fnXpWZhFXKyut9" + + "gMGEyCNoba4RU3QI/wHKWYaK74qtJpsucuLWBH6UcsHsCry6VZkwRxWwC0lb" + + "/F3Bm5UKHax5n9JHJ2amQm9zW3WJ0S5stpPObfmg5ArhbPY+pVOsTqBRlop1" + + "bYJLD/X8Qbs468Bwzej0FhoEU59ZxFrbjLSBsMUYrVrwD83JE9kEazMLVchc" + + "uCB9WT1g0hxYb7VA0BhOrWhL8F5ZH72RMCYLPI0EAQQEAQEEATEEAQQEAQEE" + + "AXgEAQQEAQEEATAEAQQEAQEEAVEEAQQEAQEEAQYEAQQEAQEEAQkEAQQEAQkE" + + "CSqGSIb3DQEJFAQBBAQBAQQBMQQBBAQBAQQBRAQBBAQBAQQBHgQBBAQBAQQB" + + "QgQBBAQBQgRCAEQAYQB2AGkAZAAgAEcALgAgAEgAbwBvAGsAJwBzACAAVgBl" + + "AHIAaQBTAGkAZwBuACwAIABJAG4AYwAuACAASQBEBAEEBAEBBAEwBAEEBAEB" + + "BAEjBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRUEAQQEAQEE" + + "ATEEAQQEAQEEARYEAQQEAQEEAQQEAQQEAQEEARQEAQQEARQEFKEcMJ798oZL" + + "FkH0OnpbUBnrTLgWBAIAAAQCAAAEAgAABAEwBAGABAEGBAEJBAkqhkiG9w0B" + + "BwYEAaAEAYAEATAEAYAEAQIEAQEEAQAEATAEAYAEAQYEAQkECSqGSIb3DQEH" + + "AQQBMAQBGwQBBgQBCgQKKoZIhvcNAQwBBgQPMA0ECEE7euvmxxwYAgEBBAGg" + + "BAGABAEEBAEIBAgQIWDGlBWxnwQBBAQBCAQI2WsMhavhSCcEAQQEAQgECPol" + + "uHJy9bm/BAEEBAEQBBCiRxtllKXkJS2anKD2q3FHBAEEBAEIBAjKy6BRFysf" + + "7gQBBAQDggMwBIIDMJWRGu2ZLZild3oz7UBdpBDUVMOA6eSoWiRIfVTo4++l" + + "RUBm8TpmmGrVkV32PEoLkoV+reqlyWCvqqSjRzi3epQiVwPQ6PV+ccLqxDhV" + + "pGWDRQ5UttDBC2+u4fUQVZi2Z1i1g2tsk6SzB3MKUCrjoWKvaDUUwXo5k9Vz" + + "qSLWCLTZCjs3RaY+jg3NbLZYtfMDdYovhCU2jMYV9adJ8MxxmJRz+zPWAJph" + + "LH8hhfkKG+wJOSszqk9BqGZUa/mnZyzeQSMTEFga1ZB/kt2e8SZFWrTZEBgJ" + + "oszsL5MObbwMDowNurnZsnS+Mf7xi01LeG0VT1fjd6rn9BzVwuMwhoqyoCNo" + + "ziUqSUyLEwnGTYYpvXLxzhNiYzW8546KdoEKDkEjhfYsc4XqSjm9NYy/BW/M" + + "qR+aL92j8hqnkrWkrWyvocUe3mWaiqt7/oOzNZiMTcV2dgjjh9HfnjSHjFGe" + + "CVhnEWzV7dQIVyc/qvNzOuND8X5IyJ28xb6a/i1vScwGuo/UDgPAaMjGw28f" + + "siOZBShzde0Kj82y8NilfYLHHeIGRW+N/grUFWhW25mAcBReXDd5JwOqM/eF" + + "y+4+zBzlO84ws88T1pkSifwtMldglN0APwr4hvUH0swfiqQOWtwyeM4t+bHd" + + "5buAlXOkSeF5rrLzZ2/Lx+JJmI2pJ/CQx3ej3bxPlx/BmarUGAxaI4le5go4" + + "KNfs4GV8U+dbEHQz+yDYL+ksYNs1eb+DjI2khbl28jhoeAFKBtu2gGOL5M9M" + + "CIP/JDOCHimu1YZRuOTAf6WISnG/0Ri3pYZsgQ0i4cXj+WfYwYVjhKX5AcDj" + + "UKnc4/Cxp+TbbgZqEKRcYVb2q0kOAxkeaNo3WCm+qvUYrwAmKp4nVB+/24rK" + + "khHiyYJQsETxtOEyvJkVxAS01djY4amuJ4jL0sYnXIhW3Ag93eavbzksGT7W" + + "Fg1ywpr1x1xpXWIIuVt1k4e+g9fy7Yx7rx0IK1qCSjNwU3QPWbaef1rp0Q/X" + + "P9IVXYkqo1g/T3SyXqrbZLO+sDjiG4IT3z3fJJqt81sRSVT0QN1ND8l93BG4" + + "QKzghYw8sZ4FwKPtLky1dDcVTgQBBAQBCAQIK/85VMKWDWYEAQQEAQgECGsO" + + "Q85CcFwPBAEEBAEIBAhaup6ot9XnQAQBBAQCgaAEgaCeCMadSm5fkLfhErYQ" + + "DgePZl/rrjP9FQ3VJZ13XrjTSjTRknAbXi0DEu2tvAbmCf0sdoVNuZIZ92W0" + + "iyaa2/A3RHA2RLPNQz5meTi1RE2N361yR0q181dC3ztkkJ8PLyd74nCtgPUX" + + "0JlsvLRrdSjPBpBQ14GiM8VjqeIY7EVFy3vte6IbPzodxaviuSc70iXM4Yko" + + "fQq6oaSjNBFRqkHrBAEEBAEIBAjlIvOf8SnfugQBBAQBCAQIutCF3Jovvl0E" + + "AQQEAQgECO7jxbucdp/3BAEEBAEIBAidxK3XDLj+BwQBBAQBCAQI3m/HMbd3" + + "TwwEAQQEA4ICOASCAjgtoCiMfTkjpCRuMhF5gNLRBiNv+xjg6GvZftR12qiJ" + + "dLeCERI5bvXbh9GD6U+DjTUfhEab/37TbiI7VOFzsI/R137sYy9Tbnu7qkSx" + + "u0bTvyXSSmio6sMRiWIcakmDbv+TDWR/xgtj7+7C6p+1jfUGXn/RjB3vlyjL" + + "Q9lFe5F84qkZjnADo66p9gor2a48fgGm/nkABIUeyzFWCiTp9v6FEzuBfeuP" + + "T9qoKSnCitaXRCru5qekF6L5LJHLNXLtIMSrbO0bS3hZK58FZAUVMaqawesJ" + + "e/sVfQip9x/aFQ6U3KlSpJkmZK4TAqp9jIfxBC8CclbuwmoXPMomiCH57ykr" + + "vkFHOGcxRcCxax5HySCwSyPDr8I4+6Kocty61i/1Xr4xJjb+3oyFStIpB24x" + + "+ALb0Mz6mUa1ls76o+iQv0VM2YFwnx+TC8KC1+O4cNOE/gKeh0ircenVX83h" + + "GNez8C5Ltg81g6p9HqZPc2pkwsneX2sJ4jMsjDhewV7TyyS3x3Uy3vTpZPek" + + "VdjYeVIcgAz8VLJOpsIjyHMB57AyT7Yj87hVVy//VODnE1T88tRXZb+D+fCg" + + "lj2weQ/bZtFzDX0ReiEQP6+yklGah59omeklIy9wctGV1o9GNZnGBSLvQ5NI" + + "61e9zmQTJD2iDjihvQA/6+edKswCjGRX6rMjRWXT5Jv436l75DVoUj09tgR9" + + "ytXSathCjQUL9MNXzUMtr7mgEUPETjM/kYBR7CNrsc+gWTWHYaSWuqKVBAEE" + + "BAEIBAh6slfZ6iqkqwQBBAQBCAQI9McJKl5a+UwEAQQEATgEOBelrmiYMay3" + + "q0OW2x2a8QQodYqdUs1TCUU4JhfFGFRy+g3yU1cP/9ZSI8gcI4skdPc31cFG" + + "grP7BAEEBAEIBAhzv/wSV+RBJQQBBAQBCAQI837ImVqqlr4EAQQEAQgECGeU" + + "gjULLnylBAEEBAEIBAjD3P4hlSBCvQQBBAQBCAQISP/qivIzf50EAQQEAQgE" + + "CKIDMX9PKxICBAEEBAOCBOgEggTocP5VVT1vWvpAV6koZupKN1btJ3C01dR6" + + "16g1zJ5FK5xL1PTdA0r6iAwVtgYdxQYnU8tht3bkNXdPJC1BdsC9oTkBg9Nr" + + "dqlF5cCzXWIezcR3ObjGLpXu49SAHvChH4emT5rytv81MYxZ7bGmlQfp8BNa" + + "0cMZz05A56LXw//WWDEzZcbKSk4tCsfMXBdGk/ngs7aILZ4FGM620PBPtD92" + + "pz2Ui/tUZqtQ0WKdLzwga1E/rl02a/x78/OdlVRNeaIYWJWLmLavX98w0PhY" + + "ha3Tbj/fqq+H3ua6Vv2Ff4VeXazkXpp4tTiqUxhc6aAGiRYckwZaP7OPSbos" + + "RKFlRLVofSGu1IVSKO+7faxV4IrVaAAzqRwLGkpJZLV7NkzkU1BwgvsAZAI4" + + "WClPDF228ygbhLwrSN2NK0s+5bKhTCNAR/LCUf3k7uip3ZSe18IwEkUMWiaZ" + + "ayktcTYn2ZjmfIfV7wIxHgWPkP1DeB+RMS7VZe9zEgJKOA16L+9SNBwJSSs9" + + "5Sb1+nmhquZmnAltsXMgwOrR12JLIgdfyyqGcNq997U0/KuHybqBVDVu0Fyr" + + "6O+q5oRmQZq6rju7h+Hb/ZUqRxRoTTSPjGD4Cu9vUqkoNVgwYOT+88FIMYun" + + "g9eChhio2kwPYwU/9BNGGzh+hAvAKcUpO016mGLImYin+FpQxodJXfpNCFpG" + + "4v4HhIwKh71OOfL6ocM/518dYwuU4Ds2/JrDhYYFsn+KprLftjrnTBnSsfYS" + + "t68b+Xr16qv9r6sseEkXbsaNbrGiZAhfHEVBOxQ4lchHrMp4zpduxG4crmpc" + + "+Jy4SadvS0uaJvADgI03DpsDYffUdriECUqAfOg/Hr7HHyr6Q9XMo1GfIarz" + + "eUHBgi1Ny0nDTWkdb7I3bIajG+Unr3KfK6dZz5Lb3g5NeclU5zintB1045Jr" + + "j9fvGGk0/2lG0n17QViBiOzGs2poTlhn7YxmiskwlkRKVafxPZNPxKILpN9s" + + "YaWGz93qER/pGMJarGJxu8sFi3+yt6FZ4pVPkvKE8JZMEPBBrmH41batS3sw" + + "sfnJ5CicAkwd8bluQpoc6qQd81HdNpS6u7djaRSDwPtYnZWu/8Hhj4DXisje" + + "FJBAjQdn2nK4MV7WKVwr+mNcVgOdc5IuOZbRLOfc3Sff6kYVuQFfcCGgAFpd" + + "nbprF/FnYXR/rghWE7fT1gfzSMNv+z5UjZ5Rtg1S/IQfUM/P7t0UqQ01/w58" + + "bTlMGihTxHiJ4Qf3o5GUzNmAyryLvID+nOFqxpr5es6kqSN4GPRHsmUIpB9t" + + "f9Nw952vhsXI9uVkhQap3JvmdAKJaIyDz6Qi7JBZvhxpghVIDh73BQTaAFP9" + + "5GUcPbYOYJzKaU5MeYEsorGoanSqPDeKDeZxjxJD4xFsqJCoutyssqIxnXUN" + + "Y3Uojbz26IJOhqIBLaUn6QVFX79buWYjJ5ZkDS7D8kq6DZeqZclt5711AO5U" + + "uz/eDSrx3d4iVHR+kSeopxFKsrK+KCH3CbBUMIFGX/GE9WPhDWCtjjNKEe8W" + + "PinQtxvv8MlqGXtv3v7ObJ2BmfIfLD0rh3EB5WuRNKL7Ssxaq14KZGEBvc7G" + + "Fx7jXLOW6ZV3SH+C3deJGlKM2kVhDdIVjjODvQzD8qw8a/ZKqDO5hGGKUTGD" + + "Psdd7O/k/Wfn+XdE+YuKIhcEAQQEAQgECJJCZNJdIshRBAEEBAEIBAiGGrlG" + + "HlKwrAQBBAQBCAQIkdvKinJYjJcEAQQEAUAEQBGiIgN/s1bvPQr+p1aQNh/X" + + "UQFmay6Vm5HIvPhoNrX86gmMjr6/sg28/WCRtSfyuYjwQkK91n7MwFLOBaU3" + + "RrsEAQQEAQgECLRqESFR50+zBAEEBAEIBAguqbAEWMTiPwQBBAQBGAQYKzUv" + + "EetQEAe3cXEGlSsY4a/MNTbzu1WbBAEEBAEIBAiVpOv1dOWZ1AQCAAAEAgAA" + + "BAIAAAQCAAAEAgAABAIAAAAAAAAAADA1MCEwCQYFKw4DAhoFAAQUvMkeVqe6" + + "D4UmMHGEQwcb8O7ZwhgEEGiX9DeqtRwQnVi+iY/6Re8AAA=="); + + private static readonly byte[] certUTF = Base64.Decode( + "MIIGVQIBAzCCBg8GCSqGSIb3DQEHAaCCBgAEggX8MIIF+DCCAsUGCSqGSIb3" + + "DQEHAaCCArYEggKyMIICrjCCAqoGCyqGSIb3DQEMCgEDoIIChTCCAoEGCiqG" + + "SIb3DQEJFgGgggJxBIICbTCCAmkwggHSoAMCAQICAQcwDQYJKoZIhvcNAQEF" + + "BQAwOTEPMA0GA1UEBxMGTGV1dmVuMRkwFwYDVQQKExBVdGltYWNvIFN1YiBD" + + "QSAyMQswCQYDVQQGEwJCRTAeFw05OTEyMzEyMzAwMDBaFw0xOTEyMzEyMzAw" + + "MDBaMFcxCzAJBgNVBAYTAkJFMQ8wDQYDVQQHEwZIYWFjaHQxEDAOBgNVBAoT" + + "B1V0aW1hY28xDDAKBgNVBAsMA1ImRDEXMBUGA1UEAxMOR2VlcnQgRGUgUHJp" + + "bnMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYGIyhTn/p0IA41ElLD" + + "fZ44PS88AAcDCiOd2DIMLck56ea+5nhI0JLyz1XgPHecc8SLFdl7vSIBA0eb" + + "tm/A7WIqIp0lcvgoyQ0qsak/dvzs+xw6r2xLCVogku4+/To6UebtfRsukXNI" + + "ckP5lWV/Ui4l+XvGdmENlEE9/BvOZIvLAgMBAAGjYzBhMBEGA1UdIwQKMAiA" + + "BlN1YkNBMjAQBgNVHQ4ECQQHVXNlcklEMjAOBgNVHQ8BAf8EBAMCBLAwGQYD" + + "VR0RBBIwEIEOVXNlcklEMkB1dGkuYmUwDwYDVR0TAQH/BAUwAwEBADANBgkq" + + "hkiG9w0BAQUFAAOBgQACS7iLLgMV4O5gFdriI7dqX55l7Qn6HiRNxlSH2kCX" + + "41X82gae4MHFc41qqsC4qm6KZWi1yvTN9XgSBCXTaw1SXGTK7SuNdoYh6ufC" + + "KuAwy5lsaetyARDksRiOIrNV9j+MRIjJMjPNg+S+ysIHTWZo2NTUuVuZ01D2" + + "jDtYPhcDFDESMBAGCSqGSIb3DQEJFTEDBAE3MIIDKwYJKoZIhvcNAQcGoIID" + + "HDCCAxgCAQAwggMRBgkqhkiG9w0BBwEwKAYKKoZIhvcNAQwBAzAaBBS5KxQC" + + "BMuZ1To+yed2j/TT45td6gICCACAggLYxQS+fu7W2sLQTkslI0EoNxLoH/WO" + + "L8NgiIgZ5temV3mgC2q0MxjVVq+SCvG89ZSTfptxOaSmYV772irFdzlrtotZ" + + "wmYk1axuFDYQ1gH0M6i9FWuhOnbk7qHclmOroXqrrbP6g3IsjwztH0+iwBCg" + + "39f63V0rr8DHiu7zZ2hBkU4/RHEsXLjaCBVNTUSssWhVLisLh2sqBJccPC2E" + + "1lw4c4WrshGQ+syLGG38ttFgXT1c+xYNpUKqJiJTLVouOH9kK3nH1hPRHKMN" + + "9CucBdUzibvkcRk1L53F3MfvjhCSNeWEmd9PKN+FtUtzRWQG3L84VGTM37Ws" + + "YcxaDwDFGcw3u1W8WFsCCkjpZecKN8P2Kp/ai/iugcXY77bYwAwpETDvQFvD" + + "nnL9oGi03HYdfeiXglC7x7dlojvnpkXDbE0nJiFwhe8Mxpx8GVlGHtP+siXg" + + "tklubg1eTCSoG9m1rsBJM717ZHXUGf32HNun2dn4vOWGocgBmokZ46KKMb9v" + + "reT39JTxi8Jlp+2cYb6Qr/oBzudR+D4iAiiVhhhEbJKPNHa61YyxF810fNI2" + + "GWlNIyN3KcI8XU6WJutm/0H3X8Y+iCSWrJ2exUktj8GiqNQ6Yx0YgEk9HI7W" + + "t9UVTIsPCgCqrV4SWCOPf6so1JqnpvlPvvNyNxSsAJ7DaJx1+oD2QQfhowk/" + + "bygkKnRo5Y15ThrTsIyQKsJHTIVy+6K5uFZnlT1DGV3DcNpuk3AY26hrAzWO" + + "TuWXsULZe7M6h6U2hTT/eplZ/mwHlXdF1VErIuusaCdkSI0doY4/Q223H40L" + + "BNU3pTezl41PLceSll00WGVr2MunlNeXKnXDJW06lnfs9BmnpV2+Lkfmf30W" + + "Pn4RKJQc+3D3SV4fCoQLIGrKiZLFfEdGJcMlySr+dJYcEtoZPuo6i/hb5xot" + + "le63h65ihNtXlEDrNpYSQqnfhjOzk5/+ZvYEcOtDObEwPTAhMAkGBSsOAwIa" + + "BQAEFMIeDI9l2Da24mtA1fbQIPc6+4dUBBQ8a4lD7j1CA1vRLhdEgPM+5hpD" + + "RgICCAA="); + + private static readonly byte[] pkcs12noFriendly = Base64.Decode( + "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCBAAwgDCABgkqhkiG9w0BBwGggCSA" + + "BIICvjCCArowggK2BgsqhkiG9w0BDAoBAqCCAqUwggKhMBsGCiqGSIb3DQEM" + + "AQMwDQQIyJDupEHvySECAQEEggKAupvM7RuZL3G4qNeJM3afElt03TVfynRT" + + "xUxAZOfx+zekHJTlnEuHJ+a16cOV6dQUgYfyMw1xcq4E+l59rVeMX9V3Zr0K" + + "tsMN9VYB/9zn62Kw6LQnY0rMlWYf4bt9Ut5ysq0hE5t9FL+NZ5FbFdWBOKsj" + + "/3oC6eNXOkOFyrY2haPJtD1hVHUosrlC0ffecV0YxPDsReeyx0R4CiYZpAUy" + + "ZD7rkxL+mSX7zTsShRiga2Q/NEhC1KZpbhO/qbyOgvH0r7CRumSMvijzDgaV" + + "IGqtrIZ2E2k5kscjcuFTW0x3OZTLAW/UnAh4JXJzC6isbdiWuswbAEBHifUC" + + "rk2f+bDJKe2gkH67J2K0yDQ3YSSibpjDX/bVfbtfmOoggK9MKQwqEeE0nbYE" + + "jzInH2OK5jPtmwppjmVA7i3Uk25w2+z7b/suUbft9hPCNjxFvzdbyCcXK4Vv" + + "xAgEbVWnIkvOQNbyaQi+DEF/4P26GwgJgXuJpMBn0zzsSZSIDLNl8eJHoKp2" + + "ZXknTi0SZkLaYlBxZlNhFoyXLfvQd6TI2aR5aCVqg1aZMBXyOWfz5t0JTVX8" + + "HTIcdXKis91iEsLB7vjcxIOASTAjKARr5tRp6OvaVterAyDOn2awYQJLLic5" + + "pQfditRAlsLkTxlDdu0/QBMXSPptO8g3R+dS7ntvCjXgZZyxpOeKkssS2l5v" + + "/B2EsfKmYA9hU4aBdW1S9o/PcF1wpVqABd8664TGJ77tCAkbdHe0VJ3Bop2X" + + "lNxlWeEeD0v0QUZLqkJoMEwi5SUE6HAWjbqGhRuHyey9E+UsdCVnQ8AxXQzL" + + "2UKOmIrXc6R25GsLPCysXuXPRFBB2Tul0V3re3hPcAAAAAAAADCABgkqhkiG" + + "9w0BBwaggDCAAgEAMIAGCSqGSIb3DQEHATAbBgoqhkiG9w0BDAEGMA0ECDXn" + + "UZu6xckzAgEBoIAEggTYQMbzAoGnRVJMbCaJJUYgaARJ4zMfxt2e12H4pX/e" + + "vnZrR1eKAMck5c2vJoEasr0i2VUcAcK12AntVIEnBwuRBcA2WrZnC28WR+O7" + + "rLdu9ymG2V3zmk66aTizaB6rcHAzs2lD74n+/zJhZNaDMBfu9LzAdWb/u6Rb" + + "AThmbw764Zyv9802pET6xrB8ureffgyvQAdlcGHM+yxaOV3ZEtS0cp7i+pb/" + + "NTiET4jAFoO1tbBrWGJSRrMKvx4ZREppMhG3e/pYglfMFl+1ejbDsOvEUKSt" + + "H+MVrgDgAv4NsUtNmBu+BIIEAIOCjrBSK3brtV0NZOWsa6hZSSGBhflbEY8s" + + "U1bDsgZIW4ZaJJvSYEXLmiWSBOgq9VxojMfjowY+zj6ePJJMyI3E7AcFa+on" + + "zZjeKxkKypER+TtpBeraqUfgf01b6olH8L2i4+1yotCQ0PS+15qRYPK6D+d3" + + "S+R4veOA6wEsNRijVcB3oQsBCi0FVdf+6MVDvjNzBCZXj0heVi+x0EE106Sz" + + "B3HaDbB/KNHMPZvvs3J3z2lWLj5w7YZ9eVmrVJKsgG2HRKxtt2IQquRj4BkS" + + "upFnMTBVgWxXgwXycauC9bgYZurs+DbijqhHfWpUrttDfavsP8aX6+i3gabK" + + "DH4LQRL7xrTcKkcUHxOTcPHLgDPhi+RevkV+BX9tdajbk4tqw1d+0wOkf1pW" + + "aTG8fUp0lUpra7EJ0lGy8t/MB3NEk/5tLk9qA2nsKKdNoEdZWiEBE0fMrH1o" + + "tWJDew3VhspT+Lkor2dLN5ydjcr3wkb76OETPeMxS91onNj5mrAMUBt66vb6" + + "Gx4CL8FTRNZ/l8Kzngzdv9PmmKPTIXbhYbn3XRGg3od2tC/oVfsqYlGAMgFO" + + "STt+BZ1BR9Phyi4jsiy8R0seCEDRWYQLbwgwVj0V8Rx9VptqRoCnB4XhGJoJ" + + "TdAz/MT7KOSxIh2F2FymTJpyImcV6X4Kcj9iY0AZQ4zj712g4yMR6xKGzRu6" + + "oIBDkFW2bdA3Lb9ePpo5GFtNyA7IbggIko6VOeeOKxaq9nALS2gsZc1yaYtp" + + "aKL8kB+dVTCXiLgQniO6eMzgonsuwFnG+42XM1vhEpAvFzeJRC0CYzebEK9n" + + "nGXKCPoqPFuw3gcPMn57NCZJ8MjT/p0wANIEm6AsgqrdFKwTRVJ1ytB/X9Ri" + + "ysmjMBs9zbFKjU9jVDg1vGBNtb7YnYg9IrYHa3e4yTu2wUJKGP2XWHVgjDR7" + + "6RtzlO4ljw0kkSMMEDle2ZbGZ6lVXbFwV0wPNPmGA6+XGJRxcddTnrM6R/41" + + "zqksFLgoNL2BdofMXwv7SzxGyvFhHdRRdBZ5dKj2K9OfXakEcm/asZGu87u8" + + "y9m7Cckw8ilSNPMdvYiFRoThICx9NiwYl1IIKGcWlb9p6RAx6XNSkY6ZZ6pE" + + "Vla1E26rbd7is1ssSeqxLXXV9anuG5HDwMIt+CIbD8fZmNTcWMzZRiaFajvR" + + "gXdyTu/UhVdhiQPF+lrxp4odgF0cXrpcGaKvOtPq04F4ad3O5EkSGucI210Q" + + "pR/jQs07Yp5xDPzsXAb8naHb84FvK1iONAEjWbfhDxqtH7KGrBbW4KEzJrv3" + + "B8GLDp+wOAFjGEdGDPkOx3y2L2HuI1XiS9LwL+psCily/A96OiUyRU8yEz4A" + + "AAAAAAAAAAAEAwAAAAAAAAAAADAtMCEwCQYFKw4DAhoFAAQU1NQjgVRH6Vg3" + + "tTy3wnQisALy9aYECKiM2gZrLi+fAAA="); + + private static readonly char[] noFriendlyPassword = "sschette12".ToCharArray(); + + private static readonly byte[] pkcs12StorageIssue = Base64.Decode( + "MIIO8QIBAzCCDrEGCSqGSIb3DQEHAaCCDqIEgg6eMIIOmjCCBBMGCSqGSIb3" + + "DQEHAaCCBAQEggQAMIID/DCCA/gGCyqGSIb3DQEMCgECoIICtjCCArIwHAYK" + + "KoZIhvcNAQwBAzAOBAgURJ+/5hA2pgICB9AEggKQYZ4POE8clgH9Bjd1XO8m" + + "sr6NiRBiA08CllHSOn2RzyAgHTa+cKaWrEVVJ9mCd9XveSUCoBF9E1C3jSl0" + + "XIqLNgYd6mWK9BpeMRImM/5crjy///K4ab9kymzkc5qc0pIpdCQCZ04YmtFP" + + "B80VCgyaoh2xoxqgjBCIgdSg5XdepdA5nXkG9EsQ1oVUyCykv20lKgKKRseG" + + "Jo23AX8YUYR7ANqP2gz9lvlX6RBczuoZ62ujopUexiQgt5SZx97sgo3o/b/C" + + "px17A2L4wLdeAYCMCsZhC2UeaqnZCHSsvnPZfRGiuSEGbV5gHLmXszLDaEdQ" + + "Bo873GTpKTTzBfRFzNCtYtZRqh2AUsInWZWQUcCeX6Ogwa0wTonkp18/tqsh" + + "Fj1fVpnsRmjJTTXFxkPtUw5GPJnDAM0t1xqV7kOjN76XnZrMyk2azQ1Mf3Hn" + + "sGpF+VRGH6JtxbM0Jm5zD9uHcmkSfNR3tP/+vHOB1mkIR9tD2cHvBg7pAlPD" + + "RfDVWynhS+UBNlQ0SEM/pgR7PytRSUoKc/hhe3N8VerF7VL3BwWfBLlZFYZH" + + "FvPQg4coxF7+We7nrSQfXvdVBP9Zf0PTdf3pbZelGCPVjOzbzY/o/cB23IwC" + + "ONxlY8SC1nJDXrPZ5sY51cg/qUqor056YqipRlI6I+FoTMmMDKPAiV1V5ibo" + + "DNQJkyv/CAbTX4+oFlxgddTwYcPZgd/GoGjiP9yBHHdRISatHwMcM06CzXJS" + + "s3MhzXWD4aNxvvSpXAngDLdlB7cm4ja2klmMzL7IuxzLXFQFFvYf7IF5I1pC" + + "YZOmTlJgp0efL9bHjuHFnh0S0lPtlGDOjJ/4YpWvSKDplcPiXhaFVjsUtclE" + + "oxCC5xppRm8QWS8xggEtMA0GCSsGAQQBgjcRAjEAMBMGCSqGSIb3DQEJFTEG" + + "BAQBAAAAMGkGCSsGAQQBgjcRATFcHloATQBpAGMAcgBvAHMAbwBmAHQAIABS" + + "AFMAQQAgAFMAQwBoAGEAbgBuAGUAbAAgAEMAcgB5AHAAdABvAGcAcgBhAHAA" + + "aABpAGMAIABQAHIAbwB2AGkAZABlAHIwgZsGCSqGSIb3DQEJFDGBjR6BigA3" + + "AGQAZQBmADUAYgA0ADMANgBjAGEAYgBkADAAMAAyAGQAZAAyADkAMAAzAGIA" + + "MQA2ADgANgBjADcAOQA0ADgAXwA0ADYAZgAyADYAZgBkADQALQA4ADEAMgBk" + + "AC0ANABlAGYAYgAtADgAMAA4ADgALQA0ADUAYQBiADkAMQA5ADEAMAA3AGMA" + + "YzCCCn8GCSqGSIb3DQEHBqCCCnAwggpsAgEAMIIKZQYJKoZIhvcNAQcBMBwG" + + "CiqGSIb3DQEMAQYwDgQIbr2xdnQ9inMCAgfQgIIKOHg9VKz+jlM+3abi3cp6" + + "/XMathxDSEJLrxJs6j5DAVX17S4sw1Q/1pptjdMdd8QtTfUB6JpfgJ5Kpn+h" + + "gZMf6M8wWue0U/RZN0D9w7o+2n+X3ItdEXu80eJVDOm7I2p8qiXtijbMbXRL" + + "Cup1lgfPM5uv2D63/hmWRXLeG8eySrJnKENngpM559V8TI2JcTUBy1ZP3kcH" + + "KbcJ/tVPnIIe4qguxfsTmDtAQviGvWUohbt+RGFmtqfgntK7o6b+S8uRSwEs" + + "fOU/pnVE9M1ugtNJZI/xeGJq6umZWXA/OrAcK7feWUwqRvfivDGQJEoggByd" + + "4/g92PhK1JGkwlCb1HdfhOOKKChowQ4zVvSOm+uBxARGhk2i5uW9I20I0vSJ" + + "px42O2VFVJweOchfp+wBtSHBKYP1ZXyXWMvOtULClosSeesbYMAwvyBfpYEz" + + "3rQt/1iZkqDmEisXk8X1aEKG1KSWaSPyb/+6glWikDm+YdQw3Khu7IZt1l/H" + + "qWGecccel+R9mT4YjRzHlahUYk4U+RNVasVpH1Kxz2j3CZqL+b3jQOwSAPd/" + + "hKI+S/pjIpBPfiC4WxORAzGZzY2j+a79B70h1DO1D9jGur3vJDbdmGBNgs6d" + + "nonE1B527SICcGeXY1MtnZCLOPvySih0AvOekbN9x2CJg+Hp9e7A3Fxni53/" + + "oMLr9wGRRDki72eXCXW98mU8VJofoWYS1/VBLXGf/f+tJ9J02PpzxleqPH9T" + + "4mE+YHnZId6cqjCXmwvMr2cMw2clDVfvkbAJRE3eZHzL7IWSO8+giXzzrTsl" + + "VbMuXVkT4oniTN7TSRsBCT3zVVmCy1QL2hPBD6KsVc+bvLgAHRov84FPrI3f" + + "kY/oJufT36VE34Eu+QjzULlvVsLE3lhjutOerVIGSP//FM4LE99hp214P0JF" + + "DgBK+3J+ihmFdW8hUXOt6BU8/MBeiroiJMWo1/f/XcduekG2ZsdGv+GNPzXI" + + "PyHRpCgAgmck1+qoUPXxHRJuNqv223OZ5MN14X7iLl5OZ+f8IWfxUnZeZ9gj" + + "HNeceElwZ+YOup1CAi3haD9jxRWhZG4NDfB4IYi4Bc/TAkXE3jCPkYEvIbj9" + + "ExaU1Ts0+lqOOcwRmBoYjVrz0xbtfR/OWlopyrDHbeL5iQcQCW/loYRapWCZ" + + "E4ekHknpX9yoAwT355vtTkl0VKXeSZHE8jREhN95aY9zCoLYwbTQDTw7qUR5" + + "UamabLew0oS0XALtuOrfX4OUOZZUstUsGBle/Pw1TE3Bhe1clhrikp0F+Xgb" + + "Xx90KqxZX/36RMnCMAD7/q+57rV7WXp2Y5tT0AUgyUMjy1F1X/b1olUfqO1u" + + "rlWIUTl2znmQ3D9uO3W4ytfgGd5DpKcl2w84MBAT9qGwKuQg/UYKbP4K/+4L" + + "Y1DWCy3utmohQ28IJtlIUkPL1G7lHX1tfq/VA+bRNTJIhMrNn06ZJpuEJHDs" + + "/ferdlMFt/d6MrwVivmPVYkb8mSbHSiI8jZOFE44sA974depsDyXafFaSsl0" + + "bVzqOAu0C/n9dIednU0xxxgDF/djdZ/QhbaDIg2VJf11wx0nw9n76B0+eeyu" + + "QLaapzxCpQNDVOAM9doBb5F1I5pXQHFQqzTNtLmqDC4x0g8IH7asyk5LCglT" + + "b1pwMqPJOL2vGWKRLhPzT+9OfSpCmYGKytf593hmGmwIgEO13hQrw31F5TYt" + + "btkbDr+Q5XilOKEczhEM+Ug7YHU7bxkckOAbxu0YeRp/57GdGLokeLJ0dRlQ" + + "+V2CfQvWJoVC6PS4PUQtjwgK2p/LU10QsEFwM/S621fGq9zGrv7+FPBATRDb" + + "k4E9D/WaRylnW11ZTrOlTchQkoHcOh0xztlFxU8jzuIuDrPQQWkoqdl6B+yf" + + "lykRNJKKxwzFiPl40nLC3nEdIzCEvR4r/9QHiWQxAVSc/wQX+an5vakUmSXS" + + "oLFjgVdY1jmvdsx2r5BQPuOR8ONGmw/muvVSMaHV85brA4uk0lxn00HD9/a0" + + "A1LCeFkabNLn9wJT8RaJeOSNmFFllLR70OHaoPSb3GyzHpvd1e6aeaimdyVH" + + "BQWJ6Ufx+HjbOGuOiN46WyE6Q27dnWxx8qF89dKB4T/J0mEXqueiUjAUnnnR" + + "Cs4zPaX53hmNBdrZGaLs+xNG8xy+iyBUJIWWfQAQjCjfHYlT9nygiUWIbVQq" + + "RHkGkAN62jsSNLgHvWVzQPNNsYq0U8TPhyyci/vc8MJytujjptcz8FPqUjg2" + + "TPv34ef9buErsm4vsdEv/8Z+9aDaNex+O3Lo3N0Aw7M5NcntFBHjFY/nBFNZ" + + "whH5YA4gQ8PLZ5qshlGvb0DFXHV/9zxnsdPkLwH47ERm5IlEAuoaWtZFxg27" + + "BjLfwU1Opk+ybDSb5WZVZrs7ljsU85p3Vaf3a//yoyr9ITYj15tTXxSPoct0" + + "fDUy1I6LjJH/+eZXKA1WSda9mDQlRocvJ0IIIlI4weJpTdm8aHIJ8OngCqOF" + + "TufcSLDM41+nxEK1LqXeAScVy74kVvvqngj6mIrbylrINZOHheEgTXrUWEc0" + + "uXS8l1YqY6K6Ru5km2jVyWi/ujrDGb6QGShC09oiDYUuUGy4gwJ3XLVX/dR3" + + "pmMExohTGiVefFP400wVZaxB9g1BQmjSEZxIaW1U1K6fk8Yni8yWB3/L/PuD" + + "0+OV+98i1sQGaPe35crIpEc7R2XJdngL0Ol1ZuvCIBfy5DQwGIawTtBnjPdi" + + "hy//QTt/isdu7C5pGaJDkZFMrfxMibr6c3xXr7wwR75sTzPNmS8mquEdLsmG" + + "h8gTUnB8/K6V11JtUExMqTimTbUw+j8PggpeBelG36breWJIz1O+dmCTGuLM" + + "x/sK/i8eiUeRvWjqYpq5DYt4URWg2WlcpcKiUxQp07/NMx0svDC+mlQGwMnJ" + + "8KOJMW1qr3TGEJ/VVKKVn6sXn/RxA+VPofYzhwZByRX87XmNdPeQKC2DHQsW" + + "6v83dua5gcnv0cv/smXt7Yr/c12i0fbIaQvj3qjtUCDucjARoBey3eCyG5H6" + + "5VHSsFnPZ2HCTum+jRSw/ENsu/77XU4BIM2fjAfswp7iIr2Xi4OZWKIj6o6q" + + "+fNgnOJjemDYHAFK+hWxClrG8b+9Eaf21o4zcHkhCfBlYv4d+xcZOIDsDPwI" + + "sf+4V+CfoBLALsa2K0pXlPplGom/a8h7CjlyaICbWpEDItqwu7NQwdMRCa7i" + + "yAyM1sVjXUdcZByS1bjOFSeBe7ygAvEl78vApLxqt8Cw11XSsOtmwssecUN/" + + "pb7iHE4OMyOgsYx9u7rZ2hMyl42n3c29IwDYMumiNqk9cwCBpQTJAQEv4VzO" + + "QE5xYDBY9SEozni+4f7B7e2Wj/LOGb3vfNVYGNpDczBFxvr2FXTQla0lNYD/" + + "aePuC++QW4KvwiGL1Zx4Jo0eoDKWYlYj0qiNlQbWfVw+raaaFnlrq+je0W6P" + + "+BrKZCncho145y+CFKRLZrN5yl/cDxwsePMVhAIMr1DzVhgBXzA3MB8wBwYF" + + "Kw4DAhoEFN4Cwj9AtArnRbOIAsRhaaoZlTNJBBTIVPqCrloqLns145CWXjb0" + + "g141BQ=="); + + private static readonly char[] storagePassword = "pass".ToCharArray(); + + private static readonly byte[] pkcs12nopass = Base64.Decode( + "MIIMvgIBAzCCDIQGCSqGSIb3DQEHAaCCDHUEggxxMIIMbTCCCS8GCSqGSIb3" + + "DQEHBqCCCSAwggkcAgEAMIIJFQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYw" + + "DgQIfnlhuZRR6/YCAggAgIII6DYgeRwq5n9kzvohZ3JuK+fB+9jZ7Or6EGBA" + + "GDxtBfHmSNUBWJEV/I8wV1zrKKoW/CaoZfA61pyrVZRd/roaqBx/koTFoh/g" + + "woyyWTRV9gYTXSVqPQgCH+e2dISAa6UGO+/YOWOOwG2X3t8tS+3FduFQFLt5" + + "cvUP98zENdm57Aef5pKpBSZDLIAoTASfmqwszWABRh2p/wKOHcCQ9Aj2e2vs" + + "pls/ntIv81MqPuxHttwX8e+3dKWGFrJRztLpCD2aua8VkSsHFsPxEHkezX4O" + + "6/VCjMCRFGophTS4dgKKtQIhZ9i/ESlr6sGKgIpyG99ALFpNEhtTKe+T3boE" + + "sEkhGDquSpu4PGz2m0W5sej1DyFkKX4zIbeMDAb1y3O7aP0F+Llo9QSeGsOA" + + "aCwND3NUAKBMOHzwdyNQcuCGCqY8j5rrSt99A5FMs3UVW3XU6hRCx7JlzO05" + + "PNCkcPRSnKSNzBhIR5W0qj4PAZnQTfX+wbtUaDLIqsObX4Muh2l3gl+JmdpO" + + "53U7ILqN8PAPly1eT+fIrUmlMmFhvo6LbTB7B2K728wsA/5wROlud/mOQz4s" + + "quS288YsnVc9ExSZKodWa3Pqcdb/cgKNJYDxrR6/eBHOj+0RLK/1yTK9ghj7" + + "IPYHoEqQbw768WK92RjM+RFGlXASkQhR9y4weWj/388uAWMIbQ+R2Zi4nb31" + + "knjqRPFThysG1bsRL04/9PgysaasfS9KYOeAlLqp+Ar4gJrof5fytBuY+6wm" + + "/J8eEdNw7VPV1cz/4rhrd2sfJQwDEN/iZoy8rTwe7wozpwZI0lwH11BBbav+" + + "1AMfI79jjxhqOeo7uxE2NzUmSd05JYI7a94tcRzGQyGEKpGxYCRamzFW23qb" + + "vG5Hcqi7Tdd7eTxw4c60l/vQLSo38g6ST5yZrK3URLiAtpioPyjrq2jnVfie" + + "QLsiAHhpHF01+t+OcKv3UjwdEyBmQ34h9klwiG7iwBFXZaPXFCF2Np1TqFVG" + + "jjBzmB+hRddEiYwN+XGCKB2Cvgc5ZMQ8LG9jQmEKLmOjuumz1ciAVY2qtl1s" + + "HYSvfNsIAV/gGzHshOVF19JmGtcQt3pMtupoRh+sh8jY2/x5eIKrj2Jx6HPd" + + "p/6IPUr54j0xSd6j7gWuXMj/eKp/utMNuBzAhkydnhXYedvTDYIj7SyPPIHa" + + "qtam8rxTDWn2AOxp7OXTgPmo1GU2zW1OLL1D3MFlS+oaRMfhgNrhW+QP5ay6" + + "ge4QLijpnSM+p0CbFAOClwzgdJV56bBVV09sDqSBXnG9MeEv5nDaH3I+GpPA" + + "UgDkaI4zT61kaGgk0uNMf3czy2ycoQzTx0iHDTXSdSqvUC1yFza8UG4AYaKz" + + "14gtSL7StvZtK0Y8oI084BINI1LgrWyrOLj7vkds4WrKhXm21BtM1GbN/pFh" + + "XI41h+XoD8KnEPqJ36rAgBo1uHqTNJCC7YikDE/dEvq6MkOx+Nug1YZRHEyi" + + "3AHry5u1HJHtxT34HXBwRXvnstuFhvU6cjc1WY1dJhu1p82TGnx7OBo/QbcM" + + "8MRrWmWuU5eW4jWbriGNGYfvZy+tHnGwy0bIeqrsHOG6/JwvfmYYXe64sryH" + + "5Qo96SZtcTJZaNFwuBY+bFUuOWm8YrT1L7Gl2Muf3pEVtNHLeYARBo1jEAym" + + "Cb4jw0oodZqbPKdyyzUZu69fdTJiQkMUcKDfHJEGK0Li9SvtdqJLiiJs57Tb" + + "YfOvn+TIuC40ssJFtmtlGCVH/0vtKLWYeW1NYAMzgI/nlhQ7W6Aroh8sZnqv" + + "SwxeQmRJaVLxiV6YveTKuVlCbqNVLeEtKYAujgnJtPemGCPbwZpwlBw6V+Dz" + + "oXveOBcUqATztWJeNv7RbU0Mk7k057+DNxXBIU+eHRGquyHQSBXxBbA+OFuu" + + "4SPfEAyoYed0HEaoKN9lIsBW1xTROI30MZvaJXvPdLsa8izXGPLnTGmoI+fv" + + "tJ644HtBCCCr3Reu82ZsTSDMxspZ9aa4ro9Oza+R5eULXDhVXedbhJBYiPPo" + + "J37El5lRqOgu2SEilhhVQq3ZCugsinCaY9P/RtWG4CFnH1IcIT5+/mivB48I" + + "2XfH6Xq6ziJdj2/r86mhEnz9sKunNvYPBDGlOvI7xucEf9AiEQoTR1xyFDbW" + + "ljL4BsJqgsHN02LyUzLwqMstwv+/JH1wUuXSK40Kik/N7+jEFW2C+/N8tN7l" + + "RPKSLaTjxVuTfdv/BH1dkV4iGFgpQrdWkWgkb+VZP9xE2mLz715eIAg13x6+" + + "n97tc9Hh375xZJqwr3QyYTXWpsK/vx04RThv8p0qMdqKvf3jVQWwnCnoeBv2" + + "L4h/uisOLY18qka/Y48ttympG+6DpmzXTwD1LycoG2SOWckCMmJhZK40+zr3" + + "NVmWf6iJtbLGMxI/kzTqbTaOfXc2MroertyM1rILRSpgnJFxJfai5Enspr9b" + + "SCwlP718jG2lQsnYlw8CuxoZAiaNy4MmC5Y3qNl3hlcggcHeLodyGkSyRsBg" + + "cEiKSL7JNvqr0X/nUeW28zVxkmQsWlp3KmST8agf+r+sQvw52fXNLdYznGZV" + + "rJrwgNOoRj0Z70MwTns3s/tCqDEsy5Sv/5dZW2uQEe7/wvmsP2WLu73Rwplg" + + "1dwi/Uo9lO9dkEzmoIK5wMPCDINxL1K+0Y79q0tIAEMDgaIxmtRpEh8/TEsA" + + "UwyEErkDsQqgGviH+ePmawJ/yehYHTRfYUgdUflwApJxRx65pDeSYkiYboMU" + + "8WSAQY2nh/p9hLlS4zbz9dCK2tzVyRkJgqNy/c4IpiHEx2l1iipW9vENglqx" + + "dYP4uqD8e3OOLjDQKizWx2t1u7GRwoEVQ3d3QzzOvsRcv7h+6vNsmYqE6phe" + + "wKFZLctpSn21zkyut444ij4sSr1OG68dEXLY0t0mATfTmXXy5GJBsdK/lLfk" + + "YTIPYYeDMle9aEicDqaKqkZUuYPnVchGp8UFMJ3M0n48OMDdDvpzBLTxxZeW" + + "cK5v/m3OEo3jgxy9wXfZdz//J3zXXqvX8LpMy1K9X0uCBTz6ERlawviMQhg1" + + "1okD5zCCAzYGCSqGSIb3DQEHAaCCAycEggMjMIIDHzCCAxsGCyqGSIb3DQEM" + + "CgECoIICpjCCAqIwHAYKKoZIhvcNAQwBAzAOBAj3QoojTSbZqgICCAAEggKA" + + "YOSp5XGdnG1pdm9CfvlAaUSHRCOyNLndoUTqteTZjHTEM9bGwNXAx4/R5H2Q" + + "PnPm5HB/ynVSXX0uKdW6YlbqUyAdV3eqE4X3Nl+K7ZoXmgAFnMr0tveBhT1b" + + "7rTi0TN4twjJzBTkKcxT8XKjvpVizUxGo+Ss5Wk8FrWLHAiC5dZvgRemtGcM" + + "w5S09Pwj+qXpjUhX1pB5/63qWPrjVf+Bfmlz4bWcqogGk0i7eg+OdTeWMrW0" + + "KR9nD1+/uNEyc4FdGtdIPnM+ax0E+vcco0ExQpTXe0xoX4JW7O71d550Wp89" + + "hAVPNrJA5eUbSWNsuz+38gjUJ+4XaAEhcA7HZIp6ZyxtzSJUoh7oqpRktoxu" + + "3cSVqVxIqAEqlNn6j0vbKfW91Od5DI5L+BIxY4xqXS7fdwipj9r6qWA8t9QU" + + "C2r1A+xXpZ4jEh6inHW9qlfACBBrYf8pSDakSR6yTbaA07LExw0IXz5oiQYt" + + "s7yx231CZlOH88bBmruLOIZsJjeg/lf63zI7Gg4F85QG3RqEJnY2pinLUTP7" + + "R62VErFZPc2a85r2dbFH1mSQIj/rT1IKe32zIW8xoHC4VwrPkT3bcLFAu2TH" + + "5k5zSI/gZUKjPDxb2dwLM4pvsj3gJ9vcFZp6BCuLkZc5rd7CyD8HK9PrBLKd" + + "H3Yngy4A08W4U3XUtIux95WE+5O/UEmSF7fr2vT//DwZArGUpBPq4Bikb8cv" + + "0wpOwUv8r0DXveeaPsxdipXlt29Ayywcs6KIidLtCaCX6/0u/XtMsGNFS+ah" + + "OlumTGBFpbLnagvIf0GKNhbg2lTjflACnxIj8d+QWsnrIU1uC1JRRKCnhpi2" + + "veeWd1m8GUb3aTFiMCMGCSqGSIb3DQEJFTEWBBS9g+Xmq/8B462FWFfaLWd/" + + "rlFxOTA7BgkqhkiG9w0BCRQxLh4sAEMAZQByAHQAeQBmAGkAawBhAHQAIAB1" + + "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI" + + "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA="); + + /** + * we generate a self signed certificate for the sake of testing - RSA + */ + public X509CertificateEntry CreateCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey, + string issuerEmail, + string subjectEmail) + { + // + // distinguished name table. + // + IDictionary issuerAttrs = new Hashtable(); + issuerAttrs.Add(X509Name.C, "AU"); + issuerAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + issuerAttrs.Add(X509Name.L, "Melbourne"); + issuerAttrs.Add(X509Name.ST, "Victoria"); + issuerAttrs.Add(X509Name.EmailAddress, issuerEmail); + + IDictionary subjectAttrs = new Hashtable(); + subjectAttrs.Add(X509Name.C, "AU"); + subjectAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + subjectAttrs.Add(X509Name.L, "Melbourne"); + subjectAttrs.Add(X509Name.ST, "Victoria"); + subjectAttrs.Add(X509Name.EmailAddress, subjectEmail); + + IList order = new ArrayList(); + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.EmailAddress); + + // + // extensions + // + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(order, issuerAttrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddDays(-30)); + certGen.SetNotAfter(DateTime.UtcNow.AddDays(30)); + certGen.SetSubjectDN(new X509Name(order, subjectAttrs)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + + return new X509CertificateEntry(certGen.Generate(privKey)); + } + + public void doTestPkcs12Store() + { + BigInteger mod = new BigInteger("bb1be8074e4787a8d77967f1575ef72dd7582f9b3347724413c021beafad8f32dba5168e280cbf284df722283dad2fd4abc750e3d6487c2942064e2d8d80641aa5866d1f6f1f83eec26b9b46fecb3b1c9856a303148a5cc899c642fb16f3d9d72f52526c751dc81622c420c82e2cfda70fe8d13f16cc7d6a613a5b2a2b5894d1", 16); + + MemoryStream stream = new MemoryStream(pkcs12, false); + Pkcs12Store store = new Pkcs12StoreBuilder().Build(); + store.Load(stream, passwd); + + string pName = null; + foreach (string n in store.Aliases) + { + if (store.IsKeyEntry(n)) + { + pName = n; + //break; + } + } + + AsymmetricKeyEntry key = store.GetKey(pName); + + if (!((RsaKeyParameters) key.Key).Modulus.Equals(mod)) + { + Fail("Modulus doesn't match."); + } + + X509CertificateEntry[] ch = store.GetCertificateChain(pName); + + if (ch.Length != 3) + { + Fail("chain was wrong length"); + } + + if (!ch[0].Certificate.SerialNumber.Equals(new BigInteger("96153094170511488342715101755496684211"))) + { + Fail("chain[0] wrong certificate."); + } + + if (!ch[1].Certificate.SerialNumber.Equals(new BigInteger("279751514312356623147411505294772931957"))) + { + Fail("chain[1] wrong certificate."); + } + + if (!ch[2].Certificate.SerialNumber.Equals(new BigInteger("11341398017"))) + { + Fail("chain[2] wrong certificate."); + } + + // + // save test + // + MemoryStream bOut = new MemoryStream(); + store.Save(bOut, passwd, new SecureRandom()); + + stream = new MemoryStream(bOut.ToArray(), false); + store.Load(stream, passwd); + + key = store.GetKey(pName); + + if (!((RsaKeyParameters)key.Key).Modulus.Equals(mod)) + { + Fail("Modulus doesn't match."); + } + + store.DeleteEntry(pName); + + if (store.GetKey(pName) != null) + { + Fail("Failed deletion test."); + } + + // + // cert chain test + // + store.SetCertificateEntry("testCert", ch[2]); + + if (store.GetCertificateChain("testCert") != null) + { + Fail("Failed null chain test."); + } + + // + // UTF 8 single cert test + // + stream = new MemoryStream(certUTF, false); + store.Load(stream, "user".ToCharArray()); + + if (store.GetCertificate("37") == null) + { + Fail("Failed to find UTF cert."); + } + + // + // try for a self generated certificate + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + X509CertificateEntry[] chain = new X509CertificateEntry[] { + CreateCert(pubKey, privKey, "issuer@bouncycastle.org", "subject@bouncycastle.org") + }; + + store = new Pkcs12StoreBuilder().Build(); + + store.SetKeyEntry("privateKey", new AsymmetricKeyEntry(privKey), chain); + + if (!store.ContainsAlias("privateKey") || !store.ContainsAlias("PRIVATEKEY")) + { + Fail("couldn't find alias privateKey"); + } + + if (store.IsCertificateEntry("privateKey")) + { + Fail("key identified as certificate entry"); + } + + if (!store.IsKeyEntry("privateKey") || !store.IsKeyEntry("PRIVATEKEY")) + { + Fail("key not identified as key entry"); + } + + if (!"privateKey".Equals(store.GetCertificateAlias(chain[0].Certificate))) + { + Fail("Did not return alias for key certificate privateKey"); + } + + MemoryStream store1Stream = new MemoryStream(); + store.Save(store1Stream, passwd, new SecureRandom()); + testNoExtraLocalKeyID(store1Stream.ToArray()); + + // + // no friendly name test + // + stream = new MemoryStream(pkcs12noFriendly, false); + store.Load(stream, noFriendlyPassword); + + pName = null; + + foreach (string n in store.Aliases) + { + if (store.IsKeyEntry(n)) + { + pName = n; + //break; + } + } + + ch = store.GetCertificateChain(pName); + + //for (int i = 0; i != ch.Length; i++) + //{ + // Console.WriteLine(ch[i]); + //} + + if (ch.Length != 1) + { + Fail("no cert found in pkcs12noFriendly"); + } + + // + // failure tests + // + ch = store.GetCertificateChain("dummy"); + + store.GetCertificateChain("DUMMY"); + + store.GetCertificate("dummy"); + + store.GetCertificate("DUMMY"); + + // + // storage test + // + stream = new MemoryStream(pkcs12StorageIssue, false); + store.Load(stream, storagePassword); + + pName = null; + + foreach (string n in store.Aliases) + { + if (store.IsKeyEntry(n)) + { + pName = n; + //break; + } + } + + ch = store.GetCertificateChain(pName); + if (ch.Length != 2) + { + Fail("Certificate chain wrong length"); + } + + store.Save(new MemoryStream(), storagePassword, new SecureRandom()); + + // + // basic certificate check + // + store.SetCertificateEntry("cert", ch[1]); + + if (!store.ContainsAlias("cert") || !store.ContainsAlias("CERT")) + { + Fail("couldn't find alias cert"); + } + + if (!store.IsCertificateEntry("cert") || !store.IsCertificateEntry("CERT")) + { + Fail("cert not identified as certificate entry"); + } + + if (store.IsKeyEntry("cert") || store.IsKeyEntry("CERT")) + { + Fail("cert identified as key entry"); + } + + if (!store.IsEntryOfType("cert", typeof(X509CertificateEntry))) + { + Fail("cert not identified as X509CertificateEntry"); + } + + if (!store.IsEntryOfType("CERT", typeof(X509CertificateEntry))) + { + Fail("CERT not identified as X509CertificateEntry"); + } + + if (store.IsEntryOfType("cert", typeof(AsymmetricKeyEntry))) + { + Fail("cert identified as key entry via AsymmetricKeyEntry"); + } + + if (!"cert".Equals(store.GetCertificateAlias(ch[1].Certificate))) + { + Fail("Did not return alias for certificate entry"); + } + + // + // test restoring of a certificate with private key originally as a ca certificate + // + store = new Pkcs12StoreBuilder().Build(); + + store.SetCertificateEntry("cert", ch[0]); + + if (!store.ContainsAlias("cert") || !store.ContainsAlias("CERT")) + { + Fail("restore: couldn't find alias cert"); + } + + if (!store.IsCertificateEntry("cert") || !store.IsCertificateEntry("CERT")) + { + Fail("restore: cert not identified as certificate entry"); + } + + if (store.IsKeyEntry("cert") || store.IsKeyEntry("CERT")) + { + Fail("restore: cert identified as key entry"); + } + + if (store.IsEntryOfType("cert", typeof(AsymmetricKeyEntry))) + { + Fail("restore: cert identified as key entry via AsymmetricKeyEntry"); + } + + if (store.IsEntryOfType("CERT", typeof(AsymmetricKeyEntry))) + { + Fail("restore: cert identified as key entry via AsymmetricKeyEntry"); + } + + if (!store.IsEntryOfType("cert", typeof(X509CertificateEntry))) + { + Fail("restore: cert not identified as X509CertificateEntry"); + } + + // + // test of reading incorrect zero-length encoding + // + stream = new MemoryStream(pkcs12nopass, false); + store.Load(stream, "".ToCharArray()); + } + + private void testSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain) + { + basicStoreTest(privKey, chain, + PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, + PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc ); + basicStoreTest(privKey, chain, + PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, + PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc ); + } + + private void basicStoreTest(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain, + DerObjectIdentifier keyAlgorithm, DerObjectIdentifier certAlgorithm) + { + Pkcs12Store store = new Pkcs12StoreBuilder() + .SetKeyAlgorithm(keyAlgorithm) + .SetCertAlgorithm(certAlgorithm) + .Build(); + + store.SetKeyEntry("key", privKey, chain); + + MemoryStream bOut = new MemoryStream(); + + store.Save(bOut, passwd, new SecureRandom()); + + store.Load(new MemoryStream(bOut.ToArray(), false), passwd); + + AsymmetricKeyEntry k = store.GetKey("key"); + + if (!k.Equals(privKey)) + { + Fail("private key didn't match"); + } + + X509CertificateEntry[] c = store.GetCertificateChain("key"); + + if (c.Length != chain.Length || !c[0].Equals(chain[0])) + { + Fail("certificates didn't match"); + } + + // check attributes + Pkcs12Entry b1 = k; + Pkcs12Entry b2 = chain[0]; + + if (b1[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] != null) + { + DerBmpString name = (DerBmpString)b1[PkcsObjectIdentifiers.Pkcs9AtFriendlyName]; + + if (!name.Equals(new DerBmpString("key"))) + { + Fail("friendly name wrong"); + } + } + else + { + Fail("no friendly name found on key"); + } + + if (b1[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] != null) + { + Asn1OctetString id = (Asn1OctetString)b1[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID]; + + if (!id.Equals(b2[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID])) + { + Fail("local key id mismatch"); + } + } + else + { + Fail("no local key id found"); + } + + // + // check algorithm types. + // + Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray()); + + Pfx pfx = new Pfx((Asn1Sequence)aIn.ReadObject()); + + ContentInfo cInfo = pfx.AuthSafe; + + Asn1OctetString auth = (Asn1OctetString)cInfo.Content; + + aIn = new Asn1InputStream(auth.GetOctets()); + Asn1Sequence s1 = (Asn1Sequence)aIn.ReadObject(); + + ContentInfo c1 = ContentInfo.GetInstance(s1[0]); + ContentInfo c2 = ContentInfo.GetInstance(s1[1]); + + aIn = new Asn1InputStream(((Asn1OctetString)c1.Content).GetOctets()); + + SafeBag sb = new SafeBag((Asn1Sequence)(((Asn1Sequence)aIn.ReadObject())[0])); + + EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(sb.BagValue); + + // check the key encryption + if (!encInfo.EncryptionAlgorithm.ObjectID.Equals(keyAlgorithm)) + { + Fail("key encryption algorithm wrong"); + } + + // check the certificate encryption + EncryptedData cb = EncryptedData.GetInstance(c2.Content); + + if (!cb.EncryptionAlgorithm.ObjectID.Equals(certAlgorithm)) + { + Fail("cert encryption algorithm wrong"); + } + } + + private void testNoExtraLocalKeyID(byte[] store1data) + { + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpg.Init(new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25)); + + AsymmetricCipherKeyPair newPair = kpg.GenerateKeyPair(); + + Pkcs12Store store1 = new Pkcs12StoreBuilder().Build(); + store1.Load(new MemoryStream(store1data, false), passwd); + + Pkcs12Store store2 = new Pkcs12StoreBuilder().Build(); + + AsymmetricKeyEntry k1 = store1.GetKey("privatekey"); + X509CertificateEntry[] chain1 = store1.GetCertificateChain("privatekey"); + + X509CertificateEntry[] chain2 = new X509CertificateEntry[chain1.Length + 1]; + + Array.Copy(chain1, 0, chain2, 1, chain1.Length); + + chain2[0] = CreateCert(newPair.Public, k1.Key, "subject@bouncycastle.org", "extra@bouncycaste.org"); + + if (chain1[0][PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) + { + Fail("localKeyID not found initially"); + } + + store2.SetKeyEntry("new", new AsymmetricKeyEntry(newPair.Private), chain2); + + MemoryStream bOut = new MemoryStream(); + + store2.Save(bOut, passwd, new SecureRandom()); + + store2.Load(new MemoryStream(bOut.ToArray(), false), passwd); + + chain2 = store2.GetCertificateChain("new"); + + if (chain2[1][PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] != null) + { + Fail("localKeyID found after save"); + } + } + + public override string Name + { + get { return "PKCS12Store"; } + } + + public override void PerformTest() + { + doTestPkcs12Store(); + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs12StoreTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/security/test/SecureRandomTest.cs b/crypto/test/src/security/test/SecureRandomTest.cs new file mode 100644 index 000000000..12e4b9a47 --- /dev/null +++ b/crypto/test/src/security/test/SecureRandomTest.cs @@ -0,0 +1,150 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Prng; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class SecureRandomTest + { +#if !NETCF_1_0 + [Test] + public void TestCryptoApi() + { + SecureRandom random = new SecureRandom( + new CryptoApiRandomGenerator()); + + checkSecureRandom(random); + } +#endif + + [Test] + public void TestDefault() + { + SecureRandom random = new SecureRandom(); + + checkSecureRandom(random); + } + + [Test] + public void TestSha1Prng() + { + SecureRandom random = SecureRandom.GetInstance("SHA1PRNG"); + random.SetSeed(SecureRandom.GetSeed(20)); + + checkSecureRandom(random); + } + + [Test] + public void TestSha256Prng() + { + SecureRandom random = SecureRandom.GetInstance("SHA256PRNG"); + random.SetSeed(SecureRandom.GetSeed(32)); + + checkSecureRandom(random); + } + + [Test] + public void TestThreadedSeed() + { + SecureRandom random = new SecureRandom( + new ThreadedSeedGenerator().GenerateSeed(20, false)); + + checkSecureRandom(random); + } + + [Test] + public void TestVmpcPrng() + { + SecureRandom random = new SecureRandom(new VmpcRandomGenerator()); + random.SetSeed(SecureRandom.GetSeed(32)); + + checkSecureRandom(random); + } + + + private static void checkSecureRandom( + SecureRandom random) + { + // Note: This will periodically (< 1e-6 probability) give a false alarm. + // That's randomness for you! + Assert.IsTrue(runChiSquaredTests(random), "Chi2 test detected possible non-randomness"); + } + + private static bool runChiSquaredTests( + SecureRandom random) + { + int passes = 0; + + for (int tries = 0; tries < 100; ++tries) + { + double chi2 = measureChiSquared(random, 1000); + if (chi2 < 285.0) // 255 degrees of freedom in test => Q ~ 10.0% for 285 + ++passes; + } + + return passes > 75; + } + + private static double measureChiSquared( + SecureRandom random, + int rounds) + { + int[] counts = new int[256]; + + byte[] bs = new byte[256]; + for (int i = 0; i < rounds; ++i) + { + random.NextBytes(bs); + + for (int b = 0; b < 256; ++b) + { + ++counts[bs[b]]; + } + } + + byte mask = SecureRandom.GetSeed(1)[0]; + for (int i = 0; i < rounds; ++i) + { + random.NextBytes(bs); + + for (int b = 0; b < 256; ++b) + { + ++counts[bs[b] ^ mask]; + } + + ++mask; + } + + byte shift = SecureRandom.GetSeed(1)[0]; + for (int i = 0; i < rounds; ++i) + { + random.NextBytes(bs); + + for (int b = 0; b < 256; ++b) + { + ++counts[(byte)(bs[b] + shift)]; + } + + ++shift; + } + + int total = 3 * rounds; + + double chi2 = 0; + for (int k = 0; k < counts.Length; ++k) + { + double diff = ((double) counts[k]) - total; + double diff2 = diff * diff; + + chi2 += diff2; + } + + chi2 /= total; + + return chi2; + } + } +} diff --git a/crypto/test/src/security/test/TestDigestUtil.cs b/crypto/test/src/security/test/TestDigestUtil.cs new file mode 100644 index 000000000..0f169f931 --- /dev/null +++ b/crypto/test/src/security/test/TestDigestUtil.cs @@ -0,0 +1,63 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class TestDigestUtilities + { + private static readonly byte[] TestBytes = new byte[100]; + + static TestDigestUtilities() + { + new SecureRandom().NextBytes(TestBytes); + } + + [Test] + public void TestAlgorithms() + { + CheckAlgorithm("GOST3411", new Gost3411Digest()); + CheckAlgorithm("MD2", new MD2Digest()); + CheckAlgorithm("MD4", new MD4Digest()); + CheckAlgorithm("MD5", new MD5Digest()); + CheckAlgorithm("RipeMD128", new RipeMD128Digest()); + CheckAlgorithm("RipeMD160", new RipeMD160Digest()); + CheckAlgorithm("RipeMD256", new RipeMD256Digest()); + CheckAlgorithm("RipeMD320", new RipeMD320Digest()); + CheckAlgorithm("SHA-1", new Sha1Digest()); + CheckAlgorithm("SHA-224", new Sha224Digest()); + CheckAlgorithm("SHA-256", new Sha256Digest()); + CheckAlgorithm("SHA-384", new Sha384Digest()); + CheckAlgorithm("SHA-512", new Sha512Digest()); + CheckAlgorithm("Tiger", new TigerDigest()); + CheckAlgorithm("Whirlpool", new WhirlpoolDigest()); + } + + private void CheckAlgorithm( + string name, + IDigest digest) + { + byte[] hash1 = MakeTestHash(digest); + byte[] hash2 = MakeTestHash(DigestUtilities.GetDigest(name)); + + Assert.AreEqual(hash1, hash2, name); + } + + private byte[] MakeTestHash( + IDigest digest) + { + for (int i = 0; i < digest.GetDigestSize(); ++i) + { + digest.Update((byte) i); + } + + digest.BlockUpdate(TestBytes, 0, TestBytes.Length); + + return DigestUtilities.DoFinal(digest); + } + } +} diff --git a/crypto/test/src/security/test/TestDotNetUtil.cs b/crypto/test/src/security/test/TestDotNetUtil.cs new file mode 100644 index 000000000..f880b388f --- /dev/null +++ b/crypto/test/src/security/test/TestDotNetUtil.cs @@ -0,0 +1,88 @@ +#if !(NETCF_1_0 || SILVERLIGHT) + +using System; +using System.Security.Cryptography; +using SystemX509 = System.Security.Cryptography.X509Certificates; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class TestDotNetUtilities + { + [Test] + public void TestRsaInterop() + { + for (int i = 0; i < 100; ++i) + { + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512); + RSAParameters rp = rsa.ExportParameters(true); + AsymmetricCipherKeyPair kp = DotNetUtilities.GetRsaKeyPair(rp); + + DotNetUtilities.ToRSA((RsaKeyParameters)kp.Public); + // TODO This method appears to not work for private keys (when no CRT info) + //DotNetUtilities.ToRSA((RsaKeyParameters)kp.Private); + DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)kp.Private); + } + } + + [Test] + public void TestX509CertificateConversion() + { + BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM=")); + BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs=")); + BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx")); + BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw==")); + BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A=")); + + DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG); + DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para); + DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para); + + IDictionary attrs = new Hashtable(); + attrs[X509Name.C] = "AU"; + attrs[X509Name.O] = "The Legion of the Bouncy Castle"; + attrs[X509Name.L] = "Melbourne"; + attrs[X509Name.ST] = "Victoria"; + attrs[X509Name.E] = "feedback-crypto@bouncycastle.org"; + + IList ord = new ArrayList(attrs.Keys); + + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + + certGen.SetIssuerDN(new X509Name(ord, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1)); + certGen.SetNotAfter(DateTime.UtcNow.AddDays(1)); + certGen.SetSubjectDN(new X509Name(ord, attrs)); + certGen.SetPublicKey(dsaPub); + certGen.SetSignatureAlgorithm("SHA1WITHDSA"); + + X509Certificate cert = certGen.Generate(dsaPriv); + + cert.CheckValidity(); + cert.Verify(dsaPub); + + SystemX509.X509Certificate dotNetCert = DotNetUtilities.ToX509Certificate(cert); + + X509Certificate certCopy = DotNetUtilities.FromX509Certificate(dotNetCert); + + Assert.AreEqual(cert, certCopy); + + certCopy.CheckValidity(); + certCopy.Verify(dsaPub); + } + } +} + +#endif diff --git a/crypto/test/src/security/test/TestEncodings.cs b/crypto/test/src/security/test/TestEncodings.cs new file mode 100644 index 000000000..557d2dc51 --- /dev/null +++ b/crypto/test/src/security/test/TestEncodings.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class TestEncodings + { + [Test] + public void TestEC() + { + BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv")); + BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R")); + BigInteger ECParraH = new BigInteger(Base64.Decode("AQ==")); + BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L")); + BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l")); + BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx")); + BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo")); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecDomain = + new ECDomainParameters( + curve, + new FpPoint(curve, + curve.FromBigInteger(ECParraGX), + curve.FromBigInteger(ECParraGY)), + ECParraN); + + ECPublicKeyParameters ecPub = new ECPublicKeyParameters( + new FpPoint( + curve, + curve.FromBigInteger(ECPubQX), + curve.FromBigInteger(ECPubQY)), + ecDomain); + + ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters(ECPrivD, ecDomain); + + SubjectPublicKeyInfo subinfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(ecPub); + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecPriv); + + ECPublicKeyParameters tecPub = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(subinfo); + ECPrivateKeyParameters tecPriv = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo); + + Assert.IsTrue(tecPub.Equals(ecPub), "EC: public key to info back to public key"); + Assert.IsTrue(tecPriv.Equals(ecPriv), "EC: private key to info back to private key"); + } + + [Test] + public void TestDH() + { + BigInteger DHParraP = new BigInteger(Base64.Decode("ALJCm1CUL6mOnyVqWTSV6Z2+DVSGOvgboOhmbyyxCrym59uVnXMmPjIgQTrmniFg7PvdcN7NNFwFmcZleULso1s=")); + BigInteger DHParraQ = new BigInteger(Base64.Decode("WSFNqEoX1MdPkrUsmkr0zt8GqkMdfA3QdDM3lliFXlNz7crOuZMfGRAgnXNPELB2fe64b2aaLgLM4zK8oXZRrQ==")); + BigInteger DHPubY = new BigInteger(Base64.Decode("AIki+8/zggCS2e488AsTNULI4LujdUeQQsZI949Dc9lKXZRmrPIC1h8NRoneHQEhpAe4Rhe0nhUOGZJekT5++SA=")); + BigInteger DHPrivX = new BigInteger(Base64.Decode("Apo67noMRO5eDWo/TtpRiBmKGw7ywh25shIu0Rs03krQmWKRbDPvdygWdJ5IpW6ZbKlCTAMhSxpz03YSeSEDmw==")); + + + DHParameters dhPara = new DHParameters(DHParraP, DHParraQ); + DHPublicKeyParameters dhPublic = new DHPublicKeyParameters(DHPubY, dhPara); + DHPrivateKeyParameters dhPrivate = new DHPrivateKeyParameters(DHPrivX, dhPara); + + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(dhPublic); + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dhPrivate); + + DHPublicKeyParameters testPubKey = (DHPublicKeyParameters) PublicKeyFactory.CreateKey(pubInfo); + DHPrivateKeyParameters testPrivKey = (DHPrivateKeyParameters) PrivateKeyFactory.CreateKey(privInfo); + + Assert.IsFalse(!testPrivKey.Equals(dhPrivate), "DH: Private key to info back to key"); + Assert.IsFalse(!testPubKey.Equals(dhPublic), "DH: Public key to info back to key"); + + Assert.IsTrue(true, "Diffe Helman Test worked."); + + } + + [Test] + public void TestElGamal() + { + + BigInteger ELGamalParaG = new BigInteger(Base64.Decode("QAZPRcsH8kHVKS5065R1Xy6QtsPvDkmDZtPuq18EJkvLrCIZivE/m5puQp3/VKJrG7dKgz4NBGpONp3HT+Cn/g==")); + BigInteger ELGamalParaP = new BigInteger(Base64.Decode("AKXmAwgkudDLI/Yxk6wk3APn+mSjX5QSyDwpchmegSIi1ZNC0Jb+IbxjroKNhRTBKjtv4/JTXtJS6IqaZv9uKes=")); + BigInteger ELGamalPubY = new BigInteger(Base64.Decode("AJ/gXuZuCA2X044otNkzs8FI36XuFu1L/YHg5cEmDvICTigycRN2E1DnhP+CTqxEqgEqX8rBe5tuGDlkTLwgNqM=")); + BigInteger ELGamalPriv = new BigInteger(Base64.Decode("CqVr+K0TpuJKQnc76MjKhxrJzGr93jnuE3mTpth486Meymt8uWEVAQj1tGc9DTt14F9aV9WIT2oYYbvLJRcwow==")); + + + + ElGamalParameters elPara = new ElGamalParameters(ELGamalParaP, ELGamalParaG); + + ElGamalPrivateKeyParameters elPriv = new ElGamalPrivateKeyParameters(ELGamalPriv, elPara); + ElGamalPublicKeyParameters elPub = new ElGamalPublicKeyParameters(ELGamalPubY, elPara); + + SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(elPub); + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(elPriv); + + ElGamalPrivateKeyParameters telPriv = (ElGamalPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo); + ElGamalPublicKeyParameters telPub = (ElGamalPublicKeyParameters)PublicKeyFactory.CreateKey(subInfo); + + + // Console.WriteLine(telPriv.Equals(elPriv)); + + + + Assert.IsTrue(telPriv.Equals(elPriv), "ELGamal Private key to into back to private key."); + Assert.IsTrue(telPub.Equals(elPub), "ELGamal Public key to into back to private key."); + + Assert.IsTrue(true, "ELGamal Test worked."); + + } + + [Test] + public void TestRsa() + { + + 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); + + SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaPublic); + RsaKeyParameters testResult = (RsaKeyParameters)PublicKeyFactory.CreateKey(subInfo); + + // check RSA public key. + + Assert.IsFalse(!testResult.Equals(rsaPublic), "RSA: test failed on public key to info and back to public key."); + + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(rsaPrivate); + testResult = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privInfo); + + Assert.IsFalse(!testResult.Equals(rsaPrivate), "RSA: private key to info back to private key."); + + Assert.IsTrue(true, "RSATest worked."); + + } + + [Test] + public void TestDSA() + { + BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM=")); + BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs=")); + BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx")); + BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw==")); + BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A=")); + + DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG); + DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para); + DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para); + + SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(dsaPub); + DsaKeyParameters testResult = (DsaKeyParameters)PublicKeyFactory.CreateKey(subInfo); + + // check RSA public key. + + Assert.IsFalse(!testResult.Equals(dsaPub), "DSA: test failed on public key to info and back to public key."); + + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dsaPriv); + testResult = (DsaPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo); + + Assert.IsFalse(!testResult.Equals(dsaPriv), "DSA: private key to info back to private key."); + + Assert.IsTrue(true, "DSATest worked."); + + } + } +} diff --git a/crypto/test/src/security/test/TestParameterUtil.cs b/crypto/test/src/security/test/TestParameterUtil.cs new file mode 100644 index 000000000..fe494212a --- /dev/null +++ b/crypto/test/src/security/test/TestParameterUtil.cs @@ -0,0 +1,74 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class TestParameterUtilities + { + [Test] + public void TestCreateKeyParameter() + { + SecureRandom random = new SecureRandom(); + + doTestCreateKeyParameter("AES", NistObjectIdentifiers.IdAes128Cbc, + 128, typeof(KeyParameter), random); + doTestCreateKeyParameter("DES", OiwObjectIdentifiers.DesCbc, + 64, typeof(DesParameters), random); + doTestCreateKeyParameter("DESEDE", PkcsObjectIdentifiers.DesEde3Cbc, + 192, typeof(DesEdeParameters), random); + doTestCreateKeyParameter("RC2", PkcsObjectIdentifiers.RC2Cbc, + 128, typeof(RC2Parameters), random); + } + + private void doTestCreateKeyParameter( + string algorithm, + DerObjectIdentifier oid, + int keyBits, + Type expectedType, + SecureRandom random) + { + int keyLength = keyBits / 8; + byte[] bytes = new byte[keyLength]; + random.NextBytes(bytes); + + KeyParameter key; + + key = ParameterUtilities.CreateKeyParameter(algorithm, bytes); + checkKeyParameter(key, expectedType, bytes); + + key = ParameterUtilities.CreateKeyParameter(oid, bytes); + checkKeyParameter(key, expectedType, bytes); + + bytes = new byte[keyLength * 2]; + random.NextBytes(bytes); + + int offset = random.Next(1, keyLength); + byte[] expected = new byte[keyLength]; + Array.Copy(bytes, offset, expected, 0, keyLength); + + key = ParameterUtilities.CreateKeyParameter(algorithm, bytes, offset, keyLength); + checkKeyParameter(key, expectedType, expected); + + key = ParameterUtilities.CreateKeyParameter(oid, bytes, offset, keyLength); + checkKeyParameter(key, expectedType, expected); + } + + private void checkKeyParameter( + KeyParameter key, + Type expectedType, + byte[] expectedBytes) + { + Assert.IsTrue(expectedType.IsInstanceOfType(key)); + Assert.IsTrue(Arrays.AreEqual(expectedBytes, key.GetKey())); + } + } +} diff --git a/crypto/test/src/security/test/TestSignerUtil.cs b/crypto/test/src/security/test/TestSignerUtil.cs new file mode 100644 index 000000000..c1140faf7 --- /dev/null +++ b/crypto/test/src/security/test/TestSignerUtil.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Security.Tests +{ + [TestFixture] + public class TestSignerUtilities + { + [Test] + public void TestAlgorithms() + { + // + // RSA parameters + // + BigInteger rsaMod = new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af66825656d43238b75503231500753f4e421e3c57", 16); + BigInteger rsaPubExp = new BigInteger("10001", 16); + + BigInteger rsaPrivExp = new BigInteger("65dad56ac7df7abb434e4cb5eeadb16093aa6da7f0033aad3815289b04757d32bfee6ade7749c8e4a323b5050a2fb9e2a99e23469e1ed4ba5bab54336af20a5bfccb8b3424cc6923db2ffca5787ed87aa87aa614cd04cedaebc8f623a2d2063017910f436dff18bb06f01758610787f8b258f0a8efd8bd7de30007c47b2a1031696c7d6523bc191d4d918927a7e0b09584ed205bd2ff4fc4382678df82353f7532b3bbb81d69e3f39070aed3fb64fce032a089e8e64955afa5213a6eb241231bd98d702fba725a9b205952fda186412d9e0d9344d2998c455ad8c2bae85ee672751466d5288304032b5b7e02f7e558c7af82c7fbf58eea0bb4ef0f001e6cd0a9", 16); + BigInteger rsaPrivP = new BigInteger("d4fd9ac3474fb83aaf832470643609659e511b322632b239b688f3cd2aad87527d6cf652fb9c9ca67940e84789444f2e99b0cb0cfabbd4de95396106c865f38e2fb7b82b231260a94df0e01756bf73ce0386868d9c41645560a81af2f53c18e4f7cdf3d51d80267372e6e0216afbf67f655c9450769cca494e4f6631b239ce1b", 16); + BigInteger rsaPrivQ = new BigInteger("c8eaa0e2a1b3a4412a702bccda93f4d150da60d736c99c7c566fdea4dd1b401cbc0d8c063daaf0b579953d36343aa18b33dbf8b9eae94452490cc905245f8f7b9e29b1a288bc66731a29e1dd1a45c9fd7f8238ff727adc49fff73991d0dc096206b9d3a08f61e7462e2b804d78cb8c5eccdb9b7fbd2ad6a8fea46c1053e1be75", 16); + BigInteger rsaPrivDP = new BigInteger("10edcb544421c0f9e123624d1099feeb35c72a8b34e008ac6fa6b90210a7543f293af4e5299c8c12eb464e70092805c7256e18e5823455ba0f504d36f5ccacac1b7cd5c58ff710f9c3f92646949d88fdd1e7ea5fed1081820bb9b0d2a8cd4b093fecfdb96dabd6e28c3a6f8c186dc86cddc89afd3e403e0fcf8a9e0bcb27af0b", 16); + BigInteger rsaPrivDQ = new BigInteger("97fc25484b5a415eaa63c03e6efa8dafe9a1c8b004d9ee6e80548fefd6f2ce44ee5cb117e77e70285798f57d137566ce8ea4503b13e0f1b5ed5ca6942537c4aa96b2a395782a4cb5b58d0936e0b0fa63b1192954d39ced176d71ef32c6f42c84e2e19f9d4dd999c2151b032b97bd22aa73fd8c5bcd15a2dca4046d5acc997021", 16); + BigInteger rsaPrivQinv = new BigInteger("4bb8064e1eff7e9efc3c4578fcedb59ca4aef0993a8312dfdcb1b3decf458aa6650d3d0866f143cbf0d3825e9381181170a0a1651eefcd7def786b8eb356555d9fa07c85b5f5cbdd74382f1129b5e36b4166b6cc9157923699708648212c484958351fdc9cf14f218dbe7fbf7cbd93a209a4681fe23ceb44bab67d66f45d1c9d", 16); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaMod, rsaPubExp); + RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters( + rsaMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv); + + // + // ECDSA parameters + // + BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv")); + BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R")); + BigInteger ECParraH = new BigInteger(Base64.Decode("AQ==")); + BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L")); + BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l")); + BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx")); + BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo")); + + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecDomain = new ECDomainParameters(curve, + new FpPoint(curve, + curve.FromBigInteger(ECParraGX), + curve.FromBigInteger(ECParraGY)), + ECParraN); + + ECPublicKeyParameters ecPub = new ECPublicKeyParameters( + new FpPoint(curve, + curve.FromBigInteger(ECPubQX), + curve.FromBigInteger(ECPubQY)), + ecDomain); + + ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters(ECPrivD, ecDomain); + + // + // DSA parameters + // + BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM=")); + BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs=")); + BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx")); + BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw==")); + BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A=")); + + DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG); + DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para); + DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para); + + // + // ECGOST3410 parameters + // + IAsymmetricCipherKeyPairGenerator ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410"); + ecGostKpg.Init( + new ECKeyGenerationParameters( + CryptoProObjectIdentifiers.GostR3410x2001CryptoProA, + new SecureRandom())); + + AsymmetricCipherKeyPair ecGostPair = ecGostKpg.GenerateKeyPair(); + + // + // GOST3410 parameters + // + IAsymmetricCipherKeyPairGenerator gostKpg = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + gostKpg.Init( + new Gost3410KeyGenerationParameters( + new SecureRandom(), + CryptoProObjectIdentifiers.GostR3410x94CryptoProA)); + + AsymmetricCipherKeyPair gostPair = gostKpg.GenerateKeyPair(); + + + + // + // signer loop + // + byte[] shortMsg = new byte[] { 1, 4, 5, 6, 8, 8, 4, 2, 1, 3 }; + byte[] longMsg = new byte[100]; + new SecureRandom().NextBytes(longMsg); + + foreach (string algorithm in SignerUtilities.Algorithms) + { + ISigner signer = SignerUtilities.GetSigner(algorithm); + + string upper = Platform.ToUpperInvariant(algorithm); + int withPos = upper.LastIndexOf("WITH"); + + string cipherName = withPos < 0 + ? upper + : upper.Substring(withPos + "WITH".Length); + + ICipherParameters signParams = null, verifyParams = null; + + if (cipherName == "RSA" || cipherName == "RSAANDMGF1") + { + signParams = rsaPrivate; + verifyParams = rsaPublic; + } + else if (cipherName == "ECDSA") + { + signParams = ecPriv; + verifyParams = ecPub; + } + else if (cipherName == "DSA") + { + signParams = dsaPriv; + verifyParams = dsaPub; + } + else if (cipherName == "ECGOST3410") + { + signParams = ecGostPair.Private; + verifyParams = ecGostPair.Public; + } + else if (cipherName == "GOST3410") + { + signParams = gostPair.Private; + verifyParams = gostPair.Public; + } + else + { + Assert.Fail("Unknown algorithm encountered: " + cipherName); + } + + signer.Init(true, signParams); + foreach (byte b in shortMsg) + { + signer.Update(b); + } + signer.BlockUpdate(longMsg, 0, longMsg.Length); + byte[] sig = signer.GenerateSignature(); + + signer.Init(false, verifyParams); + foreach (byte b in shortMsg) + { + signer.Update(b); + } + signer.BlockUpdate(longMsg, 0, longMsg.Length); + + Assert.IsTrue(signer.VerifySignature(sig), cipherName + " signer " + algorithm + " failed."); + } + } + } +} diff --git a/crypto/test/src/test/AESSICTest.cs b/crypto/test/src/test/AESSICTest.cs new file mode 100644 index 000000000..f8de35efd --- /dev/null +++ b/crypto/test/src/test/AESSICTest.cs @@ -0,0 +1,147 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// + /// Test vectors based on NIST Special Publication 800-38A, + /// "Recommendation for Block Cipher Modes of Operation" + /// + [TestFixture] + public class AesSicTest + : SimpleTest + { + private static readonly byte[][] keys = + { + Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c"), + Hex.Decode("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"), + Hex.Decode("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4") + }; + + private static readonly byte[][] plain = + { + Hex.Decode("6bc1bee22e409f96e93d7e117393172a"), + Hex.Decode("ae2d8a571e03ac9c9eb76fac45af8e51"), + Hex.Decode("30c81c46a35ce411e5fbc1191a0a52ef"), + Hex.Decode("f69f2445df4f9b17ad2b417be66c3710") + }; + + private static readonly byte[,][] cipher = + { + { + Hex.Decode("874d6191b620e3261bef6864990db6ce"), + Hex.Decode("9806f66b7970fdff8617187bb9fffdff"), + Hex.Decode("5ae4df3edbd5d35e5b4f09020db03eab"), + Hex.Decode("1e031dda2fbe03d1792170a0f3009cee") + }, + { + Hex.Decode("1abc932417521ca24f2b0459fe7e6e0b"), + Hex.Decode("090339ec0aa6faefd5ccc2c6f4ce8e94"), + Hex.Decode("1e36b26bd1ebc670d1bd1d665620abf7"), + Hex.Decode("4f78a7f6d29809585a97daec58c6b050") + }, + { + Hex.Decode("601ec313775789a5b7a7f504bbf3d228"), + Hex.Decode("f443e3ca4d62b59aca84e990cacaf5c5"), + Hex.Decode("2b0930daa23de94ce87017ba2d84988d"), + Hex.Decode("dfc9c58db67aada613c2dd08457941a6") + } + }; + + public override string Name + { + get { return "AESSIC"; } + } + + public override void PerformTest() + { + IBufferedCipher c = CipherUtilities.GetCipher("AES/SIC/NoPadding"); + + // + // NIST vectors + // + for (int i = 0; i != keys.Length; i++) + { + KeyParameter skey = ParameterUtilities.CreateKeyParameter("AES", keys[i]); + c.Init(true, new ParametersWithIV(skey, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"))); + + for (int j = 0; j != plain.Length; j++) + { + byte[] enc = c.ProcessBytes(plain[j]); + if (!AreEqual(enc, cipher[i, j])) + { + Fail("AESSIC encrypt failed: key " + i + " block " + j); + } + } + + c.Init(false, new ParametersWithIV(skey, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"))); + + for (int j = 0; j != plain.Length; j++) + { + byte[] enc = c.ProcessBytes(cipher[i, j]); + if (!AreEqual(enc, plain[j])) + { + Fail("AESSIC decrypt failed: key " + i + " block " + j); + } + } + } + + // + // check CTR also recognised. + // + c = CipherUtilities.GetCipher("AES/CTR/NoPadding"); + + KeyParameter sk = ParameterUtilities.CreateKeyParameter("AES", Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C")); + + c.Init(true, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001"))); + + byte[] crypt = c.DoFinal(Hex.Decode("00000000000000000000000000000000")); + + if (!AreEqual(crypt, Hex.Decode("D23513162B02D0F72A43A2FE4A5F97AB"))) + { + Fail("AESSIC failed test 2"); + } + + // + // check partial block processing + // + c = CipherUtilities.GetCipher("AES/CTR/NoPadding"); + + sk = ParameterUtilities.CreateKeyParameter("AES", Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C")); + + c.Init(true, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001"))); + + crypt = c.DoFinal(Hex.Decode("12345678")); + + c.Init(false, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001"))); + + crypt = c.DoFinal(crypt); + + if (!AreEqual(crypt, Hex.Decode("12345678"))) + { + Fail("AESSIC failed partial test"); + } + } + + public static void Main( + string[] args) + { + RunTest(new AesSicTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/AESTest.cs b/crypto/test/src/test/AESTest.cs new file mode 100644 index 000000000..5a1ce8046 --- /dev/null +++ b/crypto/test/src/test/AESTest.cs @@ -0,0 +1,363 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Tests +{ + /// Basic test class for the AES cipher vectors from FIPS-197 + [TestFixture] + public class AesTest + : BaseBlockCipherTest + { + internal static readonly string[] cipherTests = + { + "128", + "000102030405060708090a0b0c0d0e0f", + "00112233445566778899aabbccddeeff", + "69c4e0d86a7b0430d8cdb78070b4c55a", + "192", + "000102030405060708090a0b0c0d0e0f1011121314151617", + "00112233445566778899aabbccddeeff", + "dda97ca4864cdfe06eaf70a0ec0d7191", + "256", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "00112233445566778899aabbccddeeff", + "8ea2b7ca516745bfeafc49904b496089", + }; + + public AesTest() + : base("AES") + { + } + + [Test] + public void TestCiphers() + { + for (int i = 0; i != cipherTests.Length; i += 4) + { + doCipherTest(int.Parse(cipherTests[i]), + Hex.Decode(cipherTests[i + 1]), + Hex.Decode(cipherTests[i + 2]), + Hex.Decode(cipherTests[i + 3])); + } + } + + [Test] + public void TestOids() + { + string[] oids = { + NistObjectIdentifiers.IdAes128Ecb.Id, + NistObjectIdentifiers.IdAes128Cbc.Id, + NistObjectIdentifiers.IdAes128Ofb.Id, + NistObjectIdentifiers.IdAes128Cfb.Id, + NistObjectIdentifiers.IdAes192Ecb.Id, + NistObjectIdentifiers.IdAes192Cbc.Id, + NistObjectIdentifiers.IdAes192Ofb.Id, + NistObjectIdentifiers.IdAes192Cfb.Id, + NistObjectIdentifiers.IdAes256Ecb.Id, + NistObjectIdentifiers.IdAes256Cbc.Id, + NistObjectIdentifiers.IdAes256Ofb.Id, + NistObjectIdentifiers.IdAes256Cfb.Id + }; + + string[] names = { + "AES/ECB/PKCS7Padding", + "AES/CBC/PKCS7Padding", + "AES/OFB/NoPadding", + "AES/CFB/NoPadding", + "AES/ECB/PKCS7Padding", + "AES/CBC/PKCS7Padding", + "AES/OFB/NoPadding", + "AES/CFB/NoPadding", + "AES/ECB/PKCS7Padding", + "AES/CBC/PKCS7Padding", + "AES/OFB/NoPadding", + "AES/CFB/NoPadding" + }; + + oidTest(oids, names, 4); + } + + [Test] + public void TestWrap() + { + byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff"); + byte[] out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5"); + + wrapTest(1, "AESWrap", kek1, in1, out1); + } + + [Test] + public void TestWrapOids() + { + string[] wrapOids = + { + NistObjectIdentifiers.IdAes128Wrap.Id, + NistObjectIdentifiers.IdAes192Wrap.Id, + NistObjectIdentifiers.IdAes256Wrap.Id + }; + + wrapOidTest(wrapOids, "AESWrap"); + } + + private void doCipherTest( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", keyBytes); + + IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/ECB/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/ECB/NoPadding"); + + try + { + outCipher.Init(true, key); + } + catch (Exception e) + { + Fail("AES failed initialisation - " + e, e); + } + + try + { + inCipher.Init(false, key); + } + catch (Exception e) + { + Fail("AES failed initialisation - " + e, e); + } + + // + // encryption pass + // + MemoryStream bOut = new MemoryStream(); + + CipherStream cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + Fail("AES failed encryption - " + e, e); + } + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("AES failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + MemoryStream bIn = new MemoryStream(bytes, false); + + CipherStream cIn = new CipherStream(bIn, inCipher, null); + + try + { +// DataInputStream dIn = new DataInputStream(cIn); + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { +// bytes[i] = (byte)dIn.read(); + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; +// dIn.readFully(bytes, input.Length / 2, remaining); + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail("AES failed encryption - " + e, e); + } + + if (!AreEqual(bytes, input)) + { + Fail("AES failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + } + + [Test] + public void TestEax() + { + byte[] K = Hex.Decode("233952DEE4D5ED5F9B9C6D6FF80FF478"); + byte[] N = Hex.Decode("62EC67F9C3A4A407FCB2A8C49031A8B3"); + byte[] P = Hex.Decode("68656c6c6f20776f726c642121"); + byte[] C = Hex.Decode("2f9f76cb7659c70e4be11670a3e193ae1bc6b5762a"); + + KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K); + IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/EAX/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/EAX/NoPadding"); + + inCipher.Init(true, new ParametersWithIV(key, N)); + + byte[] enc = inCipher.DoFinal(P); + if (!AreEqual(enc, C)) + { + Fail("ciphertext doesn't match in EAX"); + } + + outCipher.Init(false, new ParametersWithIV(key, N)); + + byte[] dec = outCipher.DoFinal(C); + if (!AreEqual(dec, P)) + { + Fail("plaintext doesn't match in EAX"); + } + + try + { + inCipher = CipherUtilities.GetCipher("AES/EAX/PKCS5Padding"); + + Fail("bad padding missed in EAX"); + } + catch (SecurityUtilityException) + { + // expected + } + } + + [Test] + public void TestCcm() + { + byte[] K = Hex.Decode("404142434445464748494a4b4c4d4e4f"); + byte[] N = Hex.Decode("10111213141516"); + byte[] P = Hex.Decode("68656c6c6f20776f726c642121"); + byte[] C = Hex.Decode("39264f148b54c456035de0a531c8344f46db12b388"); + + KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K); + + IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/CCM/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/CCM/NoPadding"); + + inCipher.Init(true, new ParametersWithIV(key, N)); + + byte[] enc = inCipher.DoFinal(P); + if (!AreEqual(enc, C)) + { + Fail("ciphertext doesn't match in CCM"); + } + + outCipher.Init(false, new ParametersWithIV(key, N)); + + byte[] dec = outCipher.DoFinal(C); + if (!AreEqual(dec, P)) + { + Fail("plaintext doesn't match in CCM"); + } + + try + { + inCipher = CipherUtilities.GetCipher("AES/CCM/PKCS5Padding"); + + Fail("bad padding missed in CCM"); + } + catch (SecurityUtilityException) + { + // expected + } + } + + [Test] + public void TestGcm() + { + // Test Case 15 from McGrew/Viega + byte[] K = Hex.Decode( + "feffe9928665731c6d6a8f9467308308" + + "feffe9928665731c6d6a8f9467308308"); + byte[] P = Hex.Decode( + "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b391aafd255"); + byte[] N = Hex.Decode("cafebabefacedbaddecaf888"); + string T = "b094dac5d93471bdec1a502270e3cc6c"; + byte[] C = Hex.Decode( + "522dc1f099567d07f47f37a32a84427d" + + "643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838" + + "c5f61e6393ba7a0abcc9f662898015ad" + + T); + + KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K); + IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); + + inCipher.Init(true, new ParametersWithIV(key, N)); + + byte[] enc = inCipher.DoFinal(P); + if (!AreEqual(enc, C)) + { + Fail("ciphertext doesn't match in GCM"); + } + + outCipher.Init(false, new ParametersWithIV(key, N)); + + byte[] dec = outCipher.DoFinal(C); + if (!AreEqual(dec, P)) + { + Fail("plaintext doesn't match in GCM"); + } + + try + { + inCipher = CipherUtilities.GetCipher("AES/GCM/PKCS5Padding"); + + Fail("bad padding missed in GCM"); + } + catch (SecurityUtilityException) + { + // expected + } + } + + public override void PerformTest() + { + TestCiphers(); + TestWrap(); + TestOids(); + TestWrapOids(); + TestEax(); + TestCcm(); + TestGcm(); + } + + public static void Main( + string[] args) + { + RunTest(new AesTest()); + } + } +} diff --git a/crypto/test/src/test/AttrCertSelectorTest.cs b/crypto/test/src/test/AttrCertSelectorTest.cs new file mode 100644 index 000000000..37c1e66d2 --- /dev/null +++ b/crypto/test/src/test/AttrCertSelectorTest.cs @@ -0,0 +1,214 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class AttrCertSelectorTest + : SimpleTest + { + private static readonly RsaPrivateCrtKeyParameters RsaPrivateKeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + private static readonly byte[] holderCert = Base64.Decode( + "MIIGjTCCBXWgAwIBAgICAPswDQYJKoZIhvcNAQEEBQAwaTEdMBsGCSqGSIb3DQEJ" + + "ARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZpcmdpbmlhIFRlY2ggQ2VydGlm" + + "aWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0MQswCQYDVQQGEwJVUzAeFw0w" + + "MzAxMzExMzUyMTRaFw0wNDAxMzExMzUyMTRaMIGDMRswGQYJKoZIhvcNAQkBFgxz" + + "c2hhaEB2dC5lZHUxGzAZBgNVBAMTElN1bWl0IFNoYWggKHNzaGFoKTEbMBkGA1UE" + + "CxMSVmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAxMQswCQYDVQQK" + + "EwJ2dDELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPDc" + + "scgSKmsEp0VegFkuitD5j5PUkDuzLjlfaYONt2SN8WeqU4j2qtlCnsipa128cyKS" + + "JzYe9duUdNxquh5BPIkMkHBw4jHoQA33tk0J/sydWdN74/AHPpPieK5GHwhU7GTG" + + "rCCS1PJRxjXqse79ExAlul+gjQwHeldAC+d4A6oZAgMBAAGjggOmMIIDojAMBgNV" + + "HRMBAf8EAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCA/gwHQYD" + + "VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMB0GA1UdDgQWBBRUIoWAzlXbzBYE" + + "yVTjQFWyMMKo1jCBkwYDVR0jBIGLMIGIgBTgc3Fm+TGqKDhen+oKfbl+xVbj2KFt" + + "pGswaTEdMBsGCSqGSIb3DQEJARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZp" + + "cmdpbmlhIFRlY2ggQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0" + + "MQswCQYDVQQGEwJVU4IBADCBiwYJYIZIAYb4QgENBH4WfFZpcmdpbmlhIFRlY2gg" + + "Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgZGlnaXRhbCBjZXJ0aWZpY2F0ZXMgYXJl" + + "IHN1YmplY3QgdG8gcG9saWNpZXMgbG9jYXRlZCBhdCBodHRwOi8vd3d3LnBraS52" + + "dC5lZHUvY2EvY3BzLy4wFwYDVR0RBBAwDoEMc3NoYWhAdnQuZWR1MBkGA1UdEgQS" + + "MBCBDmlybWhlbHBAdnQuZWR1MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYn" + + "aHR0cDovL2JveDE3Ny5jYy52dC5lZHUvY2EvaXNzdWVycy5odG1sMEQGA1UdHwQ9" + + "MDswOaA3oDWGM2h0dHA6Ly9ib3gxNzcuY2MudnQuZWR1L2h0ZG9jcy1wdWJsaWMv" + + "Y3JsL2NhY3JsLmNybDBUBgNVHSAETTBLMA0GCysGAQQBtGgFAQEBMDoGCysGAQQB" + + "tGgFAQEBMCswKQYIKwYBBQUHAgEWHWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9jYS9j" + + "cHMvMD8GCWCGSAGG+EIBBAQyFjBodHRwOi8vYm94MTc3LmNjLnZ0LmVkdS9jZ2kt" + + "cHVibGljL2NoZWNrX3Jldl9jYT8wPAYJYIZIAYb4QgEDBC8WLWh0dHA6Ly9ib3gx" + + "NzcuY2MudnQuZWR1L2NnaS1wdWJsaWMvY2hlY2tfcmV2PzBLBglghkgBhvhCAQcE" + + "PhY8aHR0cHM6Ly9ib3gxNzcuY2MudnQuZWR1L35PcGVuQ0E4LjAxMDYzMC9jZ2kt" + + "cHVibGljL3JlbmV3YWw/MCwGCWCGSAGG+EIBCAQfFh1odHRwOi8vd3d3LnBraS52" + + "dC5lZHUvY2EvY3BzLzANBgkqhkiG9w0BAQQFAAOCAQEAHJ2ls9yjpZVcu5DqiE67" + + "r7BfkdMnm7IOj2v8cd4EAlPp6OPBmjwDMwvKRBb/P733kLBqFNWXWKTpT008R0KB" + + "8kehbx4h0UPz9vp31zhGv169+5iReQUUQSIwTGNWGLzrT8kPdvxiSAvdAJxcbRBm" + + "KzDic5I8PoGe48kSCkPpT1oNmnivmcu5j1SMvlx0IS2BkFMksr0OHiAW1elSnE/N" + + "RuX2k73b3FucwVxB3NRo3vgoHPCTnh9r4qItAHdxFlF+pPtbw2oHESKRfMRfOIHz" + + "CLQWSIa6Tvg4NIV3RRJ0sbCObesyg08lymalQMdkXwtRn5eGE00SHWwEUjSXP2gR" + + "3g=="); + + public override string Name + { + get { return "AttrCertSelector"; } + } + + private IX509AttributeCertificate CreateAttrCert() + { +// CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); +// X509Certificate iCert = (X509Certificate) fact +// .generateCertificate(new ByteArrayInputStream(holderCert)); + X509Certificate iCert = new X509CertificateParser().ReadCertificate(holderCert); + + // + // a sample key pair. + // + // RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( + // new BigInteger( + // "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", + // 16), new BigInteger("11", 16)); + + // + // set up the keys + // +// KeyFactory kFact = KeyFactory.getInstance("RSA", "BC"); +// PrivateKey privKey = kFact.generatePrivate(RsaPrivateKeySpec); + AsymmetricKeyParameter privKey = RsaPrivateKeySpec; + + X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator(); + + // the actual attributes + GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789@test.com"); + Asn1EncodableVector roleSyntax = new Asn1EncodableVector(roleName); + + // roleSyntax OID: 2.5.24.72 + X509Attribute attributes = new X509Attribute("2.5.24.72", + new DerSequence(roleSyntax)); + + gen.AddAttribute(attributes); + gen.SetHolder(new AttributeCertificateHolder(PrincipalUtilities.GetSubjectX509Principal(iCert))); + gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test"))); + gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + gen.SetSerialNumber(BigInteger.One); + gen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + Target targetName = new Target( + Target.Choice.Name, + new GeneralName(GeneralName.DnsName, "www.test.com")); + + Target targetGroup = new Target( + Target.Choice.Group, + new GeneralName(GeneralName.DirectoryName, "o=Test, ou=Test")); + + Target[] targets = new Target[]{ targetName, targetGroup }; + + TargetInformation targetInformation = new TargetInformation(targets); + gen.AddExtension(X509Extensions.TargetInformation.Id, true, targetInformation); + + return gen.Generate(privKey); + } + + [Test] + public void TestSelector() + { + IX509AttributeCertificate aCert = CreateAttrCert(); + X509AttrCertStoreSelector sel = new X509AttrCertStoreSelector(); + sel.AttributeCert = aCert; + bool match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate."); + } + sel.AttributeCert = null; + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate."); + } + sel.Holder = aCert.Holder; + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate holder."); + } + sel.Holder = null; + sel.Issuer = aCert.Issuer; + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate issuer."); + } + sel.Issuer = null; + +// CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); +// X509Certificate iCert = (X509Certificate) fact.generateCertificate( +// new ByteArrayInputStream(holderCert)); + X509Certificate iCert = new X509CertificateParser().ReadCertificate(holderCert); + match = aCert.Holder.Match(iCert); + if (!match) + { + Fail("Issuer holder does not match signing certificate of attribute certificate."); + } + + sel.SerialNumber = aCert.SerialNumber; + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate serial number."); + } + + sel.AttributeCertificateValid = new DateTimeObject(DateTime.UtcNow); + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate time."); + } + + sel.AddTargetName(new GeneralName(2, "www.test.com")); + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate target name."); + } + sel.SetTargetNames(null); + sel.AddTargetGroup(new GeneralName(4, "o=Test, ou=Test")); + match = sel.Match(aCert); + if (!match) + { + Fail("Selector does not match attribute certificate target group."); + } + sel.SetTargetGroups(null); + } + + public override void PerformTest() + { + TestSelector(); + } + + public static void Main( + string[] args) + { + RunTest(new AttrCertSelectorTest()); + } + } +} diff --git a/crypto/test/src/test/AttrCertTest.cs b/crypto/test/src/test/AttrCertTest.cs new file mode 100644 index 000000000..d701d007e --- /dev/null +++ b/crypto/test/src/test/AttrCertTest.cs @@ -0,0 +1,621 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class AttrCertTest + : SimpleTest + { + private static readonly RsaPrivateCrtKeyParameters RSA_PRIVATE_KEY_SPEC = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + internal static readonly 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"); + + internal static readonly byte[] signCert = Base64.Decode( + "MIIGjTCCBXWgAwIBAgICAPswDQYJKoZIhvcNAQEEBQAwaTEdMBsGCSqGSIb3DQEJ" + + "ARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZpcmdpbmlhIFRlY2ggQ2VydGlm" + + "aWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0MQswCQYDVQQGEwJVUzAeFw0w" + + "MzAxMzExMzUyMTRaFw0wNDAxMzExMzUyMTRaMIGDMRswGQYJKoZIhvcNAQkBFgxz" + + "c2hhaEB2dC5lZHUxGzAZBgNVBAMTElN1bWl0IFNoYWggKHNzaGFoKTEbMBkGA1UE" + + "CxMSVmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAxMQswCQYDVQQK" + + "EwJ2dDELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPDc" + + "scgSKmsEp0VegFkuitD5j5PUkDuzLjlfaYONt2SN8WeqU4j2qtlCnsipa128cyKS" + + "JzYe9duUdNxquh5BPIkMkHBw4jHoQA33tk0J/sydWdN74/AHPpPieK5GHwhU7GTG" + + "rCCS1PJRxjXqse79ExAlul+gjQwHeldAC+d4A6oZAgMBAAGjggOmMIIDojAMBgNV" + + "HRMBAf8EAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCA/gwHQYD" + + "VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMB0GA1UdDgQWBBRUIoWAzlXbzBYE" + + "yVTjQFWyMMKo1jCBkwYDVR0jBIGLMIGIgBTgc3Fm+TGqKDhen+oKfbl+xVbj2KFt" + + "pGswaTEdMBsGCSqGSIb3DQEJARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZp" + + "cmdpbmlhIFRlY2ggQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0" + + "MQswCQYDVQQGEwJVU4IBADCBiwYJYIZIAYb4QgENBH4WfFZpcmdpbmlhIFRlY2gg" + + "Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgZGlnaXRhbCBjZXJ0aWZpY2F0ZXMgYXJl" + + "IHN1YmplY3QgdG8gcG9saWNpZXMgbG9jYXRlZCBhdCBodHRwOi8vd3d3LnBraS52" + + "dC5lZHUvY2EvY3BzLy4wFwYDVR0RBBAwDoEMc3NoYWhAdnQuZWR1MBkGA1UdEgQS" + + "MBCBDmlybWhlbHBAdnQuZWR1MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYn" + + "aHR0cDovL2JveDE3Ny5jYy52dC5lZHUvY2EvaXNzdWVycy5odG1sMEQGA1UdHwQ9" + + "MDswOaA3oDWGM2h0dHA6Ly9ib3gxNzcuY2MudnQuZWR1L2h0ZG9jcy1wdWJsaWMv" + + "Y3JsL2NhY3JsLmNybDBUBgNVHSAETTBLMA0GCysGAQQBtGgFAQEBMDoGCysGAQQB" + + "tGgFAQEBMCswKQYIKwYBBQUHAgEWHWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9jYS9j" + + "cHMvMD8GCWCGSAGG+EIBBAQyFjBodHRwOi8vYm94MTc3LmNjLnZ0LmVkdS9jZ2kt" + + "cHVibGljL2NoZWNrX3Jldl9jYT8wPAYJYIZIAYb4QgEDBC8WLWh0dHA6Ly9ib3gx" + + "NzcuY2MudnQuZWR1L2NnaS1wdWJsaWMvY2hlY2tfcmV2PzBLBglghkgBhvhCAQcE" + + "PhY8aHR0cHM6Ly9ib3gxNzcuY2MudnQuZWR1L35PcGVuQ0E4LjAxMDYzMC9jZ2kt" + + "cHVibGljL3JlbmV3YWw/MCwGCWCGSAGG+EIBCAQfFh1odHRwOi8vd3d3LnBraS52" + + "dC5lZHUvY2EvY3BzLzANBgkqhkiG9w0BAQQFAAOCAQEAHJ2ls9yjpZVcu5DqiE67" + + "r7BfkdMnm7IOj2v8cd4EAlPp6OPBmjwDMwvKRBb/P733kLBqFNWXWKTpT008R0KB" + + "8kehbx4h0UPz9vp31zhGv169+5iReQUUQSIwTGNWGLzrT8kPdvxiSAvdAJxcbRBm" + + "KzDic5I8PoGe48kSCkPpT1oNmnivmcu5j1SMvlx0IS2BkFMksr0OHiAW1elSnE/N" + + "RuX2k73b3FucwVxB3NRo3vgoHPCTnh9r4qItAHdxFlF+pPtbw2oHESKRfMRfOIHz" + + "CLQWSIa6Tvg4NIV3RRJ0sbCObesyg08lymalQMdkXwtRn5eGE00SHWwEUjSXP2gR" + + "3g=="); + + internal static readonly byte[] certWithBaseCertificateID = Base64.Decode( + "MIIBqzCCARQCAQEwSKBGMD6kPDA6MQswCQYDVQQGEwJJVDEOMAwGA1UEChMFVU5JVE4xDDAKBgNV" + + "BAsTA0RJVDENMAsGA1UEAxMEcm9vdAIEAVMVjqB6MHikdjB0MQswCQYDVQQGEwJBVTEoMCYGA1UE" + + "ChMfVGhlIExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFByaW1h" + + "cnkgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUJvdW5jeSBDYXN0bGUwDQYJKoZIhvcNAQEFBQACBQKW" + + "RhnHMCIYDzIwMDUxMjEyMTIwMDQyWhgPMjAwNTEyMTkxMjAxMzJaMA8wDQYDVRhIMQaBBGVWSVAw" + + "DQYJKoZIhvcNAQEFBQADgYEAUAVin9StDaA+InxtXq/av6rUQLI9p1X6louBcj4kYJnxRvTrHpsr" + + "N3+i9Uq/uk5lRdAqmPFvcmSbuE3TRAsjrXON5uFiBBKZ1AouLqcr8nHbwcdwjJ9TyUNO9I4hfpSH" + + "UHHXMtBKgp4MOkhhX8xTGyWg3hp23d3GaUeg/IYlXBI="); + + internal static readonly byte[] holderCertWithBaseCertificateID = Base64.Decode( + "MIIBwDCCASmgAwIBAgIEAVMVjjANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJJVDEOMAwGA1UE" + + "ChMFVU5JVE4xDDAKBgNVBAsTA0RJVDENMAsGA1UEAxMEcm9vdDAeFw0wNTExMTExMjAxMzJaFw0w" + + "NjA2MTYxMjAxMzJaMD4xCzAJBgNVBAYTAklUMQ4wDAYDVQQKEwVVTklUTjEMMAoGA1UECxMDRElU" + + "MREwDwYDVQQDEwhMdWNhQm9yejBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr" + + "5YtqKmKXmEGb4ShypL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERoxUw" + + "EzARBglghkgBhvhCAQEEBAMCBDAwDQYJKoZIhvcNAQEFBQADgYEAsX50VPQQCWmHvPq9y9DeCpmS" + + "4szcpFAhpZyn6gYRwY9CRZVtmZKH8713XhkGDWcIEMcG0u3oTz3tdKgPU5uyIPrDEWr6w8ClUj4x" + + "5aVz5c2223+dVY7KES//JSB2bE/KCIchN3kAioQ4K8O3e0OL6oDVjsqKGw5bfahgKuSIk/Q="); + + + public override string Name + { + get { return "AttrCertTest"; } + } + + private void doTestCertWithBaseCertificateID() + { + IX509AttributeCertificate attrCert = new X509V2AttributeCertificate(certWithBaseCertificateID); + X509CertificateParser fact = new X509CertificateParser(); + X509Certificate cert = fact.ReadCertificate(holderCertWithBaseCertificateID); + + AttributeCertificateHolder holder = attrCert.Holder; + + if (holder.GetEntityNames() != null) + { + Fail("entity names set when none expected"); + } + + if (!holder.SerialNumber.Equals(cert.SerialNumber)) + { + Fail("holder serial number doesn't Match"); + } + + if (!holder.GetIssuer()[0].Equivalent(cert.IssuerDN)) + { + Fail("holder issuer doesn't Match"); + } + + if (!holder.Match(cert)) + { + Fail("holder not matching holder certificate"); + } + + if (!holder.Equals(holder.Clone())) + { + Fail("holder clone test failed"); + } + + if (!attrCert.Issuer.Equals(attrCert.Issuer.Clone())) + { + Fail("issuer clone test failed"); + } + + equalityAndHashCodeTest(attrCert, certWithBaseCertificateID); + } + + private void equalityAndHashCodeTest( + IX509AttributeCertificate attrCert, + byte[] encoding) + { + if (!attrCert.Equals(attrCert)) + { + Fail("same certificate not equal"); + } + + if (!attrCert.Holder.Equals(attrCert.Holder)) + { + Fail("same holder not equal"); + } + + if (!attrCert.Issuer.Equals(attrCert.Issuer)) + { + Fail("same issuer not equal"); + } + + if (attrCert.Holder.Equals(attrCert.Issuer)) + { + Fail("wrong holder equal"); + } + + if (attrCert.Issuer.Equals(attrCert.Holder)) + { + Fail("wrong issuer equal"); + } + + IX509AttributeCertificate attrCert2 = new X509V2AttributeCertificate(encoding); + + if (attrCert2.Holder.GetHashCode() != attrCert.Holder.GetHashCode()) + { + Fail("holder hashCode test failed"); + } + + if (!attrCert2.Holder.Equals(attrCert.Holder)) + { + Fail("holder Equals test failed"); + } + + if (attrCert2.Issuer.GetHashCode() != attrCert.Issuer.GetHashCode()) + { + Fail("issuer hashCode test failed"); + } + + if (!attrCert2.Issuer.Equals(attrCert.Issuer)) + { + Fail("issuer Equals test failed"); + } + } + + private void doTestGenerateWithCert() + { + X509CertificateParser fact = new X509CertificateParser(); + X509Certificate iCert = fact.ReadCertificate(signCert); + + // + // a sample key pair. + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + // + // set up the keys + // +// PrivateKey privKey; +// PublicKey pubKey; +// +// KeyFactory kFact = KeyFactory.getInstance("RSA"); +// +// privKey = kFact.generatePrivate(RSA_PRIVATE_KEY_SPEC); +// pubKey = kFact.generatePublic(pubKeySpec); + AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC; + + X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator(); + + // the actual attributes + GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789"); + + // roleSyntax OID: 2.5.24.72 + X509Attribute attributes = new X509Attribute("2.5.24.72", + new DerSequence(roleName)); + + gen.AddAttribute(attributes); + gen.SetHolder(new AttributeCertificateHolder(iCert)); + gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test"))); + gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + gen.SetSerialNumber(BigInteger.One); + gen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + IX509AttributeCertificate aCert = gen.Generate(privKey); + + aCert.CheckValidity(); + + aCert.Verify(pubKey); + + AttributeCertificateHolder holder = aCert.Holder; + + if (holder.GetEntityNames() != null) + { + Fail("entity names set when none expected"); + } + + if (!holder.SerialNumber.Equals(iCert.SerialNumber)) + { + Fail("holder serial number doesn't Match"); + } + + if (!holder.GetIssuer()[0].Equivalent(iCert.IssuerDN)) + { + Fail("holder issuer doesn't Match"); + } + + if (!holder.Match(iCert)) + { + Fail("generated holder not matching holder certificate"); + } + + X509Attribute[] attrs = aCert.GetAttributes("2.5.24.72"); + + if (attrs == null) + { + Fail("attributes related to 2.5.24.72 not found"); + } + + X509Attribute attr = attrs[0]; + + if (!attr.Oid.Equals("2.5.24.72")) + { + Fail("attribute oid mismatch"); + } + + Asn1Encodable[] values = attr.GetValues(); + + GeneralName role = GeneralNames.GetInstance(values[0]).GetNames()[0]; + + if (role.TagNo != GeneralName.Rfc822Name) + { + Fail("wrong general name type found in role"); + } + + if (!((IAsn1String)role.Name).GetString().Equals("DAU123456789")) + { + Fail("wrong general name value found in role"); + } + + X509Certificate sCert = fact.ReadCertificate(holderCertWithBaseCertificateID); + + if (holder.Match(sCert)) + { + Fail("generated holder matching wrong certificate"); + } + + equalityAndHashCodeTest(aCert, aCert.GetEncoded()); + } + + private void doTestGenerateWithPrincipal() + { + X509CertificateParser fact = new X509CertificateParser(); + X509Certificate iCert = fact.ReadCertificate(signCert); + + // + // a sample key pair. + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + // + // set up the keys + // +// PrivateKey privKey; +// PublicKey pubKey; +// +// KeyFactory kFact = KeyFactory.getInstance("RSA"); +// +// privKey = kFact.generatePrivate(RSA_PRIVATE_KEY_SPEC); +// pubKey = kFact.generatePublic(pubKeySpec); + AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC; + + X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator(); + + // the actual attributes + GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789"); + + // roleSyntax OID: 2.5.24.72 + X509Attribute attributes = new X509Attribute("2.5.24.72", + new DerSequence(roleName)); + + gen.AddAttribute(attributes); + gen.SetHolder(new AttributeCertificateHolder(iCert.SubjectDN)); + gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test"))); + gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + gen.SetSerialNumber(BigInteger.One); + gen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + IX509AttributeCertificate aCert = gen.Generate(privKey); + + aCert.CheckValidity(); + + aCert.Verify(pubKey); + + AttributeCertificateHolder holder = aCert.Holder; + + if (holder.GetEntityNames() == null) + { + Fail("entity names not set when expected"); + } + + if (holder.SerialNumber != null) + { + Fail("holder serial number found when none expected"); + } + + if (holder.GetIssuer() != null) + { + Fail("holder issuer found when none expected"); + } + + if (!holder.Match(iCert)) + { + Fail("generated holder not matching holder certificate"); + } + + X509Certificate sCert = fact.ReadCertificate(holderCertWithBaseCertificateID); + + if (holder.Match(sCert)) + { + Fail("principal generated holder matching wrong certificate"); + } + + equalityAndHashCodeTest(aCert, aCert.GetEncoded()); + } + + public override void PerformTest() + { + IX509AttributeCertificate aCert = new X509V2AttributeCertificate(attrCert); + X509CertificateParser fact = new X509CertificateParser(); + X509Certificate sCert = fact.ReadCertificate(signCert); + + aCert.Verify(sCert.GetPublicKey()); + + // + // search test + // + IList list = new ArrayList(); + + list.Add(sCert); + +// CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); +// CertStore store = CertStore.getInstance("Collection", ccsp); + IX509Store store = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(list)); + + ArrayList certs = new ArrayList( +// store.getCertificates(aCert.getIssuer())); + store.GetMatches(aCert.Issuer)); + + if (certs.Count != 1 || !certs.Contains(sCert)) + { + Fail("sCert not found by issuer"); + } + + X509Attribute[] attrs = aCert.GetAttributes("1.3.6.1.4.1.6760.8.1.1"); + if (attrs == null || attrs.Length != 1) + { + Fail("attribute not found"); + } + + // + // reencode test + // + aCert = new X509V2AttributeCertificate(aCert.GetEncoded()); + + aCert.Verify(sCert.GetPublicKey()); + + IX509AttributeCertificate saCert = new X509V2AttributeCertificate(aCert.GetEncoded()); + + if (!aCert.NotAfter.Equals(saCert.NotAfter)) + { + Fail("failed date comparison"); + } + + // base generator test + + // + // a sample key pair. + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC; + + // + // set up the keys + // +// PrivateKey privKey; +// PublicKey pubKey; +// +// KeyFactory kFact = KeyFactory.getInstance("RSA"); +// +// privKey = kFact.generatePrivate(privKeySpec); +// pubKey = kFact.generatePublic(pubKeySpec); + + X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator(); + + gen.AddAttribute(attrs[0]); + gen.SetHolder(aCert.Holder); + gen.SetIssuer(aCert.Issuer); + gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + gen.SetSerialNumber(aCert.SerialNumber); + gen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + + aCert = gen.Generate(privKey); + + aCert.CheckValidity(); + + aCert.Verify(pubKey); + + // as the issuer is the same this should still work (even though it is not + // technically correct + + certs = new ArrayList( +// store.getCertificates(aCert.Issuer)); + store.GetMatches(aCert.Issuer)); + + if (certs.Count != 1 || !certs.Contains(sCert)) + { + Fail("sCert not found by issuer"); + } + + attrs = aCert.GetAttributes("1.3.6.1.4.1.6760.8.1.1"); + if (attrs == null || attrs.Length != 1) + { + Fail("attribute not found"); + } + + // + // reencode test + // + aCert = new X509V2AttributeCertificate(aCert.GetEncoded()); + + aCert.Verify(pubKey); + + AttributeCertificateIssuer issuer = aCert.Issuer; + + X509Name[] principals = issuer.GetPrincipals(); + + // + // test holder + // + AttributeCertificateHolder holder = aCert.Holder; + + if (holder.GetEntityNames() == null) + { + Fail("entity names not set"); + } + + if (holder.SerialNumber != null) + { + Fail("holder serial number set when none expected"); + } + + if (holder.GetIssuer() != null) + { + Fail("holder issuer set when none expected"); + } + + principals = holder.GetEntityNames(); + + string ps = principals[0].ToString(); + + // TODO Check that this is a good enough test +// if (!ps.Equals("C=US, O=vt, OU=Class 2, OU=Virginia Tech User, CN=Markus Lorch (mlorch), EMAILADDRESS=mlorch@vt.edu")) + if (!principals[0].Equivalent(new X509Name("C=US, O=vt, OU=Class 2, OU=Virginia Tech User, CN=Markus Lorch (mlorch), EMAILADDRESS=mlorch@vt.edu"))) + { + Fail("principal[0] for entity names don't Match"); + } + + // + // extension test + // + + gen.AddExtension("1.1", true, new DerOctetString(new byte[10])); + + gen.AddExtension("2.2", false, new DerOctetString(new byte[20])); + + aCert = gen.Generate(privKey); + + ISet exts = aCert.GetCriticalExtensionOids(); + + if (exts.Count != 1 || !exts.Contains("1.1")) + { + Fail("critical extension test failed"); + } + + exts = aCert.GetNonCriticalExtensionOids(); + + if (exts.Count != 1 || !exts.Contains("2.2")) + { + Fail("non-critical extension test failed"); + } + + Asn1OctetString extString = aCert.GetExtensionValue(new DerObjectIdentifier("1.1")); + Asn1Encodable extValue = X509ExtensionUtilities.FromExtensionValue(extString); + + if (!extValue.Equals(new DerOctetString(new byte[10]))) + { + Fail("wrong extension value found for 1.1"); + } + + doTestCertWithBaseCertificateID(); + doTestGenerateWithCert(); + doTestGenerateWithPrincipal(); + } + + public static void Main( + string[] args) + { + RunTest(new AttrCertTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/BaseBlockCipherTest.cs b/crypto/test/src/test/BaseBlockCipherTest.cs new file mode 100644 index 000000000..87fb01056 --- /dev/null +++ b/crypto/test/src/test/BaseBlockCipherTest.cs @@ -0,0 +1,146 @@ +using System; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + public abstract class BaseBlockCipherTest + : SimpleTest + { + string algorithm; + + internal BaseBlockCipherTest( + string algorithm) + { + this.algorithm = algorithm; + } + + public override string Name + { + get { return algorithm; } + } + + protected void oidTest( + string[] oids, + string[] names, + int groupSize) + { + byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + + for (int i = 0; i != oids.Length; i++) + { + IBufferedCipher c1 = CipherUtilities.GetCipher(oids[i]); + IBufferedCipher c2 = CipherUtilities.GetCipher(names[i]); + CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]); + + KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey()); + + ICipherParameters cp = k; + if (names[i].IndexOf("/ECB/") < 0) + { + cp = new ParametersWithIV(cp, new byte[16]); + } + + c1.Init(true, cp); + c2.Init(false, cp); + + byte[] result = c2.DoFinal(c1.DoFinal(data)); + + if (!AreEqual(data, result)) + { + Fail("failed OID test"); + } + + if (k.GetKey().Length != (16 + ((i / groupSize) * 8))) + { + Fail("failed key length test"); + } + } + } + + protected void wrapOidTest( + string[] oids, + string name) + { + byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + + for (int i = 0; i != oids.Length; i++) + { + IWrapper c1 = WrapperUtilities.GetWrapper(oids[i]); + IWrapper c2 = WrapperUtilities.GetWrapper(name); + CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]); + + KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey()); + + c1.Init(true, k); + c2.Init(false, k); + + byte[] wrapped = c1.Wrap(data, 0, data.Length); + byte[] wKeyBytes = c2.Unwrap(wrapped, 0, wrapped.Length); + + if (!AreEqual(data, wKeyBytes)) + { + Fail("failed wrap OID test"); + } + + if (k.GetKey().Length != (16 + (i * 8))) + { + Fail("failed key length test"); + } + } + } + + protected void wrapTest( + int id, + string wrappingAlgorithm, + byte[] kek, + byte[] inBytes, + byte[] outBytes) + { + IWrapper wrapper = WrapperUtilities.GetWrapper(wrappingAlgorithm); + + wrapper.Init(true, ParameterUtilities.CreateKeyParameter(algorithm, kek)); + + try + { + byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length); + if (!AreEqual(cText, outBytes)) + { + Fail("failed wrap test " + id + " expected " + + Hex.ToHexString(outBytes) + " got " + + Hex.ToHexString(cText)); + } + } + catch (TestFailedException e) + { + throw e; + } + catch (Exception e) + { + Fail("failed wrap test exception " + e.ToString(), e); + } + + wrapper.Init(false, ParameterUtilities.CreateKeyParameter(algorithm, kek)); + + try + { + byte[] pTextBytes = wrapper.Unwrap(outBytes, 0, outBytes.Length); + + if (!AreEqual(pTextBytes, inBytes)) + { + Fail("failed unwrap test " + id + " expected " + + Hex.ToHexString(inBytes) + " got " + + Hex.ToHexString(pTextBytes)); + } + } + catch (Exception e) + { + Fail("failed unwrap test exception " + e.ToString(), e); + } + } + } +} diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs new file mode 100644 index 000000000..1e7e11ac9 --- /dev/null +++ b/crypto/test/src/test/BlockCipherTest.cs @@ -0,0 +1,978 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /** + * basic test class for a block cipher, basically this just exercises the provider, and makes sure we + * are behaving sensibly, correctness of the implementation is shown in the lightweight test classes. + */ + [TestFixture] + public class BlockCipherTest + : SimpleTest + { + private static readonly ISet validModes = CollectionUtilities.ReadOnly( + new HashSet(new string[]{ "CBC", "CCM", "CFB", "CTR", "CTS", "EAX", "ECB", "GCM", "OCB", "OFB" })); + + private static readonly string[] cipherTests1 = + { + "DES", + "466da00648ef0e1f9617b1f002e225251a3248d09172f46b9617b1f002e225250112ecb3da61bc99", + "DESede", + "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394", + "SKIPJACK", + "d4de46d52274dbb029f33b076043f8c40089f906751623de29f33b076043f8c4ac99b90f9396cb04", + "Blowfish", + "7870ebe7f6a52803eb9396ba6c5198216ce81d76d8d4c74beb9396ba6c5198211212473b05214e9f", + "Twofish", + "70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c0839e31468661bcfc57a14899ceeb0253", + "RC2", + "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b994a5b859e765797", + "RC5", + "220053543e3eca3bc9503a091ca67b08372560d8a4fdbee8c9503a091ca67b08a796d53bb8a4b7e0", + "RC5-64", + "e0b4a526ba3bc5f09199c3b1fe3737fe6d248cde70e565b0feea59ebfda375ae1946c386a48d8d8a74d7b1947ff6a788", + "RC6", + "44c97b67ca8486067f8b6c5b97632f3049e5e52c1d61fdd527dc3da39616540f19a3db39aac1ffd713795cd886cce0c0", + "IDEA", + "8c9fd56823ffdc523f6ccf7f614aa6173553e594fc7a21b53f6ccf7f614aa61740c54f7a66e95108", + "TEA", + "fcf45062104fda7c35712368b56dd4216a6ca998dc297b5435712368b56dd421208027ed2923cd0c", + "XTEA", + "4b427893d3d6aaded2afafabe25f7b233fb5589faa2b6389d2afafabe25f7b239d12979ac67e1c07", + "Camellia", + "3a68b4ad145bc2c76010669d68f2826359887afce763a78d9994143266adfaec8ba7ee562a1688ef9dfd7f897e5c44dc", + "SEED", + "d53d4ce1f48b9879420949467bfcbfbe2c6a7d4a8770bee0c71211def898d7c5024ce2007dd85accb3f69d906ae2164d", + "Noekeon", + "7e68ceb33aad9db04af6b878a16dd6c6b4f880d6c89027ba581884c10690bb6b3dbfd6ed5513e2c4f5670c3528023121", + "DES/CBC/NoPadding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a", + "DESede/CBC/NoPadding", + "4d3d7931875cf25593dc402298add8b914761e4936c9585ae22b2c1441169231", + "SKIPJACK/CBC/NoPadding", + "ceebcc2e5e2b847f9ed797b4930b95f115b9e6cf49c457fc2ea0df79ad5c8334", + "Blowfish/CBC/NoPadding", + "80823abbabc109733e7ebf3ce3344d67fc387c306b782086b452f7fbe8e844ce", + "Twofish/CBC/NoPadding", + "f819694251a00bdd403928745cd1d8a094de61f49ddf8e7692e9d81a83812943", + "RC2/CBC/NoPadding", + "a51facdb3933c9676795cd38cc3146fd4694722b468b1a979a399c77606abf99", + "RC5/CBC/NoPadding", + "9ee7517eab0280445f3a7c60c90c0f75029d65bca8b1af83ace5399d388c83c3", + "RC6/CBC/NoPadding", + "c44695633c07010f3a0d8f7ea046a642d4a96bf4e44f89fd91b46830bc95b130", + "IDEA/CBC/NoPadding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9", + "DES/CBC/PKCS5Padding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122afdc70484fb9c0232", + "DES/CBC/ISO10126Padding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8", + "DES/CBC/ISO7816-4Padding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a1f80b9b0f1be49ac", + "DES/CBC/X9.23Padding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8", + "DESede/CBC/PKCS7Padding", + "4d3d7931875cf25593dc402298add8b914761e4936c9585ae22b2c1441169231a41e40695f1cff84", + "SKIPJACK/CBC/PKCS7Padding", + "ceebcc2e5e2b847f9ed797b4930b95f115b9e6cf49c457fc2ea0df79ad5c8334df7042de5db89c96", + "Blowfish/CBC/PKCS7Padding", + "80823abbabc109733e7ebf3ce3344d67fc387c306b782086b452f7fbe8e844cef986562ab1a675e8", + "Twofish/CBC/PKCS7Padding", + "f819694251a00bdd403928745cd1d8a094de61f49ddf8e7692e9d81a838129433e5f1343d6cdb0b41838619da1541f04", + "RC2/CBC/PKCS7Padding", + "a51facdb3933c9676795cd38cc3146fd4694722b468b1a979a399c77606abf9958435525f770f137", + "RC5/CBC/PKCS7Padding", + "9ee7517eab0280445f3a7c60c90c0f75029d65bca8b1af83ace5399d388c83c3edd95ff49be76651", + "RC5-64/CBC/PKCS7Padding", + "e479fd11f89dab22d2f3dd062b1d2abd5b5962553421a5c562dc7214c3b23b8e21949fda87f2f820e5f032c552c6ec78", + "RC6/CBC/PKCS7Padding", + "c44695633c07010f3a0d8f7ea046a642d4a96bf4e44f89fd91b46830bc95b130824b972c9019a69d2dd05ef2d36b37ac", + "IDEA/CBC/PKCS7Padding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9e584751325ef7c32", + "IDEA/CBC/ISO10126Padding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b", + "IDEA/CBC/X9.23Padding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b", + "AES/CBC/PKCS7Padding", + "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7", + "AES/CBC/ISO7816-4Padding", + "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08306d84876508a33efec701118d8eeaf6d", + "Rijndael/CBC/PKCS7Padding", + "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7", + "Serpent/CBC/PKCS7Padding", + "f8940ca31aba8ce1e0693b1ae0b1e08daef6de03c80f019774280052f824ac44540bb8dd74dfad47f83f9c7ec268ca68", + "CAST5/CBC/PKCS7Padding", + "87b6dc0c5a1d23d42fa740b0548be0b298112000544610d889d6361994cf8e670a19d6af72d7289f", + "CAST6/CBC/PKCS7Padding", + "943445569cfdda174118e433828f84e137faee38cac5c827d87a3c9a5a46a07dd64e7ad8accd921f248eea627cd6826f", + "IDEA/CBC/PKCS7Padding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9e584751325ef7c32", + "DES/CBC/ZeroBytePadding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122ad3b3f002c927f1fd", + "DES/CTS/NoPadding", // official style + "60fa2f8fae5aa2a38e9ac77d0246726bcf99f75cc6e0122aeb7511e4515feb12", + "DESede/CTS/NoPadding", + "4d3d7931875cf25593dc402298add8b9e22b2c144116923114761e4936c9585a", + "SKIPJACK/CTS/NoPadding", + "ceebcc2e5e2b847f9ed797b4930b95f12ea0df79ad5c833415b9e6cf49c457fc", + "Blowfish/CTS/NoPadding", + "80823abbabc109733e7ebf3ce3344d67b452f7fbe8e844cefc387c306b782086", + "Twofish/CTS/NoPadding", + "94de61f49ddf8e7692e9d81a83812943f819694251a00bdd403928745cd1d8a0", + "AES/CTS/NoPadding", + "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", + "Rijndael/CTS/NoPadding", + "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", + "Serpent/CTS/NoPadding", + "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d", + "CAST5/CTS/NoPadding", + "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8", + "CAST6/CTS/NoPadding", + "37faee38cac5c827d87a3c9a5a46a07d943445569cfdda174118e433828f84e1", + "RC2/CTS/NoPadding", + "a51facdb3933c9676795cd38cc3146fd9a399c77606abf994694722b468b1a97", + "RC5/CTS/NoPadding", + "9ee7517eab0280445f3a7c60c90c0f75ace5399d388c83c3029d65bca8b1af83", + "RC6/CTS/NoPadding", + "d4a96bf4e44f89fd91b46830bc95b130c44695633c07010f3a0d8f7ea046a642", + "IDEA/CTS/NoPadding", + "30cd990ebdae80fe12b6c6e4fcd1c06497351c8684e4c4d9a27d985c276b3d70", + "DES/CBC/WithCTS", // older style + "60fa2f8fae5aa2a38e9ac77d0246726bcf99f75cc6e0122aeb7511e4515feb12", + "DESede/CBC/WithCTS", + "4d3d7931875cf25593dc402298add8b9e22b2c144116923114761e4936c9585a", + "SKIPJACK/CBC/WithCTS", + "ceebcc2e5e2b847f9ed797b4930b95f12ea0df79ad5c833415b9e6cf49c457fc", + "Blowfish/CBC/WithCTS", + "80823abbabc109733e7ebf3ce3344d67b452f7fbe8e844cefc387c306b782086", + "Twofish/CBC/WithCTS", + "94de61f49ddf8e7692e9d81a83812943f819694251a00bdd403928745cd1d8a0", + "AES/CBC/WithCTS", + "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", + "Rijndael/CBC/WithCTS", + "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", + "Serpent/CBC/WithCTS", + "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d", + "CAST5/CBC/WithCTS", + "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8", + "CAST6/CBC/WithCTS", + "37faee38cac5c827d87a3c9a5a46a07d943445569cfdda174118e433828f84e1", + "RC2/CBC/WithCTS", + "a51facdb3933c9676795cd38cc3146fd9a399c77606abf994694722b468b1a97", + "RC5/CBC/WithCTS", + "9ee7517eab0280445f3a7c60c90c0f75ace5399d388c83c3029d65bca8b1af83", + "RC6/CBC/WithCTS", + "d4a96bf4e44f89fd91b46830bc95b130c44695633c07010f3a0d8f7ea046a642", + "IDEA/CBC/WithCTS", + "30cd990ebdae80fe12b6c6e4fcd1c06497351c8684e4c4d9a27d985c276b3d70", + "DES/OFB/NoPadding", + "537572e480c1714f5c9a4f3b874df824dc6681b1fd6c11982debcad91e3f78b7", + "DESede/OFB/NoPadding", + "481e9872acea7fcf8e29a453242da774e5f6a28f15f7723659a73e4ff4939f80", + "SKIPJACK/OFB/NoPadding", + "71143a124e3a0cde753b60fe9b200e559018b6a0fe0682659f7c13feb9df995c", + "Blowfish/OFB/NoPadding", + "6cd6f7c5d2c655556d7a9e98a1696d1875e9f1b2fc991e28a2d55b56861e80bd", + "Twofish/OFB/NoPadding", + "821c54b1b54ae113cf74595eefe10c83b61c9682fc81f92c52f39a3a693f88b8", + "RC2/OFB/NoPadding", + "0a07cb78537cb04c0c74e28a7b86b80f80acadf87d6ef32792f1a8cf74b39f74", + "RC5/OFB/NoPadding", + "c62b233df296283b918a2b4cc53a54fbf061850e781b97332ed1bd78b88d9670", + "IDEA/OFB/NoPadding", + "dd447da3cbdcf81f4053fb446596261cb00a3c49a66085485af5f7c10ba20dad", + "DES/OFB8/NoPadding", + "53cb5010d189f94cf584e5ff1c4a9d86443c45ddb6fa3c2d1a5dadfcdf01db8a", + "DESede/OFB8/NoPadding", + "482c0c1ccd0e6d218e1cffb0a295352c2357ffaa673f2257ef5c77b6c04f03b5", + "SKIPJACK/OFB8/NoPadding", + "719ea1b432b3d2c8011e5aa873f95978420022b5e2c9c1a1c1082cd1f4999da2", + "Blowfish/OFB8/NoPadding", + "6ca6078755b263f09787d830b6fda7b7748494634bdc73ab68540cf9f6b7eccf", + "Twofish/OFB8/NoPadding", + "825dcec234ad52253d6e064b0d769bc04b1142435933f4a510ffc20d70095a88", + "RC2/OFB8/NoPadding", + "0aa26c6f6a820fe7d38da97085995ad62e2e293323a76300fcd4eb572810f7c6", + "RC5/OFB8/NoPadding", + "c601a9074dbd874f4d3293f6a32d93d9f0a4f5685d8597f0102fcc96d444f976", + "IDEA/OFB8/NoPadding", + "dd7897b6ced43d060a518bb38d570308b83b4de577eb208130daabf619e9b1fb", + "DES/CFB/NoPadding", + "537572e480c1714fec3c7424f88d4202219244c5ca8f5e4361d64f08fe747bb2", + "DESede/CFB/NoPadding", + "481e9872acea7fcfb75bb58670fe64c59123265139e357d161cd4ddb5eba042a", + "SKIPJACK/CFB/NoPadding", + "71143a124e3a0cde70a69ede4ceb14376b1e6a80bafde0a6330508dfa86a7c41", + "Blowfish/CFB/NoPadding", + "6cd6f7c5d2c6555561167fe9b10665102206869339122f1ed89efa4a985397f6", + "Twofish/CFB/NoPadding", + "821c54b1b54ae113cf74595eefe10c8308b7a438277de4f40948ac2d172d53d2", + "RC2/CFB/NoPadding", + "0a07cb78537cb04ca1401450d5cd411c7da7fa5b6baaa17bb2137bd95c9f26a5", + "RC5/CFB/NoPadding", + "c62b233df296283b989352bbebf616a19e11503ac737f9e0eaf19049cde05d34", + "IDEA/CFB/NoPadding", + "dd447da3cbdcf81fcbe4661dcbed88aed899f87585118384bd0565067fa6c13a", + "DES/CFB8/NoPadding", + "53cb0cdff712a825eb283b23c31e7323aa12495e7e751428b5c4eb89b28a25d4", + "DESede/CFB8/NoPadding", + "482cd5bf87ca4cee0b573d66a077231bfea93843ce2d1f948550a1d208e18279", + "SKIPJACK/CFB8/NoPadding", + "719eef3906bef23f7b63599285437d8e34183b165acf3e855b4e160d4f036508", + "Blowfish/CFB8/NoPadding", + "6ca63aaada9188d2410c07513cc0736b9888770768c25a5befc776beea5bdc4c", + "Twofish/CFB8/NoPadding", + "825d12af040721cf5ed4a4798647837ac5eb14d752aace28728aeb37b2010abd", + "RC2/CFB8/NoPadding", + "0aa227f94be3a32ff927c5d25647ea41d7c2a1e94012fc7f2ad6767b9664bce5", + "RC5/CFB8/NoPadding", + "c601cf88725411f119965b9cd38d6c313b91128ed7c98c7604cc62d9b210be79", + "IDEA/CFB8/NoPadding", + "dd7839d2525420d10f95eec23dbaf3463302c445972a28c563c2635191bc19af", + // TODO Check that PGPCFB modes are obsolete for C# build +// "IDEA/PGPCFB/NoPadding", +// "dd447da3cbdcf81fcbe4661dcbed88aed899f87585118384bd0565067fa6c13a", +// "IDEA/PGPCFBwithIv/NoPadding", +// "ed5adbac0e730cc0f00df7e4f6fef672ab042673106435faf3ecf3996a72a0e127b440ba9e5313501de3", + "Twofish/ECB/TBCPadding", + "70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c019d7daa58d02b89aab6e8c0d17202439", + "RC2/ECB/TBCPadding", + "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179" + }; + + private static readonly string[] cipherTests2 = + { + "DES/OFB64/NoPadding", + "537572e480c1714f5c9a4f3b874df824dc6681b1fd6c11982debcad91e", + "DES/CFB64/NoPadding", + "537572e480c1714fec3c7424f88d4202219244c5ca8f5e4361d64f08fe", + "DES/CTR/NoPadding", + "537572e480c1714fb47081d35eb18eaca9e0a5aee982f105438a0db6ce", + "DES/CTS/NoPadding", + "60fa2f8fae5aa2a38e9ac77d0246726b32df660db51a710ceb7511e451" + }; + + private static readonly byte[] input1 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f"); + private static readonly byte[] input2 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c"); + +// static RC2ParameterSpec rc2Spec = new RC2ParameterSpec(128, Hex.decode("0123456789abcdef")); + private static readonly byte[] rc2IV = Hex.Decode("0123456789abcdef"); + +// static RC5ParameterSpec rc5Spec = new RC5ParameterSpec(16, 16, 32, Hex.decode("0123456789abcdef")); +// static RC5ParameterSpec rc564Spec = new RC5ParameterSpec(16, 16, 64, Hex.decode("0123456789abcdef0123456789abcdef")); + private static readonly byte[] rc5IV = Hex.Decode("0123456789abcdef"); + private static readonly byte[] rc564IV = Hex.Decode("0123456789abcdef0123456789abcdef"); + private const int rc5Rounds = 16; + + /** + * a fake random number generator - we just want to make sure the random numbers + * aren't random so that we get the same output, while still getting to test the + * key generation facilities. + */ + private class FixedSecureRandom + : SecureRandom + { + 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 + }; + + public override void NextBytes( + byte[] bytes) + { + int offset = 0; + + while ((offset + seed.Length) < bytes.Length) + { + Array.Copy(seed, 0, bytes, offset, seed.Length); + offset += seed.Length; + } + + Array.Copy(seed, 0, bytes, offset, bytes.Length- offset); + } + } + + public override string Name + { + get { return "BlockCipher"; } + } + + private int GetIVLength( + string algorithm) + { + string[] parts = algorithm.Split('/'); + + if (parts.Length < 2) + return 0; + + string mode = parts[1]; + + int pos = mode.IndexOfAny(new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); + string baseMode = pos < 0 ? mode : mode.Substring(0, pos); + + if (!validModes.Contains(baseMode)) + throw new Exception("Unhandled mode: " + mode); + + if (baseMode == "ECB") + return 0; + + string baseAlgorithm = parts[0]; + IBufferedCipher baseCipher = CipherUtilities.GetCipher(baseAlgorithm); + return baseCipher.GetBlockSize(); + } + + private void doTest( + string algorithm, + byte[] input, + byte[] output) + { + KeyParameter key = null; + CipherKeyGenerator keyGen; + SecureRandom rand; + IBufferedCipher inCipher = null, outCipher = null; + byte[] iv = null; + CipherStream cIn, cOut; + MemoryStream bIn, bOut; + + rand = new FixedSecureRandom(); + + string[] parts = Platform.ToUpperInvariant(algorithm).Split('/'); + string baseAlgorithm = parts[0]; + string mode = parts.Length > 1 ? parts[1] : null; + +#if !INCLUDE_IDEA + if (baseAlgorithm.Equals("IDEA")) + { + return; + } +#endif + + try + { + keyGen = GeneratorUtilities.GetKeyGenerator(baseAlgorithm); + + // TODO Add Algorithm property to CipherKeyGenerator? +// if (!keyGen.getAlgorithm().Equals(baseAlgorithm)) +// { +// Fail("wrong key generator returned!"); +// } + + // TODO Add new Init method to CipherKeyGenerator? +// keyGen.Init(rand); + keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength)); + + byte[] keyBytes = keyGen.GenerateKey(); + + if (algorithm.StartsWith("RC5")) + { + key = new RC5Parameters(keyBytes, rc5Rounds); + } + else + { + key = ParameterUtilities.CreateKeyParameter(baseAlgorithm, keyBytes); + } + + inCipher = CipherUtilities.GetCipher(algorithm); + outCipher = CipherUtilities.GetCipher(algorithm); + + if (!Platform.ToUpperInvariant(inCipher.AlgorithmName).StartsWith(baseAlgorithm)) + { + Fail("wrong cipher returned!"); + } + + ICipherParameters parameters = key; + + int ivLength = GetIVLength(algorithm); + + if (ivLength > 0) + { + if (baseAlgorithm == "RC2") + { + iv = rc2IV; + } + else if (baseAlgorithm == "RC5") + { + iv = rc5IV; + } + else if (baseAlgorithm == "RC5-64") + { + iv = rc564IV; + } + else + { + // NB: rand always generates same values each test run + iv = rand.GenerateSeed(ivLength); + } + + parameters = new ParametersWithIV(key, iv); + } + + // NB: 'rand' still needed e.g. for some paddings + parameters = new ParametersWithRandom(parameters, rand); + + outCipher.Init(true, parameters); + } + catch (Exception e) + { + Fail("" + algorithm + " failed initialisation - " + e.ToString(), e); + } + + // + // grab the iv if there is one + // + try + { + // The Java version set this implicitly, but we set it explicity + //byte[] iv = outCipher.getIV(); + + if (iv != null) + { + // TODO Examine short IV handling for these FIPS-compliant modes in Java build + if (mode.StartsWith("CFB") + || mode.StartsWith("GOFB") + || mode.StartsWith("OFB") + || mode.StartsWith("OPENPGPCFB")) + { + // These modes automatically pad out the IV if it is short + } + else + { + try + { + byte[] nIv = new byte[iv.Length- 1]; + inCipher.Init(false, new ParametersWithIV(key, nIv)); + Fail("failed to pick up short IV"); + } + //catch (InvalidAlgorithmParameterException e) + catch (ArgumentException) + { + // ignore - this is what we want... + } + } + + //IvParameterSpec spec = new IvParameterSpec(iv); + inCipher.Init(false, new ParametersWithIV(key, iv)); + } + else + { + inCipher.Init(false, key); + } + } + catch (Exception e) + { + Fail("" + algorithm + " failed initialisation - " + e.ToString()); + } + + // + // encryption pass + // + bOut = new MemoryStream(); + cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length/ 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length/ 2, input.Length- input.Length/ 2); + cOut.Close(); + } + catch (IOException e) + { + Fail("" + algorithm + " failed encryption - " + e.ToString()); + } + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("" + algorithm + " failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + bIn = new MemoryStream(bytes, false); + cIn = new CipherStream(bIn, inCipher, null); + + try + { + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length/ 2; i++) + { + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail("" + algorithm + " failed decryption - " + e.ToString()); + } + + if (!AreEqual(bytes, input)) + { + Fail("" + algorithm + " failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + } + + // TODO Make private again and call from PerformTest + public void doTestExceptions() + { + // TODO Put back in +// SecretKeyFactory skF = null; +// +// try +// { +// skF = SecretKeyFactory.getInstance("DESede"); +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } +// +// KeySpec ks = null; +// SecretKey secKey = null; +// byte[] bb = new byte[24]; +// +// try +// { +// skF.getKeySpec(null, null); +// +// Fail("failed exception test - no exception thrown"); +// } +// catch (InvalidKeySpecException e) +// { +// // ignore okay +// } +// catch (Exception e) +// { +// Fail("failed exception test.", e); +// } +// try +// { +// ks = (KeySpec)new DESedeKeySpec(bb); +// skF.getKeySpec(null, ks.getClass()); +// +// Fail("failed exception test - no exception thrown"); +// } +// catch (InvalidKeySpecException e) +// { +// // ignore okay; +// } +// catch (Exception e) +// { +// Fail("failed exception test.", e); +// } +// try +// { +// skF.getKeySpec(secKey, null); +// } +// catch (InvalidKeySpecException e) +// { +// // ignore okay +// } +// catch (Exception e) +// { +// Fail("failed exception test.", e); +// } + + try + { + CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator("DESede"); + + try + { + kg.Init(new KeyGenerationParameters(new SecureRandom(), int.MinValue)); + + Fail("failed exception test - no exception thrown"); + } +// catch (InvalidParameterException) + catch (ArgumentException) + { + // ignore okay + } + catch (Exception e) + { + Fail("failed exception test.", e); + } + } + catch (Exception e) + { + Fail("unexpected exception.", e); + } + + // TODO Put back in +// try +// { +// skF = SecretKeyFactory.getInstance("DESede"); +// +// try +// { +// skF.translateKey(null); +// +// Fail("failed exception test - no exception thrown"); +// } +// catch (InvalidKeyException) +// { +// // ignore okay +// } +// catch (Exception e) +// { +// Fail("failed exception test.", e); +// } +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } + +// try +// { +// byte[] rawDESKey = { (byte)128, (byte)131, (byte)133, (byte)134, +// (byte)137, (byte)138, (byte)140, (byte)143 }; +// +//// SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES"); +// KeyParameter cipherKey = new DesParameters(rawDESKey); +// +// IBufferedCipher cipher = CipherUtilities.GetCipher("DES/CBC/NoPadding"); +// +// try +// { +// // According specification engineInit(int opmode, Key key, +// // SecureRandom random) throws InvalidKeyException if this +// // cipher is being +// // initialized for decryption and requires algorithm parameters +// // that cannot be determined from the given key +//// cipher.Init(false, cipherKey, (SecureRandom)null); +// cipher.Init(false, new ParametersWithRandom(cipherKey, new SecureRandom())); +// +// Fail("failed exception test - no InvalidKeyException thrown"); +// } +// catch (InvalidKeyException) +// { +// // ignore +// } +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } + + try + { +// byte[] rawDESKey = { -128, -125, -123, -122, -119, -118 }; + byte[] rawDESKey = { 128, 131, 133, 134, 137, 138 }; + +// SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES"); + +// IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/NoPadding"); + try + { + KeyParameter cipherKey = new DesParameters(rawDESKey); + + // According specification engineInit(int opmode, Key key, + // SecureRandom random) throws InvalidKeyException if the given + // key is inappropriate for initializing this cipher +// cipher.Init(true, cipherKey); + +// Fail("failed exception test - no InvalidKeyException thrown"); + Fail("failed exception test - no ArgumentException thrown"); + } +// catch (InvalidKeyException) + catch (ArgumentException) + { + // ignore + } + } + catch (Exception e) + { + Fail("unexpected exception.", e); + } + +// try +// { +//// byte[] rawDESKey = { -128, -125, -123, -122, -119, -118, -117, -115, -114 }; +// byte[] rawDESKey = { 128, 131, 133, 134, 137, 138, 139, 141, 142 }; +// +//// SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES"); +// KeyParameter cipherKey = new DesParameters(rawDESKey); +// +// IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/NoPadding"); +// try +// { +// // According specification engineInit(int opmode, Key key, +// // SecureRandom random) throws InvalidKeyException if the given +// // key is inappropriate for initializing this cipher +// cipher.Init(true, cipherKey); +// +// Fail("failed exception test - no InvalidKeyException thrown"); +// } +// catch (InvalidKeyException) +// { +// // ignore +// } +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } + + + try + { + byte[] rawDESKey = { (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143 }; + +// SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES"); + KeyParameter cipherKey = new DesParameters(rawDESKey); + + IBufferedCipher ecipher = CipherUtilities.GetCipher("DES/ECB/PKCS5Padding"); + ecipher.Init(true, cipherKey); + + byte[] cipherText = new byte[0]; + try + { + // According specification Method engineUpdate(byte[] input, + // int inputOffset, int inputLen, byte[] output, int + // outputOffset) + // throws ShortBufferException - if the given output buffer is + // too + // small to hold the result +// ecipher.update(new byte[20], 0, 20, cipherText); + ecipher.ProcessBytes(new byte[20], 0, 20, cipherText, 0); + +// Fail("failed exception test - no ShortBufferException thrown"); + Fail("failed exception test - no DataLengthException thrown"); + } +// catch (ShortBufferException) + catch (DataLengthException) + { + // ignore + } + } + catch (Exception e) + { + Fail("unexpected exception.", e); + } + + // TODO Put back in +// try +// { +// KeyGenerator keyGen = KeyGenerator.getInstance("DES"); +// +// keyGen.init((SecureRandom)null); +// +// // According specification engineGenerateKey() doesn't throw any exceptions. +// +// SecretKey key = keyGen.generateKey(); +// if (key == null) +// { +// Fail("key is null!"); +// } +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } +// +// try +// { +// AlgorithmParameters algParams = AlgorithmParameters.getInstance("DES"); +// +// algParams.init(new IvParameterSpec(new byte[8])); +// +// // According specification engineGetEncoded() returns +// // the parameters in their primary encoding format. The primary +// // encoding +// // format for parameters is ASN.1, if an ASN.1 specification for +// // this type +// // of parameters exists. +// byte[] iv = algParams.getEncoded(); +// +// if (iv.Length!= 10) +// { +// Fail("parameters encoding wrong length - " + iv.Length); +// } +// } +// catch (Exception e) +// { +// Fail("unexpected exception.", e); +// } + + try + { + try + { +// AlgorithmParameters algParams = AlgorithmParameters.getInstance("DES"); + + byte[] encoding = new byte[10]; + encoding[0] = 3; + encoding[1] = 8; + +// algParams.init(encoding, "ASN.1"); + ParameterUtilities.GetCipherParameters( + "AES", + ParameterUtilities.CreateKeyParameter("AES", new byte[16]), + Asn1Object.FromByteArray(encoding)); + +// Fail("failed exception test - no IOException thrown"); + Fail("failed exception test - no Exception thrown"); + } +// catch (IOException) + catch (ArgumentException) + { + // okay + } + +// try +// { +// IBufferedCipher c = CipherUtilities.GetCipher("DES"); +// +// Key k = new PublicKey() +// { +// +// public string getAlgorithm() +// { +// return "STUB"; +// } +// +// public string getFormat() +// { +// return null; +// } +// +// public byte[] getEncoded() +// { +// return null; +// } +// +// }; +// +// c.Init(true, k); +// +// Fail("failed exception test - no InvalidKeyException thrown for public key"); +// } +// catch (InvalidKeyException e) +// { +// // okay +// } +// +// try +// { +// IBufferedCipher c = CipherUtilities.GetCipher("DES"); +// +// Key k = new PrivateKey() +// { +// +// public string getAlgorithm() +// { +// return "STUB"; +// } +// +// public string getFormat() +// { +// return null; +// } +// +// public byte[] getEncoded() +// { +// return null; +// } +// +// }; +// +// c.Init(false, k); +// +// Fail("failed exception test - no InvalidKeyException thrown for private key"); +// } +// catch (InvalidKeyException e) +// { +// // okay +// } + } + catch (Exception e) + { + Fail("unexpected exception.", e); + } + } + + public override void PerformTest() + { + for (int i = 0; i != cipherTests1.Length; i += 2) + { + doTest(cipherTests1[i], input1, Hex.Decode(cipherTests1[i + 1])); + } + + for (int i = 0; i != cipherTests2.Length; i += 2) + { + doTest(cipherTests2[i], input2, Hex.Decode(cipherTests2[i + 1])); + } + + // + // check for less than a block + // + try + { + IBufferedCipher c = CipherUtilities.GetCipher("AES/CTS/NoPadding"); + + c.Init(true, ParameterUtilities.CreateKeyParameter("AES", new byte[16])); + + c.DoFinal(new byte[4]); + + Fail("CTS failed to throw exception"); + } + catch (Exception e) + { +// if (!(e is IllegalBlockSizeException)) + if (!(e is DataLengthException)) + { + Fail("CTS exception test - " + e, e); + } + } + + doTestExceptions(); + } + + public static void Main( + string[] args) + { + RunTest(new BlockCipherTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/CMacTest.cs b/crypto/test/src/test/CMacTest.cs new file mode 100644 index 000000000..f80caca7d --- /dev/null +++ b/crypto/test/src/test/CMacTest.cs @@ -0,0 +1,276 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /** + * CMAC tester - AES Official Test Vectors. + */ + [TestFixture] + public class CMacTest + : SimpleTest + { + private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c"); + private static readonly byte[] keyBytes192 = Hex.Decode( + "8e73b0f7da0e6452c810f32b809079e5" + + "62f8ead2522c6b7b"); + private static readonly byte[] keyBytes256 = Hex.Decode( + "603deb1015ca71be2b73aef0857d7781" + + "1f352c073b6108d72d9810a30914dff4"); + + private static readonly byte[] input0 = Hex.Decode(""); + private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a"); + private static readonly byte[] input40 = Hex.Decode( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411"); + private static readonly byte[] input64 = Hex.Decode( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710"); + + private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746"); + private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c"); + private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827"); + private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe"); + + private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367"); + private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184"); + private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e"); + private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11"); + + private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983"); + private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c"); + private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6"); + private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410"); + + private static readonly byte[] output_des_ede = Hex.Decode("1ca670dea381d37c"); + + public CMacTest() + { + } + + public override void PerformTest() + { +// Mac mac = Mac.getInstance("AESCMAC", "BC"); + IMac mac = MacUtilities.GetMac("AESCMAC"); + + //128 bytes key + +// SecretKeySpec key = new SecretKeySpec(keyBytes128, "AES"); + KeyParameter key = new KeyParameter(keyBytes128); + + // 0 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + byte[] output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k128_m0)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k128_m0) + + " got " + Hex.ToHexString(output)); + } + + // 16 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k128_m16)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k128_m16) + + " got " + Hex.ToHexString(output)); + } + + // 40 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k128_m40)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k128_m40) + + " got " + Hex.ToHexString(output)); + } + + // 64 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k128_m64)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k128_m64) + + " got " + Hex.ToHexString(output)); + } + + //192 bytes key + +// key = new SecretKeySpec(keyBytes192, "AES"); + key = new KeyParameter(keyBytes192); + + // 0 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k192_m0)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k192_m0) + + " got " + Hex.ToHexString(output)); + } + + // 16 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k192_m16)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k192_m16) + + " got " + Hex.ToHexString(output)); + } + + // 40 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k192_m40)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k192_m40) + + " got " + Hex.ToHexString(output)); + } + + // 64 bytes message - 192 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k192_m64)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k192_m64) + + " got " + Hex.ToHexString(output)); + } + + //256 bytes key + +// key = new SecretKeySpec(keyBytes256, "AES"); + key = new KeyParameter(keyBytes256); + + // 0 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k256_m0)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k256_m0) + + " got " + Hex.ToHexString(output)); + } + + // 16 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input16, 0, input16.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k256_m16)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k256_m16) + + " got " + Hex.ToHexString(output)); + } + + // 40 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input40, 0, input40.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k256_m40)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k256_m40) + + " got " + Hex.ToHexString(output)); + } + + // 64 bytes message - 256 bytes key + mac.Init(key); + + mac.BlockUpdate(input64, 0, input64.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_k256_m64)) + { + Fail("Failed - expected " + Hex.ToHexString(output_k256_m64) + + " got " + Hex.ToHexString(output)); + } + +// mac = Mac.getInstance("DESedeCMAC", "BC"); + mac = MacUtilities.GetMac("DESedeCMAC"); + + //DESede + +// key = new SecretKeySpec(keyBytes128, "DESede"); + key = new KeyParameter(keyBytes128); + + // 0 bytes message - 128 bytes key + mac.Init(key); + + mac.BlockUpdate(input0, 0, input0.Length); + + output = MacUtilities.DoFinal(mac); + + if (!AreEqual(output, output_des_ede)) + { + Fail("Failed - expected " + Hex.ToHexString(output_des_ede) + + " got " + Hex.ToHexString(output)); + } + } + + public override string Name + { + get { return "CMac"; } + } + + public static void Main(string[] args) + { + RunTest(new CMacTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/CRL5Test.cs b/crypto/test/src/test/CRL5Test.cs new file mode 100644 index 000000000..ebd74af69 --- /dev/null +++ b/crypto/test/src/test/CRL5Test.cs @@ -0,0 +1,257 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class Crl5Test + : SimpleTest + { + private static readonly byte[] indirectCrl = Base64.Decode( + "MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV" + +"BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0" + +"MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO" + +"Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3" + +"MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0" + +"MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/jFw0wMzAx" + +"MTMxMTI2NTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+QXDTAzMDExMzExMjY1NlowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/4hcNMDQwNzEzMDc1ODM4WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/eFw0wMzAy" + +"MTcwNjMzMjVaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP98XDTAzMDIxNzA2MzMyNVowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/0xcNMDMwMjE3MDYzMzI1WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/dFw0wMzAx" + +"MTMxMTI4MTRaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9cXDTAzMDExMzExMjcwN1owZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/2BcNMDMwMTEzMTEyNzA3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/VFw0wMzA0" + +"MzAxMjI3NTNaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9YXDTAzMDQzMDEyMjc1M1owZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/xhcNMDMwMjEyMTM0NTQwWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQTjCBkAIEL64/xRcNMDMw" + +"MjEyMTM0NTQwWjB5MHcGA1UdHQEB/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoG" + +"A1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwG" + +"BwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNTpQTjB+AgQvrj/CFw0w" + +"MzAyMTIxMzA5MTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRww" + +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNV" + +"BAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj/BFw0wMzAyMTIxMzA4NDBaMHkw" + +"dwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No" + +"ZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAY" + +"BgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uP74XDTAzMDIxNzA2MzcyNVow" + +"ZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz" + +"Y2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3Qg" + +"Q0EgMTE6UE4wgZACBC+uP70XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0BAf8EbTBr" + +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx" + +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU" + +"ZXN0IENBIDU6UE4wgZACBC+uP7AXDTAzMDIxMjEzMDg1OVoweTB3BgNVHR0BAf8E" + +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln" + +"RyBUZXN0IENBIDU6UE4wgZACBC+uP68XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0B" + +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr" + +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR" + +"U2lnRyBUZXN0IENBIDU6UE4wfgIEL64/kxcNMDMwNDEwMDUyNjI4WjBnMGUGA1Ud" + +"HQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVs" + +"ZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQ" + +"TjCBkAIEL64/khcNMDMwNDEwMDUyNjI4WjB5MHcGA1UdHQEB/wRtMGukaTBnMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UE" + +"CxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0Eg" + +"NTpQTjB+AgQvrj8/Fw0wMzAyMjYxMTA0NDRaMGcwZQYDVR0dAQH/BFswWaRXMFUx" + +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYH" + +"AoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj8+Fw0w" + +"MzAyMjYxMTA0NDRaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRww" + +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgw" + +"DAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uPs0X" + +"DTAzMDUyMDA1MjczNlowZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUx" + +"HDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgG" + +"A1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZACBC+uPswXDTAzMDUyMDA1MjczNlow" + +"eTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz" + +"Y2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwEx" + +"MBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4wfgIEL64+PBcNMDMwNjE3MTAzNDE2" + +"WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1" + +"dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVz" + +"dCBDQSAxMTpQTjCBkAIEL64+OxcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB/wRt" + +"MGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBB" + +"RzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdH" + +"IFRlc3QgQ0EgNjpQTjCBkAIEL64+OhcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB" + +"/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtv" + +"bSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFT" + +"aWdHIFRlc3QgQ0EgNjpQTjB+AgQvrj45Fw0wMzA2MTcxMzAxMDBaMGcwZQYDVR0d" + +"AQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxl" + +"a29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBO" + +"MIGQAgQvrj44Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJ" + +"BgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQL" + +"FAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA2" + +"OlBOMIGQAgQvrj43Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcx" + +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYD" + +"VQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBD" + +"QSA2OlBOMIGQAgQvrj42Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6Rp" + +"MGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAw" + +"DgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVz" + +"dCBDQSA2OlBOMIGQAgQvrj4zFw0wMzA2MTcxMDM3NDlaMHkwdwYDVR0dAQH/BG0w" + +"a6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH" + +"MRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cg" + +"VGVzdCBDQSA2OlBOMH4CBC+uPjEXDTAzMDYxNzEwNDI1OFowZzBlBgNVHR0BAf8E" + +"WzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZAC" + +"BC+uPjAXDTAzMDYxNzEwNDI1OFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UE" + +"BhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1Rl" + +"bGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4w" + +"gZACBC+uPakXDTAzMTAyMjExMzIyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkG" + +"A1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsU" + +"B1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6" + +"UE4wgZACBC+uPLIXDTA1MDMxMTA2NDQyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzEL" + +"MAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNV" + +"BAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENB" + +"IDY6UE4wgZACBC+uPKsXDTA0MDQwMjA3NTQ1M1oweTB3BgNVHR0BAf8EbTBrpGkw" + +"ZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAO" + +"BgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0" + +"IENBIDY6UE4wgZACBC+uOugXDTA1MDEyNzEyMDMyNFoweTB3BgNVHR0BAf8EbTBr" + +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx" + +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU" + +"ZXN0IENBIDY6UE4wgZACBC+uOr4XDTA1MDIxNjA3NTcxNloweTB3BgNVHR0BAf8E" + +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln" + +"RyBUZXN0IENBIDY6UE4wgZACBC+uOqcXDTA1MDMxMDA1NTkzNVoweTB3BgNVHR0B" + +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr" + +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR" + +"U2lnRyBUZXN0IENBIDY6UE4wgZACBC+uOjwXDTA1MDUxMTEwNDk0NloweTB3BgNV" + +"HR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UE" + +"AxQRU2lnRyBUZXN0IENBIDY6UE4wgaoCBC+sbdUXDTA1MTExMTEwMDMyMVowgZIw" + +"gY8GA1UdHQEB/wSBhDCBgaR/MH0xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0" + +"c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj" + +"MS8wDAYHAoIGAQoHFBMBMTAfBgNVBAMUGFRlbGVTZWMgUEtTIFNpZ0cgQ0EgMTpQ" + +"TjCBlQIEL64uaBcNMDYwMTIzMTAyNTU1WjB+MHwGA1UdHQEB/wRyMHCkbjBsMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEWMBQGA1UE" + +"CxQNWmVudHJhbGUgQm9ubjEnMAwGBwKCBgEKBxQTATEwFwYDVQQDFBBUVEMgVGVz" + +"dCBDQSA5OlBOMIGVAgQvribHFw0wNjA4MDEwOTQ4NDRaMH4wfAYDVR0dAQH/BHIw" + +"cKRuMGwxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH" + +"MRYwFAYDVQQLFA1aZW50cmFsZSBCb25uMScwDAYHAoIGAQoHFBMBMTAXBgNVBAMU" + +"EFRUQyBUZXN0IENBIDk6UE6ggZswgZgwCwYDVR0UBAQCAhEMMB8GA1UdIwQYMBaA" + +"FANbyNumDI9545HwlCF26NuOJC45MA8GA1UdHAEB/wQFMAOEAf8wVwYDVR0SBFAw" + +"ToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1ULVRlbGVTZWMgVGVzdCBESVIg" + +"ODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1kZTANBgkqhkiG9w0BAQUFAAOB" + +"gQBewL5gLFHpeOWO07Vk3Gg7pRDuAlvaovBH4coCyCWpk5jEhUfFSYEDuaQB7do4" + +"IlJmeTHvkI0PIZWJ7bwQ2PVdipPWDx0NVwS/Cz5jUKiS3BbAmZQZOueiKLFpQq3A" + +"b8aOHA7WHU4078/1lM+bgeu33Ln1CGykEbmSjA/oKPi/JA=="); + + private static readonly byte[] directCrl = Base64.Decode( + "MIIGXTCCBckCAQEwCgYGKyQDAwECBQAwdDELMAkGA1UEBhMCREUxHDAaBgNVBAoU" + +"E0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0MS4w" + +"DAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBOFw0w" + +"NjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIElTAVAgQvrj/pFw0wMzA3MjIw" + +"NTQxMjhaMBUCBC+uP+oXDTAzMDcyMjA1NDEyOFowFQIEL64/5xcNMDQwNDA1MTMx" + +"ODE3WjAVAgQvrj/oFw0wNDA0MDUxMzE4MTdaMBUCBC+uP+UXDTAzMDExMzExMTgx" + +"MVowFQIEL64/5hcNMDMwMTEzMTExODExWjAVAgQvrj/jFw0wMzAxMTMxMTI2NTZa" + +"MBUCBC+uP+QXDTAzMDExMzExMjY1NlowFQIEL64/4hcNMDQwNzEzMDc1ODM4WjAV" + +"AgQvrj/eFw0wMzAyMTcwNjMzMjVaMBUCBC+uP98XDTAzMDIxNzA2MzMyNVowFQIE" + +"L64/0xcNMDMwMjE3MDYzMzI1WjAVAgQvrj/dFw0wMzAxMTMxMTI4MTRaMBUCBC+u" + +"P9cXDTAzMDExMzExMjcwN1owFQIEL64/2BcNMDMwMTEzMTEyNzA3WjAVAgQvrj/V" + +"Fw0wMzA0MzAxMjI3NTNaMBUCBC+uP9YXDTAzMDQzMDEyMjc1M1owFQIEL64/xhcN" + +"MDMwMjEyMTM0NTQwWjAVAgQvrj/FFw0wMzAyMTIxMzQ1NDBaMBUCBC+uP8IXDTAz" + +"MDIxMjEzMDkxNlowFQIEL64/wRcNMDMwMjEyMTMwODQwWjAVAgQvrj++Fw0wMzAy" + +"MTcwNjM3MjVaMBUCBC+uP70XDTAzMDIxNzA2MzcyNVowFQIEL64/sBcNMDMwMjEy" + +"MTMwODU5WjAVAgQvrj+vFw0wMzAyMTcwNjM3MjVaMBUCBC+uP5MXDTAzMDQxMDA1" + +"MjYyOFowFQIEL64/khcNMDMwNDEwMDUyNjI4WjAVAgQvrj8/Fw0wMzAyMjYxMTA0" + +"NDRaMBUCBC+uPz4XDTAzMDIyNjExMDQ0NFowFQIEL64+zRcNMDMwNTIwMDUyNzM2" + +"WjAVAgQvrj7MFw0wMzA1MjAwNTI3MzZaMBUCBC+uPjwXDTAzMDYxNzEwMzQxNlow" + +"FQIEL64+OxcNMDMwNjE3MTAzNDE2WjAVAgQvrj46Fw0wMzA2MTcxMDM0MTZaMBUC" + +"BC+uPjkXDTAzMDYxNzEzMDEwMFowFQIEL64+OBcNMDMwNjE3MTMwMTAwWjAVAgQv" + +"rj43Fw0wMzA2MTcxMzAxMDBaMBUCBC+uPjYXDTAzMDYxNzEzMDEwMFowFQIEL64+" + +"MxcNMDMwNjE3MTAzNzQ5WjAVAgQvrj4xFw0wMzA2MTcxMDQyNThaMBUCBC+uPjAX" + +"DTAzMDYxNzEwNDI1OFowFQIEL649qRcNMDMxMDIyMTEzMjI0WjAVAgQvrjyyFw0w" + +"NTAzMTEwNjQ0MjRaMBUCBC+uPKsXDTA0MDQwMjA3NTQ1M1owFQIEL6466BcNMDUw" + +"MTI3MTIwMzI0WjAVAgQvrjq+Fw0wNTAyMTYwNzU3MTZaMBUCBC+uOqcXDTA1MDMx" + +"MDA1NTkzNVowFQIEL646PBcNMDUwNTExMTA0OTQ2WjAVAgQvrG3VFw0wNTExMTEx" + +"MDAzMjFaMBUCBC+uLmgXDTA2MDEyMzEwMjU1NVowFQIEL64mxxcNMDYwODAxMDk0" + +"ODQ0WqCBijCBhzALBgNVHRQEBAICEQwwHwYDVR0jBBgwFoAUA1vI26YMj3njkfCU" + +"IXbo244kLjkwVwYDVR0SBFAwToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1U" + +"LVRlbGVTZWMgVGVzdCBESVIgODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1k" + +"ZTAKBgYrJAMDAQIFAAOBgQArj4eMlbAwuA2aS5O4UUUHQMKKdK/dtZi60+LJMiMY" + +"ojrMIf4+ZCkgm1Ca0Cd5T15MJxVHhh167Ehn/Hd48pdnAP6Dfz/6LeqkIHGWMHR+" + +"z6TXpwWB+P4BdUec1ztz04LypsznrHcLRa91ixg9TZCb1MrOG+InNhleRs1ImXk8" + +"MQ=="); + + public override string Name + { + get { return "CRL5"; } + } + + [Test] + public void TestIndirectCrl() + { + X509Crl crl = new X509CrlParser().ReadCrl(indirectCrl); + + foreach (X509CrlEntry crlEntry in crl.GetRevokedCertificates()) + { + if (crlEntry.GetCertificateIssuer() == null) + { + Fail("certificate issuer CRL entry extension is null"); + } + } + } + + [Test] + public void TestDirectCrl() + { + X509Crl crl = new X509CrlParser().ReadCrl(directCrl); + + foreach (X509CrlEntry crlEntry in crl.GetRevokedCertificates()) + { + if (crlEntry.GetCertificateIssuer() != null) + { + Fail("certificate issuer CRL entry extension is not null"); + } + } + } + + public override void PerformTest() + { + TestIndirectCrl(); + TestDirectCrl(); + } + + public static void Main( + string[] args) + { + RunTest(new Crl5Test()); + } + } +} diff --git a/crypto/test/src/test/CamelliaTest.cs b/crypto/test/src/test/CamelliaTest.cs new file mode 100644 index 000000000..f8e3520a3 --- /dev/null +++ b/crypto/test/src/test/CamelliaTest.cs @@ -0,0 +1,204 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Ntt; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Tests +{ + /// Basic test class for Camellia + [TestFixture] + public class CamelliaTest + : BaseBlockCipherTest + { + internal static readonly string[] cipherTests = + { + "128", + "0123456789abcdeffedcba9876543210", + "0123456789abcdeffedcba9876543210", + "67673138549669730857065648eabe43", + "192", + "0123456789abcdeffedcba98765432100011223344556677", + "0123456789abcdeffedcba9876543210", + "b4993401b3e996f84ee5cee7d79b09b9", + "256", + "0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff", + "0123456789abcdeffedcba9876543210", + "9acc237dff16d76c20ef7c919e3a7509", + }; + + public CamelliaTest() + : base("Camellia") + { + } + + [Test] + public void TestCiphers() + { + for (int i = 0; i != cipherTests.Length; i += 4) + { + doCipherTest(int.Parse(cipherTests[i]), + Hex.Decode(cipherTests[i + 1]), + Hex.Decode(cipherTests[i + 2]), + Hex.Decode(cipherTests[i + 3])); + } + } + + [Test] + public void TestWrap() + { + byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff"); + byte[] out1 = Hex.Decode("635d6ac46eedebd3a7f4a06421a4cbd1746b24795ba2f708"); + + wrapTest(1, "CamelliaWrap", kek1, in1, out1); + } + + [Test] + public void TestOids() + { + string[] oids = { + NttObjectIdentifiers.IdCamellia128Cbc.Id, + NttObjectIdentifiers.IdCamellia192Cbc.Id, + NttObjectIdentifiers.IdCamellia256Cbc.Id + }; + + string[] names = { + "Camellia/CBC/PKCS7Padding", + "Camellia/CBC/PKCS7Padding", + "Camellia/CBC/PKCS7Padding" + }; + + oidTest(oids, names, 1); + } + + [Test] + public void TestWrapOids() + { + string[] wrapOids = { + NttObjectIdentifiers.IdCamellia128Wrap.Id, + NttObjectIdentifiers.IdCamellia192Wrap.Id, + NttObjectIdentifiers.IdCamellia256Wrap.Id + }; + + wrapOidTest(wrapOids, "CamelliaWrap"); + } + + public void doCipherTest( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + KeyParameter key = ParameterUtilities.CreateKeyParameter("Camellia", keyBytes); + + IBufferedCipher inCipher = CipherUtilities.GetCipher("Camellia/ECB/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("Camellia/ECB/NoPadding"); + + try + { + outCipher.Init(true, key); + } + catch (Exception e) + { + Fail("Camellia failed initialisation - " + e.ToString(), e); + } + + try + { + inCipher.Init(false, key); + } + catch (Exception e) + { + Fail("Camellia failed initialisation - " + e.ToString(), e); + } + + // + // encryption pass + // + MemoryStream bOut = new MemoryStream(); + CipherStream cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + Fail("Camellia failed encryption - " + e.ToString(), e); + } + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("Camellia failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + MemoryStream bIn = new MemoryStream(bytes, false); + CipherStream cIn = new CipherStream(bIn, inCipher, null); + + try + { +// DataInputStream dIn = new DataInputStream(cIn); + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { +// bytes[i] = (byte)dIn.read(); + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; +// dIn.readFully(bytes, input.Length / 2, remaining); + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail("Camellia failed encryption - " + e.ToString(), e); + } + + if (!AreEqual(bytes, input)) + { + Fail("Camellia failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + } + + public override void PerformTest() + { + TestCiphers(); + TestWrap(); + TestOids(); + TestWrapOids(); + } + + public static void Main( + string[] args) + { + RunTest(new CamelliaTest()); + } + } +} diff --git a/crypto/test/src/test/CertPathBuilderTest.cs b/crypto/test/src/test/CertPathBuilderTest.cs new file mode 100644 index 000000000..e31bde866 --- /dev/null +++ b/crypto/test/src/test/CertPathBuilderTest.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class CertPathBuilderTest + : SimpleTest + { + private void baseTest() + { +// CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); + X509CertificateParser certParser = new X509CertificateParser(); + X509CrlParser crlParser = new X509CrlParser(); + + // initialise CertStore + X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin); + X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin); + X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin); + X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin); + X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin); + + IList certList = new ArrayList(); + certList.Add(rootCert); + certList.Add(interCert); + certList.Add(finalCert); + + IList crlList = new ArrayList(); + crlList.Add(rootCrl); + crlList.Add(interCrl); + +// CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); +// CertStore store = CertStore.getInstance("Collection", ccsp, "BC"); + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509CrlStore = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + // NB: Month is 1-based in .NET + //DateTime validDate = new DateTime(2008, 9, 4, 14, 49, 10).ToUniversalTime(); + DateTime validDate = new DateTime(2008, 9, 4, 5, 49, 10); + + //Searching for rootCert by subjectDN without CRL + ISet trust = new HashSet(); + trust.Add(new TrustAnchor(rootCert, null)); + +// CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX","BC"); + PkixCertPathBuilder cpb = new PkixCertPathBuilder(); + X509CertStoreSelector targetConstraints = new X509CertStoreSelector(); + targetConstraints.Subject = finalCert.SubjectDN; + PkixBuilderParameters parameters = new PkixBuilderParameters(trust, targetConstraints); +// parameters.addCertStore(store); + parameters.AddStore(x509CertStore); + parameters.AddStore(x509CrlStore); + parameters.Date = new DateTimeObject(validDate); + PkixCertPathBuilderResult result = cpb.Build(parameters); + PkixCertPath path = result.CertPath; + + if (path.Certificates.Count != 2) + { + Fail("wrong number of certs in baseTest path"); + } + } + + private void v0Test() + { + // create certificates and CRLs + AsymmetricCipherKeyPair rootPair = TestUtilities.GenerateRsaKeyPair(); + AsymmetricCipherKeyPair interPair = TestUtilities.GenerateRsaKeyPair(); + AsymmetricCipherKeyPair endPair = TestUtilities.GenerateRsaKeyPair(); + + X509Certificate rootCert = TestUtilities.GenerateRootCert(rootPair); + X509Certificate interCert = TestUtilities.GenerateIntermediateCert(interPair.Public, rootPair.Private, rootCert); + X509Certificate endCert = TestUtilities.GenerateEndEntityCert(endPair.Public, interPair.Private, interCert); + + BigInteger revokedSerialNumber = BigInteger.Two; + X509Crl rootCRL = TestUtilities.CreateCrl(rootCert, rootPair.Private, revokedSerialNumber); + X509Crl interCRL = TestUtilities.CreateCrl(interCert, interPair.Private, revokedSerialNumber); + + // create CertStore to support path building + IList certList = new ArrayList(); + certList.Add(rootCert); + certList.Add(interCert); + certList.Add(endCert); + + IList crlList = new ArrayList(); + crlList.Add(rootCRL); + crlList.Add(interCRL); + +// CollectionCertStoreParameters parameters = new CollectionCertStoreParameters(list); +// CertStore store = CertStore.getInstance("Collection", parameters); + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + IX509Store x509CrlStore = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + ISet trust = new HashSet(); + trust.Add(new TrustAnchor(rootCert, null)); + + // build the path +// CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); + PkixCertPathBuilder builder = new PkixCertPathBuilder(); + X509CertStoreSelector pathConstraints = new X509CertStoreSelector(); + + pathConstraints.Subject = endCert.SubjectDN; + + PkixBuilderParameters buildParams = new PkixBuilderParameters(trust, pathConstraints); +// buildParams.addCertStore(store); + buildParams.AddStore(x509CertStore); + buildParams.AddStore(x509CrlStore); + + buildParams.Date = new DateTimeObject(DateTime.UtcNow); + + PkixCertPathBuilderResult result = builder.Build(buildParams); + PkixCertPath path = result.CertPath; + + if (path.Certificates.Count != 2) + { + Fail("wrong number of certs in v0Test path"); + } + } + + public override void PerformTest() + { + baseTest(); + v0Test(); + } + + public override string Name + { + get { return "CertPathBuilder"; } + } + + public static void Main( + string[] args) + { + RunTest(new CertPathBuilderTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/CertPathTest.cs b/crypto/test/src/test/CertPathTest.cs new file mode 100644 index 000000000..f1a7c94f6 --- /dev/null +++ b/crypto/test/src/test/CertPathTest.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class CertPathTest + : SimpleTest + { + internal static readonly byte[] rootCertBin = Base64.Decode( + "MIIBqzCCARQCAQEwDQYJKoZIhvcNAQEFBQAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRLUjhPe4YUdLo6EcjKcWUOG7CydFTH53Pr1lWjOkbmszYDpkhCTT9LOsI+disk18nkBxSl8DAHTqV+VxtuTPt64iyi10YxyDeep+DwZG/f8cVQv97U3hA9cLurZ2CofkMLGr6JpSGCMZ9FcstcTdHB4lbErIJ54YqfF4pNOs4/AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAgyrTEFY7ALpeY59jL6xFOLpuPqoBOWrUWv6O+zy5BCU0qiX71r3BpigtxRj+DYcfLIM9FNERDoHu3TthD3nwYWUBtFX8N0QUJIdJabxqAMhLjSC744koiFpCYse5Ye3ZvEdFwDzgAQsJTp5eFGgTZPkPzcdhkFJ2p9+OWs+cb24="); + internal static readonly byte[] interCertBin = Base64.Decode( + "MIICSzCCAbSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlMB4XDTA4MDkwNDA0NDUwOFoXDTA4MDkxMTA0NDUwOFowKDEmMCQGA1UEAxMdVGVzdCBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAISS9OOZ2wxzdWny9aVvk4Joq+dwSJ+oqvHUxX3PflZyuiLiCBUOUE4q59dGKdtNX5fIfwyK3cpV0e73Y/0fwfM3m9rOWFrCKOhfeswNTes0w/2PqPVVDDsF/nj7NApuqXwioeQlgTL251RDF4sVoxXqAU7lRkcqwZt3mwqS4KTJAgMBAAGjgY4wgYswRgYDVR0jBD8wPYAUhv8BOT27EB9JaCccJD4YASPP5XWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGWCAQEwHQYDVR0OBBYEFL/IwAGOkHzaQyPZegy79CwM5oTFMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4GBAE4TRgUz4sUvZyVdZxqV+XyNRnqXAeLOOqFGYv2D96tQrS+zjd0elVlT6lFrtchZdOmmX7R6/H/tjMWMcTBICZyRYrvK8cCAmDOI+EIdq5p6lj2Oq6Pbw/wruojAqNrpaR6IkwNpWtdOSSupv4IJL+YU9q2YFTh4R1j3tOkPoFGr"); + internal static readonly byte[] finalCertBin = Base64.Decode( + "MIICRjCCAa+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB8xHTAbBgNVBAMTFFRlc3QgRW5kIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChpUeo0tPYywWKiLlbWKNJBcCpSaLSlaZ+4+yer1AxI5yJIVHP6SAlBghlbD5Qne5ImnN/15cz1xwYAiul6vGKJkVPlFEe2Mr+g/J/WJPQQPsjbZ1G+vxbAwXEDA4KaQrnpjRZFq+CdKHwOjuPLYS/MYQNgdIvDVEQcTbPQ8GaiQIDAQABo4GIMIGFMEYGA1UdIwQ/MD2AFL/IwAGOkHzaQyPZegy79CwM5oTFoSKkIDAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlggEBMB0GA1UdDgQWBBSVkw+VpqBf3zsLc/9GdkK9TzHPwDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0BAQUFAAOBgQBLv/0bVDjzTs/y1vN3FUiZNknEbzupIZduTuXJjqv/vBX+LDPjUfu/+iOCXOSKoRn6nlOWhwB1z6taG2usQkFG8InMkRcPREi2uVgFdhJ/1C3dAWhsdlubjdL926bftXvxnx/koDzyrePW5U96RlOQM2qLvbaky2Giz6hrc3Wl+w=="); + internal static readonly byte[] rootCrlBin = Base64.Decode( + "MIIBYjCBzAIBATANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlFw0wODA5MDQwNDQ1MDhaFw0wODA5MDQwNzMxNDhaMCIwIAIBAhcNMDgwOTA0MDQ0NTA4WjAMMAoGA1UdFQQDCgEJoFYwVDBGBgNVHSMEPzA9gBSG/wE5PbsQH0loJxwkPhgBI8/ldaEipCAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZYIBATAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOBgQCAbaFCo0BNG4AktVf6jjBLeawP1u0ELYkOCEGvYZE0mBpQ+OvFg7subZ6r3lRIj030nUli28sPFtu5ZQMBNcpE4nS1ziF44RfT3Lp5UgHx9x17Krz781iEyV+7zU8YxYMY9wULD+DCuK294kGKIssVNbmTYXZatBNoXQN5CLIocA=="); + internal static readonly byte[] interCrlBin = Base64.Decode( + "MIIBbDCB1gIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZRcNMDgwOTA0MDQ0NTA4WhcNMDgwOTA0MDczMTQ4WjAiMCACAQIXDTA4MDkwNDA0NDUwOFowDDAKBgNVHRUEAwoBCaBWMFQwRgYDVR0jBD8wPYAUv8jAAY6QfNpDI9l6DLv0LAzmhMWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGWCAQEwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADgYEAEVCr5TKs5yguGgLH+dBzmSPoeSIWJFLsgWwJEit/iUDJH3dgYmaczOcGxIDtbYYHLWIHM+P2YRyQz3MEkCXEgm/cx4y7leAmux5l+xQWgmxFPz+197vaphPeCZo+B7V1CWtm518gcq4mrs9ovfgNqgyFj7KGjcBpWdJE32KMt50="); + + /* + * certpath with a circular reference + */ + internal static readonly byte[] certA = Base64.Decode( + "MIIC6jCCAlOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBjTEPMA0GA1UEAxMGSW50" + + "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX" + + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq" + + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2NTda" + + "Fw0xNzAzMzAwODQ0MDBaMIGlMScwJQYDVQQDHh4AQQByAG0AaQBuACAASADkAGIA" + + "ZQByAGwAaQBuAGcxCzAJBgNVBAYTAkNIMQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNV" + + "BAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNwaGVyZSBBRzEQMA4GA1UECxMHVGVzdGlu" + + "ZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5AcHJpdmFzcGhlcmUuY29tMIGfMA0GCSqG" + + "SIb3DQEBAQUAA4GNADCBiQKBgQCfHfyVs5dbxG35H/Thd29qR4NZU88taCu/OWA1" + + "GdACI02lXWYpmLWiDgnU0ULP+GG8OnVp1IES9fz2zcrXKQ19xZzsen/To3h5sNte" + + "cJpS00XMM24q/jDwy5NvkBP9YIfFKQ1E/0hFHXcqwlw+b/y/v6YGsZCU2h6QDzc4" + + "5m0+BwIDAQABo0AwPjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DAeBglg" + + "hkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAJEu" + + "KiSfIwsY7SfobMLrv2v/BtLhGLi4RnmjiwzBhuv5rn4rRfBpq1ppmqQMJ2pmA67v" + + "UWCY+mNwuyjHyivpCCyJGsZ9d5H09g2vqxzkDBMz7X9VNMZYFH8j/R3/Cfvqks31" + + "z0OFslJkeKLa1I0P/dfVHsRKNkLRT3Ws5LKksErQ"); + + internal static readonly byte[] certB = Base64.Decode( + "MIICtTCCAh6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50" + + "ZXIyMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX" + + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq" + + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2Mzha" + + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjMxCzAJBgNVBAYTAkNI" + + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw" + + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A" + + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxCXIB" + + "QRnmVvl2h7Q+0SsRxDLnyM1dJG9jMa+UCCmHy0k/ZHs5VirSbjEJSjkQ9BGeh9SC" + + "7JwbMpXO7UE+gcVc2RnWUY+MA+fWIeTV4KtkYA8WPu8wVGCXbN8wwh/StOocszxb" + + "g+iLvGeh8CYSRqg6QN3S/02etH3o8H4e7Z0PZwIDAQABoyMwITAPBgNVHRMBAf8E" + + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCtWdirSsmt" + + "+CBBCNn6ZnbU3QqQfiiQIomjenNEHESJgaS/+PvPE5i3xWFXsunTHLW321/Km16I" + + "7+ZvT8Su1cqHg79NAT8QB0yke1saKSy2C0Pic4HwrNqVBWFNSxMU0hQzpx/ZXDbZ" + + "DqIXAp5EfyRYBy2ul+jm6Rot6aFgzuopKg=="); + + internal static readonly byte[] certC = Base64.Decode( + "MIICtTCCAh6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50" + + "ZXIxMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX" + + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq" + + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ0Mzla" + + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjIxCzAJBgNVBAYTAkNI" + + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw" + + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A" + + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0rLr6" + + "f2/ONeJzTb0q9M/NNX+MnAFMSqiQGVBkT76u5nOH4KLkpHXkzI82JI7GuQMzoT3a" + + "+RP1hO6FneO92ms2soC6xiOFb4EC69Dfhh87Nww5O35JxVF0bzmbmIAWd6P/7zGh" + + "nd2S4tKkaZcubps+C0j9Fgi0hipVicAOUVVoDQIDAQABoyMwITAPBgNVHRMBAf8E" + + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCLPvc1IMA4" + + "YP+PmnEldyUoRWRnvPWjBGeu0WheBP7fdcnGBf93Nmc5j68ZN+eTZ5VMuZ99YdvH" + + "CXGNX6oodONLU//LlFKdLl5xjLAS5X9p1RbOEGytnalqeiEpjk4+C/7rIBG1kllO" + + "dItmI6LlEMV09Hkpg6ZRAUmRkb8KrM4X7A=="); + + internal static readonly byte[] certD = Base64.Decode( + "MIICtTCCAh6gAwIBAgIBBjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50" + + "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX" + + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq" + + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ5NTNa" + + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjExCzAJBgNVBAYTAkNI" + + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw" + + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A" + + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCae3TP" + + "jIVKeASqvNabaiUHAMGUgFxB7L0yUsIj39azLcLtUj4S7XkDf7SMGtYV0JY1XNaQ" + + "sHJAsnJivDZc50oiYvqDYfgFZx5+AsN5l5X5rjRzs/OX+Jo+k1OgsIyu6+mf9Kfb" + + "5IdWOVB2EcOg4f9tPjLM8CIj9Pp7RbKLyqUUgwIDAQABoyMwITAPBgNVHRMBAf8E" + + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCgr9kUdWUT" + + "Lt9UcztSzR3pnHRsyvS0E/z850OKQKS5/VxLEalpFvhj+3EcZ7Y6mFxaaS2B7vXg" + + "2YWyqV1PRb6iF7/u9EXkpSTKGrJahwANirCa3V/HTUuPdCE2GITlnWI8h3eVA+xQ" + + "D4LF0PXHOkXbwmhXRSb10lW1bSGkUxE9jg=="); + + private void doTestExceptions() + { + byte[] enc = { (byte)0, (byte)2, (byte)3, (byte)4, (byte)5 }; +// MyCertPath mc = new MyCertPath(enc); + MemoryStream os = new MemoryStream(); + MemoryStream ins; + byte[] arr; + + // TODO Support serialization of cert paths? +// ObjectOutputStream oos = new ObjectOutputStream(os); +// oos.WriteObject(mc); +// oos.Flush(); +// oos.Close(); + + try + { +// CertificateFactory cFac = CertificateFactory.GetInstance("X.509"); + arr = os.ToArray(); + ins = new MemoryStream(arr, false); +// cFac.generateCertPath(ins); + new PkixCertPath(ins); + } + catch (CertificateException) + { + // ignore okay + } + +// CertificateFactory cf = CertificateFactory.GetInstance("X.509"); + X509CertificateParser cf = new X509CertificateParser(); + IList certCol = new ArrayList(); + + certCol.Add(cf.ReadCertificate(certA)); + certCol.Add(cf.ReadCertificate(certB)); + certCol.Add(cf.ReadCertificate(certC)); + certCol.Add(cf.ReadCertificate(certD)); + +// CertPathBuilder pathBuilder = CertPathBuilder.GetInstance("PKIX"); + PkixCertPathBuilder pathBuilder = new PkixCertPathBuilder(); + X509CertStoreSelector select = new X509CertStoreSelector(); + select.Subject = ((X509Certificate)certCol[0]).SubjectDN; + + ISet trustanchors = new HashSet(); + trustanchors.Add(new TrustAnchor(cf.ReadCertificate(rootCertBin), null)); + +// CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certCol)); + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certCol)); + + PkixBuilderParameters parameters = new PkixBuilderParameters(trustanchors, select); + parameters.AddStore(x509CertStore); + + try + { + PkixCertPathBuilderResult result = pathBuilder.Build(parameters); + PkixCertPath path = result.CertPath; + Fail("found cert path in circular set"); + } + catch (PkixCertPathBuilderException) + { + // expected + } + } + + public override void PerformTest() + { + X509CertificateParser cf = new X509CertificateParser(); + + X509Certificate rootCert = cf.ReadCertificate(rootCertBin); + X509Certificate interCert = cf.ReadCertificate(interCertBin); + X509Certificate finalCert = cf.ReadCertificate(finalCertBin); + + //Testing CertPath generation from List + IList list = new ArrayList(); + list.Add(interCert); +// CertPath certPath1 = cf.generateCertPath(list); + PkixCertPath certPath1 = new PkixCertPath(list); + + //Testing CertPath encoding as PkiPath + byte[] encoded = certPath1.GetEncoded("PkiPath"); + + //Testing CertPath generation from InputStream + MemoryStream inStream = new MemoryStream(encoded, false); +// CertPath certPath2 = cf.generateCertPath(inStream, "PkiPath"); + PkixCertPath certPath2 = new PkixCertPath(inStream, "PkiPath"); + + //Comparing both CertPathes + if (!certPath2.Equals(certPath1)) + { + Fail("CertPath differ after encoding and decoding."); + } + + encoded = certPath1.GetEncoded("PKCS7"); + + //Testing CertPath generation from InputStream + inStream = new MemoryStream(encoded, false); +// certPath2 = cf.generateCertPath(inStream, "PKCS7"); + certPath2 = new PkixCertPath(inStream, "PKCS7"); + + //Comparing both CertPathes + if (!certPath2.Equals(certPath1)) + { + Fail("CertPath differ after encoding and decoding."); + } + + encoded = certPath1.GetEncoded("PEM"); + + //Testing CertPath generation from InputStream + inStream = new MemoryStream(encoded, false); +// certPath2 = cf.generateCertPath(inStream, "PEM"); + certPath2 = new PkixCertPath(inStream, "PEM"); + + //Comparing both CertPathes + if (!certPath2.Equals(certPath1)) + { + Fail("CertPath differ after encoding and decoding."); + } + + // + // empty list test + // + list = new ArrayList(); + +// CertPath certPath = CertificateFactory.GetInstance("X.509","BC").generateCertPath(list); + PkixCertPath certPath = new PkixCertPath(list); + if (certPath.Certificates.Count != 0) + { + Fail("list wrong size."); + } + + // + // exception tests + // + doTestExceptions(); + } + + public override string Name + { + get { return "CertPath"; } + } + + public static void Main( + string[] args) + { + RunTest(new CertPathTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + +// private class MyCertificate : X509Certificate +// { +// private readonly string type; +// private readonly byte[] encoding; +// +// public MyCertificate(string type, byte[] encoding) +//// : base(type) +// { +// this.type = type; +// +// // don't copy to allow null parameter in test +// this.encoding = encoding; +// } +// +// public override byte[] GetEncoded() +// { +// // do copy to force NPE in test +// return (byte[])encoding.Clone(); +// } +// +// public override void Verify(AsymmetricKeyParameter publicKey) +// { +// } +// +// public override string ToString() +// { +// return "[My test Certificate, type: " + type + "]"; +// } +// +// public override AsymmetricKeyParameter GetPublicKey() +// { +// throw new NotImplementedException(); +// +//// return new PublicKey() +//// { +//// public string getAlgorithm() +//// { +//// return "TEST"; +//// } +//// +//// public byte[] getEncoded() +//// { +//// return new byte[] { (byte)1, (byte)2, (byte)3 }; +//// } +//// +//// public string getFormat() +//// { +//// return "TEST_FORMAT"; +//// } +//// }; +// } +// } + +// private class MyCertPath : PkixCertPath +// { +// private readonly ArrayList certificates; +// +// private readonly ArrayList encodingNames; +// +// private readonly byte[] encoding; +// +// public MyCertPath(byte[] encoding) +// : base("MyEncoding") +// { +// this.encoding = encoding; +// certificates = new ArrayList(); +// certificates.Add(new MyCertificate("MyEncoding", encoding)); +// encodingNames = new ArrayList(); +// encodingNames.Add("MyEncoding"); +// } +// +// public override IList Certificates +// { +// get { return CollectionUtilities.ReadOnly(certificates); } +// } +// +// public override byte[] GetEncoded() +// { +// return (byte[])encoding.Clone(); +// } +// +// public override byte[] GetEncoded( +// string encoding) +// { +// if (Type.Equals(encoding)) +// { +// return (byte[])this.encoding.Clone(); +// } +// throw new CertificateEncodingException("Encoding not supported: " +// + encoding); +// } +// +// public override IEnumerable Encodings +// { +// get { return new EnumerableProxy(encodingNames); } +// } +// } + } +} diff --git a/crypto/test/src/test/CertPathValidatorTest.cs b/crypto/test/src/test/CertPathValidatorTest.cs new file mode 100644 index 000000000..a92bb9b31 --- /dev/null +++ b/crypto/test/src/test/CertPathValidatorTest.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class CertPathValidatorTest + : SimpleTest + { + private byte[] AC_PR = Base64.Decode( + "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFU1RDQ0F6R2dBd0lC" + + "QWdJQkJUQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR" + + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU" + + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs" + + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5" + + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW" + + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy" + + "bHNaV2x5WVRBZUZ3MHdNakEwTURReE9UTTVNREJhRncwd05UQTBNRFF5DQpN" + + "elU1TURCYU1HRXhDekFKQmdOVkJBWVRBa0pTTVJNd0VRWURWUVFLRXdwSlEx" + + "QXRRbkpoYzJsc01UMHdPd1lEDQpWUVFERXpSQmRYUnZjbWxrWVdSbElFTmxj" + + "blJwWm1sallXUnZjbUVnWkdFZ1VISmxjMmxrWlc1amFXRWdaR0VnDQpVbVZ3" + + "ZFdKc2FXTmhNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJD" + + "Z0tDQVFFQXMwc0t5NGsrDQp6b016aldyMTQxeTVYQ045UGJMZERFQXN2cjZ4" + + "Z0NCN1l5bEhIQ1NBYmpGR3dOQ0R5NlVxN1h0VjZ6UHdIMXpGDQpFWENlS3Jm" + + "UUl5YXBXSEZ4V1VKajBMblFrY1RZM1FOR1huK0JuVk9EVTZDV3M1c3NoZktH" + + "RXZyVlQ1Z214V1NmDQp4OFlsdDgzY1dwUE1QZzg3VDlCaHVIbHQzazh2M2Ev" + + "NmRPbmF2dytOYTAyZExBaDBlNzZqcCtQUS9LK0pHZlBuDQphQjVVWURrZkd0" + + "em5uTTNBV01tY3VJK0o0ek5OMDZaa3ZnbDFsdEo2UU1qcnZEUFlSak9ndDlT" + + "cklpY1NmbEo4DQptVDdHWGRRaXJnQUNXc3g1QURBSklRK253TU1vNHlyTUtx" + + "SlFhNFFDMHhhT0QvdkdVcG9SaDQzT0FTZFp3c3YvDQpPWFlybmVJeVAwVCs4" + + "UUlEQVFBQm80RzNNSUcwTUQwR0ExVWRId1EyTURRd01xQXdvQzZHTEdoMGRI" + + "QTZMeTloDQpZM0poYVhvdWFXTndZbkpoYzJsc0xtZHZkaTVpY2k5TVExSmhZ" + + "M0poYVhvdVkzSnNNQklHQTFVZElBUUxNQWt3DQpCd1lGWUV3QkFRRXdIUVlE" + + "VlIwT0JCWUVGREpUVFlKNE9TWVB5T09KZkVMZXhDaHppK2hiTUI4R0ExVWRJ" + + "d1FZDQpNQmFBRklyNjhWZUVFUk0xa0VMNlYwbFVhUTJreFBBM01BNEdBMVVk" + + "RHdFQi93UUVBd0lCQmpBUEJnTlZIUk1CDQpBZjhFQlRBREFRSC9NQTBHQ1Nx" + + "R1NJYjNEUUVCQlFVQUE0SUJBUUJRUFNoZ1lidnFjaWV2SDVVb3ZMeXhkbkYr" + + "DQpFcjlOeXF1SWNkMnZ3Y0N1SnpKMkQ3WDBUcWhHQ0JmUEpVVkdBVWorS0NP" + + "SDFCVkgva1l1OUhsVHB1MGtKWFBwDQpBQlZkb2hJUERqRHhkbjhXcFFSL0Yr" + + "ejFDaWtVcldIMDR4eTd1N1p6UUpLSlBuR0loY1FpOElyRm1PYkllMEc3DQpY" + + "WTZPTjdPRUZxY21KTFFHWWdtRzFXMklXcytQd1JwWTdENGhLVEFoVjFSNkVv" + + "amE1L3BPcmVDL09kZXlQWmVxDQo1SUZTOUZZZk02U0Npd2hrK3l2Q1FHbVo0" + + "YzE5SjM0ZjVFYkRrK1NQR2tEK25EQ0E3L3VMUWNUMlJURE14SzBaDQpuZlo2" + + "Nm1Sc0ZjcXRGaWdScjVFcmtKZDdoUVV6eHNOV0VrNzJEVUFIcVgvNlNjeWtt" + + "SkR2V0plSUpqZlcNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg=="); + + private byte[] AC_RAIZ_ICPBRASIL = Base64.Decode( + "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFdURDQ0E2Q2dBd0lC" + + "QWdJQkJEQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR" + + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU" + + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs" + + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5" + + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW" + + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy" + + "bHNaV2x5WVRBZUZ3MHdNVEV4TXpBeE1qVTRNREJhRncweE1URXhNekF5DQpN" + + "elU1TURCYU1JRzBNUXN3Q1FZRFZRUUdFd0pDVWpFVE1CRUdBMVVFQ2hNS1NV" + + "TlFMVUp5WVhOcGJERTlNRHNHDQpBMVVFQ3hNMFNXNXpkR2wwZFhSdklFNWhZ" + + "Mmx2Ym1Gc0lHUmxJRlJsWTI1dmJHOW5hV0VnWkdFZ1NXNW1iM0p0DQpZV05o" + + "YnlBdElFbFVTVEVSTUE4R0ExVUVCeE1JUW5KaGMybHNhV0V4Q3pBSkJnTlZC" + + "QWdUQWtSR01URXdMd1lEDQpWUVFERXloQmRYUnZjbWxrWVdSbElFTmxjblJw" + + "Wm1sallXUnZjbUVnVW1GcGVpQkNjbUZ6YVd4bGFYSmhNSUlCDQpJakFOQmdr" + + "cWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBd1BNdWR3WC9odm0r" + + "VWgyYi9sUUFjSFZBDQppc2FtYUxrV2Rrd1A5L1MvdE9LSWdSckw2T3krWklH" + + "bE9VZGQ2dVl0azlNYS8zcFVwZ2NmTkFqMHZZbTVnc3lqDQpRbzllbXNjK3g2" + + "bTRWV3drOWlxTVpTQ0s1RVFrQXEvVXQ0bjdLdUxFMStnZGZ0d2RJZ3hmVXNQ" + + "dDRDeU5yWTUwDQpRVjU3S00yVVQ4eDVycm16RWpyN1RJQ0dwU1VBbDJnVnFl" + + "NnhhaWkrYm1ZUjFRcm1XYUJTQUc1OUxya3Jqcll0DQpiUmhGYm9VRGUxREsr" + + "NlQ4czVMNms4Yzhva3BiSHBhOXZlTXp0RFZDOXNQSjYwTVdYaDZhblZLbzFV" + + "Y0xjYlVSDQp5RWVOdlpuZVZSS0FBVTZvdXdkakR2d2xzYUt5ZEZLd2VkMFRv" + + "UTQ3Ym1VS2djbSt3VjNlVFJrMzZVT25Ud0lEDQpBUUFCbzRIU01JSFBNRTRH" + + "QTFVZElBUkhNRVV3UXdZRllFd0JBUUF3T2pBNEJnZ3JCZ0VGQlFjQ0FSWXNh" + + "SFIwDQpjRG92TDJGamNtRnBlaTVwWTNCaWNtRnphV3d1WjI5MkxtSnlMMFJR" + + "UTJGamNtRnBlaTV3WkdZd1BRWURWUjBmDQpCRFl3TkRBeW9EQ2dMb1lzYUhS" + + "MGNEb3ZMMkZqY21GcGVpNXBZM0JpY21GemFXd3VaMjkyTG1KeUwweERVbUZq" + + "DQpjbUZwZWk1amNtd3dIUVlEVlIwT0JCWUVGSXI2OFZlRUVSTTFrRUw2VjBs" + + "VWFRMmt4UEEzTUE4R0ExVWRFd0VCDQovd1FGTUFNQkFmOHdEZ1lEVlIwUEFR" + + "SC9CQVFEQWdFR01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQVpBNWMxDQpV" + + "L2hnSWg2T2NnTEFmaUpnRldwdm1EWldxbFYzMC9iSEZwajhpQm9iSlNtNXVE" + + "cHQ3VGlyWWgxVXhlM2ZRYUdsDQpZakplKzl6ZCtpelBSYkJxWFBWUUEzNEVY" + + "Y3drNHFwV3VmMWhIcmlXZmRyeDhBY3FTcXI2Q3VRRndTcjc1Rm9zDQpTemx3" + + "REFEYTcwbVQ3d1pqQW1RaG5aeDJ4SjZ3ZldsVDlWUWZTLy9KWWVJYzdGdWUy" + + "Sk5MZDAwVU9TTU1haUsvDQp0NzllbktOSEVBMmZ1cEgzdkVpZ2Y1RWg0YlZB" + + "TjVWb2hyVG02TVk1M3g3WFFaWnIxTUU3YTU1bEZFblNlVDB1DQptbE9BalIy" + + "bUFidlNNNVg1b1NaTnJtZXRkenlUajJmbENNOENDN01MYWIwa2tkbmdSSWxV" + + "QkdIRjEvUzVubVBiDQpLKzlBNDZzZDMzb3FLOG44DQotLS0tLUVORCBDRVJU" + + "SUZJQ0FURS0tLS0tDQo="); + + private byte[] schefer = Base64.Decode( + "MIIEnDCCBAWgAwIBAgICIPAwDQYJKoZIhvcNAQEEBQAwgcAxCzAJBgNVBAYT" + + "AkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1MDA4IFdpZXNiYWRl" + + "bjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAYBgNVBAsTEVNDSFVG" + + "QSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBCZW51dHplciBTZXJ2" + + "aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu" + + "ZGUwHhcNMDQwMzMwMTEwODAzWhcNMDUwMzMwMTEwODAzWjCBnTELMAkGA1UE" + + "BhMCREUxCjAIBgNVBAcTASAxIzAhBgNVBAoTGlNIUyBJbmZvcm1hdGlvbnNz" + + "eXN0ZW1lIEFHMRwwGgYDVQQLExM2MDAvMDU5NDktNjAwLzA1OTQ5MRgwFgYD" + + "VQQDEw9TY2hldHRlciBTdGVmYW4xJTAjBgkqhkiG9w0BCQEWFlN0ZWZhbi5T" + + "Y2hldHRlckBzaHMuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJD0" + + "95Bi76fkAMjJNTGPDiLPHmZXNsmakngDeS0juzKMeJA+TjXFouhYh6QyE4Bl" + + "Nf18fT4mInlgLefwf4t6meIWbiseeTo7VQdM+YrbXERMx2uHsRcgZMsiMYHM" + + "kVfYMK3SMJ4nhCmZxrBkoTRed4gXzVA1AA8YjjTqMyyjvt4TAgMBAAGjggHE" + + "MIIBwDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIEsDALBgNVHQ8EBAMC" + + "BNAwOQYJYIZIAYb4QgENBCwWKlplcnRpZmlrYXQgbnVyIGZ1ZXIgU0NIVUZB" + + "LU9ubGluZSBndWVsdGlnLjAdBgNVHQ4EFgQUXReirhBfg0Yhf6MsBWoo/nPa" + + "hGwwge0GA1UdIwSB5TCB4oAUf2UyCaBV9JUeG9lS1Yo6OFBUdEKhgcakgcMw" + + "gcAxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1" + + "MDA4IFdpZXNiYWRlbjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAY" + + "BgNVBAsTEVNDSFVGQSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBC" + + "ZW51dHplciBTZXJ2aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNj" + + "aHVmYS1vbmxpbmUuZGWCAQAwIQYDVR0RBBowGIEWU3RlZmFuLlNjaGV0dGVy" + + "QHNocy5kZTAmBgNVHRIEHzAdgRt6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu" + + "ZGUwDQYJKoZIhvcNAQEEBQADgYEAWzZtN9XQ9uyrFXqSy3hViYwV751+XZr0" + + "YH5IFhIS+9ixNAu8orP3bxqTaMhpwoU7T/oSsyGGSkb3fhzclgUADbA2lrOI" + + "GkeB/m+FArTwRbwpqhCNTwZywOp0eDosgPjCX1t53BB/m/2EYkRiYdDGsot0" + + "kQPOVGSjQSQ4+/D+TM8="); + + public override void PerformTest() + { + X509CertificateParser certParser = new X509CertificateParser(); + X509CrlParser crlParser = new X509CrlParser(); + + // initialise CertStore + X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin); + X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin); + X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin); + X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin); + X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin); + + IList x509Certs = new ArrayList(); + x509Certs.Add(rootCert); + x509Certs.Add(interCert); + x509Certs.Add(finalCert); + + IList x509Crls = new ArrayList(); + x509Crls.Add(rootCrl); + x509Crls.Add(interCrl); + +// CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); +// CertStore store = CertStore.GetInstance("Collection", ccsp); +// X509CollectionStoreParameters ccsp = new X509CollectionStoreParameters(list); + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(x509Certs)); + IX509Store x509CrlStore = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(x509Crls)); + + // NB: Month is 1-based in .NET + //DateTime validDate = new DateTime(2008,9,4,14,49,10).ToUniversalTime(); + DateTime validDate = new DateTime(2008, 9, 4, 5, 49, 10); + + //validating path + IList certchain = new ArrayList(); + certchain.Add(finalCert); + certchain.Add(interCert); +// CertPath cp = CertificateFactory.GetInstance("X.509").GenerateCertPath(certchain); + PkixCertPath cp = new PkixCertPath(certchain); + ISet trust = new HashSet(); + trust.Add(new TrustAnchor(rootCert, null)); + +// CertPathValidator cpv = CertPathValidator.GetInstance("PKIX"); + PkixCertPathValidator cpv = new PkixCertPathValidator(); + PkixParameters param = new PkixParameters(trust); + param.AddStore(x509CertStore); + param.AddStore(x509CrlStore); + param.Date = new DateTimeObject(validDate); + MyChecker checker = new MyChecker(); + param.AddCertPathChecker(checker); + + PkixCertPathValidatorResult result = (PkixCertPathValidatorResult) cpv.Validate(cp, param); + PkixPolicyNode policyTree = result.PolicyTree; + AsymmetricKeyParameter subjectPublicKey = result.SubjectPublicKey; + + if (checker.GetCount() != 2) + { + Fail("checker not evaluated for each certificate"); + } + + if (!subjectPublicKey.Equals(finalCert.GetPublicKey())) + { + Fail("wrong public key returned"); + } + + // + // invalid path containing a valid one test + // + try + { + // initialise CertStore + rootCert = certParser.ReadCertificate(AC_RAIZ_ICPBRASIL); + interCert = certParser.ReadCertificate(AC_PR); + finalCert = certParser.ReadCertificate(schefer); + + x509Certs = new ArrayList(); + x509Certs.Add(rootCert); + x509Certs.Add(interCert); + x509Certs.Add(finalCert); + +// ccsp = new CollectionCertStoreParameters(list); +// store = CertStore.GetInstance("Collection", ccsp); +// ccsp = new X509CollectionStoreParameters(list); + x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(x509Certs)); + + // NB: Month is 1-based in .NET + //validDate = new DateTime(2004,3,21,2,21,10).ToUniversalTime(); + validDate = new DateTime(2004, 3, 20, 19, 21, 10); + + //validating path + certchain = new ArrayList(); + certchain.Add(finalCert); + certchain.Add(interCert); +// cp = CertificateFactory.GetInstance("X.509").GenerateCertPath(certchain); + cp = new PkixCertPath(certchain); + trust = new HashSet(); + trust.Add(new TrustAnchor(rootCert, null)); + +// cpv = CertPathValidator.GetInstance("PKIX"); + cpv = new PkixCertPathValidator(); + param = new PkixParameters(trust); + param.AddStore(x509CertStore); + param.IsRevocationEnabled = false; + param.Date = new DateTimeObject(validDate); + + result =(PkixCertPathValidatorResult) cpv.Validate(cp, param); + policyTree = result.PolicyTree; + subjectPublicKey = result.SubjectPublicKey; + + Fail("Invalid path validated"); + } + catch (Exception e) + { + if (e is PkixCertPathValidatorException + && e.Message.StartsWith("Could not validate certificate signature.")) + { + return; + } + Fail("unexpected exception", e); + } + } + + public override string Name + { + get { return "CertPathValidator"; } + } + + public static void Main( + string[] args) + { + RunTest(new CertPathValidatorTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private class MyChecker + : PkixCertPathChecker + { + private static int count; + + public override void Init(bool forward) + { + } + + public override bool IsForwardCheckingSupported() + { + return true; + } + + public override ISet GetSupportedExtensions() + { + return null; + } + + public override void Check(X509Certificate cert, ICollection unresolvedCritExts) + { + count++; + } + + public int GetCount() + { + return count; + } + } + } +} diff --git a/crypto/test/src/test/CertTest.cs b/crypto/test/src/test/CertTest.cs new file mode 100644 index 000000000..382ff326d --- /dev/null +++ b/crypto/test/src/test/CertTest.cs @@ -0,0 +1,2544 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class CertTest + : SimpleTest + { + // + // server.crt + // + private static readonly 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 + // + private static readonly 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 + // + private static readonly byte[] cert3 = Base64.Decode( + "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" + + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" + + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" + + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" + + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" + + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" + + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" + + "zl9HYIMxATFyqSiD9jsx"); + + // + // v3-cert1.pem + // + private static readonly 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 + // + private static readonly 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="); + + // + // pem encoded pkcs7 + // + private static readonly byte[] cert6 = Base64.Decode( + "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w" + + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG" + + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy" + + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw" + + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi" + + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A" + + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH" + + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF" + + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d" + + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix" + + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR" + + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD" + + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj" + + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy" + + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy" + + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j" + + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg" + + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B" + + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB" + + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc" + + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG" + + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv" + + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B" + + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0" + + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg" + + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ" + + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln" + + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB" + + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx" + + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy" + + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD" + + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl" + + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz" + + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m" + + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb" + + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK" + + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB" + + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0" + + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo" + + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB" + + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R" + + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y" + + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j" + + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu" + + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE" + + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg" + + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG" + + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU" + + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG" + + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w" + + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O" + + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy" + + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA=="); + + // + // dsaWithSHA1 cert + // + private static readonly byte[] cert7 = Base64.Decode( + "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7" + + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh" + + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj" + + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z" + + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa" + + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw" + + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj" + + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE" + + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3" + + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn" + + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc" + + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg" + + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q" + + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH" + + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC" + + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC" + + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY" + + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1" + + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ" + + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T" + + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU" + + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji" + + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID" + + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh" + + "cg=="); + + // + // testcrl.pem + // + private static readonly byte[] crl1 = Base64.Decode( + "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT" + + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw" + + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw" + + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw" + + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw" + + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw" + + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw" + + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw" + + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw" + + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF" + + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ" + + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt" + + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v"); + + // + // ecdsa cert with extra octet string. + // +// private static readonly byte[] oldEcdsa = Base64.Decode( +// "MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ" +// + "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw" +// + "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV" +// + "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w" +// + "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb" +// + "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ" +// + "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5" +// + "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///" +// + "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////" +// + "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/" +// + "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq" +// + "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw" +// + "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G" +// + "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR"); + + private static readonly byte[] uncompressedPtEC = Base64.Decode( + "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ" + + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD" + + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw" + + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK" + + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G" + + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0" + + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ" + + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT" + + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2" + + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7" + + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA" + + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD" + + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn" + + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH" + + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB" + + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI" + + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt" + + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD" + + "z+fauEg="); + + private static readonly byte[] keyUsage = Base64.Decode( + "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE" + + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50" + + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs" + + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp" + + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0" + + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa" + + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV" + + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw" + + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50" + + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL" + + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv" + + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV" + + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173" + + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw" + + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50" + + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff" + + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE" + + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50" + + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD" + + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D" + + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx" + + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW" + + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG" + + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI" + + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ" + + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU" + + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE" + + "PHayXOw="); + + private static readonly byte[] nameCert = Base64.Decode( + "MIIEFjCCA3+gAwIBAgIEdS8BozANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJE"+ + "RTERMA8GA1UEChQIREFURVYgZUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRQ0Eg"+ + "REFURVYgRDAzIDE6UE4wIhgPMjAwMTA1MTAxMDIyNDhaGA8yMDA0MDUwOTEwMjI0"+ + "OFowgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIFAZCYXllcm4xEjAQBgNVBAcUCU7I"+ + "dXJuYmVyZzERMA8GA1UEChQIREFURVYgZUcxHTAbBgNVBAUTFDAwMDAwMDAwMDA4"+ + "OTU3NDM2MDAxMR4wHAYDVQQDFBVEaWV0bWFyIFNlbmdlbmxlaXRuZXIwgaEwDQYJ"+ + "KoZIhvcNAQEBBQADgY8AMIGLAoGBAJLI/LJLKaHoMk8fBECW/od8u5erZi6jI8Ug"+ + "C0a/LZyQUO/R20vWJs6GrClQtXB+AtfiBSnyZOSYzOdfDI8yEKPEv8qSuUPpOHps"+ + "uNCFdLZF1vavVYGEEWs2+y+uuPmg8q1oPRyRmUZ+x9HrDvCXJraaDfTEd9olmB/Z"+ + "AuC/PqpjAgUAwAAAAaOCAcYwggHCMAwGA1UdEwEB/wQCMAAwDwYDVR0PAQH/BAUD"+ + "AwdAADAxBgNVHSAEKjAoMCYGBSskCAEBMB0wGwYIKwYBBQUHAgEWD3d3dy56cy5k"+ + "YXRldi5kZTApBgNVHREEIjAggR5kaWV0bWFyLnNlbmdlbmxlaXRuZXJAZGF0ZXYu"+ + "ZGUwgYQGA1UdIwR9MHuhc6RxMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1"+ + "bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0"+ + "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE6CBACm8LkwDgYHAoIG"+ + "AQoMAAQDAQEAMEcGA1UdHwRAMD4wPKAUoBKGEHd3dy5jcmwuZGF0ZXYuZGWiJKQi"+ + "MCAxCzAJBgNVBAYTAkRFMREwDwYDVQQKFAhEQVRFViBlRzAWBgUrJAgDBAQNMAsT"+ + "A0VVUgIBBQIBATAdBgNVHQ4EFgQUfv6xFP0xk7027folhy+ziZvBJiwwLAYIKwYB"+ + "BQUHAQEEIDAeMBwGCCsGAQUFBzABhhB3d3cuZGlyLmRhdGV2LmRlMA0GCSqGSIb3"+ + "DQEBBQUAA4GBAEOVX6uQxbgtKzdgbTi6YLffMftFr2mmNwch7qzpM5gxcynzgVkg"+ + "pnQcDNlm5AIbS6pO8jTCLfCd5TZ5biQksBErqmesIl3QD+VqtB+RNghxectZ3VEs"+ + "nCUtcE7tJ8O14qwCb3TxS9dvIUFiVi4DjbxX46TdcTbTaK8/qr6AIf+l"); + + private static readonly byte[] probSelfSignedCert = Base64.Decode( + "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF" + + "MScwJQYDVQQKEx4gRElSRUNUSU9OIEdFTkVSQUxFIERFUyBJTVBPVFMxGjAYBgNV" + + "BAMTESBBQyBNSU5FRkkgQiBURVNUMB4XDTA0MDUwNzEyMDAwMFoXDTE0MDUwNzEy" + + "MDAwMFowRTEnMCUGA1UEChMeIERJUkVDVElPTiBHRU5FUkFMRSBERVMgSU1QT1RT" + + "MRowGAYDVQQDExEgQUMgTUlORUZJIEIgVEVTVDCBnzANBgkqhkiG9w0BAQEFAAOB" + + "jQAwgYkCgYEAveoCUOAukZdcFCs2qJk76vSqEX0ZFzHqQ6faBPZWjwkgUNwZ6m6m" + + "qWvvyq1cuxhoDvpfC6NXILETawYc6MNwwxsOtVVIjuXlcF17NMejljJafbPximEt" + + "DQ4LcQeSp4K7FyFlIAMLyt3BQ77emGzU5fjFTvHSUNb3jblx0sV28c0CAwEAAaOB" + + "tTCBsjAfBgNVHSMEGDAWgBSEJ4bLbvEQY8cYMAFKPFD1/fFXlzAdBgNVHQ4EFgQU" + + "hCeGy27xEGPHGDABSjxQ9f3xV5cwDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIB" + + "AQQEAwIBBjA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vYWRvbmlzLnBrNy5jZXJ0" + + "cGx1cy5uZXQvZGdpLXRlc3QuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" + + "AQEFBQADgYEAmToHJWjd3+4zknfsP09H6uMbolHNGG0zTS2lrLKpzcmkQfjhQpT9" + + "LUTBvfs1jdjo9fGmQLvOG+Sm51Rbjglb8bcikVI5gLbclOlvqLkm77otjl4U4Z2/" + + "Y0vP14Aov3Sn3k+17EfReYUZI4liuB95ncobC4e8ZM++LjQcIM0s+Vs="); + + + private static readonly byte[] gost34102001base = Base64.Decode( + "MIIB1DCCAYECEEjpVKXP6Wn1yVz3VeeDQa8wCgYGKoUDAgIDBQAwbTEfMB0G" + + "A1UEAwwWR29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRv" + + "UHJvMQswCQYDVQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIw" + + "MDFAZXhhbXBsZS5jb20wHhcNMDUwMjAzMTUxNjQ2WhcNMTUwMjAzMTUxNjQ2" + + "WjBtMR8wHQYDVQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQK" + + "DAlDcnlwdG9Qcm8xCzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0" + + "UjM0MTAtMjAwMUBleGFtcGxlLmNvbTBjMBwGBiqFAwICEzASBgcqhQMCAiQA" + + "BgcqhQMCAh4BA0MABECElWh1YAIaQHUIzROMMYks/eUFA3pDXPRtKw/nTzJ+" + + "V4/rzBa5lYgD0Jp8ha4P5I3qprt+VsfLsN8PZrzK6hpgMAoGBiqFAwICAwUA" + + "A0EAHw5dw/aw/OiNvHyOE65kvyo4Hp0sfz3csM6UUkp10VO247ofNJK3tsLb" + + "HOLjUaqzefrlGb11WpHYrvWFg+FcLA=="); + + private static readonly byte[] gost341094base = Base64.Decode( + "MIICDzCCAbwCEBcxKsIb0ghYvAQeUjfQdFAwCgYGKoUDAgIEBQAwaTEdMBsG" + + "A1UEAwwUR29zdFIzNDEwLTk0IGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1By" + + "bzELMAkGA1UEBhMCUlUxJzAlBgkqhkiG9w0BCQEWGEdvc3RSMzQxMC05NEBl" + + "eGFtcGxlLmNvbTAeFw0wNTAyMDMxNTE2NTFaFw0xNTAyMDMxNTE2NTFaMGkx" + + "HTAbBgNVBAMMFEdvc3RSMzQxMC05NCBleGFtcGxlMRIwEAYDVQQKDAlDcnlw" + + "dG9Qcm8xCzAJBgNVBAYTAlJVMScwJQYJKoZIhvcNAQkBFhhHb3N0UjM0MTAt" + + "OTRAZXhhbXBsZS5jb20wgaUwHAYGKoUDAgIUMBIGByqFAwICIAIGByqFAwIC" + + "HgEDgYQABIGAu4Rm4XmeWzTYLIB/E6gZZnFX/oxUJSFHbzALJ3dGmMb7R1W+" + + "t7Lzk2w5tUI3JoTiDRCKJA4fDEJNKzsRK6i/ZjkyXJSLwaj+G2MS9gklh8x1" + + "G/TliYoJgmjTXHemD7aQEBON4z58nJHWrA0ILD54wbXCtrcaqCqLRYGTMjJ2" + + "+nswCgYGKoUDAgIEBQADQQBxKNhOmjgz/i5CEgLOyKyz9pFGkDcaymsWYQWV" + + "v7CZ0pTM8IzMzkUBW3GHsUjCFpanFZDfg2zuN+3kT+694n9B"); + + private static readonly byte[] gost341094A = Base64.Decode( + "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOZGVmYXVsdDM0MTAtOTQx" + + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1vbGExDDAKBgNVBAgT" + + "A01FTDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx" + + "MzExNTdaFw0wNjAzMjkxMzExNTdaMIGBMRcwFQYDVQQDEw5kZWZhdWx0MzQxMC05NDENMAsGA1UE" + + "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLW9sYTEMMAoGA1UECBMDTUVMMQsw" + + "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq" + + "hQMCAiACBgcqhQMCAh4BA4GEAASBgIQACDLEuxSdRDGgdZxHmy30g/DUYkRxO9Mi/uSHX5NjvZ31" + + "b7JMEMFqBtyhql1HC5xZfUwZ0aT3UnEFDfFjLP+Bf54gA+LPkQXw4SNNGOj+klnqgKlPvoqMGlwa" + + "+hLPKbS561WpvB2XSTgbV+pqqXR3j6j30STmybelEV3RdS2Now8wDTALBgNVHQ8EBAMCB4AwCgYG" + + "KoUDAgIEBQADQQBCFy7xWRXtNVXflKvDs0pBdBuPzjCMeZAXVxK8vUxsxxKu76d9CsvhgIFknFRi" + + "wWTPiZenvNoJ4R1uzeX+vREm"); + + private static readonly byte[] gost341094B = Base64.Decode( + "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOcGFyYW0xLTM0MTAtOTQx" + + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNVBAgT" + + "A01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx" + + "MzEzNTZaFw0wNjAzMjkxMzEzNTZaMIGBMRcwFQYDVQQDEw5wYXJhbTEtMzQxMC05NDENMAsGA1UE" + + "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMDTWVsMQsw" + + "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq" + + "hQMCAiADBgcqhQMCAh4BA4GEAASBgEa+AAcZmijWs1M9x5Pn9efE8D9ztG1NMoIt0/hNZNqln3+j" + + "lMZjyqPt+kTLIjtmvz9BRDmIDk6FZz+4LhG2OTL7yGpWfrMxMRr56nxomTN9aLWRqbyWmn3brz9Y" + + "AUD3ifnwjjIuW7UM84JNlDTOdxx0XRUfLQIPMCXe9cO02Xskow8wDTALBgNVHQ8EBAMCB4AwCgYG" + + "KoUDAgIEBQADQQBzFcnuYc/639OTW+L5Ecjw9KxGr+dwex7lsS9S1BUgKa3m1d5c+cqI0B2XUFi5" + + "4iaHHJG0dCyjtQYLJr0OZjRw"); + + private static readonly byte[] gost34102001A = Base64.Decode( + "MIICCzCCAbigAwIBAgIBATAKBgYqhQMCAgMFADCBhDEaMBgGA1UEAxMRZGVmYXVsdC0zNDEwLTIw" + + "MDExDTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNV" + + "BAgTA01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAz" + + "MjkxMzE4MzFaFw0wNjAzMjkxMzE4MzFaMIGEMRowGAYDVQQDExFkZWZhdWx0LTM0MTAtMjAwMTEN" + + "MAsGA1UEChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMD" + + "TWVsMQswCQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MGMwHAYGKoUDAgIT" + + "MBIGByqFAwICIwEGByqFAwICHgEDQwAEQG/4c+ZWb10IpeHfmR+vKcbpmSOClJioYmCVgnojw0Xn" + + "ned0KTg7TJreRUc+VX7vca4hLQaZ1o/TxVtfEApK/O6jDzANMAsGA1UdDwQEAwIHgDAKBgYqhQMC" + + "AgMFAANBAN8y2b6HuIdkD3aWujpfQbS1VIA/7hro4vLgDhjgVmev/PLzFB8oTh3gKhExpDo82IEs" + + "ZftGNsbbyp1NFg7zda0="); + + private static readonly byte[] gostCA1 = Base64.Decode( + "MIIDNDCCAuGgAwIBAgIQZLcKDcWcQopF+jp4p9jylDAKBgYqhQMCAgQFADBm" + + "MQswCQYDVQQGEwJSVTEPMA0GA1UEBxMGTW9zY293MRcwFQYDVQQKEw5PT08g" + + "Q3J5cHRvLVBybzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxFzAVBgNVBAMTDkNQ" + + "IENTUCBUZXN0IENBMB4XDTAyMDYwOTE1NTIyM1oXDTA5MDYwOTE1NTkyOVow" + + "ZjELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2NvdzEXMBUGA1UEChMOT09P" + + "IENyeXB0by1Qcm8xFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5D" + + "UCBDU1AgVGVzdCBDQTCBpTAcBgYqhQMCAhQwEgYHKoUDAgIgAgYHKoUDAgIe" + + "AQOBhAAEgYAYglywKuz1nMc9UiBYOaulKy53jXnrqxZKbCCBSVaJ+aCKbsQm" + + "glhRFrw6Mwu8Cdeabo/ojmea7UDMZd0U2xhZFRti5EQ7OP6YpqD0alllo7za" + + "4dZNXdX+/ag6fOORSLFdMpVx5ganU0wHMPk67j+audnCPUj/plbeyccgcdcd" + + "WaOCASIwggEeMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud" + + "DgQWBBTe840gTo4zt2twHilw3PD9wJaX0TCBygYDVR0fBIHCMIG/MDygOqA4" + + "hjYtaHR0cDovL2ZpZXdhbGwvQ2VydEVucm9sbC9DUCUyMENTUCUyMFRlc3Ql" + + "MjBDQSgzKS5jcmwwRKBCoECGPmh0dHA6Ly93d3cuY3J5cHRvcHJvLnJ1L0Nl" + + "cnRFbnJvbGwvQ1AlMjBDU1AlMjBUZXN0JTIwQ0EoMykuY3JsMDmgN6A1hjMt" + + "ZmlsZTovL1xcZmlld2FsbFxDZXJ0RW5yb2xsXENQIENTUCBUZXN0IENBKDMp" + + "LmNybC8wEgYJKwYBBAGCNxUBBAUCAwMAAzAKBgYqhQMCAgQFAANBAIJi7ni7" + + "9rwMR5rRGTFftt2k70GbqyUEfkZYOzrgdOoKiB4IIsIstyBX0/ne6GsL9Xan" + + "G2IN96RB7KrowEHeW+k="); + + private static readonly byte[] gostCA2 = Base64.Decode( + "MIIC2DCCAoWgAwIBAgIQe9ZCugm42pRKNcHD8466zTAKBgYqhQMCAgMFADB+" + + "MRowGAYJKoZIhvcNAQkBFgtzYmFAZGlndC5ydTELMAkGA1UEBhMCUlUxDDAK" + + "BgNVBAgTA01FTDEUMBIGA1UEBxMLWW9zaGthci1PbGExDTALBgNVBAoTBERp" + + "Z3QxDzANBgNVBAsTBkNyeXB0bzEPMA0GA1UEAxMGc2JhLUNBMB4XDTA0MDgw" + + "MzEzMzE1OVoXDTE0MDgwMzEzNDAxMVowfjEaMBgGCSqGSIb3DQEJARYLc2Jh" + + "QGRpZ3QucnUxCzAJBgNVBAYTAlJVMQwwCgYDVQQIEwNNRUwxFDASBgNVBAcT" + + "C1lvc2hrYXItT2xhMQ0wCwYDVQQKEwREaWd0MQ8wDQYDVQQLEwZDcnlwdG8x" + + "DzANBgNVBAMTBnNiYS1DQTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMC" + + "Ah4BA0MABEDMSy10CuOH+i8QKG2UWA4XmCt6+BFrNTZQtS6bOalyDY8Lz+G7" + + "HybyipE3PqdTB4OIKAAPsEEeZOCZd2UXGQm5o4HaMIHXMBMGCSsGAQQBgjcU" + + "AgQGHgQAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud" + + "DgQWBBRJJl3LcNMxkZI818STfoi3ng1xoDBxBgNVHR8EajBoMDGgL6Athito" + + "dHRwOi8vc2JhLmRpZ3QubG9jYWwvQ2VydEVucm9sbC9zYmEtQ0EuY3JsMDOg" + + "MaAvhi1maWxlOi8vXFxzYmEuZGlndC5sb2NhbFxDZXJ0RW5yb2xsXHNiYS1D" + + "QS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwCgYGKoUDAgIDBQADQQA+BRJHbc/p" + + "q8EYl6iJqXCuR+ozRmH7hPAP3c4KqYSC38TClCgBloLapx/3/WdatctFJW/L" + + "mcTovpq088927shE"); + + private static readonly byte[] inDirectCrl = Base64.Decode( + "MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV" + +"BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0" + +"MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO" + +"Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3" + +"MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0" + +"MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/jFw0wMzAx" + +"MTMxMTI2NTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+QXDTAzMDExMzExMjY1NlowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/4hcNMDQwNzEzMDc1ODM4WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/eFw0wMzAy" + +"MTcwNjMzMjVaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP98XDTAzMDIxNzA2MzMyNVowZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/0xcNMDMwMjE3MDYzMzI1WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/dFw0wMzAx" + +"MTMxMTI4MTRaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9cXDTAzMDExMzExMjcwN1owZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/2BcNMDMwMTEzMTEyNzA3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/VFw0wMzA0" + +"MzAxMjI3NTNaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9YXDTAzMDQzMDEyMjc1M1owZzBlBgNV" + +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + +"UE4wfgIEL64/xhcNMDMwMjEyMTM0NTQwWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + +"BgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQTjCBkAIEL64/xRcNMDMw" + +"MjEyMTM0NTQwWjB5MHcGA1UdHQEB/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoG" + +"A1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwG" + +"BwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNTpQTjB+AgQvrj/CFw0w" + +"MzAyMTIxMzA5MTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRww" + +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNV" + +"BAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj/BFw0wMzAyMTIxMzA4NDBaMHkw" + +"dwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No" + +"ZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAY" + +"BgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uP74XDTAzMDIxNzA2MzcyNVow" + +"ZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz" + +"Y2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3Qg" + +"Q0EgMTE6UE4wgZACBC+uP70XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0BAf8EbTBr" + +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx" + +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU" + +"ZXN0IENBIDU6UE4wgZACBC+uP7AXDTAzMDIxMjEzMDg1OVoweTB3BgNVHR0BAf8E" + +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln" + +"RyBUZXN0IENBIDU6UE4wgZACBC+uP68XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0B" + +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr" + +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR" + +"U2lnRyBUZXN0IENBIDU6UE4wfgIEL64/kxcNMDMwNDEwMDUyNjI4WjBnMGUGA1Ud" + +"HQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVs" + +"ZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQ" + +"TjCBkAIEL64/khcNMDMwNDEwMDUyNjI4WjB5MHcGA1UdHQEB/wRtMGukaTBnMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UE" + +"CxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0Eg" + +"NTpQTjB+AgQvrj8/Fw0wMzAyMjYxMTA0NDRaMGcwZQYDVR0dAQH/BFswWaRXMFUx" + +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYH" + +"AoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj8+Fw0w" + +"MzAyMjYxMTA0NDRaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRww" + +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgw" + +"DAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uPs0X" + +"DTAzMDUyMDA1MjczNlowZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUx" + +"HDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgG" + +"A1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZACBC+uPswXDTAzMDUyMDA1MjczNlow" + +"eTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz" + +"Y2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwEx" + +"MBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4wfgIEL64+PBcNMDMwNjE3MTAzNDE2" + +"WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1" + +"dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVz" + +"dCBDQSAxMTpQTjCBkAIEL64+OxcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB/wRt" + +"MGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBB" + +"RzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdH" + +"IFRlc3QgQ0EgNjpQTjCBkAIEL64+OhcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB" + +"/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtv" + +"bSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFT" + +"aWdHIFRlc3QgQ0EgNjpQTjB+AgQvrj45Fw0wMzA2MTcxMzAxMDBaMGcwZQYDVR0d" + +"AQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxl" + +"a29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBO" + +"MIGQAgQvrj44Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJ" + +"BgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQL" + +"FAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA2" + +"OlBOMIGQAgQvrj43Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcx" + +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYD" + +"VQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBD" + +"QSA2OlBOMIGQAgQvrj42Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6Rp" + +"MGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAw" + +"DgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVz" + +"dCBDQSA2OlBOMIGQAgQvrj4zFw0wMzA2MTcxMDM3NDlaMHkwdwYDVR0dAQH/BG0w" + +"a6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH" + +"MRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cg" + +"VGVzdCBDQSA2OlBOMH4CBC+uPjEXDTAzMDYxNzEwNDI1OFowZzBlBgNVHR0BAf8E" + +"WzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZAC" + +"BC+uPjAXDTAzMDYxNzEwNDI1OFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UE" + +"BhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1Rl" + +"bGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4w" + +"gZACBC+uPakXDTAzMTAyMjExMzIyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkG" + +"A1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsU" + +"B1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6" + +"UE4wgZACBC+uPLIXDTA1MDMxMTA2NDQyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzEL" + +"MAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNV" + +"BAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENB" + +"IDY6UE4wgZACBC+uPKsXDTA0MDQwMjA3NTQ1M1oweTB3BgNVHR0BAf8EbTBrpGkw" + +"ZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAO" + +"BgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0" + +"IENBIDY6UE4wgZACBC+uOugXDTA1MDEyNzEyMDMyNFoweTB3BgNVHR0BAf8EbTBr" + +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx" + +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU" + +"ZXN0IENBIDY6UE4wgZACBC+uOr4XDTA1MDIxNjA3NTcxNloweTB3BgNVHR0BAf8E" + +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g" + +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln" + +"RyBUZXN0IENBIDY6UE4wgZACBC+uOqcXDTA1MDMxMDA1NTkzNVoweTB3BgNVHR0B" + +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr" + +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR" + +"U2lnRyBUZXN0IENBIDY6UE4wgZACBC+uOjwXDTA1MDUxMTEwNDk0NloweTB3BgNV" + +"HR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + +"bGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UE" + +"AxQRU2lnRyBUZXN0IENBIDY6UE4wgaoCBC+sbdUXDTA1MTExMTEwMDMyMVowgZIw" + +"gY8GA1UdHQEB/wSBhDCBgaR/MH0xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0" + +"c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj" + +"MS8wDAYHAoIGAQoHFBMBMTAfBgNVBAMUGFRlbGVTZWMgUEtTIFNpZ0cgQ0EgMTpQ" + +"TjCBlQIEL64uaBcNMDYwMTIzMTAyNTU1WjB+MHwGA1UdHQEB/wRyMHCkbjBsMQsw" + +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEWMBQGA1UE" + +"CxQNWmVudHJhbGUgQm9ubjEnMAwGBwKCBgEKBxQTATEwFwYDVQQDFBBUVEMgVGVz" + +"dCBDQSA5OlBOMIGVAgQvribHFw0wNjA4MDEwOTQ4NDRaMH4wfAYDVR0dAQH/BHIw" + +"cKRuMGwxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH" + +"MRYwFAYDVQQLFA1aZW50cmFsZSBCb25uMScwDAYHAoIGAQoHFBMBMTAXBgNVBAMU" + +"EFRUQyBUZXN0IENBIDk6UE6ggZswgZgwCwYDVR0UBAQCAhEMMB8GA1UdIwQYMBaA" + +"FANbyNumDI9545HwlCF26NuOJC45MA8GA1UdHAEB/wQFMAOEAf8wVwYDVR0SBFAw" + +"ToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1ULVRlbGVTZWMgVGVzdCBESVIg" + +"ODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1kZTANBgkqhkiG9w0BAQUFAAOB" + +"gQBewL5gLFHpeOWO07Vk3Gg7pRDuAlvaovBH4coCyCWpk5jEhUfFSYEDuaQB7do4" + +"IlJmeTHvkI0PIZWJ7bwQ2PVdipPWDx0NVwS/Cz5jUKiS3BbAmZQZOueiKLFpQq3A" + +"b8aOHA7WHU4078/1lM+bgeu33Ln1CGykEbmSjA/oKPi/JA=="); + + private static readonly byte[] directCRL = Base64.Decode( + "MIIGXTCCBckCAQEwCgYGKyQDAwECBQAwdDELMAkGA1UEBhMCREUxHDAaBgNVBAoU" + +"E0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0MS4w" + +"DAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBOFw0w" + +"NjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIElTAVAgQvrj/pFw0wMzA3MjIw" + +"NTQxMjhaMBUCBC+uP+oXDTAzMDcyMjA1NDEyOFowFQIEL64/5xcNMDQwNDA1MTMx" + +"ODE3WjAVAgQvrj/oFw0wNDA0MDUxMzE4MTdaMBUCBC+uP+UXDTAzMDExMzExMTgx" + +"MVowFQIEL64/5hcNMDMwMTEzMTExODExWjAVAgQvrj/jFw0wMzAxMTMxMTI2NTZa" + +"MBUCBC+uP+QXDTAzMDExMzExMjY1NlowFQIEL64/4hcNMDQwNzEzMDc1ODM4WjAV" + +"AgQvrj/eFw0wMzAyMTcwNjMzMjVaMBUCBC+uP98XDTAzMDIxNzA2MzMyNVowFQIE" + +"L64/0xcNMDMwMjE3MDYzMzI1WjAVAgQvrj/dFw0wMzAxMTMxMTI4MTRaMBUCBC+u" + +"P9cXDTAzMDExMzExMjcwN1owFQIEL64/2BcNMDMwMTEzMTEyNzA3WjAVAgQvrj/V" + +"Fw0wMzA0MzAxMjI3NTNaMBUCBC+uP9YXDTAzMDQzMDEyMjc1M1owFQIEL64/xhcN" + +"MDMwMjEyMTM0NTQwWjAVAgQvrj/FFw0wMzAyMTIxMzQ1NDBaMBUCBC+uP8IXDTAz" + +"MDIxMjEzMDkxNlowFQIEL64/wRcNMDMwMjEyMTMwODQwWjAVAgQvrj++Fw0wMzAy" + +"MTcwNjM3MjVaMBUCBC+uP70XDTAzMDIxNzA2MzcyNVowFQIEL64/sBcNMDMwMjEy" + +"MTMwODU5WjAVAgQvrj+vFw0wMzAyMTcwNjM3MjVaMBUCBC+uP5MXDTAzMDQxMDA1" + +"MjYyOFowFQIEL64/khcNMDMwNDEwMDUyNjI4WjAVAgQvrj8/Fw0wMzAyMjYxMTA0" + +"NDRaMBUCBC+uPz4XDTAzMDIyNjExMDQ0NFowFQIEL64+zRcNMDMwNTIwMDUyNzM2" + +"WjAVAgQvrj7MFw0wMzA1MjAwNTI3MzZaMBUCBC+uPjwXDTAzMDYxNzEwMzQxNlow" + +"FQIEL64+OxcNMDMwNjE3MTAzNDE2WjAVAgQvrj46Fw0wMzA2MTcxMDM0MTZaMBUC" + +"BC+uPjkXDTAzMDYxNzEzMDEwMFowFQIEL64+OBcNMDMwNjE3MTMwMTAwWjAVAgQv" + +"rj43Fw0wMzA2MTcxMzAxMDBaMBUCBC+uPjYXDTAzMDYxNzEzMDEwMFowFQIEL64+" + +"MxcNMDMwNjE3MTAzNzQ5WjAVAgQvrj4xFw0wMzA2MTcxMDQyNThaMBUCBC+uPjAX" + +"DTAzMDYxNzEwNDI1OFowFQIEL649qRcNMDMxMDIyMTEzMjI0WjAVAgQvrjyyFw0w" + +"NTAzMTEwNjQ0MjRaMBUCBC+uPKsXDTA0MDQwMjA3NTQ1M1owFQIEL6466BcNMDUw" + +"MTI3MTIwMzI0WjAVAgQvrjq+Fw0wNTAyMTYwNzU3MTZaMBUCBC+uOqcXDTA1MDMx" + +"MDA1NTkzNVowFQIEL646PBcNMDUwNTExMTA0OTQ2WjAVAgQvrG3VFw0wNTExMTEx" + +"MDAzMjFaMBUCBC+uLmgXDTA2MDEyMzEwMjU1NVowFQIEL64mxxcNMDYwODAxMDk0" + +"ODQ0WqCBijCBhzALBgNVHRQEBAICEQwwHwYDVR0jBBgwFoAUA1vI26YMj3njkfCU" + +"IXbo244kLjkwVwYDVR0SBFAwToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1U" + +"LVRlbGVTZWMgVGVzdCBESVIgODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1k" + +"ZTAKBgYrJAMDAQIFAAOBgQArj4eMlbAwuA2aS5O4UUUHQMKKdK/dtZi60+LJMiMY" + +"ojrMIf4+ZCkgm1Ca0Cd5T15MJxVHhh167Ehn/Hd48pdnAP6Dfz/6LeqkIHGWMHR+" + +"z6TXpwWB+P4BdUec1ztz04LypsznrHcLRa91ixg9TZCb1MrOG+InNhleRs1ImXk8" + +"MQ=="); + + private static readonly byte[] pkcs7CrlProblem = Base64.Decode( + "MIIwSAYJKoZIhvcNAQcCoIIwOTCCMDUCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCEsAwggP4MIIC4KADAgECAgF1MA0GCSqGSIb3DQEBBQUAMEUx" + + "CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR4wHAYDVQQD" + + "ExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUwHhcNMDQxMjAyMjEyNTM5WhcNMDYx" + + "MjMwMjEyNTM5WjBMMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMR2VvVHJ1c3Qg" + + "SW5jMSYwJAYDVQQDEx1HZW9UcnVzdCBBZG9iZSBPQ1NQIFJlc3BvbmRlcjCB" + + "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4gnNYhtw7U6QeVXZODnGhHMj" + + "+OgZ0DB393rEk6a2q9kq129IA2e03yKBTfJfQR9aWKc2Qj90dsSqPjvTDHFG" + + "Qsagm2FQuhnA3fb1UWhPzeEIdm6bxDsnQ8nWqKqxnWZzELZbdp3I9bBLizIq" + + "obZovzt60LNMghn/unvvuhpeVSsCAwEAAaOCAW4wggFqMA4GA1UdDwEB/wQE" + + "AwIE8DCB5QYDVR0gAQH/BIHaMIHXMIHUBgkqhkiG9y8BAgEwgcYwgZAGCCsG" + + "AQUFBwICMIGDGoGAVGhpcyBjZXJ0aWZpY2F0ZSBoYXMgYmVlbiBpc3N1ZWQg" + + "aW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBBY3JvYmF0IENyZWRlbnRpYWxzIENQ" + + "UyBsb2NhdGVkIGF0IGh0dHA6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNl" + + "cy9jcHMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jl" + + "c291cmNlcy9jcHMwEwYDVR0lBAwwCgYIKwYBBQUHAwkwOgYDVR0fBDMwMTAv" + + "oC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9hZG9iZWNhMS5j" + + "cmwwHwYDVR0jBBgwFoAUq4BZw2WDbR19E70Zw+wajw1HaqMwDQYJKoZIhvcN" + + "AQEFBQADggEBAENJf1BD7PX5ivuaawt90q1OGzXpIQL/ClzEeFVmOIxqPc1E" + + "TFRq92YuxG5b6+R+k+tGkmCwPLcY8ipg6ZcbJ/AirQhohzjlFuT6YAXsTfEj" + + "CqEZfWM2sS7crK2EYxCMmKE3xDfPclYtrAoz7qZvxfQj0TuxHSstHZv39wu2" + + "ZiG1BWiEcyDQyTgqTOXBoZmfJtshuAcXmTpgkrYSrS37zNlPTGh+pMYQ0yWD" + + "c8OQRJR4OY5ZXfdna01mjtJTOmj6/6XPoLPYTq2gQrc2BCeNJ4bEhLb7sFVB" + + "PbwPrpzTE/HRbQHDrzj0YimDxeOUV/UXctgvYwHNtEkcBLsOm/uytMYwggSh" + + "MIIDiaADAgECAgQ+HL0oMA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNVBAYTAlVT" + + "MSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UE" + + "CxMUQWRvYmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3Qg" + + "Q0EwHhcNMDMwMTA4MjMzNzIzWhcNMjMwMTA5MDAwNzIzWjBpMQswCQYDVQQG" + + "EwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxHTAb" + + "BgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYwFAYDVQQDEw1BZG9iZSBS" + + "b290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzE9UhPen" + + "ouczU38/nBKIayyZR2d+Dx65rRSI+cMQ2B3w8NWfaQovWTWwzGypTJwVoJ/O" + + "IL+gz1Ti4CBmRT85hjh+nMSOByLGJPYBErA131XqaZCw24U3HuJOB7JCoWoT" + + "aaBm6oCREVkqmwh5WiBELcm9cziLPC/gQxtdswvwrzUaKf7vppLdgUydPVmO" + + "rTE8QH6bkTYG/OJcjdGNJtVcRc+vZT+xqtJilvSoOOq6YEL09BxKNRXO+E4i" + + "Vg+VGMX4lp+f+7C3eCXpgGu91grwxnSUnfMPUNuad85LcIMjjaDKeCBEXDxU" + + "ZPHqojAZn+pMBk0GeEtekt8i0slns3rSAQIDAQABo4IBTzCCAUswEQYJYIZI" + + "AYb4QgEBBAQDAgAHMIGOBgNVHR8EgYYwgYMwgYCgfqB8pHoweDELMAkGA1UE" + + "BhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMR0w" + + "GwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEWMBQGA1UEAxMNQWRvYmUg" + + "Um9vdCBDQTENMAsGA1UEAxMEQ1JMMTArBgNVHRAEJDAigA8yMDAzMDEwODIz" + + "MzcyM1qBDzIwMjMwMTA5MDAwNzIzWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgw" + + "FoAUgrc4SpOqmxDvgLvZVOLxD/uAnN4wHQYDVR0OBBYEFIK3OEqTqpsQ74C7" + + "2VTi8Q/7gJzeMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjYu" + + "MDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQAy2p9DdcH6b8lv26sdNjc+" + + "vGEZNrcCPB0jWZhsnu5NhedUyCAfp9S74r8Ad30ka3AvXME6dkm10+AjhCpx" + + "aiLzwScpmBX2NZDkBEzDjbyfYRzn/SSM0URDjBa6m02l1DUvvBHOvfdRN42f" + + "kOQU8Rg/vulZEjX5M5LznuDVa5pxm5lLyHHD4bFhCcTl+pHwQjo3fTT5cujN" + + "qmIcIenV9IIQ43sFti1oVgt+fpIsb01yggztVnSynbmrLSsdEF/bJ3Vwj/0d" + + "1+ICoHnlHOX/r2RAUS2em0fbQqV8H8KmSLDXvpJpTaT2KVfFeBEY3IdRyhOy" + + "Yp1PKzK9MaXB+lKrBYjIMIIEyzCCA7OgAwIBAgIEPhy9tTANBgkqhkiG9w0B" + + "AQUFADBpMQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJ" + + "bmNvcnBvcmF0ZWQxHTAbBgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYw" + + "FAYDVQQDEw1BZG9iZSBSb290IENBMB4XDTA0MDExNzAwMDMzOVoXDTE1MDEx" + + "NTA4MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu" + + "Yy4xHjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTCCASIwDQYJKoZI" + + "hvcNAQEBBQADggEPADCCAQoCggEBAKfld+BkeFrnOYW8r9L1WygTDlTdSfrO" + + "YvWS/Z6Ye5/l+HrBbOHqQCXBcSeCpz7kB2WdKMh1FOE4e9JlmICsHerBLdWk" + + "emU+/PDb69zh8E0cLoDfxukF6oVPXj6WSThdSG7H9aXFzRr6S3XGCuvgl+Qw" + + "DTLiLYW+ONF6DXwt3TQQtKReJjOJZk46ZZ0BvMStKyBaeB6DKZsmiIo89qso" + + "13VDZINH2w1KvXg0ygDizoNtbvgAPFymwnsINS1klfQlcvn0x0RJm9bYQXK3" + + "5GNZAgL3M7Lqrld0jMfIUaWvuHCLyivytRuzq1dJ7E8rmidjDEk/G+27pf13" + + "fNZ7vR7M+IkCAwEAAaOCAZ0wggGZMBIGA1UdEwEB/wQIMAYBAf8CAQEwUAYD" + + "VR0gBEkwRzBFBgkqhkiG9y8BAgEwODA2BggrBgEFBQcCARYqaHR0cHM6Ly93" + + "d3cuYWRvYmUuY29tL21pc2MvcGtpL2Nkc19jcC5odG1sMBQGA1UdJQQNMAsG" + + "CSqGSIb3LwEBBTCBsgYDVR0fBIGqMIGnMCKgIKAehhxodHRwOi8vY3JsLmFk" + + "b2JlLmNvbS9jZHMuY3JsMIGAoH6gfKR6MHgxCzAJBgNVBAYTAlVTMSMwIQYD" + + "VQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRv" + + "YmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0ExDTAL" + + "BgNVBAMTBENSTDEwCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFIK3OEqTqpsQ" + + "74C72VTi8Q/7gJzeMB0GA1UdDgQWBBSrgFnDZYNtHX0TvRnD7BqPDUdqozAZ" + + "BgkqhkiG9n0HQQAEDDAKGwRWNi4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA" + + "PzlZLqIAjrFeEWEs0uC29YyJhkXOE9mf3YSaFGsITF+Gl1j0pajTjyH4R35Q" + + "r3floW2q3HfNzTeZ90Jnr1DhVERD6zEMgJpCtJqVuk0sixuXJHghS/KicKf4" + + "YXJJPx9epuIRF1siBRnznnF90svmOJMXApc0jGnYn3nQfk4kaShSnDaYaeYR" + + "DJKcsiWhl6S5zfwS7Gg8hDeyckhMQKKWnlG1CQrwlSFisKCduoodwRtWgft8" + + "kx13iyKK3sbalm6vnVc+5nufS4vI+TwMXoV63NqYaSroafBWk0nL53zGXPEy" + + "+A69QhzEViJKn2Wgqt5gt++jMMNImbRObIqgfgF1VjCCBUwwggQ0oAMCAQIC" + + "AgGDMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1H" + + "ZW9UcnVzdCBJbmMuMR4wHAYDVQQDExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUw" + + "HhcNMDYwMzI0MTU0MjI5WhcNMDkwNDA2MTQ0MjI5WjBzMQswCQYDVQQGEwJV" + + "UzELMAkGA1UECBMCTUExETAPBgNVBAoTCEdlb1RydXN0MR0wGwYDVQQDExRN" + + "YXJrZXRpbmcgRGVwYXJ0bWVudDElMCMGCSqGSIb3DQEJARYWbWFya2V0aW5n" + + "QGdlb3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB" + + "ANmvajTO4XJvAU2nVcLmXeCnAQX7RZt+7+ML3InmqQ3LCGo1weop09zV069/" + + "1x/Nmieol7laEzeXxd2ghjGzwfXafqQEqHn6+vBCvqdNPoSi63fSWhnuDVWp" + + "KVDOYgxOonrXl+Cc43lu4zRSq+Pi5phhrjDWcH74a3/rdljUt4c4GFezFXfa" + + "w2oTzWkxj2cTSn0Szhpr17+p66UNt8uknlhmu4q44Speqql2HwmCEnpLYJrK" + + "W3fOq5D4qdsvsLR2EABLhrBezamLI3iGV8cRHOUTsbTMhWhv/lKfHAyf4XjA" + + "z9orzvPN5jthhIfICOFq/nStTgakyL4Ln+nFAB/SMPkCAwEAAaOCAhYwggIS" + + "MA4GA1UdDwEB/wQEAwIF4DCB5QYDVR0gAQH/BIHaMIHXMIHUBgkqhkiG9y8B" + + "AgEwgcYwgZAGCCsGAQUFBwICMIGDGoGAVGhpcyBjZXJ0aWZpY2F0ZSBoYXMg" + + "YmVlbiBpc3N1ZWQgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBBY3JvYmF0IENy" + + "ZWRlbnRpYWxzIENQUyBsb2NhdGVkIGF0IGh0dHA6Ly93d3cuZ2VvdHJ1c3Qu" + + "Y29tL3Jlc291cmNlcy9jcHMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2Vv" + + "dHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwOgYDVR0fBDMwMTAvoC2gK4YpaHR0" + + "cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9hZG9iZWNhMS5jcmwwHwYDVR0j" + + "BBgwFoAUq4BZw2WDbR19E70Zw+wajw1HaqMwRAYIKwYBBQUHAQEEODA2MDQG" + + "CCsGAQUFBzABhihodHRwOi8vYWRvYmUtb2NzcC5nZW90cnVzdC5jb20vcmVz" + + "cG9uZGVyMBQGA1UdJQQNMAsGCSqGSIb3LwEBBTA8BgoqhkiG9y8BAQkBBC4w" + + "LAIBAYYnaHR0cDovL2Fkb2JlLXRpbWVzdGFtcC5nZW90cnVzdC5jb20vdHNh" + + "MBMGCiqGSIb3LwEBCQIEBTADAgEBMAwGA1UdEwQFMAMCAQAwDQYJKoZIhvcN" + + "AQEFBQADggEBAAOhy6QxOo+i3h877fvDvTa0plGD2bIqK7wMdNqbMDoSWied" + + "FIcgcBOIm2wLxOjZBAVj/3lDq59q2rnVeNnfXM0/N0MHI9TumHRjU7WNk9e4" + + "+JfJ4M+c3anrWOG3NE5cICDVgles+UHjXetHWql/LlP04+K2ZOLb6LE2xGnI" + + "YyLW9REzCYNAVF+/WkYdmyceHtaBZdbyVAJq0NAJPsfgY1pWcBo31Mr1fpX9" + + "WrXNTYDCqMyxMImJTmN3iI68tkXlNrhweQoArKFqBysiBkXzG/sGKYY6tWKU" + + "pzjLc3vIp/LrXC5zilROes8BSvwu1w9qQrJNcGwo7O4uijoNtyYil1Exgh1Q" + + "MIIdTAIBATBLMEUxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJ" + + "bmMuMR4wHAYDVQQDExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUCAgGDMAkGBSsO" + + "AwIaBQCgggxMMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwIwYJKoZIhvcN" + + "AQkEMRYEFP4R6qIdpQJzWyzrqO8X1ZfJOgChMIIMCQYJKoZIhvcvAQEIMYIL" + + "+jCCC/agggZ5MIIGdTCCA6gwggKQMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV" + + "BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR4wHAYDVQQDExVHZW9U" + + "cnVzdCBDQSBmb3IgQWRvYmUXDTA2MDQwNDE3NDAxMFoXDTA2MDQwNTE3NDAx" + + "MFowggIYMBMCAgC5Fw0wNTEwMTEyMDM2MzJaMBICAVsXDTA0MTEwNDE1MDk0" + + "MVowEwICALgXDTA1MTIxMjIyMzgzOFowEgIBWhcNMDQxMTA0MTUwOTMzWjAT" + + "AgIA5hcNMDUwODI3MDQwOTM4WjATAgIAtxcNMDYwMTE2MTc1NTEzWjATAgIA" + + "hhcNMDUxMjEyMjIzODU1WjATAgIAtRcNMDUwNzA2MTgzODQwWjATAgIA4BcN" + + "MDYwMzIwMDc0ODM0WjATAgIAgRcNMDUwODAyMjIzMTE1WjATAgIA3xcNMDUx" + + "MjEyMjIzNjUwWjASAgFKFw0wNDExMDQxNTA5MTZaMBICAUQXDTA0MTEwNDE1" + + "MDg1M1owEgIBQxcNMDQxMDAzMDEwMDQwWjASAgFsFw0wNDEyMDYxOTQ0MzFa" + + "MBMCAgEoFw0wNjAzMDkxMjA3MTJaMBMCAgEkFw0wNjAxMTYxNzU1MzRaMBIC" + + "AWcXDTA1MDMxODE3NTYxNFowEwICAVEXDTA2MDEzMTExMjcxMVowEgIBZBcN" + + "MDQxMTExMjI0ODQxWjATAgIA8RcNMDUwOTE2MTg0ODAxWjATAgIBThcNMDYw" + + "MjIxMjAxMDM2WjATAgIAwRcNMDUxMjEyMjIzODE2WjASAgFiFw0wNTAxMTAx" + + "NjE5MzRaMBICAWAXDTA1MDExMDE5MDAwNFowEwICAL4XDTA1MDUxNzE0NTYx" + + "MFowDQYJKoZIhvcNAQEFBQADggEBAEKhRMS3wVho1U3EvEQJZC8+JlUngmZQ" + + "A78KQbHPWNZWFlNvPuf/b0s7Lu16GfNHXh1QAW6Y5Hi1YtYZ3YOPyMd4Xugt" + + "gCdumbB6xtKsDyN5RvTht6ByXj+CYlYqsL7RX0izJZ6mJn4fjMkqzPKNOjb8" + + "kSn5T6rn93BjlATtCE8tPVOM8dnqGccRE0OV59+nDBXc90UMt5LdEbwaUOap" + + "snVB0oLcNm8d/HnlVH6RY5LnDjrT4vwfe/FApZtTecEWsllVUXDjSpwfcfD/" + + "476/lpGySB2otALqzImlA9R8Ok3hJ8dnF6hhQ5Oe6OJMnGYgdhkKbxsKkdib" + + "tTVl3qmH5QAwggLFMIIBrQIBATANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQG" + + "EwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxHTAb" + + "BgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYwFAYDVQQDEw1BZG9iZSBS" + + "b290IENBFw0wNjAxMjcxODMzMzFaFw0wNzAxMjcwMDAwMDBaMIHeMCMCBD4c" + + "vUAXDTAzMDEyMTIzNDY1NlowDDAKBgNVHRUEAwoBBDAjAgQ+HL1BFw0wMzAx" + + "MjEyMzQ3MjJaMAwwCgYDVR0VBAMKAQQwIwIEPhy9YhcNMDMwMTIxMjM0NzQy" + + "WjAMMAoGA1UdFQQDCgEEMCMCBD4cvWEXDTA0MDExNzAxMDg0OFowDDAKBgNV" + + "HRUEAwoBBDAjAgQ+HL2qFw0wNDAxMTcwMTA5MDVaMAwwCgYDVR0VBAMKAQQw" + + "IwIEPhy9qBcNMDQwMTE3MDEzOTI5WjAMMAoGA1UdFQQDCgEEoC8wLTAKBgNV" + + "HRQEAwIBDzAfBgNVHSMEGDAWgBSCtzhKk6qbEO+Au9lU4vEP+4Cc3jANBgkq" + + "hkiG9w0BAQUFAAOCAQEAwtXF9042wG39icUlsotn5tpE3oCusLb/hBpEONhx" + + "OdfEQOq0w5hf/vqaxkcf71etA+KpbEUeSVaHMHRPhx/CmPrO9odE139dJdbt" + + "9iqbrC9iZokFK3h/es5kg73xujLKd7C/u5ngJ4mwBtvhMLjFjF2vJhPKHL4C" + + "IgMwdaUAhrcNzy16v+mw/VGJy3Fvc6oCESW1K9tvFW58qZSNXrMlsuidgunM" + + "hPKG+z0SXVyCqL7pnqKiaGddcgujYGOSY4S938oVcfZeZQEODtSYGlzldojX" + + "C1U1hCK5+tHAH0Ox/WqRBIol5VCZQwJftf44oG8oviYq52aaqSejXwmfT6zb" + + "76GCBXUwggVxMIIFbQoBAKCCBWYwggViBgkrBgEFBQcwAQEEggVTMIIFTzCB" + + "taIWBBS+8EpykfXdl4h3z7m/NZfdkAQQERgPMjAwNjA0MDQyMDIwMTVaMGUw" + + "YzA7MAkGBSsOAwIaBQAEFEb4BuZYkbjBjOjT6VeA/00fBvQaBBT3fTSQniOp" + + "BbHBSkz4xridlX0bsAICAYOAABgPMjAwNjA0MDQyMDIwMTVaoBEYDzIwMDYw" + + "NDA1MDgyMDE1WqEjMCEwHwYJKwYBBQUHMAECBBIEEFqooq/R2WltD7TposkT" + + "BhMwDQYJKoZIhvcNAQEFBQADgYEAMig6lty4b0JDsT/oanfQG5x6jVKPACpp" + + "1UA9SJ0apJJa7LeIdDFmu5C2S/CYiKZm4A4P9cAu0YzgLHxE4r6Op+HfVlAG" + + "6bzUe1P/hi1KCJ8r8wxOZAktQFPSzs85RAZwkHMfB0lP2e/h666Oye+Zf8VH" + + "RaE+/xZ7aswE89HXoumgggQAMIID/DCCA/gwggLgoAMCAQICAXUwDQYJKoZI" + + "hvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu" + + "Yy4xHjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTAeFw0wNDEyMDIy" + + "MTI1MzlaFw0wNjEyMzAyMTI1MzlaMEwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK" + + "EwxHZW9UcnVzdCBJbmMxJjAkBgNVBAMTHUdlb1RydXN0IEFkb2JlIE9DU1Ag" + + "UmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiCc1iG3Dt" + + "TpB5Vdk4OcaEcyP46BnQMHf3esSTprar2SrXb0gDZ7TfIoFN8l9BH1pYpzZC" + + "P3R2xKo+O9MMcUZCxqCbYVC6GcDd9vVRaE/N4Qh2bpvEOydDydaoqrGdZnMQ" + + "tlt2ncj1sEuLMiqhtmi/O3rQs0yCGf+6e++6Gl5VKwIDAQABo4IBbjCCAWow" + + "DgYDVR0PAQH/BAQDAgTwMIHlBgNVHSABAf8EgdowgdcwgdQGCSqGSIb3LwEC" + + "ATCBxjCBkAYIKwYBBQUHAgIwgYMagYBUaGlzIGNlcnRpZmljYXRlIGhhcyBi" + + "ZWVuIGlzc3VlZCBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIEFjcm9iYXQgQ3Jl" + + "ZGVudGlhbHMgQ1BTIGxvY2F0ZWQgYXQgaHR0cDovL3d3dy5nZW90cnVzdC5j" + + "b20vcmVzb3VyY2VzL2NwczAxBggrBgEFBQcCARYlaHR0cDovL3d3dy5nZW90" + + "cnVzdC5jb20vcmVzb3VyY2VzL2NwczATBgNVHSUEDDAKBggrBgEFBQcDCTA6" + + "BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxz" + + "L2Fkb2JlY2ExLmNybDAfBgNVHSMEGDAWgBSrgFnDZYNtHX0TvRnD7BqPDUdq" + + "ozANBgkqhkiG9w0BAQUFAAOCAQEAQ0l/UEPs9fmK+5prC33SrU4bNekhAv8K" + + "XMR4VWY4jGo9zURMVGr3Zi7Eblvr5H6T60aSYLA8txjyKmDplxsn8CKtCGiH" + + "OOUW5PpgBexN8SMKoRl9YzaxLtysrYRjEIyYoTfEN89yVi2sCjPupm/F9CPR" + + "O7EdKy0dm/f3C7ZmIbUFaIRzINDJOCpM5cGhmZ8m2yG4BxeZOmCSthKtLfvM" + + "2U9MaH6kxhDTJYNzw5BElHg5jlld92drTWaO0lM6aPr/pc+gs9hOraBCtzYE" + + "J40nhsSEtvuwVUE9vA+unNMT8dFtAcOvOPRiKYPF45RX9Rdy2C9jAc20SRwE" + + "uw6b+7K0xjANBgkqhkiG9w0BAQEFAASCAQC7a4yICFGCEMPlJbydK5qLG3rV" + + "sip7Ojjz9TB4nLhC2DgsIHds8jjdq2zguInluH2nLaBCVS+qxDVlTjgbI2cB" + + "TaWS8nglC7nNjzkKAsa8vThA8FZUVXTW0pb74jNJJU2AA27bb4g+4WgunCrj" + + "fpYp+QjDyMmdrJVqRmt5eQN+dpVxMS9oq+NrhOSEhyIb4/rejgNg9wnVK1ms" + + "l5PxQ4x7kpm7+Ua41//owkJVWykRo4T1jo4eHEz1DolPykAaKie2VKH/sMqR" + + "Spjh4E5biKJLOV9fKivZWKAXByXfwUbbMsJvz4v/2yVHFy9xP+tqB5ZbRoDK" + + "k8PzUyCprozn+/22oYIPijCCD4YGCyqGSIb3DQEJEAIOMYIPdTCCD3EGCSqG" + + "SIb3DQEHAqCCD2Iwgg9eAgEDMQswCQYFKw4DAhoFADCB+gYLKoZIhvcNAQkQ" + + "AQSggeoEgecwgeQCAQEGAikCMCEwCQYFKw4DAhoFAAQUoT97qeCv3FXYaEcS" + + "gY8patCaCA8CAiMHGA8yMDA2MDQwNDIwMjA1N1owAwIBPAEB/wIIO0yRre3L" + + "8/6ggZCkgY0wgYoxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNl" + + "dHRzMRAwDgYDVQQHEwdOZWVkaGFtMRUwEwYDVQQKEwxHZW9UcnVzdCBJbmMx" + + "EzARBgNVBAsTClByb2R1Y3Rpb24xJTAjBgNVBAMTHGFkb2JlLXRpbWVzdGFt" + + "cC5nZW90cnVzdC5jb22gggzJMIIDUTCCAjmgAwIBAgICAI8wDQYJKoZIhvcN" + + "AQEFBQAwRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4x" + + "HjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTAeFw0wNTAxMTAwMTI5" + + "MTBaFw0xNTAxMTUwODAwMDBaMIGKMQswCQYDVQQGEwJVUzEWMBQGA1UECBMN" + + "TWFzc2FjaHVzZXR0czEQMA4GA1UEBxMHTmVlZGhhbTEVMBMGA1UEChMMR2Vv" + + "VHJ1c3QgSW5jMRMwEQYDVQQLEwpQcm9kdWN0aW9uMSUwIwYDVQQDExxhZG9i" + + "ZS10aW1lc3RhbXAuZ2VvdHJ1c3QuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN" + + "ADCBiQKBgQDRbxJotLFPWQuuEDhKtOMaBUJepGxIvWxeahMbq1DVmqnk88+j" + + "w/5lfPICPzQZ1oHrcTLSAFM7Mrz3pyyQKQKMqUyiemzuG/77ESUNfBNSUfAF" + + "PdtHuDMU8Is8ABVnFk63L+wdlvvDIlKkE08+VTKCRdjmuBVltMpQ6QcLFQzm" + + "AQIDAQABo4GIMIGFMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly9jcmwuZ2Vv" + + "dHJ1c3QuY29tL2NybHMvYWRvYmVjYTEuY3JsMB8GA1UdIwQYMBaAFKuAWcNl" + + "g20dfRO9GcPsGo8NR2qjMA4GA1UdDwEB/wQEAwIGwDAWBgNVHSUBAf8EDDAK" + + "BggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAQEAmnyXjdtX+F79Nf0KggTd" + + "6YC2MQD9s09IeXTd8TP3rBmizfM+7f3icggeCGakNfPRmIUMLoa0VM5Kt37T" + + "2X0TqzBWusfbKx7HnX4v1t/G8NJJlT4SShSHv+8bjjU4lUoCmW2oEcC5vXwP" + + "R5JfjCyois16npgcO05ZBT+LLDXyeBijE6qWmwLDfEpLyILzVRmyU4IE7jvm" + + "rgb3GXwDUvd3yQXGRRHbPCh3nj9hBGbuzyt7GnlqnEie3wzIyMG2ET/wvTX5" + + "4BFXKNe7lDLvZj/MXvd3V7gMTSVW0kAszKao56LfrVTgp1VX3UBQYwmQqaoA" + + "UwFezih+jEvjW6cYJo/ErDCCBKEwggOJoAMCAQICBD4cvSgwDQYJKoZIhvcN" + + "AQEFBQAwaTELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMg" + + "SW5jb3Jwb3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEW" + + "MBQGA1UEAxMNQWRvYmUgUm9vdCBDQTAeFw0wMzAxMDgyMzM3MjNaFw0yMzAx" + + "MDkwMDA3MjNaMGkxCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0" + + "ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRvYmUgVHJ1c3QgU2Vydmlj" + + "ZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUA" + + "A4IBDwAwggEKAoIBAQDMT1SE96ei5zNTfz+cEohrLJlHZ34PHrmtFIj5wxDY" + + "HfDw1Z9pCi9ZNbDMbKlMnBWgn84gv6DPVOLgIGZFPzmGOH6cxI4HIsYk9gES" + + "sDXfVeppkLDbhTce4k4HskKhahNpoGbqgJERWSqbCHlaIEQtyb1zOIs8L+BD" + + "G12zC/CvNRop/u+mkt2BTJ09WY6tMTxAfpuRNgb84lyN0Y0m1VxFz69lP7Gq" + + "0mKW9Kg46rpgQvT0HEo1Fc74TiJWD5UYxfiWn5/7sLd4JemAa73WCvDGdJSd" + + "8w9Q25p3zktwgyONoMp4IERcPFRk8eqiMBmf6kwGTQZ4S16S3yLSyWezetIB" + + "AgMBAAGjggFPMIIBSzARBglghkgBhvhCAQEEBAMCAAcwgY4GA1UdHwSBhjCB" + + "gzCBgKB+oHykejB4MQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lz" + + "dGVtcyBJbmNvcnBvcmF0ZWQxHTAbBgNVBAsTFEFkb2JlIFRydXN0IFNlcnZp" + + "Y2VzMRYwFAYDVQQDEw1BZG9iZSBSb290IENBMQ0wCwYDVQQDEwRDUkwxMCsG" + + "A1UdEAQkMCKADzIwMDMwMTA4MjMzNzIzWoEPMjAyMzAxMDkwMDA3MjNaMAsG" + + "A1UdDwQEAwIBBjAfBgNVHSMEGDAWgBSCtzhKk6qbEO+Au9lU4vEP+4Cc3jAd" + + "BgNVHQ4EFgQUgrc4SpOqmxDvgLvZVOLxD/uAnN4wDAYDVR0TBAUwAwEB/zAd" + + "BgkqhkiG9n0HQQAEEDAOGwhWNi4wOjQuMAMCBJAwDQYJKoZIhvcNAQEFBQAD" + + "ggEBADLan0N1wfpvyW/bqx02Nz68YRk2twI8HSNZmGye7k2F51TIIB+n1Lvi" + + "vwB3fSRrcC9cwTp2SbXT4COEKnFqIvPBJymYFfY1kOQETMONvJ9hHOf9JIzR" + + "REOMFrqbTaXUNS+8Ec6991E3jZ+Q5BTxGD++6VkSNfkzkvOe4NVrmnGbmUvI" + + "ccPhsWEJxOX6kfBCOjd9NPly6M2qYhwh6dX0ghDjewW2LWhWC35+kixvTXKC" + + "DO1WdLKduastKx0QX9sndXCP/R3X4gKgeeUc5f+vZEBRLZ6bR9tCpXwfwqZI" + + "sNe+kmlNpPYpV8V4ERjch1HKE7JinU8rMr0xpcH6UqsFiMgwggTLMIIDs6AD" + + "AgECAgQ+HL21MA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNVBAYTAlVTMSMwIQYD" + + "VQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRv" + + "YmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0EwHhcN" + + "MDQwMTE3MDAwMzM5WhcNMTUwMTE1MDgwMDAwWjBFMQswCQYDVQQGEwJVUzEW" + + "MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgQ0Eg" + + "Zm9yIEFkb2JlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp+V3" + + "4GR4Wuc5hbyv0vVbKBMOVN1J+s5i9ZL9nph7n+X4esFs4epAJcFxJ4KnPuQH" + + "ZZ0oyHUU4Th70mWYgKwd6sEt1aR6ZT788Nvr3OHwTRwugN/G6QXqhU9ePpZJ" + + "OF1Ibsf1pcXNGvpLdcYK6+CX5DANMuIthb440XoNfC3dNBC0pF4mM4lmTjpl" + + "nQG8xK0rIFp4HoMpmyaIijz2qyjXdUNkg0fbDUq9eDTKAOLOg21u+AA8XKbC" + + "ewg1LWSV9CVy+fTHREmb1thBcrfkY1kCAvczsuquV3SMx8hRpa+4cIvKK/K1" + + "G7OrV0nsTyuaJ2MMST8b7bul/Xd81nu9Hsz4iQIDAQABo4IBnTCCAZkwEgYD" + + "VR0TAQH/BAgwBgEB/wIBATBQBgNVHSAESTBHMEUGCSqGSIb3LwECATA4MDYG" + + "CCsGAQUFBwIBFipodHRwczovL3d3dy5hZG9iZS5jb20vbWlzYy9wa2kvY2Rz" + + "X2NwLmh0bWwwFAYDVR0lBA0wCwYJKoZIhvcvAQEFMIGyBgNVHR8Egaowgacw" + + "IqAgoB6GHGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Nkcy5jcmwwgYCgfqB8pHow" + + "eDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jw" + + "b3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEWMBQGA1UE" + + "AxMNQWRvYmUgUm9vdCBDQTENMAsGA1UEAxMEQ1JMMTALBgNVHQ8EBAMCAQYw" + + "HwYDVR0jBBgwFoAUgrc4SpOqmxDvgLvZVOLxD/uAnN4wHQYDVR0OBBYEFKuA" + + "WcNlg20dfRO9GcPsGo8NR2qjMBkGCSqGSIb2fQdBAAQMMAobBFY2LjADAgSQ" + + "MA0GCSqGSIb3DQEBBQUAA4IBAQA/OVkuogCOsV4RYSzS4Lb1jImGRc4T2Z/d" + + "hJoUawhMX4aXWPSlqNOPIfhHflCvd+Whbarcd83NN5n3QmevUOFUREPrMQyA" + + "mkK0mpW6TSyLG5ckeCFL8qJwp/hhckk/H16m4hEXWyIFGfOecX3Sy+Y4kxcC" + + "lzSMadifedB+TiRpKFKcNphp5hEMkpyyJaGXpLnN/BLsaDyEN7JySExAopae" + + "UbUJCvCVIWKwoJ26ih3BG1aB+3yTHXeLIorextqWbq+dVz7me59Li8j5PAxe" + + "hXrc2phpKuhp8FaTScvnfMZc8TL4Dr1CHMRWIkqfZaCq3mC376Mww0iZtE5s" + + "iqB+AXVWMYIBgDCCAXwCAQEwSzBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN" + + "R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgQ0EgZm9yIEFkb2Jl" + + "AgIAjzAJBgUrDgMCGgUAoIGMMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB" + + "BDAcBgkqhkiG9w0BCQUxDxcNMDYwNDA0MjAyMDU3WjAjBgkqhkiG9w0BCQQx" + + "FgQUp7AnXBqoNcarvO7fMJut1og2U5AwKwYLKoZIhvcNAQkQAgwxHDAaMBgw" + + "FgQU1dH4eZTNhgxdiSABrat6zsPdth0wDQYJKoZIhvcNAQEBBQAEgYCinr/F" + + "rMiQz/MRm9ZD5YGcC0Qo2dRTPd0Aop8mZ4g1xAhKFLnp7lLsjCbkSDpVLDBh" + + "cnCk7CV+3FT5hlvt8OqZlR0CnkSnCswLFhrppiWle6cpxlwGqyAteC8uKtQu" + + "wjE5GtBKLcCOAzQYyyuNZZeB6oCZ+3mPhZ62FxrvvEGJCgAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); + + private static readonly byte[] emptyDNCert = Base64.Decode( + "MIICfTCCAeagAwIBAgIBajANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJVUzEMMAoGA1UEChMD" + + "Q0RXMQkwBwYDVQQLEwAxCTAHBgNVBAcTADEJMAcGA1UECBMAMRowGAYDVQQDExFUZW1wbGFyIFRl" + + "c3QgMTAyNDEiMCAGCSqGSIb3DQEJARYTdGVtcGxhcnRlc3RAY2R3LmNvbTAeFw0wNjA1MjIwNTAw" + + "MDBaFw0xMDA1MjIwNTAwMDBaMHwxCzAJBgNVBAYTAlVTMQwwCgYDVQQKEwNDRFcxCTAHBgNVBAsT" + + "ADEJMAcGA1UEBxMAMQkwBwYDVQQIEwAxGjAYBgNVBAMTEVRlbXBsYXIgVGVzdCAxMDI0MSIwIAYJ" + + "KoZIhvcNAQkBFhN0ZW1wbGFydGVzdEBjZHcuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB" + + "gQDH3aJpJBfM+A3d84j5YcU6zEQaQ76u5xO9NSBmHjZykKS2kCcUqPpvVOPDA5WgV22dtKPh+lYV" + + "iUp7wyCVwAKibq8HIbihHceFqMKzjwC639rMoDJ7bi/yzQWz1Zg+075a4FGPlUKn7Yfu89wKkjdW" + + "wDpRPXc/agqBnrx5pJTXzQIDAQABow8wDTALBgNVHQ8EBAMCALEwDQYJKoZIhvcNAQEEBQADgYEA" + + "RRsRsjse3i2/KClFVd6YLZ+7K1BE0WxFyY2bbytkwQJSxvv3vLSuweFUbhNxutb68wl/yW4GLy4b" + + "1QdyswNxrNDXTuu5ILKhRDDuWeocz83aG2KGtr3JlFyr3biWGEyn5WUOE6tbONoQDJ0oPYgI6CAc" + + "EHdUp0lioOCt6UOw7Cs="); + + private static readonly byte[] gostRFC4491_94 = Base64.Decode( + "MIICCzCCAboCECMO42BGlSTOxwvklBgufuswCAYGKoUDAgIEMGkxHTAbBgNVBAMM" + + "FEdvc3RSMzQxMC05NCBleGFtcGxlMRIwEAYDVQQKDAlDcnlwdG9Qcm8xCzAJBgNV" + + "BAYTAlJVMScwJQYJKoZIhvcNAQkBFhhHb3N0UjM0MTAtOTRAZXhhbXBsZS5jb20w" + + "HhcNMDUwODE2MTIzMjUwWhcNMTUwODE2MTIzMjUwWjBpMR0wGwYDVQQDDBRHb3N0" + + "UjM0MTAtOTQgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYDVQQGEwJS" + + "VTEnMCUGCSqGSIb3DQEJARYYR29zdFIzNDEwLTk0QGV4YW1wbGUuY29tMIGlMBwG" + + "BiqFAwICFDASBgcqhQMCAiACBgcqhQMCAh4BA4GEAASBgLuEZuF5nls02CyAfxOo" + + "GWZxV/6MVCUhR28wCyd3RpjG+0dVvrey85NsObVCNyaE4g0QiiQOHwxCTSs7ESuo" + + "v2Y5MlyUi8Go/htjEvYJJYfMdRv05YmKCYJo01x3pg+2kBATjeM+fJyR1qwNCCw+" + + "eMG1wra3Gqgqi0WBkzIydvp7MAgGBiqFAwICBANBABHHCH4S3ALxAiMpR3aPRyqB" + + "g1DjB8zy5DEjiULIc+HeIveF81W9lOxGkZxnrFjXBSqnjLeFKgF1hffXOAP7zUM="); + + private static readonly byte[] gostRFC4491_2001 = Base64.Decode( + "MIIB0DCCAX8CECv1xh7CEb0Xx9zUYma0LiEwCAYGKoUDAgIDMG0xHzAdBgNVBAMM" + + "Fkdvc3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkG" + + "A1UEBhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUu" + + "Y29tMB4XDTA1MDgxNjE0MTgyMFoXDTE1MDgxNjE0MTgyMFowbTEfMB0GA1UEAwwW" + + "R29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYD" + + "VQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIwMDFAZXhhbXBsZS5j" + + "b20wYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAhJVodWACGkB1" + + "CM0TjDGJLP3lBQN6Q1z0bSsP508yfleP68wWuZWIA9CafIWuD+SN6qa7flbHy7Df" + + "D2a8yuoaYDAIBgYqhQMCAgMDQQA8L8kJRLcnqeyn1en7U23Sw6pkfEQu3u0xFkVP" + + "vFQ/3cHeF26NG+xxtZPz3TaTVXdoiYkXYiD02rEx1bUcM97i"); + + private class DudPublicKey + : AsymmetricKeyParameter + { + public DudPublicKey() + : base(false) + { + } + + public string Algorithm + { + get { return null; } + } + + public string Format + { + get { return null; } + } + + public byte[] GetEncoded() + { + return null; + } + } + + private AsymmetricKeyParameter dudPublicKey = new DudPublicKey(); + + public override string Name + { + get { return "CertTest"; } + } + + internal void checkCertificate( + int id, + byte[] bytes) + { + string dump = ""; + + try + { + X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes); + + AsymmetricKeyParameter k = cert.GetPublicKey(); + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e); + } + } + + internal void checkNameCertificate( + int id, + byte[] bytes) + { + string dump = ""; + + try + { + X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes); + + AsymmetricKeyParameter k = cert.GetPublicKey(); + if (!cert.IssuerDN.ToString().Equals("C=DE,O=DATEV eG,0.2.262.1.10.7.20=1+CN=CA DATEV D03 1:PN")) + { + Fail(id + " failed - name test."); + } + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e); + } + + } + + internal void checkKeyUsage( + int id, + byte[] bytes) + { + string dump = ""; + + try + { + X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes); + + AsymmetricKeyParameter k = cert.GetPublicKey(); + + if (cert.GetKeyUsage()[7]) + { + Fail("error generating cert - key usage wrong."); + } + + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e); + } + + } + + internal void checkSelfSignedCertificate( + int id, + byte[] bytes) + { + string dump = ""; + + try + { + X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes); + + AsymmetricKeyParameter k = cert.GetPublicKey(); + + cert.Verify(k); + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e); + } + } + + /** + * we Generate a self signed certificate for the sake of testing - RSA + */ + internal void checkCreation1() + { + // + // a sample key pair. + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + // + // set up the keys + // +// AsymmetricKeyParameter privKey; +// AsymmetricKeyParameter pubKey; + +// KeyFactory fact = KeyFactory.GetInstance("RSA"); +// +// privKey = fact.generatePrivate(privKeySpec); +// pubKey = fact.generatePublic(pubKeySpec); + + // + // distinguished name table. + // + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + // + // extensions + // + + // + // create the certificate - version 3 - without extensions + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + ISet dummySet = cert.GetNonCriticalExtensionOids(); + if (dummySet != null) + { + Fail("non-critical oid set should be null"); + } + dummySet = cert.GetCriticalExtensionOids(); + if (dummySet != null) + { + Fail("critical oid set should be null"); + } + + // + // create the certificate - version 3 - with extensions + // + certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + certGen.AddExtension("2.5.29.15", true, + new X509KeyUsage(X509KeyUsage.EncipherOnly)); + certGen.AddExtension("2.5.29.37", true, + new DerSequence(KeyPurposeID.AnyExtendedKeyUsage)); + certGen.AddExtension("2.5.29.17", true, + new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test@test.test"))); + + cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded()); + + if (!cert.GetKeyUsage()[7]) + { + Fail("error generating cert - key usage wrong."); + } + + IList l = cert.GetExtendedKeyUsage(); + if (!l[0].Equals(KeyPurposeID.AnyExtendedKeyUsage.Id)) + { + Fail("failed extended key usage test"); + } + + foreach (IList gn in cert.GetSubjectAlternativeNames()) + { + if (!gn[1].Equals("test@test.test")) + { + Fail("failed subject alternative names test"); + } + } + + // Console.WriteLine(cert); + + // + // create the certificate - version 1 + // + X509V1CertificateGenerator certGen1 = new X509V1CertificateGenerator(); + + certGen1.SetSerialNumber(BigInteger.One); + certGen1.SetIssuerDN(new X509Name(ord, values)); + certGen1.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen1.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen1.SetSubjectDN(new X509Name(ord, values)); + certGen1.SetPublicKey(pubKey); + certGen1.SetSignatureAlgorithm("MD5WithRSAEncryption"); + + cert = certGen1.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded()); + + // Console.WriteLine(cert); + if (!cert.IssuerDN.Equivalent(cert.SubjectDN)) + { + Fail("name comparison fails"); + } + } + + /** + * we Generate a self signed certificate for the sake of testing - DSA + */ + internal void checkCreation2() + { + // + // set up the keys + // + AsymmetricKeyParameter privKey; + AsymmetricKeyParameter pubKey; + + try + { +// KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA", "SUN"); +// g.initialize(512, new SecureRandom()); +// KeyPair p = g.generateKeyPair(); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); + DsaParametersGenerator dpg = new DsaParametersGenerator(); + dpg.Init(512, 25, new SecureRandom()); + g.Init(new DsaKeyGenerationParameters(new SecureRandom(), dpg.GenerateParameters())); + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + privKey = p.Private; + pubKey = p.Public; + } + catch (Exception e) + { + Fail("error setting up keys - " + e.ToString()); + return; + } + + // + // distinguished name table. + // + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + // + // extensions + // + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("SHA1withDSA"); + + try + { + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded()); + + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail("error setting generating cert - " + e.ToString()); + } + + // + // create the certificate - version 1 + // + X509V1CertificateGenerator certGen1 = new X509V1CertificateGenerator(); + + certGen1.SetSerialNumber(BigInteger.One); + certGen1.SetIssuerDN(new X509Name(ord, values)); + certGen1.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen1.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen1.SetSubjectDN(new X509Name(ord, values)); + certGen1.SetPublicKey(pubKey); + certGen1.SetSignatureAlgorithm("SHA1withDSA"); + + try + { + X509Certificate cert = certGen1.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded()); + + //Console.WriteLine(cert); + } + catch (Exception e) + { + Fail("error setting generating cert - " + e.ToString()); + } + + // + // exception test + // + try + { + certGen.SetPublicKey(dudPublicKey); + + Fail("key without encoding not detected in v1"); + } + catch (ArgumentException) + { + // expected + } + } + + /** + * we Generate a self signed certificate for the sake of testing - ECDSA + */ + internal void checkCreation3() + { + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + // + // set up the keys + // +// AsymmetricKeyParameter privKey; +// AsymmetricKeyParameter pubKey; +// +// try +// { +// KeyFactory fact = KeyFactory.GetInstance("ECDSA"); +// +// privKey = fact.generatePrivate(privKeySpec); +// pubKey = fact.generatePublic(pubKeySpec); +// } +// catch (Exception e) +// { +// Fail("error setting up keys - " + e.ToString()); +// return; +// } + + // + // distinguished name table. + // + IDictionary attrs = new Hashtable(); + IList order = new ArrayList(); + + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.E, "feedback-crypto@bouncycastle.org"); + + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.E); + + + // + // ToString test + // + X509Name p = new X509Name(order, attrs); + string s = p.ToString(); + + if (!s.Equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne,ST=Victoria,E=feedback-crypto@bouncycastle.org")) + { + Fail("ordered X509Principal test failed - s = " + s + "."); + } + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(order, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(order, attrs)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("SHA1withECDSA"); + + try + { + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + X509CertificateParser fact = new X509CertificateParser(); + cert = fact.ReadCertificate(cert.GetEncoded()); + + // + // try with point compression turned off + // +// ((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED"); + FpPoint q = (FpPoint) pubKey.Q; + pubKey = new ECPublicKeyParameters( + pubKey.AlgorithmName, + new FpPoint(q.Curve, q.X, q.Y, false), + pubKey.Parameters); + + certGen.SetPublicKey(pubKey); + + cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = fact.ReadCertificate(cert.GetEncoded()); + + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail("error setting generating cert - " + e.ToString()); + } + + X509Name pr = new X509Name("O=\"The Bouncy Castle, The Legion of\",E=feedback-crypto@bouncycastle.org,ST=Victoria,L=Melbourne,C=AU"); + + if (!pr.ToString().Equals("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto@bouncycastle.org,ST=Victoria,L=Melbourne,C=AU")) + { + Fail("string based X509Principal test failed."); + } + + pr = new X509Name("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto@bouncycastle.org,ST=Victoria,L=Melbourne,C=AU"); + + if (!pr.ToString().Equals("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto@bouncycastle.org,ST=Victoria,L=Melbourne,C=AU")) + { + Fail("string based X509Principal test failed."); + } + } + + /** + * we Generate a self signed certificate for the sake of testing - SHA224withECDSA + */ + private void createECCert( + string algorithm, + DerObjectIdentifier algOid) + { + FpCurve curve = new FpCurve( + new BigInteger("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"), // q (or p) + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16), // a + new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, +// curve.DecodePoint(Hex.Decode("02C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G + curve.DecodePoint(Hex.Decode("0200C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16)); // n + + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", +// curve.DecodePoint(Hex.Decode("026BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q + curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q + spec); + +// // +// // set up the keys +// // +// AsymmetricKeyParameter privKey; +// AsymmetricKeyParameter pubKey; +// +// KeyFactory fact = KeyFactory.GetInstance("ECDSA"); +// +// privKey = fact.generatePrivate(privKeySpec); +// pubKey = fact.generatePublic(pubKeySpec); + + + // + // distinguished name table. + // + IDictionary attrs = new Hashtable(); + IList order = new ArrayList(); + + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.E, "feedback-crypto@bouncycastle.org"); + + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.E); + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(order, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(order, attrs)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm(algorithm); + + + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + X509CertificateParser fact = new X509CertificateParser(); + cert = fact.ReadCertificate(cert.GetEncoded()); + + // + // try with point compression turned off + // +// ((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED"); + FpPoint q = (FpPoint) pubKey.Q; + pubKey = new ECPublicKeyParameters( + pubKey.AlgorithmName, + new FpPoint(q.Curve, q.X, q.Y, false), + pubKey.Parameters); + + certGen.SetPublicKey(pubKey); + + cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + cert = fact.ReadCertificate(cert.GetEncoded()); + + if (!cert.SigAlgOid.Equals(algOid.ToString())) + { + Fail("ECDSA oid incorrect."); + } + + if (cert.GetSigAlgParams() != null) + { + Fail("sig parameters present"); + } + + ISigner sig = SignerUtilities.GetSigner(algorithm); + + sig.Init(false, pubKey); + + byte[] b = cert.GetTbsCertificate(); + sig.BlockUpdate(b, 0, b.Length); + + if (!sig.VerifySignature(cert.GetSignature())) + { + Fail("EC certificate signature not mapped correctly."); + } + // Console.WriteLine(cert); + } + + private void checkCrl( + int id, + byte[] bytes) + { + string dump = ""; + + try + { + X509Crl cert = new X509CrlParser().ReadCrl(bytes); + + // Console.WriteLine(cert); + } + catch (Exception e) + { + Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e); + } + + } + + private void checkCrlCreation1() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25)); + + X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); + DateTime now = DateTime.UtcNow; + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + crlGen.SetIssuerDN(new X509Name("CN=Test CA")); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + crlGen.AddCrlEntry(BigInteger.One, now, CrlReason.PrivilegeWithdrawn); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, + new AuthorityKeyIdentifierStructure(pair.Public)); + + X509Crl crl = crlGen.Generate(pair.Private); + + if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true)) + { + Fail("failed CRL issuer test"); + } + + Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); + + if (authExt == null) + { + Fail("failed to find CRL extension"); + } + + AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + + X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One); + + if (entry == null) + { + Fail("failed to find CRL entry"); + } + + if (!entry.SerialNumber.Equals(BigInteger.One)) + { + Fail("CRL cert serial number does not match"); + } + + if (!entry.HasExtensions) + { + Fail("CRL entry extension not found"); + } + + Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode); + + if (ext != null) + { + DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext); + + if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn) + { + Fail("CRL entry reasonCode wrong"); + } + } + else + { + Fail("CRL entry reasonCode not found"); + } + } + + private void checkCrlCreation2() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25)); + + X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); + DateTime now = DateTime.UtcNow; + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + crlGen.SetIssuerDN(new X509Name("CN=Test CA")); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + IList extOids = new ArrayList(); + IList extValues = new ArrayList(); + + CrlReason crlReason = new CrlReason(CrlReason.PrivilegeWithdrawn); + + try + { + extOids.Add(X509Extensions.ReasonCode); + extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded()))); + } + catch (IOException e) + { + throw new ArgumentException("error encoding reason: " + e); + } + + X509Extensions entryExtensions = new X509Extensions(extOids, extValues); + + crlGen.AddCrlEntry(BigInteger.One, now, entryExtensions); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public)); + + X509Crl crl = crlGen.Generate(pair.Private); + + if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true)) + { + Fail("failed CRL issuer test"); + } + + Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); + + if (authExt == null) + { + Fail("failed to find CRL extension"); + } + + AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + + X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One); + + if (entry == null) + { + Fail("failed to find CRL entry"); + } + + if (!entry.SerialNumber.Equals(BigInteger.One)) + { + Fail("CRL cert serial number does not match"); + } + + if (!entry.HasExtensions) + { + Fail("CRL entry extension not found"); + } + + Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode); + + if (ext != null) + { + DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext); + + if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn) + { + Fail("CRL entry reasonCode wrong"); + } + } + else + { + Fail("CRL entry reasonCode not found"); + } + } + + private void checkCrlCreation3() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpGen.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25)); + + X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); + DateTime now = DateTime.UtcNow; + AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair(); + + crlGen.SetIssuerDN(new X509Name("CN=Test CA")); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + IList extOids = new ArrayList(); + IList extValues = new ArrayList(); + + CrlReason crlReason = new CrlReason(CrlReason.PrivilegeWithdrawn); + + try + { + extOids.Add(X509Extensions.ReasonCode); + extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded()))); + } + catch (IOException e) + { + throw new ArgumentException("error encoding reason: " + e); + } + + X509Extensions entryExtensions = new X509Extensions(extOids, extValues); + + crlGen.AddCrlEntry(BigInteger.One, now, entryExtensions); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public)); + + X509Crl crl = crlGen.Generate(pair.Private); + + if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true)) + { + Fail("failed CRL issuer test"); + } + + Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); + + if (authExt == null) + { + Fail("failed to find CRL extension"); + } + + AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + + X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One); + + if (entry == null) + { + Fail("failed to find CRL entry"); + } + + if (!entry.SerialNumber.Equals(BigInteger.One)) + { + Fail("CRL cert serial number does not match"); + } + + if (!entry.HasExtensions) + { + Fail("CRL entry extension not found"); + } + + Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode); + + if (ext != null) + { + DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext); + + if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn) + { + Fail("CRL entry reasonCode wrong"); + } + } + else + { + Fail("CRL entry reasonCode not found"); + } + + // + // check loading of existing CRL + // + crlGen = new X509V2CrlGenerator(); + now = DateTime.UtcNow; + + crlGen.SetIssuerDN(new X509Name("CN=Test CA")); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + crlGen.AddCrl(crl); + + crlGen.AddCrlEntry(BigInteger.Two, now, entryExtensions); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public)); + + X509Crl newCrl = crlGen.Generate(pair.Private); + + int count = 0; + bool oneFound = false; + bool twoFound = false; + + foreach (X509CrlEntry crlEnt in newCrl.GetRevokedCertificates()) + { + if (crlEnt.SerialNumber.IntValue == 1) + { + oneFound = true; + } + else if (crlEnt.SerialNumber.IntValue == 2) + { + twoFound = true; + } + + count++; + } + + if (count != 2) + { + Fail("wrong number of CRLs found"); + } + + if (!oneFound || !twoFound) + { + Fail("wrong CRLs found in copied list"); + } + + // + // check factory read back + // + X509Crl readCrl = new X509CrlParser().ReadCrl(newCrl.GetEncoded()); + + if (readCrl == null) + { + Fail("crl not returned!"); + } + +// ICollection col = cFact.generateCRLs(new ByteArrayInputStream(newCrl.getEncoded())); + ICollection col = new X509CrlParser().ReadCrls(newCrl.GetEncoded()); + + if (col.Count != 1) + { + Fail("wrong number of CRLs found in collection"); + } + } + + /** + * we Generate a self signed certificate for the sake of testing - GOST3410 + */ + internal void checkCreation4() + { + // + // set up the keys + // + AsymmetricKeyParameter privKey; + AsymmetricKeyParameter pubKey; + +// GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec("GostR3410-94-CryptoPro-A"); +// g.initialize(gost3410P, new SecureRandom()); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + g.Init( + new Gost3410KeyGenerationParameters( + new SecureRandom(), + CryptoProObjectIdentifiers.GostR3410x94CryptoProA)); + + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + privKey = p.Private; + pubKey = p.Public; + + // + // distinguished name table. + // + IDictionary attrs = new Hashtable(); + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.E, "feedback-crypto@bouncycastle.org"); + + IList order = new ArrayList(); + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.E); + + // + // extensions + // + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(order, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(order, attrs)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("GOST3411withGOST3410"); + + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + // + // check verifies in general + // + cert.Verify(pubKey); + + // + // check verifies with contained key + // + cert.Verify(cert.GetPublicKey()); + + cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded()); + + //Console.WriteLine(cert); + + //check getEncoded() + byte[] bytesch = cert.GetEncoded(); + } + + internal void checkCreation5() + { + // + // a sample key pair. + // + RsaKeyParameters pubKey = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + // + // set up the keys + // + SecureRandom rand = new SecureRandom(); +// AsymmetricKeyParameter privKey; +// AsymmetricKeyParameter pubKey; +// +// KeyFactory fact = KeyFactory.GetInstance("RSA"); +// +// privKey = fact.generatePrivate(privKeySpec); +// pubKey = fact.generatePublic(pubKeySpec); + + // + // distinguished name table. + // + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + // + // create base certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + certGen.AddExtension("2.5.29.15", true, + new X509KeyUsage(X509KeyUsage.EncipherOnly)); + certGen.AddExtension("2.5.29.37", true, + new DerSequence(KeyPurposeID.AnyExtendedKeyUsage)); + certGen.AddExtension("2.5.29.17", true, + new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test@test.test"))); + + X509Certificate baseCert = certGen.Generate(privKey); + + // + // copy certificate + // + certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + + certGen.CopyAndAddExtension(new DerObjectIdentifier("2.5.29.15"), true, baseCert); + certGen.CopyAndAddExtension("2.5.29.37", false, baseCert); + + X509Certificate cert = certGen.Generate(privKey); + + cert.CheckValidity(DateTime.UtcNow); + + cert.Verify(pubKey); + + DerObjectIdentifier oid1 = new DerObjectIdentifier("2.5.29.15"); + if (!baseCert.GetExtensionValue(oid1).Equals(cert.GetExtensionValue(oid1))) + { + Fail("2.5.29.15 differs"); + } + + DerObjectIdentifier oid2 = new DerObjectIdentifier("2.5.29.37"); + if (!baseCert.GetExtensionValue(oid2).Equals(cert.GetExtensionValue(oid2))) + { + Fail("2.5.29.37 differs"); + } + + // + // exception test + // + try + { + certGen.CopyAndAddExtension("2.5.99.99", true, baseCert); + + Fail("exception not thrown on dud extension copy"); + } + catch (CertificateParsingException) + { + // expected + } + + try + { + certGen.SetPublicKey(dudPublicKey); + + certGen.Generate(privKey); + + Fail("key without encoding not detected in v3"); + } + catch (ArgumentException) + { + // expected + } + } + + private void doTestForgedSignature() + { + string cert = "MIIBsDCCAVoCAQYwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV" + + "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD" + + "VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU4NTVa" + + "Fw0wNjEwMTEyMzU4NTVaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs" + + "YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy" + + "IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD" + + "hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u" + + "12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAbynCRIlUQgaqyNgU" + + "DF6P14yRKUtX8akOP2TwStaSiVf/akYqfLFm3UGka5XbPj4rifrZ0/sOoZEEBvHQ" + + "e20sRA=="; + + X509Certificate x509 = new X509CertificateParser().ReadCertificate(Base64.Decode(cert)); + + try + { + x509.Verify(x509.GetPublicKey()); + + Fail("forged RSA signature passed"); + } + catch (Exception) + { + // expected + } + } + + private void pemTest() + { + X509Certificate cert = readPemCert(PemData.CERTIFICATE_1); + if (cert == null) + { + Fail("PEM cert not read"); + } + cert = readPemCert("-----BEGIN CERTIFICATE-----" + PemData.CERTIFICATE_2); + if (cert == null) + { + Fail("PEM cert with extraneous header not read"); + } + X509Crl crl = new X509CrlParser().ReadCrl(Encoding.ASCII.GetBytes(PemData.CRL_1)); + if (crl == null) + { + Fail("PEM crl not read"); + } + ArrayList col = new ArrayList( + new X509CertificateParser().ReadCertificates(Encoding.ASCII.GetBytes(PemData.CERTIFICATE_2))); + if (col.Count != 1 || !col.Contains(cert)) + { + Fail("PEM cert collection not right"); + } + col = new ArrayList( + new X509CrlParser().ReadCrls(Encoding.ASCII.GetBytes(PemData.CRL_2))); + if (col.Count != 1 || !col.Contains(crl)) + { + Fail("PEM crl collection not right"); + } + } + + private static X509Certificate readPemCert( + string pemData) + { + return new X509CertificateParser().ReadCertificate(Encoding.ASCII.GetBytes(pemData)); + } + + private void pkcs7Test() + { + Asn1Encodable rootCert = Asn1Object.FromByteArray(CertPathTest.rootCertBin); + Asn1Encodable rootCrl = Asn1Object.FromByteArray(CertPathTest.rootCrlBin); + + X509CertificateParser certParser = new X509CertificateParser(); + X509CrlParser crlParser = new X509CrlParser(); + + SignedData sigData = new SignedData( + DerSet.Empty, + new ContentInfo(CmsObjectIdentifiers.Data, null), + new DerSet( + rootCert, + new DerTaggedObject(false, 2, Asn1Object.FromByteArray(AttrCertTest.attrCert))), + new DerSet(rootCrl), + DerSet.Empty); + + ContentInfo info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData); + + X509Certificate cert = certParser.ReadCertificate(info.GetEncoded()); + if (cert == null || !AreEqual(cert.GetEncoded(), rootCert.ToAsn1Object().GetEncoded())) + { + Fail("PKCS7 cert not read"); + } + X509Crl crl = crlParser.ReadCrl(info.GetEncoded()); + if (crl == null || !AreEqual(crl.GetEncoded(), rootCrl.ToAsn1Object().GetEncoded())) + { + Fail("PKCS7 crl not read"); + } + ArrayList col = new ArrayList(certParser.ReadCertificates(info.GetEncoded())); + if (col.Count != 1 || !col.Contains(cert)) + { + Fail("PKCS7 cert collection not right"); + } + col = new ArrayList(crlParser.ReadCrls(info.GetEncoded())); + if (col.Count != 1 || !col.Contains(crl)) + { + Fail("PKCS7 crl collection not right"); + } + + // data with no certificates or CRLs + + sigData = new SignedData(DerSet.Empty, new ContentInfo(CmsObjectIdentifiers.Data, null), DerSet.Empty, DerSet.Empty, DerSet.Empty); + + info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData); + + cert = certParser.ReadCertificate(info.GetEncoded()); + if (cert != null) + { + Fail("PKCS7 cert present"); + } + crl = crlParser.ReadCrl(info.GetEncoded()); + if (crl != null) + { + Fail("PKCS7 crl present"); + } + + // data with absent certificates and CRLS + + sigData = new SignedData(DerSet.Empty, new ContentInfo(CmsObjectIdentifiers.Data, null), null, null, DerSet.Empty); + + info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData); + + cert = certParser.ReadCertificate(info.GetEncoded()); + if (cert != null) + { + Fail("PKCS7 cert present"); + } + crl = crlParser.ReadCrl(info.GetEncoded()); + if (crl != null) + { + Fail("PKCS7 crl present"); + } + + // + // sample message + // + ICollection certCol = certParser.ReadCertificates(pkcs7CrlProblem); + ICollection crlCol = crlParser.ReadCrls(pkcs7CrlProblem); + + if (crlCol.Count != 0) + { + Fail("wrong number of CRLs: " + crlCol.Count); + } + + if (certCol.Count != 4) + { + Fail("wrong number of Certs: " + certCol.Count); + } + } + + private void createPssCert( + string algorithm) + { + AsymmetricCipherKeyPair keyPair = GenerateLongFixedKeys(); + + AsymmetricKeyParameter privKey = keyPair.Private; + AsymmetricKeyParameter pubKey = keyPair.Public; + + // + // distinguished name table. + // + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + // + // create base certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name(ord, values)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name(ord, values)); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm(algorithm); + certGen.AddExtension("2.5.29.15", true, + new X509KeyUsage(X509KeyUsage.EncipherOnly)); + certGen.AddExtension("2.5.29.37", true, + new DerSequence(KeyPurposeID.AnyExtendedKeyUsage)); + certGen.AddExtension("2.5.29.17", true, + new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test@test.test"))); + + X509Certificate baseCert = certGen.Generate(privKey); + + baseCert.Verify(pubKey); + } + + private static AsymmetricCipherKeyPair GenerateLongFixedKeys() + { +// RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( + RsaKeyParameters pubKey = new RsaKeyParameters(false, + new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16), + new BigInteger("010001",16)); + +// RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( + RsaPrivateCrtKeyParameters privKey = 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)); + +// KeyFactory fact = KeyFactory.getInstance("RSA", "BC"); +// +// PrivateKey privKey = fact.generatePrivate(privKeySpec); +// PublicKey pubKey = fact.generatePublic(pubKeySpec); + + return new AsymmetricCipherKeyPair(pubKey, privKey); + } + + private void doTestNullDerNullCert() + { + AsymmetricCipherKeyPair keyPair = GenerateLongFixedKeys(); + + AsymmetricKeyParameter pubKey = keyPair.Public; + AsymmetricKeyParameter privKey = keyPair.Private; + + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name("CN=Test")); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name("CN=Test")); + certGen.SetPublicKey(pubKey); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + X509Certificate cert = certGen.Generate(privKey); + + X509CertificateStructure certStruct = X509CertificateStructure.GetInstance( + Asn1Object.FromByteArray(cert.GetEncoded())); + + Asn1Encodable tbsCertificate = certStruct.TbsCertificate; + AlgorithmIdentifier sig = certStruct.SignatureAlgorithm; + + DerSequence seq = new DerSequence( + tbsCertificate, + new AlgorithmIdentifier(sig.ObjectID), + certStruct.Signature); + + try + { + // verify + byte[] encoded = seq.GetEncoded(); + X509CertificateParser fact = new X509CertificateParser(); + cert = fact.ReadCertificate(encoded); + cert.Verify(cert.GetPublicKey()); + } + catch (Exception e) + { + Fail("doTestNullDerNull failed - exception " + e.ToString(), e); + } + } + + public override void PerformTest() + { + checkCertificate(1, cert1); + checkCertificate(2, cert2); + checkCertificate(3, cert3); + checkCertificate(4, cert4); + checkCertificate(5, cert5); + // This cert uses an incorrect encoding (compressed wrapped in extra octet string) + // which the Java build supports backwards, but we choose not to for C# build +// checkCertificate(6, oldEcdsa); + checkCertificate(7, cert7); + + checkKeyUsage(8, keyUsage); + checkSelfSignedCertificate(9, uncompressedPtEC); + checkNameCertificate(10, nameCert); + + checkSelfSignedCertificate(11, probSelfSignedCert); + checkSelfSignedCertificate(12, gostCA1); + checkSelfSignedCertificate(13, gostCA2); + checkSelfSignedCertificate(14, gost341094base); + checkSelfSignedCertificate(15, gost34102001base); + checkSelfSignedCertificate(16, gost341094A); + checkSelfSignedCertificate(17, gost341094B); + checkSelfSignedCertificate(17, gost34102001A); + + checkCrl(1, crl1); + + checkCreation1(); + checkCreation2(); + checkCreation3(); + checkCreation4(); + checkCreation5(); + + createECCert("SHA1withECDSA", X9ObjectIdentifiers.ECDsaWithSha1); + createECCert("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + createECCert("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + createECCert("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + createECCert("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + + createPssCert("SHA1withRSAandMGF1"); + createPssCert("SHA224withRSAandMGF1"); + createPssCert("SHA256withRSAandMGF1"); + createPssCert("SHA384withRSAandMGF1"); + + checkCrlCreation1(); + checkCrlCreation2(); + checkCrlCreation3(); + + pemTest(); + pkcs7Test(); + + doTestForgedSignature(); + + doTestNullDerNullCert(); + + checkCertificate(18, emptyDNCert); + } + + public static void Main( + string[] args) + { + RunTest(new CertTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/CipherStreamTest.cs b/crypto/test/src/test/CipherStreamTest.cs new file mode 100644 index 000000000..0809dfe80 --- /dev/null +++ b/crypto/test/src/test/CipherStreamTest.cs @@ -0,0 +1,449 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// Check that cipher input/output streams are working correctly + [TestFixture] + public class CipherStreamTest + : SimpleTest + { + private static readonly byte[] RK = Hex.Decode("0123456789ABCDEF"); + private static readonly byte[] RIN = Hex.Decode("4e6f772069732074"); + private static readonly byte[] ROUT = Hex.Decode("3afbb5c77938280d"); + + private static byte[] SIN = Hex.Decode( + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000"); + private static readonly byte[] SK = Hex.Decode("80000000000000000000000000000000"); + private static readonly byte[] SIV = Hex.Decode("0000000000000000"); + private static readonly byte[] SOUT = Hex.Decode( + "4DFA5E481DA23EA09A31022050859936" + + "DA52FCEE218005164F267CB65F5CFD7F" + + "2B4F97E0FF16924A52DF269515110A07" + + "F9E460BC65EF95DA58F740B7D1DBB0AA"); + + private static readonly byte[] HCIN = new byte[64]; + private static readonly byte[] HCIV = new byte[32]; + + private static readonly byte[] HCK256A = new byte[32]; + private static readonly byte[] HC256A = Hex.Decode( + "5B078985D8F6F30D42C5C02FA6B67951" + + "53F06534801F89F24E74248B720B4818" + + "CD9227ECEBCF4DBF8DBF6977E4AE14FA" + + "E8504C7BC8A9F3EA6C0106F5327E6981"); + + private static readonly byte[] HCK128A = new byte[16]; + private static readonly byte[] HC128A = Hex.Decode( + "82001573A003FD3B7FD72FFB0EAF63AA" + + "C62F12DEB629DCA72785A66268EC758B" + + "1EDB36900560898178E0AD009ABF1F49" + + "1330DC1C246E3D6CB264F6900271D59C"); + + private void doRunTest( + string name, + int ivLength) + { + string lCode = "ABCDEFGHIJKLMNOPQRSTUVWXY0123456789"; + + string baseName = name; + if (name.IndexOf('/') >= 0) + { + baseName = name.Substring(0, name.IndexOf('/')); + } + + CipherKeyGenerator kGen = GeneratorUtilities.GetKeyGenerator(baseName); + + IBufferedCipher inCipher = CipherUtilities.GetCipher(name); + IBufferedCipher outCipher = CipherUtilities.GetCipher(name); + KeyParameter key = ParameterUtilities.CreateKeyParameter(baseName, kGen.GenerateKey()); + MemoryStream bIn = new MemoryStream(Encoding.ASCII.GetBytes(lCode), false); + MemoryStream bOut = new MemoryStream(); + + // In the Java build, this IV would be implicitly created and then retrieved with getIV() + ICipherParameters cipherParams = key; + if (ivLength > 0) + { + cipherParams = new ParametersWithIV(cipherParams, new byte[ivLength]); + } + + inCipher.Init(true, cipherParams); + + // TODO Should we provide GetIV() method on IBufferedCipher? + //if (inCipher.getIV() != null) + //{ + // outCipher.Init(false, new ParametersWithIV(key, inCipher.getIV())); + //} + //else + //{ + // outCipher.Init(false, key); + //} + outCipher.Init(false, cipherParams); + + CipherStream cIn = new CipherStream(bIn, inCipher, null); + CipherStream cOut = new CipherStream(bOut, null, outCipher); + + int c; + + while ((c = cIn.ReadByte()) >= 0) + { + cOut.WriteByte((byte)c); + } + + cIn.Close(); + + cOut.Flush(); + cOut.Close(); + + byte[] bs = bOut.ToArray(); + string res = Encoding.ASCII.GetString(bs, 0, bs.Length); + + if (!res.Equals(lCode)) + { + Fail("Failed - decrypted data doesn't match."); + } + } + + private void doTestAlgorithm( + string name, + byte[] keyBytes, + byte[] iv, + byte[] plainText, + byte[] cipherText) + { + KeyParameter key = ParameterUtilities.CreateKeyParameter(name, keyBytes); + + IBufferedCipher inCipher = CipherUtilities.GetCipher(name); + IBufferedCipher outCipher = CipherUtilities.GetCipher(name); + + if (iv != null) + { + inCipher.Init(true, new ParametersWithIV(key, iv)); + outCipher.Init(false, new ParametersWithIV(key, iv)); + } + else + { + inCipher.Init(true, key); + outCipher.Init(false, key); + } + + byte[] enc = inCipher.DoFinal(plainText); + if (!AreEqual(enc, cipherText)) + { + Fail(name + ": cipher text doesn't match"); + } + + byte[] dec = outCipher.DoFinal(enc); + + if (!AreEqual(dec, plainText)) + { + Fail(name + ": plain text doesn't match"); + } + } + + private void doTestException( + string name, + int ivLength) + { + try + { + byte[] key128 = { + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143, + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143 + }; + + byte[] key256 = { + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143, + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143, + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143, + (byte)128, (byte)131, (byte)133, (byte)134, + (byte)137, (byte)138, (byte)140, (byte)143 }; + + byte[] keyBytes; + if (name.Equals("HC256")) + { + keyBytes = key256; + } + else + { + keyBytes = key128; + } + + KeyParameter cipherKey = ParameterUtilities.CreateKeyParameter(name, keyBytes); + + ICipherParameters cipherParams = cipherKey; + if (ivLength > 0) + { + cipherParams = new ParametersWithIV(cipherParams, new byte[ivLength]); + } + + IBufferedCipher ecipher = CipherUtilities.GetCipher(name); + ecipher.Init(true, cipherParams); + + byte[] cipherText = new byte[0]; + try + { + // According specification Method engineUpdate(byte[] input, + // int inputOffset, int inputLen, byte[] output, int + // outputOffset) + // throws ShortBufferException - if the given output buffer is + // too + // small to hold the result + ecipher.ProcessBytes(new byte[20], 0, 20, cipherText, 0); + +// Fail("failed exception test - no ShortBufferException thrown"); + Fail("failed exception test - no DataLengthException thrown"); + } +// catch (ShortBufferException e) + catch (DataLengthException) + { + // ignore + } + + // NB: The lightweight engine doesn't take public/private keys +// try +// { +// IBufferedCipher c = CipherUtilities.GetCipher(name); +// +// // Key k = new PublicKey() +// // { +// // +// // public string getAlgorithm() +// // { +// // return "STUB"; +// // } +// // +// // public string getFormat() +// // { +// // return null; +// // } +// // +// // public byte[] getEncoded() +// // { +// // return null; +// // } +// // +// // }; +// AsymmetricKeyParameter k = new AsymmetricKeyParameter(false); +// c.Init(true, k); +// +// Fail("failed exception test - no InvalidKeyException thrown for public key"); +// } +// catch (InvalidKeyException) +// { +// // okay +// } +// +// try +// { +// IBufferedCipher c = CipherUtilities.GetCipher(name); +// +// // Key k = new PrivateKey() +// // { +// // +// // public string getAlgorithm() +// // { +// // return "STUB"; +// // } +// // +// // public string getFormat() +// // { +// // return null; +// // } +// // +// // public byte[] getEncoded() +// // { +// // return null; +// // } +// // +// // }; +// +// AsymmetricKeyParameter k = new AsymmetricKeyParameter(true); +// c.Init(false, k); +// +// Fail("failed exception test - no InvalidKeyException thrown for private key"); +// } +// catch (InvalidKeyException) +// { +// // okay +// } + } + catch (Exception e) + { + Fail("unexpected exception.", e); + } + } + + [Test] + public void TestRC4() + { + doRunTest("RC4", 0); + } + + [Test] + public void TestRC4Exception() + { + doTestException("RC4", 0); + } + + [Test] + public void TestRC4Algorithm() + { + doTestAlgorithm("RC4", RK, null, RIN, ROUT); + } + + [Test] + public void TestSalsa20() + { + doRunTest("Salsa20", 8); + } + + [Test] + public void TestSalsa20Exception() + { + doTestException("Salsa20", 8); + } + + [Test] + public void TestSalsa20Algorithm() + { + doTestAlgorithm("Salsa20", SK, SIV, SIN, SOUT); + } + + [Test] + public void TestHC128() + { + doRunTest("HC128", 16); + } + + [Test] + public void TestHC128Exception() + { + doTestException("HC128", 16); + } + + [Test] + public void TestHC128Algorithm() + { + doTestAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A); + } + + [Test] + public void TestHC256() + { + doRunTest("HC256", 32); + } + + [Test] + public void TestHC256Exception() + { + doTestException("HC256", 32); + } + + [Test] + public void TestHC256Algorithm() + { + doTestAlgorithm("HC256", HCK256A, HCIV, HCIN, HC256A); + } + + [Test] + public void TestVmpc() + { + doRunTest("VMPC", 16); + } + + [Test] + public void TestVmpcException() + { + doTestException("VMPC", 16); + } + +// [Test] +// public void TestVmpcAlgorithm() +// { +// doTestAlgorithm("VMPC", a, iv, in, a); +// } + + [Test] + public void TestVmpcKsa3() + { + doRunTest("VMPC-KSA3", 16); + } + + [Test] + public void TestVmpcKsa3Exception() + { + doTestException("VMPC-KSA3", 16); + } + +// [Test] +// public void TestVmpcKsa3Algorithm() +// { +// doTestAlgorithm("VMPC-KSA3", a, iv, in, a); +// } + + [Test] + public void TestDesEcbPkcs7() + { + doRunTest("DES/ECB/PKCS7Padding", 0); + } + + [Test] + public void TestDesCfbNoPadding() + { + doRunTest("DES/CFB8/NoPadding", 0); + } + + public override void PerformTest() + { + TestRC4(); + TestRC4Exception(); + TestRC4Algorithm(); + TestSalsa20(); + TestSalsa20Exception(); + TestSalsa20Algorithm(); + TestHC128(); + TestHC128Exception(); + TestHC128Algorithm(); + TestHC256(); + TestHC256Exception(); + TestHC256Algorithm(); + TestVmpc(); + TestVmpcException(); +// TestVmpcAlgorithm(); + TestVmpcKsa3(); + TestVmpcKsa3Exception(); +// TestVmpcKsa3Algorithm(); + TestDesEcbPkcs7(); + TestDesCfbNoPadding(); + } + + public override string Name + { + get { return "CipherStreamTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new CipherStreamTest()); + } + } +} diff --git a/crypto/test/src/test/DESedeTest.cs b/crypto/test/src/test/DESedeTest.cs new file mode 100644 index 000000000..d84b994f0 --- /dev/null +++ b/crypto/test/src/test/DESedeTest.cs @@ -0,0 +1,298 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// + /// Basic test class for key generation for a DES-EDE block cipher, basically + /// this just exercises the provider, and makes sure we are behaving sensibly, + /// correctness of the implementation is shown in the lightweight test classes. + /// + [TestFixture] + public class DesEdeTest + : SimpleTest + { + private static string[] cipherTests1 = + { + "112", + "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394", + "128", + "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394", + "168", + "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89", + "192", + "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89", + }; + + private static byte[] input1 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f"); + + /** + * a fake random number generator - we just want to make sure the random numbers + * aren't random so that we get the same output, while still getting to test the + * key generation facilities. + */ + private class FixedSecureRandom + : SecureRandom + { + private 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 + }; + + public override void NextBytes( + byte[] bytes) + { + int offset = 0; + + while ((offset + seed.Length) < bytes.Length) + { + Array.Copy(seed, 0, bytes, offset, seed.Length); + offset += seed.Length; + } + + Array.Copy(seed, 0, bytes, offset, bytes.Length - offset); + } + } + + public override string Name + { + get { return "DESEDE"; } + } + + private void wrapTest( + string alg, + int id, + byte[] kek, + byte[] iv, + byte[] input, + byte[] output) + { + try + { + IWrapper wrapper = WrapperUtilities.GetWrapper(alg + "Wrap"); + + KeyParameter desEdeKey = new DesEdeParameters(kek); + wrapper.Init(true, new ParametersWithIV(desEdeKey, iv)); + + try + { +// byte[] cText = wrapper.Wrap(new SecretKeySpec(input, alg)); + byte[] cText = wrapper.Wrap(input, 0, input.Length); + + if (!Arrays.AreEqual(cText, output)) + { + Fail("failed wrap test " + id + " expected " + + Hex.ToHexString(output) + " got " + Hex.ToHexString(cText)); + } + } + catch (Exception e) + { + Fail("failed wrap test exception " + e.ToString()); + } + + wrapper.Init(false, desEdeKey); + + try + { +// Key pText = wrapper.unwrap(output, alg, IBufferedCipher.SECRET_KEY); + byte[] pText = wrapper.Unwrap(output, 0, output.Length); +// if (!Arrays.AreEqual(pText.getEncoded(), input)) + if (!Arrays.AreEqual(pText, input)) + { + Fail("failed unwrap test " + id + " expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(pText)); + } + } + catch (Exception e) + { + Fail("failed unwrap test exception " + e.ToString()); + } + } + catch (Exception ex) + { + Fail("failed exception " + ex.ToString()); + } + } + + private void doTest( + string alg, + int strength, + byte[] input, + byte[] output) + { + KeyParameter key = null; + CipherKeyGenerator keyGen; + SecureRandom rand; + IBufferedCipher inCipher = null; + IBufferedCipher outCipher = null; + CipherStream cIn; + CipherStream cOut; + MemoryStream bIn; + MemoryStream bOut; + + rand = new FixedSecureRandom(); + + try + { + keyGen = GeneratorUtilities.GetKeyGenerator(alg); + keyGen.Init(new KeyGenerationParameters(rand, strength)); + + key = new DesEdeParameters(keyGen.GenerateKey()); + + inCipher = CipherUtilities.GetCipher(alg + "/ECB/PKCS7Padding"); + outCipher = CipherUtilities.GetCipher(alg + "/ECB/PKCS7Padding"); + + outCipher.Init(true, new ParametersWithRandom(key, rand)); + } + catch (Exception e) + { + Fail(alg + " failed initialisation - " + e.ToString()); + } + + try + { + inCipher.Init(false, key); + } + catch (Exception e) + { + Fail(alg + " failed initialisation - " + e.ToString()); + } + + // + // encryption pass + // + bOut = new MemoryStream(); + + cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + Fail(alg + " failed encryption - " + e.ToString()); + } + + byte[] bytes = bOut.ToArray(); + + if (!Arrays.AreEqual(bytes, output)) + { + Fail(alg + " failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + bIn = new MemoryStream(bytes, false); + + cIn = new CipherStream(bIn, inCipher, null); + + try + { +// DataInputStream dIn = new DataInputStream(cIn); + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { + bytes[i] = (byte)dIn.ReadByte(); + } +// dIn.readFully(bytes, input.Length / 2, bytes.Length - input.Length / 2); + int remaining = bytes.Length - input.Length / 2; + byte[] rest = dIn.ReadBytes(remaining); + if (rest.Length != remaining) + throw new Exception("IO problem with BinaryReader"); + rest.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail(alg + " failed encryption - " + e.ToString()); + } + + if (!Arrays.AreEqual(bytes, input)) + { + Fail(alg + " failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + + // TODO Put back in +// // +// // keyspec test +// // +// try +// { +// SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(alg); +// DESedeKeySpec keySpec = (DESedeKeySpec)keyFactory.getKeySpec((SecretKey)key, DESedeKeySpec.class); +// +// if (!equalArray(key.getEncoded(), keySpec.getKey(), 16)) +// { +// Fail(alg + " KeySpec does not match key."); +// } +// } +// catch (Exception e) +// { +// Fail(alg + " failed keyspec - " + e.ToString()); +// } + } + + public override void PerformTest() + { + for (int i = 0; i != cipherTests1.Length; i += 2) + { + doTest("DESEDE", int.Parse(cipherTests1[i]), input1, Hex.Decode(cipherTests1[i + 1])); + } + + for (int i = 0; i != cipherTests1.Length; i += 2) + { + doTest("TDEA", int.Parse(cipherTests1[i]), input1, Hex.Decode(cipherTests1[i + 1])); + } + + byte[] kek1 = Hex.Decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f"); + byte[] iv1 = Hex.Decode("5dd4cbfc96f5453b"); + byte[] in1 = Hex.Decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98"); + byte[] out1 = Hex.Decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4"); + + wrapTest("DESEDE", 1, kek1, iv1, in1, out1); + wrapTest("TDEA", 1, kek1, iv1, in1, out1); + } + + public static void Main( + string[] args) + { + RunTest(new DesEdeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/DHTest.cs b/crypto/test/src/test/DHTest.cs new file mode 100644 index 000000000..9a3610c18 --- /dev/null +++ b/crypto/test/src/test/DHTest.cs @@ -0,0 +1,650 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class DHTest + : SimpleTest + { + private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16); + private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16); + + private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16); + private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16); + + // public key with mismatched oid/parameters + private byte[] oldPubEnc = Base64.Decode( + "MIIBnzCCARQGByqGSM4+AgEwggEHAoGBAPxSrN417g43VAM9sZRf1dt6AocAf7D6" + + "WVCtqEDcBJrMzt63+g+BNJzhXVtbZ9kp9vw8L/0PHgzv0Ot/kOLX7Khn+JalOECW" + + "YlkyBhmOVbjR79TY5u2GAlvG6pqpizieQNBCEMlUuYuK1Iwseil6VoRuA13Zm7uw" + + "WO1eZmaJtY7LAoGAQaPRCFKM5rEdkMrV9FNzeSsYRs8m3DqPnnJHpuySpyO9wUcX" + + "OOJcJY5qvHbDO5SxHXu/+bMgXmVT6dXI5o0UeYqJR7fj6pR4E6T0FwG55RFr5Ok4" + + "3C4cpXmaOu176SyWuoDqGs1RDGmYQjwbZUi23DjaaTFUly9LCYXMliKrQfEDgYQA" + + "AoGAQUGCBN4TaBw1BpdBXdTvTfCU69XDB3eyU2FOBE3UWhpx9D8XJlx4f5DpA4Y6" + + "6sQMuCbhfmjEph8W7/sbMurM/awR+PSR8tTY7jeQV0OkmAYdGK2nzh0ZSifMO1oE" + + "NNhN2O62TLs67msxT28S4/S89+LMtc98mevQ2SX+JF3wEVU="); + + // bogus key with full PKCS parameter set + private byte[] oldFullParams = Base64.Decode( + "MIIBIzCCARgGByqGSM4+AgEwggELAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E" + + "AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f" + + "6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv" + + "8iIDGZ3RSAHHAoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlX" + + "jrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6j" + + "fwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqAgFk" + + "AwUAAgIH0A=="); + + private byte[] samplePubEnc = Base64.Decode( + "MIIBpjCCARsGCSqGSIb3DQEDATCCAQwCgYEA/X9TgR11EilS30qcLuzk5/YRt1I8" + + "70QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWk" + + "n5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX" + + "Ku/yIgMZndFIAccCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdR" + + "WVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWR" + + "bqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoC" + + "AgIAA4GEAAKBgEIiqxoUW6E6GChoOgcfNbVFclW91ITf5MFSUGQwt2R0RHoOhxvO" + + "lZhNs++d0VPATLAyXovjfgENT9SGCbuZttYcqqLdKTbMXBWPek+rfnAl9E4iEMED" + + "IDd83FJTKs9hQcPAm7zmp0Xm1bGF9CbUFjP5G02265z7eBmHDaT0SNlB"); + + private byte[] samplePrivEnc = Base64.Decode( + "MIIBZgIBADCCARsGCSqGSIb3DQEDATCCAQwCgYEA/X9TgR11EilS30qcLuzk5/YR" + + "t1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZ" + + "UKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOu" + + "K2HXKu/yIgMZndFIAccCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0H" + + "gmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuz" + + "pnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7P" + + "SSoCAgIABEICQAZYXnBHazxXUUdFP4NIf2Ipu7du0suJPZQKKff81wymi2zfCfHh" + + "uhe9gQ9xdm4GpzeNtrQ8/MzpTy+ZVrtd29Q="); + + public override string Name + { + get { return "DH"; } + } + + private void doTestGP( + string algName, + int size, + int privateValueSize, + BigInteger g, + BigInteger p) + { + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator(algName); + + DHParameters dhParams = new DHParameters(p, g, null, privateValueSize); + KeyGenerationParameters kgp = new DHKeyGenerationParameters(new SecureRandom(), dhParams); + + keyGen.Init(kgp); + + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = keyGen.GenerateKeyPair(); + + IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algName); + + checkKeySize(privateValueSize, aKeyPair); + + aKeyAgreeBasic.Init(aKeyPair.Private); + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = keyGen.GenerateKeyPair(); + + IBasicAgreement bKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algName); + + checkKeySize(privateValueSize, bKeyPair); + + bKeyAgreeBasic.Init(bKeyPair.Private); + + // + // agreement + // +// aKeyAgreeBasic.doPhase(bKeyPair.Public, true); +// bKeyAgreeBasic.doPhase(aKeyPair.Public, true); +// +// BigInteger k1 = new BigInteger(aKeyAgreeBasic.generateSecret()); +// BigInteger k2 = new BigInteger(bKeyAgreeBasic.generateSecret()); + BigInteger k1 = aKeyAgreeBasic.CalculateAgreement(bKeyPair.Public); + BigInteger k2 = bKeyAgreeBasic.CalculateAgreement(aKeyPair.Public); + + if (!k1.Equals(k2)) + { + Fail(size + " bit 2-way test failed"); + } + + // + // public key encoding test + // +// byte[] pubEnc = aKeyPair.Public.GetEncoded(); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded(); + +// KeyFactory keyFac = KeyFactory.getInstance(algName); +// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +// DHPublicKey pubKey = (DHPublicKey)keyFac.generatePublic(pubX509); + DHPublicKeyParameters pubKey = (DHPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc); +// DHParameterSpec spec = pubKey.Parameters; + DHParameters spec = pubKey.Parameters; + + if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P)) + { + Fail(size + " bit public key encoding/decoding test failed on parameters"); + } + + if (!((DHPublicKeyParameters)aKeyPair.Public).Y.Equals(pubKey.Y)) + { + Fail(size + " bit public key encoding/decoding test failed on y value"); + } + + // + // public key serialisation test + // + // TODO Put back in +// MemoryStream bOut = new MemoryStream(); +// ObjectOutputStream oOut = new ObjectOutputStream(bOut); +// +// oOut.WriteObject(aKeyPair.Public); +// +// MemoryStream bIn = new MemoryStream(bOut.ToArray(), false); +// ObjectInputStream oIn = new ObjectInputStream(bIn); +// +// pubKey = (DHPublicKeyParameters)oIn.ReadObject(); + spec = pubKey.Parameters; + + if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P)) + { + Fail(size + " bit public key serialisation test failed on parameters"); + } + + if (!((DHPublicKeyParameters)aKeyPair.Public).Y.Equals(pubKey.Y)) + { + Fail(size + " bit public key serialisation test failed on y value"); + } + + // + // private key encoding test + // +// byte[] privEnc = aKeyPair.Private.GetEncoded(); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded(); +// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +// DHPrivateKeyParameters privKey = (DHPrivateKey)keyFac.generatePrivate(privPKCS8); + DHPrivateKeyParameters privKey = (DHPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc); + + spec = privKey.Parameters; + + if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P)) + { + Fail(size + " bit private key encoding/decoding test failed on parameters"); + } + + if (!((DHPrivateKeyParameters)aKeyPair.Private).X.Equals(privKey.X)) + { + Fail(size + " bit private key encoding/decoding test failed on y value"); + } + + // + // private key serialisation test + // + // TODO Put back in +// bOut = new MemoryStream(); +// oOut = new ObjectOutputStream(bOut); +// +// oOut.WriteObject(aKeyPair.Private); +// +// bIn = new MemoryStream(bOut.ToArray(), false); +// oIn = new ObjectInputStream(bIn); +// +// privKey = (DHPrivateKeyParameters)oIn.ReadObject(); + spec = privKey.Parameters; + + if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P)) + { + Fail(size + " bit private key serialisation test failed on parameters"); + } + + if (!((DHPrivateKeyParameters)aKeyPair.Private).X.Equals(privKey.X)) + { + Fail(size + " bit private key serialisation test failed on y value"); + } + + // + // three party test + // + IAsymmetricCipherKeyPairGenerator aPairGen = GeneratorUtilities.GetKeyPairGenerator(algName); + aPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec)); + AsymmetricCipherKeyPair aPair = aPairGen.GenerateKeyPair(); + + IAsymmetricCipherKeyPairGenerator bPairGen = GeneratorUtilities.GetKeyPairGenerator(algName); + bPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec)); + AsymmetricCipherKeyPair bPair = bPairGen.GenerateKeyPair(); + + IAsymmetricCipherKeyPairGenerator cPairGen = GeneratorUtilities.GetKeyPairGenerator(algName); + cPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec)); + AsymmetricCipherKeyPair cPair = cPairGen.GenerateKeyPair(); + + + IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement(algName); + aKeyAgree.Init(aPair.Private); + + IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement(algName); + bKeyAgree.Init(bPair.Private); + + IBasicAgreement cKeyAgree = AgreementUtilities.GetBasicAgreement(algName); + cKeyAgree.Init(cPair.Private); + +// Key ac = aKeyAgree.doPhase(cPair.Public, false); +// Key ba = bKeyAgree.doPhase(aPair.Public, false); +// Key cb = cKeyAgree.doPhase(bPair.Public, false); +// +// aKeyAgree.doPhase(cb, true); +// bKeyAgree.doPhase(ac, true); +// cKeyAgree.doPhase(ba, true); +// +// BigInteger aShared = new BigInteger(aKeyAgree.generateSecret()); +// BigInteger bShared = new BigInteger(bKeyAgree.generateSecret()); +// BigInteger cShared = new BigInteger(cKeyAgree.generateSecret()); + + DHPublicKeyParameters ac = new DHPublicKeyParameters(aKeyAgree.CalculateAgreement(cPair.Public), spec); + DHPublicKeyParameters ba = new DHPublicKeyParameters(bKeyAgree.CalculateAgreement(aPair.Public), spec); + DHPublicKeyParameters cb = new DHPublicKeyParameters(cKeyAgree.CalculateAgreement(bPair.Public), spec); + + BigInteger aShared = aKeyAgree.CalculateAgreement(cb); + BigInteger bShared = bKeyAgree.CalculateAgreement(ac); + BigInteger cShared = cKeyAgree.CalculateAgreement(ba); + + if (!aShared.Equals(bShared)) + { + Fail(size + " bit 3-way test failed (a and b differ)"); + } + + if (!cShared.Equals(bShared)) + { + Fail(size + " bit 3-way test failed (c and b differ)"); + } + } + + private void doTestExplicitWrapping( + int size, + int privateValueSize, + BigInteger g, + BigInteger p) + { + DHParameters dhParams = new DHParameters(p, g, null, privateValueSize); + + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH"); + + keyGen.Init(new DHKeyGenerationParameters(new SecureRandom(), dhParams)); + + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = keyGen.GenerateKeyPair(); + + IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("DH"); + + checkKeySize(privateValueSize, aKeyPair); + + aKeyAgree.Init(aKeyPair.Private); + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = keyGen.GenerateKeyPair(); + + IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement("DH"); + + checkKeySize(privateValueSize, bKeyPair); + + bKeyAgree.Init(bKeyPair.Private); + + // + // agreement + // +// aKeyAgree.doPhase(bKeyPair.Public, true); +// bKeyAgree.doPhase(aKeyPair.Public, true); +// +// SecretKey k1 = aKeyAgree.generateSecret(PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id); +// SecretKey k2 = bKeyAgree.generateSecret(PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id); + + // TODO Does this really test the same thing as the above code? + BigInteger b1 = aKeyAgree.CalculateAgreement(bKeyPair.Public); + BigInteger b2 = bKeyAgree.CalculateAgreement(aKeyPair.Public); + + if (!b1.Equals(b2)) + { + Fail("Explicit wrapping test failed"); + } + } + + private void checkKeySize( + int privateValueSize, + AsymmetricCipherKeyPair aKeyPair) + { + if (privateValueSize != 0) + { + DHPrivateKeyParameters key = (DHPrivateKeyParameters)aKeyPair.Private; + + if (key.X.BitLength != privateValueSize) + { + Fail("limited key check failed for key size " + privateValueSize); + } + } + } + +// TODO Put back in +// private void doTestRandom( +// int size) +// { +// AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DH"); +// a.init(size, new SecureRandom()); +// AlgorithmParameters parameters = a.generateParameters(); +// +// byte[] encodeParams = parameters.GetEncoded(); +// +// AlgorithmParameters a2 = AlgorithmParameters.getInstance("DH"); +// a2.init(encodeParams); +// +// // a and a2 should be equivalent! +// byte[] encodeParams_2 = a2.GetEncoded(); +// +// if (!areEqual(encodeParams, encodeParams_2)) +// { +// Fail("encode/Decode parameters failed"); +// } +// +// DHParameterSpec dhP = (DHParameterSpec)parameters.getParameterSpec(DHParameterSpec.class); +// +// doTestGP("DH", size, 0, dhP.G, dhP.P); +// } + + [Test] + public void TestECDH() + { + doTestECDH("ECDH"); + } + + [Test] + public void TestECDHC() + { + doTestECDH("ECDHC"); + } + + private void doTestECDH( + string algorithm) + { + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator(algorithm); + +// EllipticCurve curve = new EllipticCurve( +// new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q +// new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a +// new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, +// ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n + BigInteger.One); //1); // h + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair(); + + IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algorithm); + + aKeyAgreeBasic.Init(aKeyPair.Private); + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair(); + + IBasicAgreement bKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algorithm); + + bKeyAgreeBasic.Init(bKeyPair.Private); + + // + // agreement + // +// aKeyAgreeBasic.doPhase(bKeyPair.Public, true); +// bKeyAgreeBasic.doPhase(aKeyPair.Public, true); +// +// BigInteger k1 = new BigInteger(aKeyAgreeBasic.generateSecret()); +// BigInteger k2 = new BigInteger(bKeyAgreeBasic.generateSecret()); + BigInteger k1 = aKeyAgreeBasic.CalculateAgreement(bKeyPair.Public); + BigInteger k2 = bKeyAgreeBasic.CalculateAgreement(aKeyPair.Public); + + if (!k1.Equals(k2)) + { + Fail(algorithm + " 2-way test failed"); + } + + // + // public key encoding test + // +// byte[] pubEnc = aKeyPair.Public.GetEncoded(); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded(); + +// KeyFactory keyFac = KeyFactory.getInstance(algorithm); +// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +// ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc); + + ECDomainParameters ecDP = pubKey.Parameters; + +// if (!pubKey.getW().Equals(((ECPublicKeyParameters)aKeyPair.Public).getW())) + if (!pubKey.Q.Equals(((ECPublicKeyParameters)aKeyPair.Public).Q)) + { +// Console.WriteLine(" expected " + pubKey.getW().getAffineX() + " got " + ((ECPublicKey)aKeyPair.Public).getW().getAffineX()); +// Console.WriteLine(" expected " + pubKey.getW().getAffineY() + " got " + ((ECPublicKey)aKeyPair.Public).getW().getAffineY()); +// Fail(algorithm + " public key encoding (W test) failed"); + Console.WriteLine(" expected " + pubKey.Q.X.ToBigInteger() + + " got " + ((ECPublicKeyParameters)aKeyPair.Public).Q.X.ToBigInteger()); + Console.WriteLine(" expected " + pubKey.Q.Y.ToBigInteger() + + " got " + ((ECPublicKeyParameters)aKeyPair.Public).Q.Y.ToBigInteger()); + Fail(algorithm + " public key encoding (Q test) failed"); + } + +// if (!pubKey.Parameters.getGenerator().Equals(((ECPublicKeyParameters)aKeyPair.Public).Parameters.getGenerator())) + if (!pubKey.Parameters.G.Equals(((ECPublicKeyParameters)aKeyPair.Public).Parameters.G)) + { + Fail(algorithm + " public key encoding (G test) failed"); + } + + // + // private key encoding test + // +// byte[] privEnc = aKeyPair.Private.GetEncoded(); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded(); + +// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +// ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); + ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc); + +// if (!privKey.getS().Equals(((ECPrivateKey)aKeyPair.Private).getS())) + if (!privKey.D.Equals(((ECPrivateKeyParameters)aKeyPair.Private).D)) + { +// Fail(algorithm + " private key encoding (S test) failed"); + Fail(algorithm + " private key encoding (D test) failed"); + } + +// if (!privKey.Parameters.getGenerator().Equals(((ECPrivateKey)aKeyPair.Private).Parameters.getGenerator())) + if (!privKey.Parameters.G.Equals(((ECPrivateKeyParameters)aKeyPair.Private).Parameters.G)) + { + Fail(algorithm + " private key encoding (G test) failed"); + } + } + + [Test] + public void TestExceptions() + { + DHParameters dhParams = new DHParameters(p512, g512); + + try + { + IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement("DH"); + +// aKeyAgreeBasic.generateSecret("DES"); + aKeyAgreeBasic.CalculateAgreement(null); + } + catch (InvalidOperationException) + { + // okay + } + catch (Exception e) + { + Fail("Unexpected exception: " + e, e); + } + } + + private void doTestDesAndDesEde( + BigInteger g, + BigInteger p) + { + DHParameters dhParams = new DHParameters(p, g, null, 256); + + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH"); + + keyGen.Init(new DHKeyGenerationParameters(new SecureRandom(), dhParams)); + + AsymmetricCipherKeyPair kp = keyGen.GenerateKeyPair(); + + IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreement("DH"); + + keyAgreement.Init(kp.Private); + BigInteger agreed = keyAgreement.CalculateAgreement(kp.Public); + byte[] agreedBytes = agreed.ToByteArrayUnsigned(); + + // TODO Figure out where the magic happens of choosing the right + // bytes from 'agreedBytes' for each key type - need C# equivalent? + // (see JCEDHKeyAgreement.engineGenerateSecret) + +// SecretKey key = keyAgreement.generateSecret("DES"); +// +// if (key.getEncoded().length != 8) +// { +// Fail("DES length wrong"); +// } +// +// if (!DESKeySpec.isParityAdjusted(key.getEncoded(), 0)) +// { +// Fail("DES parity wrong"); +// } +// +// key = keyAgreement.generateSecret("DESEDE"); +// +// if (key.getEncoded().length != 24) +// { +// Fail("DESEDE length wrong"); +// } +// +// if (!DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0)) +// { +// Fail("DESEDE parity wrong"); +// } +// +// key = keyAgreement.generateSecret("Blowfish"); +// +// if (key.getEncoded().length != 16) +// { +// Fail("Blowfish length wrong"); +// } + } + + [Test] + public void TestFunction() + { + doTestGP("DH", 512, 0, g512, p512); + doTestGP("DiffieHellman", 768, 0, g768, p768); + doTestGP("DIFFIEHELLMAN", 1024, 0, g1024, p1024); + doTestGP("DH", 512, 64, g512, p512); + doTestGP("DiffieHellman", 768, 128, g768, p768); + doTestGP("DIFFIEHELLMAN", 1024, 256, g1024, p1024); + doTestExplicitWrapping(512, 0, g512, p512); + doTestDesAndDesEde(g768, p768); + + // TODO Put back in + //doTestRandom(256); + } + + [Test] + public void TestEnc() + { +// KeyFactory kFact = KeyFactory.getInstance("DH", "BC"); +// +// Key k = kFact.generatePrivate(new PKCS8EncodedKeySpec(samplePrivEnc)); + AsymmetricKeyParameter k = PrivateKeyFactory.CreateKey(samplePrivEnc); + byte[] encoded = PrivateKeyInfoFactory.CreatePrivateKeyInfo(k).GetEncoded(); + + if (!Arrays.AreEqual(samplePrivEnc, encoded)) + { + Fail("private key re-encode failed"); + } + +// k = kFact.generatePublic(new X509EncodedKeySpec(samplePubEnc)); + k = PublicKeyFactory.CreateKey(samplePubEnc); + encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded(); + + if (!Arrays.AreEqual(samplePubEnc, encoded)) + { + Fail("public key re-encode failed"); + } + +// k = kFact.generatePublic(new X509EncodedKeySpec(oldPubEnc)); + k = PublicKeyFactory.CreateKey(oldPubEnc); + encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded(); + + if (!Arrays.AreEqual(oldPubEnc, encoded)) + { + Fail("old public key re-encode failed"); + } + +// k = kFact.generatePublic(new X509EncodedKeySpec(oldFullParams)); + k = PublicKeyFactory.CreateKey(oldFullParams); + encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded(); + + if (!Arrays.AreEqual(oldFullParams, encoded)) + { + Fail("old full public key re-encode failed"); + } + } + + public override void PerformTest() + { + TestEnc(); + TestFunction(); + TestECDH(); + TestECDHC(); + TestExceptions(); + } + + public static void Main( + string[] args) + { + RunTest(new DHTest()); + } + } +} diff --git a/crypto/test/src/test/DSATest.cs b/crypto/test/src/test/DSATest.cs new file mode 100644 index 000000000..a8b8bec3b --- /dev/null +++ b/crypto/test/src/test/DSATest.cs @@ -0,0 +1,888 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class DsaTest + : SimpleTest + { + private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); + private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded"); + + private static readonly SecureRandom random = FixedSecureRandom.From(k1, k2); + + // TODO How shall we satisfy this compatibility test? +// [Test] +// public void TestCompat() +// { +// if (Security.getProvider("SUN") == null) +// return; +// ISigner s = SignerUtilities.GetSigner("DSA", "SUN"); +// KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA", "SUN"); +// byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; +// +// g.initialize(512, new SecureRandom()); +// +// KeyPair p = g.generateKeyPair(); +// +// PrivateKey sKey = p.Private; +// PublicKey vKey = p.Public; +// +// // +// // sign SUN - verify with BC +// // +// s.Init(true, sKey); +// +// s.update(data); +// +// byte[] sigBytes = s.GenerateSignature(); +// +// s = SignerUtilities.GetSigner("DSA"); +// +// s.Init(false, vKey); +// +// s.update(data); +// +// if (!s.VerifySignature(sigBytes)) +// { +// Fail("SUN -> BC verification failed"); +// } +// +// // +// // sign BC - verify with SUN +// // +// +// s.Init(true, sKey); +// +// s.update(data); +// +// sigBytes = s.GenerateSignature(); +// +// s = SignerUtilities.GetSigner("DSA", "SUN"); +// +// s.Init(false, vKey); +// +// s.update(data); +// +// if (!s.VerifySignature(sigBytes)) +// { +// Fail("BC -> SUN verification failed"); +// } +// +// // +// // key encoding test - BC decoding Sun keys +// // +// KeyFactory f = KeyFactory.GetInstance("DSA"); +// X509EncodedKeySpec x509s = new X509EncodedKeySpec(vKey.GetEncoded()); +// DSAPublicKey k1 = (DSAPublicKey)f.generatePublic(x509s); +// +// if (!k1.Y.Equals(((DSAPublicKey)vKey).Y)) +// { +// Fail("public number not decoded properly"); +// } +// +// if (!k1.Parameters.G.Equals(((DSAPublicKey)vKey).Parameters.G)) +// { +// Fail("public generator not decoded properly"); +// } +// +// if (!k1.Parameters.P.Equals(((DSAPublicKey)vKey).Parameters.P)) +// { +// Fail("public p value not decoded properly"); +// } +// +// if (!k1.Parameters.Q.Equals(((DSAPublicKey)vKey).Parameters.Q)) +// { +// Fail("public q value not decoded properly"); +// } +// +// PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(sKey.GetEncoded()); +// DSAPrivateKey k2 = (DSAPrivateKey)f.generatePrivate(pkcs8); +// +// if (!k2.X.Equals(((DSAPrivateKey)sKey).X)) +// { +// Fail("private number not decoded properly"); +// } +// +// if (!k2.Parameters.G.Equals(((DSAPrivateKey)sKey).Parameters.G)) +// { +// Fail("private generator not decoded properly"); +// } +// +// if (!k2.Parameters.P.Equals(((DSAPrivateKey)sKey).Parameters.P)) +// { +// Fail("private p value not decoded properly"); +// } +// +// if (!k2.Parameters.Q.Equals(((DSAPrivateKey)sKey).Parameters.Q)) +// { +// Fail("private q value not decoded properly"); +// } +// +// // +// // key decoding test - SUN decoding BC keys +// // +// f = KeyFactory.GetInstance("DSA", "SUN"); +// x509s = new X509EncodedKeySpec(k1.GetEncoded()); +// +// vKey = (DSAPublicKey)f.generatePublic(x509s); +// +// if (!k1.Y.Equals(((DSAPublicKey)vKey).Y)) +// { +// Fail("public number not decoded properly"); +// } +// +// if (!k1.Parameters.G.Equals(((DSAPublicKey)vKey).Parameters.G)) +// { +// Fail("public generator not decoded properly"); +// } +// +// if (!k1.Parameters.P.Equals(((DSAPublicKey)vKey).Parameters.P)) +// { +// Fail("public p value not decoded properly"); +// } +// +// if (!k1.Parameters.Q.Equals(((DSAPublicKey)vKey).Parameters.Q)) +// { +// Fail("public q value not decoded properly"); +// } +// +// pkcs8 = new PKCS8EncodedKeySpec(k2.GetEncoded()); +// sKey = (DSAPrivateKey)f.generatePrivate(pkcs8); +// +// if (!k2.X.Equals(((DSAPrivateKey)sKey).X)) +// { +// Fail("private number not decoded properly"); +// } +// +// if (!k2.Parameters.G.Equals(((DSAPrivateKey)sKey).Parameters.G)) +// { +// Fail("private generator not decoded properly"); +// } +// +// if (!k2.Parameters.P.Equals(((DSAPrivateKey)sKey).Parameters.P)) +// { +// Fail("private p value not decoded properly"); +// } +// +// if (!k2.Parameters.Q.Equals(((DSAPrivateKey)sKey).Parameters.Q)) +// { +// Fail("private q value not decoded properly"); +// } +// } + + [Test] + public void TestNONEwithDSA() + { + byte[] dummySha1 = Hex.Decode("01020304050607080910111213141516"); + + SecureRandom rand = new SecureRandom(); + + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, rand); + + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); + g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters())); + + AsymmetricCipherKeyPair kp = g.GenerateKeyPair(); + + ISigner sig = SignerUtilities.GetSigner("NONEwithDSA"); + sig.Init(true, kp.Private); + sig.BlockUpdate(dummySha1, 0, dummySha1.Length); + byte[] sigBytes = sig.GenerateSignature(); + + sig.Init(false, kp.Public); + sig.BlockUpdate(dummySha1, 0, dummySha1.Length); + sig.VerifySignature(sigBytes); + + // reset test + + sig.BlockUpdate(dummySha1, 0, dummySha1.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("NONEwithDSA failed to reset"); + } + + // lightweight test + DsaSigner signer = new DsaSigner(); + Asn1Sequence derSig = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(sigBytes)); + + signer.Init(false, kp.Public); + + if (!signer.VerifySignature(dummySha1, + DerInteger.GetInstance(derSig[0]).Value, DerInteger.GetInstance(derSig[1]).Value)) + { + Fail("NONEwithDSA not really NONE!"); + } + } + + /** + * X9.62 - 1998,
    + * J.3.2, Page 155, ECDSA over the field Fp
    + * an example with 239 bit prime + */ + [Test] + public void TestECDsa239BitPrime() + { + BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176"); + BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783"); + + byte[] kData = BigIntegers.AsUnsignedByteArray( + new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655")); + + SecureRandom k = FixedSecureRandom.From(kData); + + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); + +// KeyFactory f = KeyFactory.GetInstance("ECDSA"); +// PrivateKey sKey = f.generatePrivate(priKey); +// PublicKey vKey = f.generatePublic(pubKey); + AsymmetricKeyParameter sKey = priKey; + AsymmetricKeyParameter vKey = pubKey; + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + byte[] message = Encoding.ASCII.GetBytes("abc"); + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("239 Bit EC verification failed"); + } + + BigInteger[] sig = DerDecode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail("r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + /** + * X9.62 - 1998,
    + * J.2.1, Page 100, ECDSA over the field F2m
    + * an example with 191 bit binary field + */ + [Test] + public void TestECDsa239BitBinary() + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174"); + + byte[] kData = BigIntegers.AsUnsignedByteArray( + new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = FixedSecureRandom.From(kData); + + ECCurve curve = new F2mCurve( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); // h + + ECPrivateKeyParameters sKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + parameters); + + ECPublicKeyParameters vKey = new ECPublicKeyParameters( + "ECDSA", + curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + parameters); + + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); + byte[] message = Encoding.ASCII.GetBytes("abc"); + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("239 Bit EC verification failed"); + } + + BigInteger[] sig = DerDecode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail("r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + [Test] + public void TestECDsa239BitBinaryRipeMD160() + { + DoTestECDsa239BitBinary("RIPEMD160withECDSA", TeleTrusTObjectIdentifiers.ECSignWithRipeMD160); + } + + [Test] + public void TestECDsa239BitBinarySha1() + { + DoTestECDsa239BitBinary("SHA1withECDSA", TeleTrusTObjectIdentifiers.ECSignWithSha1); + } + + [Test] + public void TestECDsa239BitBinarySha224() + { + DoTestECDsa239BitBinary("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + } + + [Test] + public void TestECDsa239BitBinarySha256() + { + DoTestECDsa239BitBinary("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + } + + [Test] + public void TestECDsa239BitBinarySha384() + { + DoTestECDsa239BitBinary("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + } + + [Test] + public void TestECDsa239BitBinarySha512() + { + DoTestECDsa239BitBinary("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + } + + private void DoTestECDsa239BitBinary( + string algorithm, + DerObjectIdentifier oid) + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174"); + + byte[] kData = BigIntegers.AsUnsignedByteArray( + new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = FixedSecureRandom.From(kData); + + ECCurve curve = new F2mCurve( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); // h + + ECPrivateKeyParameters sKey = new ECPrivateKeyParameters( + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + parameters); + + ECPublicKeyParameters vKey = new ECPublicKeyParameters( + curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + parameters); + + ISigner sgr = SignerUtilities.GetSigner(algorithm); + byte[] message = Encoding.ASCII.GetBytes("abc"); + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr = SignerUtilities.GetSigner(oid.Id); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("239 Bit EC RIPEMD160 verification failed"); + } + } + + private void doTestBadStrength( + int strength) + { +// IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); + + // test exception + // + try + { + SecureRandom rand = new SecureRandom(); + + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(strength, 80, rand); + +// g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters())); + + Fail("illegal parameter " + strength + " check failed."); + } + catch (ArgumentException) + { + // expected + } + } + + [Test] + public void TestGeneration() + { + ISigner s = SignerUtilities.GetSigner("DSA"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + SecureRandom rand = new SecureRandom(); + + // KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA"); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); + + // test exception + // + + doTestBadStrength(513); + doTestBadStrength(510); + doTestBadStrength(1025); + + //g.initialize(512, rand); + { + DsaParametersGenerator pGen = new DsaParametersGenerator(); + pGen.Init(512, 80, rand); + + g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters())); + } + + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + AsymmetricKeyParameter sKey = p.Private; + AsymmetricKeyParameter vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("DSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("DSA verification failed"); + } + + + + // + // ECDSA Fp generation test + // + s = SignerUtilities.GetSigner("ECDSA"); + + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + g = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + g.Init(new ECKeyGenerationParameters(ecSpec, rand)); + + p = g.GenerateKeyPair(); + + sKey = p.Private; + vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("ECDSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("ECDSA verification failed"); + } + + // + // ECDSA F2m generation test + // + s = SignerUtilities.GetSigner("ECDSA"); + + curve = new F2mCurve( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ecSpec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); // h + + g = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + g.Init(new ECKeyGenerationParameters(ecSpec, rand)); + + p = g.GenerateKeyPair(); + + sKey = p.Private; + vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("ECDSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("ECDSA verification failed"); + } + } + + [Test] + public void TestParameters() + { +// AlgorithmParameterGenerator a = AlgorithmParameterGenerator.GetInstance("DSA"); +// a.init(512, random); + DsaParametersGenerator a = new DsaParametersGenerator(); + a.Init(512, 20, random); + +// AlgorithmParameters parameters = a.generateParameters(); + DsaParameters p = a.GenerateParameters(); + +// byte[] encodeParams = parameters.GetEncoded(); + byte[] encodeParams = new DsaParameter(p.P, p.Q, p.G).GetDerEncoded(); + +// AlgorithmParameters a2 = AlgorithmParameters.GetInstance("DSA"); +// a2.init(encodeParams); + DsaParameter dsaP = DsaParameter.GetInstance(Asn1Object.FromByteArray(encodeParams)); + DsaParameters p2 = new DsaParameters(dsaP.P, dsaP.Q, dsaP.G); + + // a and a2 should be equivalent! +// byte[] encodeParams_2 = a2.GetEncoded(); + byte[] encodeParams_2 = new DsaParameter(p2.P, p2.Q, p2.G).GetDerEncoded(); + + if (!AreEqual(encodeParams, encodeParams_2)) + { + Fail("encode/Decode parameters failed"); + } + +// DSAParameterSpec dsaP = (DSAParameterSpec)parameters.getParameterSpec(typeof(DSAParameterSpec)); + +// KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA"); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); +// g.initialize(dsaP, new SecureRandom()); + g.Init(new DsaKeyGenerationParameters(new SecureRandom(), p)); +// KeyPair p = g.generateKeyPair(); + AsymmetricCipherKeyPair pair = g.GenerateKeyPair(); + +// PrivateKey sKey = p.Private; +// PublicKey vKey = p.Public; + AsymmetricKeyParameter sKey = pair.Private; + AsymmetricKeyParameter vKey = pair.Public; + + ISigner s = SignerUtilities.GetSigner("DSA"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("DSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("DSA verification failed"); + } + } + + [Test] + public void TestDsa2Parameters() + { + byte[] seed = Hex.Decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0"); + + //AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DSA", "BC"); + //a.init(2048, new DSATestSecureRandom(seed)); + DsaParametersGenerator a = new DsaParametersGenerator(new Sha256Digest()); + a.Init(new DsaParameterGenerationParameters(2048, 256, 80, new DsaTestSecureRandom(seed))); + + //AlgorithmParameters parameters = a.generateParameters(); + + //DSAParameterSpec dsaP = (DSAParameterSpec)parameters.getParameterSpec(DSAParameterSpec.class); + DsaParameters dsaP = a.GenerateParameters(); + + if (!dsaP.Q.Equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16))) + { + Fail("Q incorrect"); + } + + if (!dsaP.P.Equals(new BigInteger( + "F56C2A7D366E3EBDEAA1891FD2A0D099" + + "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" + + "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" + + "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" + + "5909132627F51A0C866877E672E555342BDF9355347DBD43" + + "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" + + "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" + + "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" + + "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" + + "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" + + "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16))) + { + Fail("P incorrect"); + } + + if (!dsaP.G.Equals(new BigInteger( + "8DC6CC814CAE4A1C05A3E186A6FE27EA" + + "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" + + "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" + + "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" + + "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" + + "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" + + "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" + + "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" + + "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" + + "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" + + "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16))) + { + Fail("G incorrect"); + } + + //KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA"); + //g.initialize(dsaP, FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))); + g.Init(new DsaKeyGenerationParameters(FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), dsaP)); + //KeyPair p = g.generateKeyPair(); + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + //DSAPrivateKey sKey = (DSAPrivateKey)p.getPrivate(); + //DSAPublicKey vKey = (DSAPublicKey)p.getPublic(); + DsaPrivateKeyParameters sKey = (DsaPrivateKeyParameters)p.Private; + DsaPublicKeyParameters vKey = (DsaPublicKeyParameters)p.Public; + + if (!vKey.Y.Equals(new BigInteger( + "2828003D7C747199143C370FDD07A286" + + "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" + + "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" + + "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" + + "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" + + "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" + + "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" + + "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" + + "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" + + "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" + + "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16))) + { + Fail("Y value incorrect"); + } + + if (!sKey.X.Equals( + new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16))) + { + Fail("X value incorrect"); + } + + //byte[] encodeParams = parameters.getEncoded(); + byte[] encodeParams = new DsaParameter(dsaP.P, dsaP.Q, dsaP.G).GetDerEncoded(); + + //AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA", "BC"); + //a2.init(encodeParams); + DsaParameter dsaP2 = DsaParameter.GetInstance(Asn1Object.FromByteArray(encodeParams)); + DsaParameters p2 = new DsaParameters(dsaP.P, dsaP.Q, dsaP.G); + + // a and a2 should be equivalent! + //byte[] encodeParams_2 = a2.GetEncoded(); + byte[] encodeParams_2 = new DsaParameter(p2.P, p2.Q, p2.G).GetDerEncoded(); + + if (!AreEqual(encodeParams, encodeParams_2)) + { + Fail("encode/decode parameters failed"); + } + + ISigner s = SignerUtilities.GetSigner("DSA"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("DSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("DSA verification failed"); + } + } + + public override void PerformTest() + { + // TODO +// TestCompat(); + TestNONEwithDSA(); + TestECDsa239BitPrime(); + TestECDsa239BitBinary(); + TestECDsa239BitBinaryRipeMD160(); + TestECDsa239BitBinarySha1(); + TestECDsa239BitBinarySha224(); + TestECDsa239BitBinarySha256(); + TestECDsa239BitBinarySha384(); + TestECDsa239BitBinarySha512(); + + TestGeneration(); + TestParameters(); + TestDsa2Parameters(); + } + + protected BigInteger[] DerDecode( + byte[] encoding) + { + Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + + return new BigInteger[] + { + ((DerInteger)s[0]).Value, + ((DerInteger)s[1]).Value + }; + } + + public override string Name + { + get { return "DSA/ECDSA"; } + } + + public static void Main( + string[] args) + { + RunTest(new DsaTest()); + } + + private class DsaTestSecureRandom + : FixedSecureRandom + { + private bool first = true; + + public DsaTestSecureRandom(byte[] value) + : base(Arrays.Clone(value)) + { + } + + public override void NextBytes(byte[] bytes) + { + if (first) + { + base.NextBytes(bytes); + first = false; + } + else + { + bytes[bytes.Length - 1] = 2; + } + } + } + } +} diff --git a/crypto/test/src/test/DigestTest.cs b/crypto/test/src/test/DigestTest.cs new file mode 100644 index 000000000..5d840ee66 --- /dev/null +++ b/crypto/test/src/test/DigestTest.cs @@ -0,0 +1,175 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class DigestTest + : SimpleTest + { + private static string[,] abcVectors = + { + { "MD2", "da853b0d3f88d99b30283a69e6ded6bb" }, + { "MD4", "a448017aaf21d8525fc10ae87aa6729d" }, + { "MD5", "900150983cd24fb0d6963f7d28e17f72"}, + { "SHA-1", "a9993e364706816aba3e25717850c26c9cd0d89d" }, + { "SHA-224", "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" }, + { "SHA-256", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" }, + { "SHA-384", "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7" }, + { "SHA-512", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" }, + { "SHA-512/224", "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA" }, + { "SHA-512/256", "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23" }, + { "RIPEMD128", "c14a12199c66e4ba84636b0f69144c77" }, + { "RIPEMD160", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" }, + { "RIPEMD256", "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65" }, + { "RIPEMD320", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d" }, + { "Tiger", "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93" }, + { "GOST3411", "b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c" }, + { "WHIRLPOOL", "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5" } + }; + + public override string Name + { + get { return "Digest"; } + } + + void doTest( + string algorithm) + { + byte[] message = Encoding.ASCII.GetBytes("hello world"); + + IDigest digest = DigestUtilities.GetDigest(algorithm); + +// byte[] result = digest.digest(message); + digest.BlockUpdate(message, 0, message.Length); + byte[] result = DigestUtilities.DoFinal(digest); + +// byte[] result2 = digest.digest(message); + digest.BlockUpdate(message, 0, message.Length); + byte[] result2 = DigestUtilities.DoFinal(digest); + + // test one digest the same message with the same instance + if (!AreEqual(result, result2)) + { + Fail("Result object 1 not equal"); + } + + // test two, single byte updates + for (int i = 0; i < message.Length; i++) + { + digest.Update(message[i]); + } +// result2 = digest.digest(); + result2 = DigestUtilities.DoFinal(digest); + + if (!AreEqual(result, result2)) + { + Fail("Result object 2 not equal"); + } + + // test three, two half updates + digest.BlockUpdate(message, 0, message.Length/2); + digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2); +// result2 = digest.digest(); + result2 = DigestUtilities.DoFinal(digest); + + if (!AreEqual(result, result2)) + { + Fail("Result object 3 not equal"); + } + + // TODO Should we support Clone'ing of digests? +// // test four, clone test +// digest.BlockUpdate(message, 0, message.Length/2); +// IDigest d = (IDigest)digest.Clone(); +// digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2); +//// result2 = digest.digest(); +// result2 = new byte[digest.GetDigestSize()]; +// digest.DoFinal(result2, 0); +// +// if (!AreEqual(result, result2)) +// { +// Fail("Result object 4(a) not equal"); +// } +// +// d.BlockUpdate(message, message.Length/2, message.Length-message.Length/2); +//// result2 = d.digest(); +// result2 = new byte[d.GetDigestSize()]; +// d.DoFinal(result2, 0); +// +// if (!AreEqual(result, result2)) +// { +// Fail("Result object 4(b) not equal"); +// } + + // test five, check reset() method + digest.BlockUpdate(message, 0, message.Length/2); + digest.Reset(); + digest.BlockUpdate(message, 0, message.Length/2); + digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2); +// result2 = digest.digest(); + result2 = DigestUtilities.DoFinal(digest); + + if (!AreEqual(result, result2)) + { + Fail("Result object 5 not equal"); + } + } + + /** + * Test the hash against a standard value for the string "abc" + * + * @param algorithm algorithm to test + * @param hash expected value + * @return the test result. + */ + void doAbcTest( + string algorithm, + string hash) + { + byte[] abc = { (byte)0x61, (byte)0x62, (byte)0x63 }; + + IDigest digest = DigestUtilities.GetDigest(algorithm); + +// byte[] result = digest.digest(abc); + digest.BlockUpdate(abc, 0, abc.Length); + byte[] result = DigestUtilities.DoFinal(digest); + + if (!AreEqual(result, Hex.Decode(hash))) + { + Fail("abc result not equal for " + algorithm); + } + } + + public override void PerformTest() + { + for (int i = 0; i != abcVectors.GetLength(0); i++) + { + doTest(abcVectors[i, 0]); + + doAbcTest(abcVectors[i, 0], abcVectors[i, 1]); + } + } + + public static void Main( + string[] args) + { + RunTest(new DigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/ECDSA5Test.cs b/crypto/test/src/test/ECDSA5Test.cs new file mode 100644 index 000000000..bbde6b446 --- /dev/null +++ b/crypto/test/src/test/ECDSA5Test.cs @@ -0,0 +1,300 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class ECDsa5Test + : SimpleTest + { +// private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); +// private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded"); +// +// private SecureRandom random = FixedSecureRandom.From(k1, k2); + + [Test] + public void DecodeTest() + { +// EllipticCurve curve = new EllipticCurve( +// new ECFieldFp(new BigInteger("6277101735386680763835789423207666416083908700390324961279")), // q +// new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a +// new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + ECCurve curve = new FpCurve( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b + +// ECPoint p = ECPointUtil.DecodePoint(curve, Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")); + ECPoint p = curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")); + + BigInteger x = p.X.ToBigInteger(); //p.getAffineX(); + + if (!x.Equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16))) + { + Fail("x uncompressed incorrectly"); + } + + BigInteger y = p.Y.ToBigInteger(); //p.getAffineX(); + if (!y.Equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16))) + { + Fail("y uncompressed incorrectly"); + } + } + + /** + * X9.62 - 1998,
    + * J.3.2, Page 155, ECDSA over the field Fp
    + * an example with 239 bit prime + */ + [Test] + public void TestECDsa239BitPrime() + { + BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176"); + BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783"); + + byte[] kData = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + +// EllipticCurve curve = new EllipticCurve( +// new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q +// new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a +// new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, +// ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n + BigInteger.One); //1); // h + + ECPrivateKeyParameters sKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeyParameters vKey = new ECPublicKeyParameters( + "ECDSA", +// ECPointUtil.DecodePoint(curve, Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); +// KeyFactory f = KeyFactory.getInstance("ECDSA"); +// AsymmetricKeyParameter sKey = f.generatePrivate(priKey); +// AsymmetricKeyParameter vKey = f.generatePublic(pubKey); + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("239 Bit EC verification failed"); + } + + BigInteger[] sig = derDecode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail("r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + /** + * X9.62 - 1998,
    + * J.2.1, Page 100, ECDSA over the field F2m
    + * an example with 191 bit binary field + */ + [Test] + public void TestECDsa239BitBinary() + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174"); + + byte[] kData = new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363").ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + +// EllipticCurve curve = new EllipticCurve( +// new ECFieldF2m(239, // m +// new int[] { 36 }), // k +// new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a +// new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + ECCurve curve = new F2mCurve( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECDomainParameters parameters = new ECDomainParameters( + curve, +// ECPointUtil.DecodePoint(curve, Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.ValueOf(4)); //4); // h + + ECPrivateKeyParameters sKey = new ECPrivateKeyParameters( + "ECDSA", + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + parameters); + + ECPublicKeyParameters vKey = new ECPublicKeyParameters( + "ECDSA", +// ECPointUtil.DecodePoint(curve, Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + parameters); + + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); +// KeyFactory f = KeyFactory.getInstance("ECDSA"); +// AsymmetricKeyParameter sKey = f.generatePrivate(priKeySpec); +// AsymmetricKeyParameter vKey = f.generatePublic(pubKeySpec); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("239 Bit EC verification failed"); + } + + BigInteger[] sig = derDecode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail("r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail("s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + [Test] + public void TestGeneration() + { + // + // ECDSA generation test + // + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + ISigner s = SignerUtilities.GetSigner("ECDSA"); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + +// EllipticCurve curve = new EllipticCurve( +// new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q +// new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a +// new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, +// ECPointUtil.DecodePoint(curve, + curve.DecodePoint( + Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n + BigInteger.One); //1); // h + + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + AsymmetricKeyParameter sKey = p.Private; + AsymmetricKeyParameter vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("ECDSA"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("ECDSA verification failed"); + } + } + + protected BigInteger[] derDecode( + byte[] encoding) + { + Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + + return new BigInteger[] + { + ((DerInteger)s[0]).Value, + ((DerInteger)s[1]).Value + }; + } + + public override string Name + { + get { return "ECDSA5"; } + } + + public override void PerformTest() + { + DecodeTest(); + TestECDsa239BitPrime(); + TestECDsa239BitBinary(); + TestGeneration(); + } + + public static void Main( + string[] args) + { + RunTest(new ECDsa5Test()); + } + } +} diff --git a/crypto/test/src/test/ECEncodingTest.cs b/crypto/test/src/test/ECEncodingTest.cs new file mode 100644 index 000000000..0e80d611a --- /dev/null +++ b/crypto/test/src/test/ECEncodingTest.cs @@ -0,0 +1,243 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class ECEncodingTest + : SimpleTest + { + public override string Name + { + get { return "ECEncodingTest"; } + } + + /** J.4.7 An Example with m = 304 */ + private int m = 304; + + /** f = 010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000807 */ + private int k1 = 1; + private int k2 = 2; + private int k3 = 11; + private static readonly byte[] hexa = {(byte)0xFD, 0x0D, 0x69, 0x31, 0x49, (byte)0xA1, 0x18, (byte)0xF6, 0x51 + , (byte)0xE6, (byte)0xDC, (byte)0xE6, (byte)0x80, 0x20, (byte)0x85, 0x37, 0x7E, 0x5F, (byte)0x88, 0x2D, 0x1B, 0x51 + , 0x0B, 0x44, 0x16, 0x00, 0x74, (byte)0xC1, 0x28, (byte)0x80, 0x78, 0x36, 0x5A, 0x03 + , (byte)0x96, (byte)0xC8, (byte)0xE6, (byte)0x81}; + private static readonly byte[] hexb = {(byte)0xBD, (byte)0xDB, (byte)0x97, (byte)0xE5, (byte)0x55 + , (byte)0xA5, (byte)0x0A, (byte)0x90, (byte)0x8E, (byte)0x43, (byte)0xB0 + , (byte)0x1C, (byte)0x79, (byte)0x8E, (byte)0xA5, (byte)0xDA, (byte)0xA6 + , (byte)0x78, (byte)0x8F, (byte)0x1E, (byte)0xA2, (byte)0x79 + , (byte)0x4E, (byte)0xFC, (byte)0xF5, (byte)0x71, (byte)0x66, (byte)0xB8 + , (byte)0xC1, (byte)0x40, (byte)0x39, (byte)0x60, (byte)0x1E + , (byte)0x55, (byte)0x82, (byte)0x73, (byte)0x40, (byte)0xBE}; + private static readonly BigInteger a = new BigInteger(1, hexa); + private static readonly BigInteger b = new BigInteger(1, hexb); + + /** Base point G (with point compression) */ + private byte[] enc = {0x02, 0x19, 0x7B, 0x07, (byte)0x84, 0x5E, (byte)0x9B, (byte)0xE2, (byte)0xD9, 0x6A, (byte)0xDB, 0x0F + , 0x5F, 0x3C, 0x7F, 0x2C, (byte)0xFF, (byte)0xBD, 0x7A, 0x3E, (byte)0xB8, (byte)0xB6, (byte)0xFE, + (byte)0xC3, 0x5C, 0x7F, (byte)0xD6, 0x7F, 0x26, (byte)0xDD, (byte)0xF6 + , 0x28, 0x5A, 0x64, 0x4F, 0x74, 0x0A, 0x26, 0x14}; + + private void doTestPointCompression() + { + ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b); + curve.DecodePoint(enc); + + int[] ks = new int[3]; + ks[0] = k3; + ks[1] = k2; + ks[2] = k1; + } + + public override void PerformTest() + { + byte[] ecParams = Hex.Decode("3081C8020101302806072A8648CE3D0101021D00D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF303C041C68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43041C2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B0439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD021D00D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F020101"); + doTestParams(ecParams, true); + + doTestParams(ecParams, false); + + ecParams = Hex.Decode("3081C8020101302806072A8648CE3D0101021D00D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF303C041C56E6C7E4F11A7B4B961A4DCB5BD282EB22E42E9BCBE3E7B361F18012041C4BE3E7B361F18012F2353D22975E02D8D05D2C6F3342DD8F57D4C76F0439048D127A0C27E0DE207ED3B7FB98F83C8BD5A2A57C827F4B97874DEB2C1BAEB0C006958CE61BB1FC81F5389E288CB3E86E2ED91FB47B08FCCA021D00D7C134AA264366862A18302575D11A5F7AABFBA3D897FF5CA727AF53020101"); + doTestParams(ecParams, true); + + doTestParams(ecParams, false); + + ecParams = Hex.Decode("30820142020101303c06072a8648ce3d0101023100fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff3066043100fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc043100b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef046104aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f023100ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973020101"); + doTestParams(ecParams, true); + + doTestParams(ecParams, false); + + doTestPointCompression(); + } + + private void doTestParams( + byte[] ecParameterEncoded, + bool compress) + { +// string keyStorePass = "myPass"; + Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(ecParameterEncoded); + X9ECParameters x9 = new X9ECParameters(seq); + AsymmetricCipherKeyPair kp = null; + bool success = false; + while (!success) + { + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); +// kpg.Init(new ECParameterSpec(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed())); + ECDomainParameters ecParams = new ECDomainParameters( + x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); + kpg.Init(new ECKeyGenerationParameters(ecParams, new SecureRandom())); + kp = kpg.GenerateKeyPair(); + // The very old Problem... we need a certificate chain to + // save a private key... + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) kp.Public; + + if (!compress) + { + //pubKey.setPointFormat("UNCOMPRESSED"); + pubKey = SetPublicUncompressed(pubKey, false); + } + + byte[] x = pubKey.Q.X.ToBigInteger().ToByteArrayUnsigned(); + byte[] y = pubKey.Q.Y.ToBigInteger().ToByteArrayUnsigned(); + if (x.Length == y.Length) + { + success = true; + } + } + + // The very old Problem... we need a certificate chain to + // save a private key... + + X509CertificateEntry[] chain = new X509CertificateEntry[] { + new X509CertificateEntry(GenerateSelfSignedSoftECCert(kp, compress)) + }; + +// KeyStore keyStore = KeyStore.getInstance("BKS"); +// keyStore.load(null, keyStorePass.ToCharArray()); + Pkcs12Store keyStore = new Pkcs12StoreBuilder().Build(); + + keyStore.SetCertificateEntry("ECCert", chain[0]); + + ECPrivateKeyParameters privateECKey = (ECPrivateKeyParameters) kp.Private; + keyStore.SetKeyEntry("ECPrivKey", new AsymmetricKeyEntry(privateECKey), chain); + + // Test ec sign / verify + ECPublicKeyParameters pub = (ECPublicKeyParameters) kp.Public; +// string oldPrivateKey = new string(Hex.encode(privateECKey.getEncoded())); + byte[] oldPrivateKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateECKey).GetDerEncoded(); + string oldPrivateKey = Hex.ToHexString(oldPrivateKeyBytes); +// string oldPublicKey = new string(Hex.encode(pub.getEncoded())); + byte[] oldPublicKeyBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub).GetDerEncoded(); + string oldPublicKey = Hex.ToHexString(oldPublicKeyBytes); + ECPrivateKeyParameters newKey = (ECPrivateKeyParameters) + keyStore.GetKey("ECPrivKey").Key; + ECPublicKeyParameters newPubKey = (ECPublicKeyParameters) + keyStore.GetCertificate("ECCert").Certificate.GetPublicKey(); + + if (!compress) + { + // TODO Private key compression? + //newKey.setPointFormat("UNCOMPRESSED"); + //newPubKey.setPointFormat("UNCOMPRESSED"); + newPubKey = SetPublicUncompressed(newPubKey, false); + } + +// string newPrivateKey = new string(Hex.encode(newKey.getEncoded())); + byte[] newPrivateKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(newKey).GetDerEncoded(); + string newPrivateKey = Hex.ToHexString(newPrivateKeyBytes); +// string newPublicKey = new string(Hex.encode(newPubKey.getEncoded())); + byte[] newPublicKeyBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(newPubKey).GetDerEncoded(); + string newPublicKey = Hex.ToHexString(newPublicKeyBytes); + + if (!oldPrivateKey.Equals(newPrivateKey)) +// if (!privateECKey.Equals(newKey)) + { + Fail("failed private key comparison"); + } + + if (!oldPublicKey.Equals(newPublicKey)) +// if (!pub.Equals(newPubKey)) + { + Fail("failed public key comparison"); + } + } + + /** + * Create a self signed cert for our software emulation + * + * @param kp + * is the keypair for our certificate + * @return a self signed cert for our software emulation + * @throws InvalidKeyException + * on error + * @throws SignatureException + * on error + */ + private X509Certificate GenerateSelfSignedSoftECCert( + AsymmetricCipherKeyPair kp, + bool compress) + { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + ECPrivateKeyParameters privECKey = (ECPrivateKeyParameters) kp.Private; + ECPublicKeyParameters pubECKey = (ECPublicKeyParameters) kp.Public; + + if (!compress) + { + // TODO Private key compression? + //privECKey.setPointFormat("UNCOMPRESSED"); + //pubECKey.setPointFormat("UNCOMPRESSED"); + pubECKey = SetPublicUncompressed(pubECKey, false); + } + + certGen.SetSignatureAlgorithm("ECDSAwithSHA1"); + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name("CN=Software emul (EC Cert)")); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50000)); + certGen.SetSubjectDN(new X509Name("CN=Software emul (EC Cert)")); + certGen.SetPublicKey(pubECKey); + + return certGen.Generate(privECKey); + } + + private ECPublicKeyParameters SetPublicUncompressed( + ECPublicKeyParameters key, + bool withCompression) + { + ECPoint p = key.Q; + return new ECPublicKeyParameters( + key.AlgorithmName, + p.Curve.CreatePoint(p.X.ToBigInteger(), p.Y.ToBigInteger(), withCompression), + key.Parameters); + } + + public static void Main( + string[] args) + { + RunTest(new ECEncodingTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/ECNRTest.cs b/crypto/test/src/test/ECNRTest.cs new file mode 100644 index 000000000..8a24443c2 --- /dev/null +++ b/crypto/test/src/test/ECNRTest.cs @@ -0,0 +1,204 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class ECNRTest + : SimpleTest + { + private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); + private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded"); + + private readonly SecureRandom random = FixedSecureRandom.From(k1, k2); + + /** + * X9.62 - 1998,
    + * J.3.2, Page 155, ECDSA over the field Fp
    + * an example with 239 bit prime + */ + [Test] + public void TestECNR239bitPrime() + { + BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693"); + BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143"); + + byte[] kData = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + + X9ECParameters p = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v1); + ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECCurve curve = spec.Curve; + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR"); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + checkSignature(239, priKey, pubKey, sgr, k, message, r, s); + } + + // ------------------------------------------------------------------------- + + /** + * X9.62 - 1998,
    + * Page 104-105, ECDSA over the field Fp
    + * an example with 192 bit prime + */ + [Test] + public void TestECNR192bitPrime() + { + BigInteger r = new BigInteger("2474388605162950674935076940284692598330235697454145648371"); + BigInteger s = new BigInteger("2997192822503471356158280167065034437828486078932532073836"); + + byte[] kData = new BigInteger("dcc5d1f1020906df2782360d36b2de7a17ece37d503784af", 16).ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + + X9ECParameters p = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime192v1); + ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECCurve curve = spec.Curve; + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + curve.DecodePoint(Hex.Decode("0262B12D60690CDCF330BABAB6E69763B471F994DD702D16A5")), // Q + spec); + + ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR"); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + checkSignature(192, priKey, pubKey, sgr, k, message, r, s); + } + + // ------------------------------------------------------------------------- + + /** + * SEC 2: Recommended Elliptic Curve Domain Parameters - September 2000,
    + * Page 17-19, Recommended 521-bit Elliptic Curve Domain Parameters over Fp
    + * an ECC example with a 521 bit prime and a 512 bit hash + */ + [Test] + public void TestECNR521bitPrime() + { + BigInteger r = new BigInteger("1820641608112320695747745915744708800944302281118541146383656165330049339564439316345159057453301092391897040509935100825960342573871340486684575368150970954"); + BigInteger s = new BigInteger("6358277176448326821136601602749690343031826490505780896013143436153111780706227024847359990383467115737705919410755190867632280059161174165591324242446800763"); + + byte[] kData = new BigInteger("cdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", 16).ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + + X9ECParameters p = SecNamedCurves.GetByOid(SecObjectIdentifiers.SecP521r1); + ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H); + ECCurve curve = spec.Curve; + + ECPrivateKeyParameters priKey = new ECPrivateKeyParameters( + new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q + spec); + + ISigner sgr = SignerUtilities.GetSigner("SHA512withECNR"); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + checkSignature(521, priKey, pubKey, sgr, k, message, r, s); + } + + private void checkSignature( + int size, + ECPrivateKeyParameters sKey, + ECPublicKeyParameters vKey, + ISigner sgr, + SecureRandom k, + byte[] message, + BigInteger r, + BigInteger s) + { + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail(size + " bit EC verification failed"); + } + + BigInteger[] sig = derDecode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail(size + "bit" + + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail(size + "bit" + + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + protected BigInteger[] derDecode( + byte[] encoding) + { + Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + + return new BigInteger[] + { + ((DerInteger)s[0]).Value, + ((DerInteger)s[1]).Value + }; + } + + public override string Name + { + get { return "ECNR"; } + } + + public override void PerformTest() + { + TestECNR192bitPrime(); + TestECNR239bitPrime(); + TestECNR521bitPrime(); + } + + public static void Main( + string[] args) + { + RunTest(new ECNRTest()); + } + } +} diff --git a/crypto/test/src/test/ElGamalTest.cs b/crypto/test/src/test/ElGamalTest.cs new file mode 100644 index 000000000..9a87ea9b1 --- /dev/null +++ b/crypto/test/src/test/ElGamalTest.cs @@ -0,0 +1,334 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class ElGamalTest + : SimpleTest + { + private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16); + private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16); + + private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16); + private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16); + + public override string Name + { + get { return "ElGamal"; } + } + + [Test] + public void TestGP512() + { + doTestGP(512, 0, g512, p512); + doTestGP(512, 64, g512, p512); + } + + [Test] + public void TestGP768() + { + doTestGP(768, 0, g768, p768); + doTestGP(768, 128, g768, p768); + } + + [Test] + public void TestGP1024() + { + doTestGP(1024, 0, g1024, p1024); + doTestGP(1024, 256, g1024, p1024); + } + + [Test] + public void TestRandom256() + { + doTestRandom(256); + } + + private void doTestGP( + int size, + int privateValueSize, + BigInteger g, + BigInteger p) + { + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("ElGamal"); + +// DHParameterSpec elParams = new DHParameterSpec(p, g); +// keyGen.initialize(elParams); + ElGamalParameters elParams = new ElGamalParameters(p, g, privateValueSize); + ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters( + new SecureRandom(), elParams); + keyGen.Init(elKgp); + + AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair(); + SecureRandom rand = new SecureRandom(); + + checkKeySize(privateValueSize, keyPair); + + IBufferedCipher cipher = CipherUtilities.GetCipher("ElGamal"); + + cipher.Init(true, new ParametersWithRandom(keyPair.Public, rand)); + + byte[] inBytes = Encoding.ASCII.GetBytes("This is a test"); + + if (cipher.GetOutputSize(inBytes.Length) != (size / 8) * 2) + { + Fail("getOutputSize wrong on encryption"); + } + + byte[] outBytes = cipher.DoFinal(inBytes); + + cipher.Init(false, keyPair.Private); + + if (cipher.GetOutputSize(outBytes.Length) != (size / 8) - 1) + { + Fail("GetOutputSize wrong on decryption"); + } + + + // + // No Padding - maximum length + // + byte[] modBytes = ((ElGamalPublicKeyParameters)keyPair.Public).Parameters.P.ToByteArray(); + byte[] maxInput = new byte[modBytes.Length - 1]; + + maxInput[0] |= 0x7f; + + cipher.Init(true, new ParametersWithRandom(keyPair.Public, rand)); + + outBytes = cipher.DoFinal(maxInput); + + cipher.Init(false, keyPair.Private); + + outBytes = cipher.DoFinal(outBytes); + + if (!AreEqual(outBytes, maxInput)) + { + Fail("NoPadding test failed on decrypt expected " + + Hex.ToHexString(maxInput) + " got " + + Hex.ToHexString(outBytes)); + } + + + // + // encrypt/decrypt + // + IBufferedCipher c1 = CipherUtilities.GetCipher("ElGamal"); + IBufferedCipher c2 = CipherUtilities.GetCipher("ElGamal"); + + c1.Init(true, new ParametersWithRandom(keyPair.Public, rand)); + + byte[] out1 = c1.DoFinal(inBytes); + + c2.Init(false, keyPair.Private); + + byte[] out2 = c2.DoFinal(out1); + + if (!AreEqual(inBytes, out2)) + { + Fail(size + " encrypt test failed"); + } + + + // + // encrypt/decrypt with update + // + int outLen = c1.ProcessBytes(inBytes, 0, 2, out1, 0); + + outLen += c1.DoFinal(inBytes, 2, inBytes.Length - 2, out1, outLen); + + outLen = c2.ProcessBytes(out1, 0, 2, out2, 0); + + outLen += c2.DoFinal(out1, 2, out1.Length - 2, out2, outLen); + + if (!AreEqual(inBytes, out2)) + { + Fail(size + " encrypt with update test failed"); + } + + + + // + // public key encoding test + // +// byte[] pubEnc = keyPair.Public.GetEncoded(); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public).GetDerEncoded(); + +// KeyFactory keyFac = KeyFactory.GetInstance("ElGamal"); +// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +// DHPublicKeyParameters pubKey = (DHPublicKeyParameters)keyFac.generatePublic(pubX509); + ElGamalPublicKeyParameters pubKey = (ElGamalPublicKeyParameters) + PublicKeyFactory.CreateKey(pubEnc); + ElGamalParameters spec = pubKey.Parameters; + + if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P)) + { + Fail(size + " bit public key encoding/decoding test failed on parameters"); + } + + if (!((ElGamalPublicKeyParameters)keyPair.Public).Y.Equals(pubKey.Y)) + { + Fail(size + " bit public key encoding/decoding test failed on y value"); + } + +/* + // + // public key serialisation test + // + // TODO Is there some standard this serialization must conform to? + BinaryFormatter formatter = new BinaryFormatter(); + + MemoryStream bOut = new MemoryStream(); +// ObjectOutputStream oOut = new ObjectOutputStream(bOut); +// oOut.writeObject(keyPair.Public); + formatter.Serialize(bOut, keyPair.Public); + + MemoryStream bIn = new MemoryStream(bOut.ToArray(), false); +// ObjectInputStream oIn = new ObjectInputStream(bIn); +// pubKey = (DHPublicKeyParameters)oIn.readObject(); + pubKey = (ElGamalPublicKeyParameters) formatter.Deserialize(bIn); + spec = pubKey.Parameters; + + if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P)) + { + Fail(size + " bit public key serialisation test failed on parameters"); + } + + if (!((ElGamalPublicKeyParameters )keyPair.Public).Y.Equals(pubKey.Y)) + { + Fail(size + " bit public key serialisation test failed on y value"); + } +*/ + + // + // private key encoding test + // + // TODO Keys don't support GetEncoded +// byte[] privEnc = keyPair.Private.GetEncoded(); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private).GetDerEncoded(); + +// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +// DHPrivateKeyParameters privKey = (DHPrivateKeyParameters)keyFac.generatePrivate(privPKCS8); + ElGamalPrivateKeyParameters privKey = (ElGamalPrivateKeyParameters) + PrivateKeyFactory.CreateKey(privEnc); + + spec = privKey.Parameters; + + if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P)) + { + Fail(size + " bit private key encoding/decoding test failed on parameters"); + } + + if (!((ElGamalPrivateKeyParameters)keyPair.Private).X.Equals(privKey.X)) + { + Fail(size + " bit private key encoding/decoding test failed on y value"); + } + +/* + // + // private key serialisation test + // + bOut = new MemoryStream(); +// oOut = new ObjectOutputStream(bOut); +// oOut.writeObject(keyPair.Private); + formatter.Serialize(bOut, keyPair.Private); + + bIn = new MemoryStream(bOut.ToArray(), false); +// oIn = new ObjectInputStream(bIn); +// privKey = (DHPrivateKeyParameters)oIn.readObject(); + privKey = (ElGamalPrivateKeyParameters) formatter.Deserialize(bIn); + spec = privKey.Parameters; + + if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P)) + { + Fail(size + " bit private key serialisation test failed on parameters"); + } + + if (!((ElGamalPrivateKeyParameters) keyPair.Private).X.Equals(privKey.X)) + { + Fail(size + " bit private key serialisation test failed on y value"); + } +*/ + } + + private void checkKeySize(int privateValueSize, AsymmetricCipherKeyPair aKeyPair) + { + if (privateValueSize != 0) + { +// DHPrivateKey key = (DHPrivateKey)aKeyPair.getPrivate(); + ElGamalPrivateKeyParameters key = (ElGamalPrivateKeyParameters) aKeyPair.Private; + + if (key.X.BitLength != privateValueSize) + { + Fail("limited key check failed for key size " + privateValueSize); + } + } + } + + private void doTestRandom( + int size) + { +// AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("ElGamal"); +// a.init(size, new SecureRandom()); + ElGamalParametersGenerator a = new ElGamalParametersGenerator(); + a.Init(size, 20, new SecureRandom()); + +// AlgorithmParameters parameters = a.generateParameters(); + ElGamalParameters p = a.GenerateParameters(); + +// byte[] encodeParams = parameters.GetEncoded(); + byte[] encodeParams = new ElGamalParameter(p.P, p.G).GetDerEncoded(); + +// AlgorithmParameters a2 = AlgorithmParameters.getInstance("ElGamal"); +// a2.init(encodeParams); + ElGamalParameter elP = new ElGamalParameter((Asn1Sequence) Asn1Object.FromByteArray(encodeParams)); + ElGamalParameters p2 = new ElGamalParameters(elP.P, elP.G); + + // a and a2 should be equivalent! +// byte[] encodeParams_2 = a2.GetEncoded(); + byte[] encodeParams_2 = new ElGamalParameter(p2.P, p2.G).GetDerEncoded(); + + if (!AreEqual(encodeParams, encodeParams_2)) + { + Fail(this.Name + ": encode/decode parameters failed"); + } + +// DHParameters elP = (DHParameters)parameters.getParameterSpec(typeof(DHParameters)); + + doTestGP(size, 0, elP.G, elP.P); + } + + public override void PerformTest() + { + TestGP512(); + TestGP768(); + TestGP1024(); + TestRandom256(); + } + + public static void Main( + string[] args) + { + RunTest(new ElGamalTest()); + } + } +} diff --git a/crypto/test/src/test/EncryptedPrivateKeyInfoTest.cs b/crypto/test/src/test/EncryptedPrivateKeyInfoTest.cs new file mode 100644 index 000000000..baac5ff7f --- /dev/null +++ b/crypto/test/src/test/EncryptedPrivateKeyInfoTest.cs @@ -0,0 +1,154 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class EncryptedPrivateKeyInfoTest + : SimpleTest + { + private const string alg = "1.2.840.113549.1.12.1.3"; // 3 key triple DES with SHA-1 + + public override void PerformTest() + { + IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA"); + fact.Init(new KeyGenerationParameters(new SecureRandom(), 512)); + + AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair(); + + AsymmetricKeyParameter priKey = keyPair.Private; + AsymmetricKeyParameter pubKey = keyPair.Public; + + // + // set up the parameters + // + byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int iterationCount = 100; + Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(alg, salt, iterationCount); + char[] password1 = { 'h', 'e', 'l', 'l', 'o' }; + +// AlgorithmParameters parameters = AlgorithmParameters.getInstance(alg); +// +// parameters.init(defParams); + + // + // set up the key + // +// PBEKeySpec pbeSpec = new PBEKeySpec(password1); +// SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg); + +// IBufferedCipher cipher = CipherUtilities.GetCipher(alg); + IWrapper wrapper = WrapperUtilities.GetWrapper(alg); + + ICipherParameters parameters = PbeUtilities.GenerateCipherParameters( + alg, password1, defParams); + +// cipher.Init(IBufferedCipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), parameters); + wrapper.Init(true, parameters); + +// byte[] wrappedKey = cipher.Wrap(priKey); + byte[] pkb = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey).GetDerEncoded(); + byte[] wrappedKey = wrapper.Wrap(pkb, 0, pkb.Length); + + // + // create encrypted object + // + + // TODO Figure out what this was supposed to do +// EncryptedPrivateKeyInfo pInfo = new EncryptedPrivateKeyInfo(parameters, wrappedKey); + PrivateKeyInfo plain = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey); + EncryptedPrivateKeyInfo pInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + alg, password1, salt, iterationCount, plain); + + + // + // decryption step + // + char[] password2 = { 'h', 'e', 'l', 'l', 'o' }; + +// pbeSpec = new PBEKeySpec(password2); +// +// cipher = CipherUtilities.GetCipher(pInfo.EncryptionAlgorithm); +// +// cipher.Init(false, keyFact.generateSecret(pbeSpec), pInfo.getAlgParameters()); +// +// PKCS8EncodedKeySpec keySpec = pInfo.getKeySpec(cipher); + PrivateKeyInfo decrypted = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password2, pInfo); + +// if (!MessageDigest.isEqual(priKey.GetEncoded(), keySpec.GetEncoded())) + if (!decrypted.Equals(plain)) + { + Fail("Private key does not match"); + } + + // + // using ICipherParameters test + // +// pbeSpec = new PBEKeySpec(password1); +// keyFact = SecretKeyFactory.getInstance(alg); +// cipher = CipherUtilities.GetCipher(alg); + wrapper = WrapperUtilities.GetWrapper(alg); + +// cipher.init(IBufferedCipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), parameters); + wrapper.Init(true, parameters); + +// wrappedKey = cipher.wrap(priKey); + wrappedKey = wrapper.Wrap(pkb, 0, pkb.Length); + + // + // create encrypted object + // + + // TODO Figure out what this was supposed to do +// pInfo = new EncryptedPrivateKeyInfo(cipher.getParameters(), wrappedKey); + plain = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey); + pInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + alg, password1, salt, iterationCount, plain); + + // + // decryption step + // +// pbeSpec = new PBEKeySpec(password2); +// +// cipher = CipherUtilities.GetCipher(pInfo.getAlgName()); +// +// cipher.init(IBufferedCipher.DECRYPT_MODE, keyFact.generateSecret(pbeSpec), pInfo.getAlgParameters()); +// +// keySpec = pInfo.getKeySpec(cipher); + decrypted = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password2, pInfo); + +// if (!MessageDigest.isEqual(priKey.GetEncoded(), keySpec.GetEncoded())) + if (!decrypted.Equals(plain)) + { + Fail("Private key does not match"); + } + } + + public override string Name + { + get { return "EncryptedPrivateKeyInfoTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new EncryptedPrivateKeyInfoTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/FIPSDESTest.cs b/crypto/test/src/test/FIPSDESTest.cs new file mode 100644 index 000000000..1f40e1591 --- /dev/null +++ b/crypto/test/src/test/FIPSDESTest.cs @@ -0,0 +1,205 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// + /// Basic FIPS test class for a block cipher, just to make sure ECB/CBC/OFB/CFB are behaving + /// correctly. Tests from FIPS 81. + /// + [TestFixture] + public class FipsDesTest + : ITest + { + private static readonly string[] fips1Tests = + { + "DES/ECB/NoPadding", + "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53", + "DES/CBC/NoPadding", + "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6", + "DES/CFB/NoPadding", + "f3096249c7f46e51a69e839b1a92f78403467133898ea622" + }; + + private static readonly string[] fips2Tests = + { + "DES/CFB8/NoPadding", + "f31fda07011462ee187f", + "DES/OFB8/NoPadding", + "f34a2850c9c64985d684" + }; + + private static readonly byte[] input1 = Hex.Decode("4e6f77206973207468652074696d6520666f7220616c6c20"); + private static readonly byte[] input2 = Hex.Decode("4e6f7720697320746865"); + + public string Name + { + get { return "FIPSDES"; } + } + + public ITestResult doTest( + string algorithm, + byte[] input, + byte[] output) + { + KeyParameter key; + IBufferedCipher inCipher, outCipher; + CipherStream cIn, cOut; + MemoryStream bIn, bOut; + +// IvParameterSpec spec = new IvParameterSpec(); + byte[] spec = Hex.Decode("1234567890abcdef"); + + try + { + key = new DesParameters(Hex.Decode("0123456789abcdef")); + + inCipher = CipherUtilities.GetCipher(algorithm); + outCipher = CipherUtilities.GetCipher(algorithm); + + if (algorithm.StartsWith("DES/ECB")) + { + outCipher.Init(true, key); + } + else + { + outCipher.Init(true, new ParametersWithIV(key, spec)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed initialisation - " + e.ToString(), e); + } + + try + { + if (algorithm.StartsWith("DES/ECB")) + { + inCipher.Init(false, key); + } + else + { + inCipher.Init(false, new ParametersWithIV(key, spec)); + } + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed initialisation - " + e.ToString(), e); + } + + // + // encryption pass + // + bOut = new MemoryStream(); + cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - " + e.ToString()); + } + + byte[] bytes = bOut.ToArray(); + + if (!Arrays.AreEqual(bytes, output)) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - expected " + + Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + bIn = new MemoryStream(bytes, false); + cIn = new CipherStream(bIn, inCipher, null); + + try + { + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - " + e.ToString()); + } + + if (!Arrays.AreEqual(bytes, input)) + { + return new SimpleTestResult(false, Name + ": " + algorithm + " failed decryption - expected " + + Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes)); + } + + return new SimpleTestResult(true, Name + ": " + algorithm + " Okay"); + } + + public ITestResult Perform() + { + for (int i = 0; i != fips1Tests.Length; i += 2) + { + ITestResult result = doTest(fips1Tests[i], input1, Hex.Decode(fips1Tests[i + 1])); + if (!result.IsSuccessful()) + { + return result; + } + } + + for (int i = 0; i != fips2Tests.Length; i += 2) + { + ITestResult result = doTest(fips2Tests[i], input2, Hex.Decode(fips2Tests[i + 1])); + if (!result.IsSuccessful()) + { + return result; + } + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + public static void Main( + string[] args) + { + ITest test = new FipsDesTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/GOST28147Test.cs b/crypto/test/src/test/GOST28147Test.cs new file mode 100644 index 000000000..0adfad334 --- /dev/null +++ b/crypto/test/src/test/GOST28147Test.cs @@ -0,0 +1,245 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// Basic test class for the GOST28147 cipher + [TestFixture] + public class Gost28147Test + : SimpleTest + { + private static string[] cipherTests = + { + "256", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "4e6f77206973207468652074696d6520666f7220616c6c20", + "281630d0d5770030068c252d841e84149ccc1912052dbc02", + + "256", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "4e6f77206973207468652074696d65208a920c6ed1a804f5", + "88e543dfc04dc4f764fa7b624741cec07de49b007bf36065" + }; + + public override string Name + { + get { return "GOST28147"; } + } + + private void doTestEcb( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + IBufferedCipher inCipher, outCipher; + CipherStream cIn, cOut; + MemoryStream bIn, bOut; + + KeyParameter key = ParameterUtilities.CreateKeyParameter("GOST28147", keyBytes); + + inCipher = CipherUtilities.GetCipher("GOST28147/ECB/NoPadding"); + outCipher = CipherUtilities.GetCipher("GOST28147/ECB/NoPadding"); + outCipher.Init(true, key); + inCipher.Init(false, key); + + // + // encryption pass + // + bOut = new MemoryStream(); + cOut = new CipherStream(bOut, null, outCipher); + + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("GOST28147 failed encryption - expected " + + Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + bIn = new MemoryStream(bytes, false); + cIn = new CipherStream(bIn, inCipher, null); + + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + + if (!AreEqual(bytes, input)) + { + Fail("GOST28147 failed decryption - expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes)); + } + } + + private void doTestCfb( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + IBufferedCipher inCipher, outCipher; + CipherStream cIn, cOut; + MemoryStream bIn, bOut; + + KeyParameter key = ParameterUtilities.CreateKeyParameter("GOST28147", keyBytes); + + inCipher = CipherUtilities.GetCipher("GOST28147/CFB8/NoPadding"); + outCipher = CipherUtilities.GetCipher("GOST28147/CFB8/NoPadding"); + byte[] iv = {1,2,3,4,5,6,7,8}; + + outCipher.Init(true, new ParametersWithIV(key, iv)); + inCipher.Init(false, new ParametersWithIV(key, iv)); + + // + // encryption pass + // + bOut = new MemoryStream(); + cOut = new CipherStream(bOut, null, outCipher); + + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("GOST28147 failed encryption - expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + bIn = new MemoryStream(bytes, false); + cIn = new CipherStream(bIn, inCipher, null); + + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + + if (!AreEqual(bytes, input)) + { + Fail("GOST28147 failed decryption - expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes)); + } + } + + private void doOidTest() + { + string[] oids = { + CryptoProObjectIdentifiers.GostR28147Cbc.Id, + }; + + string[] names = { + "GOST28147/CBC/PKCS7Padding" + }; + + try + { + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; +// IvParameterSpec ivSpec = new IvParameterSpec(new byte[8]); + byte[] iv = new byte[8]; + + for (int i = 0; i != oids.Length; i++) + { + IBufferedCipher c1 = CipherUtilities.GetCipher(oids[i]); + IBufferedCipher c2 = CipherUtilities.GetCipher(names[i]); + +// KeyGenerator kg = KeyGenerator.getInstance(oids[i]); +// SecretKey k = kg.generateKey(); + CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]); + KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey()); + + c1.Init(true, new ParametersWithIV(k, iv)); + c2.Init(false, new ParametersWithIV(k, iv)); + + byte[] result = c2.DoFinal(c1.DoFinal(data)); + + if (!AreEqual(data, result)) + { + Fail("failed OID test"); + } + } + } + catch (Exception ex) + { + Fail("failed exception " + ex.ToString(), ex); + } + } + + public override void PerformTest() + { + for (int i = 0; i != cipherTests.Length; i += 8) + { + doTestEcb(int.Parse(cipherTests[i]), + Hex.Decode(cipherTests[i + 1]), + Hex.Decode(cipherTests[i + 2]), + Hex.Decode(cipherTests[i + 3])); + + doTestCfb(int.Parse(cipherTests[i + 4]), + Hex.Decode(cipherTests[i + 4 + 1]), + Hex.Decode(cipherTests[i + 4 + 2]), + Hex.Decode(cipherTests[i + 4 + 3])); + + doOidTest(); + } + } + + public static void Main( + string[] args) + { + RunTest(new Gost28147Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} \ No newline at end of file diff --git a/crypto/test/src/test/GOST3410Test.cs b/crypto/test/src/test/GOST3410Test.cs new file mode 100644 index 000000000..e8c2c1c76 --- /dev/null +++ b/crypto/test/src/test/GOST3410Test.cs @@ -0,0 +1,383 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class Gost3410Test + : SimpleTest + { + private void ecGOST3410Test() + { + BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395"); + BigInteger s = new BigInteger("46959264877825372965922731380059061821746083849389763294914877353246631700866"); + + byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").ToByteArrayUnsigned(); + + SecureRandom k = FixedSecureRandom.From(kData); + + BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p + + ECCurve curve = new FpCurve( + mod_p, // p + new BigInteger("7"), // a + new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, + curve.CreatePoint( + new BigInteger("2"), + new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280"), + false), + new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q + + ECPrivateKeyParameters sKey = new ECPrivateKeyParameters( + "ECGOST3410", + new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d + spec); + + ECPublicKeyParameters vKey = new ECPublicKeyParameters( + "ECGOST3410", + curve.CreatePoint( + new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403"), + new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994"), + false), + spec); + + ISigner sgr = SignerUtilities.GetSigner("ECGOST3410"); + + sgr.Init(true, new ParametersWithRandom(sKey, k)); + + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail("ECGOST3410 verification failed"); + } + + BigInteger[] sig = decode(sigBytes); + + if (!r.Equals(sig[0])) + { + Fail( + ": r component wrong." + SimpleTest.NewLine + + " expecting: " + r + SimpleTest.NewLine + + " got : " + sig[0]); + } + + if (!s.Equals(sig[1])) + { + Fail( + ": s component wrong." + SimpleTest.NewLine + + " expecting: " + s + SimpleTest.NewLine + + " got : " + sig[1]); + } + } + + private void generationTest() + { + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + ISigner s = SignerUtilities.GetSigner("GOST3410"); + + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + g.Init( + new Gost3410KeyGenerationParameters( + new SecureRandom(), + CryptoProObjectIdentifiers.GostR3410x94CryptoProA)); + + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + AsymmetricKeyParameter sKey = p.Private; + AsymmetricKeyParameter vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("GOST3410"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("GOST3410 verification failed"); + } + + // + // default initialisation test + // + s = SignerUtilities.GetSigner("GOST3410"); + g = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + + // TODO This is supposed to be a 'default initialisation' test, but don't have a factory + // These values are defaults from JCE provider + g.Init( + new Gost3410KeyGenerationParameters( + new SecureRandom(), + CryptoProObjectIdentifiers.GostR3410x94CryptoProA)); + + p = g.GenerateKeyPair(); + + sKey = p.Private; + vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("GOST3410"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("GOST3410 verification failed"); + } + + // + // encoded test + // + //KeyFactory f = KeyFactory.getInstance("GOST3410"); + //X509EncodedKeySpec x509s = new X509EncodedKeySpec(vKey.GetEncoded()); + //Gost3410PublicKeyParameters k1 = (Gost3410PublicKeyParameters)f.generatePublic(x509s); + byte[] vKeyEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded(); + Gost3410PublicKeyParameters k1 = (Gost3410PublicKeyParameters) + PublicKeyFactory.CreateKey(vKeyEnc); + + if (!k1.Y.Equals(((Gost3410PublicKeyParameters)vKey).Y)) + { + Fail("public number not decoded properly"); + } + + //PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(sKey.GetEncoded()); + //Gost3410PrivateKeyParameters k2 = (Gost3410PrivateKeyParameters)f.generatePrivate(pkcs8); + byte[] sKeyEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded(); + Gost3410PrivateKeyParameters k2 = (Gost3410PrivateKeyParameters) + PrivateKeyFactory.CreateKey(sKeyEnc); + + if (!k2.X.Equals(((Gost3410PrivateKeyParameters)sKey).X)) + { + Fail("private number not decoded properly"); + } + + // + // ECGOST3410 generation test + // + s = SignerUtilities.GetSigner("ECGOST3410"); + g = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410"); + + BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p + + ECCurve curve = new FpCurve( + mod_p, // p + new BigInteger("7"), // a + new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, + curve.CreatePoint( + new BigInteger("2"), + new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280"), + false), + new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q + + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + p = g.GenerateKeyPair(); + + sKey = p.Private; + vKey = p.Public; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("ECGOST3410"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("ECGOST3410 verification failed"); + } + } + + private void keyStoreTest( + AsymmetricKeyParameter sKey, + AsymmetricKeyParameter vKey) +// throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, NoSuchProviderException, SignatureException, InvalidKeyException, UnrecoverableKeyException + { + // + // keystore test + // +// KeyStore ks = KeyStore.GetInstance("JKS"); +// ks.Load(null, null); + Pkcs12StoreBuilder ksBuilder = new Pkcs12StoreBuilder(); + Pkcs12Store ks = ksBuilder.Build(); + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name("CN=Test")); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name("CN=Test")); + certGen.SetPublicKey(vKey); + certGen.SetSignatureAlgorithm("GOST3411withGOST3410"); + + X509Certificate cert = certGen.Generate(sKey); + X509CertificateEntry certEntry = new X509CertificateEntry(cert); + +// ks.SetKeyEntry("gost", sKey, "gost".ToCharArray(), new X509Certificate[] { cert }); + ks.SetKeyEntry("gost", new AsymmetricKeyEntry(sKey), new X509CertificateEntry[] { certEntry }); + + MemoryStream bOut = new MemoryStream(); + + ks.Save(bOut, "gost".ToCharArray(), new SecureRandom()); + +// ks = KeyStore.getInstance("JKS"); + ks = ksBuilder.Build(); + + ks.Load(new MemoryStream(bOut.ToArray(), false), "gost".ToCharArray()); + +// AsymmetricKeyParameter gKey = (AsymmetricKeyParameter)ks.GetKey("gost", "gost".ToCharArray()); +// AsymmetricKeyEntry gKeyEntry = (AsymmetricKeyEntry) + ks.GetKey("gost"); + } + + private void parametersTest() + { +// AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("GOST3410"); +// a.init(512, random); +// AlgorithmParameters params = a.generateParameters(); +// +// byte[] encodeParams = params.getEncoded(); +// +// AlgorithmParameters a2 = AlgorithmParameters.getInstance("GOST3410"); +// a2.init(encodeParams); +// +// // a and a2 should be equivalent! +// byte[] encodeParams_2 = a2.getEncoded(); +// +// if (!arrayEquals(encodeParams, encodeParams_2)) +// { +// Fail("encode/decode parameters failed"); +// } + +// GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec( +// CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B.getId()); +// g.initialize(gost3410P, new SecureRandom()); + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410"); + g.Init( + new Gost3410KeyGenerationParameters( + new SecureRandom(), + CryptoProObjectIdentifiers.GostR3410x94CryptoProB)); + + AsymmetricCipherKeyPair p = g.GenerateKeyPair(); + + AsymmetricKeyParameter sKey = p.Private; + AsymmetricKeyParameter vKey = p.Public; + + ISigner s = SignerUtilities.GetSigner("GOST3410"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + s.Init(true, sKey); + + s.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = s.GenerateSignature(); + + s = SignerUtilities.GetSigner("GOST3410"); + + s.Init(false, vKey); + + s.BlockUpdate(data, 0, data.Length); + + if (!s.VerifySignature(sigBytes)) + { + Fail("GOST3410 verification failed"); + } + + keyStoreTest(sKey, vKey); + } + + private BigInteger[] decode( + byte[] encoding) + { + byte[] r = new byte[32]; + byte[] s = new byte[32]; + + Array.Copy(encoding, 0, s, 0, 32); + Array.Copy(encoding, 32, r, 0, 32); + + BigInteger[] sig = new BigInteger[2]; + + sig[0] = new BigInteger(1, r); + sig[1] = new BigInteger(1, s); + + return sig; + } + + public override string Name + { + get { return "GOST3410/ECGOST3410"; } + } + + public override void PerformTest() + { + ecGOST3410Test(); + generationTest(); + parametersTest(); + } + + public static void Main( + string[] args) + { + RunTest(new Gost3410Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/HMacTest.cs b/crypto/test/src/test/HMacTest.cs new file mode 100644 index 000000000..e4f5cb9c1 --- /dev/null +++ b/crypto/test/src/test/HMacTest.cs @@ -0,0 +1,189 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// HMAC tester + [TestFixture] + public class HMacTest + : SimpleTest + { + private static byte[] keyBytes = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + private static byte[] message = Encoding.ASCII.GetBytes("Hi There"); + private static byte[] output1 = Hex.Decode("b617318655057264e28bc0b6fb378c8ef146be00"); + private static byte[] outputMD5 = Hex.Decode("5ccec34ea9656392457fa1ac27f08fbc"); + private static byte[] outputMD2 = Hex.Decode("dc1923ef5f161d35bef839ca8c807808"); + private static byte[] outputMD4 = Hex.Decode("5570ce964ba8c11756cdc3970278ff5a"); + private static byte[] output224 = Hex.Decode("896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"); + private static byte[] output256 = Hex.Decode("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); + private static byte[] output384 = Hex.Decode("afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6"); + private static byte[] output512 = Hex.Decode("87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"); + private static byte[] output512_224 = Hex.Decode("b244ba01307c0e7a8ccaad13b1067a4cf6b961fe0c6a20bda3d92039"); + private static byte[] output512_256 = Hex.Decode("9f9126c3d9c3c330d760425ca8a217e31feae31bfe70196ff81642b868402eab"); + private static byte[] outputRipeMD128 = Hex.Decode("fda5717fb7e20cf05d30bb286a44b05d"); + private static byte[] outputRipeMD160 = Hex.Decode("24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668"); + private static byte[] outputTiger = Hex.Decode("1d7a658c75f8f004916e7b07e2a2e10aec7de2ae124d3647"); + private static byte[] outputOld384 = Hex.Decode("0a046aaa0255e432912228f8ccda437c8a8363fb160afb0570ab5b1fd5ddc20eb1888b9ed4e5b6cb5bc034cd9ef70e40"); + private static byte[] outputOld512 = Hex.Decode("9656975ee5de55e75f2976ecce9a04501060b9dc22a6eda2eaef638966280182477fe09f080b2bf564649cad42af8607a2bd8d02979df3a980f15e2326a0a22a"); + + public void doTestHMac( + string hmacName, + byte[] output) + { + KeyParameter key = new KeyParameter(keyBytes); //, hmacName); + + IMac mac = MacUtilities.GetMac(hmacName); + + mac.Init(key); + + mac.Reset(); + + mac.BlockUpdate(message, 0, message.Length); + +// byte[] outBytes = mac.DoFinal(); + byte[] outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output)) + { + Fail("Failed - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(outBytes)); + } + + // no key generator for the old algorithms + if (hmacName.StartsWith("Old")) + { + return; + } + + CipherKeyGenerator kGen = GeneratorUtilities.GetKeyGenerator(hmacName); + + mac.Init(new KeyParameter(kGen.GenerateKey())); // hmacName + + mac.BlockUpdate(message, 0, message.Length); + +// outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + } + + private void doTestExceptions() + { + IMac mac = MacUtilities.GetMac("HmacSHA1"); + + byte [] b = {(byte)1, (byte)2, (byte)3, (byte)4, (byte)5}; +// KeyParameter sks = new KeyParameter(b); //, "HmacSHA1"); +// RC5ParameterSpec algPS = new RC5ParameterSpec(100, 100, 100); + RC5Parameters rc5Parameters = new RC5Parameters(b, 100); + + try + { +// mac.Init(sks, algPS); + mac.Init(rc5Parameters); + } +// catch (InvalidAlgorithmParameterException e) + catch (Exception) + { + // ignore okay + } + + try + { + mac.Init(null); //, null); + } +// catch (InvalidKeyException) +// { +// // ignore okay +// } +// catch (InvalidAlgorithmParameterException e) + catch (Exception) + { + // ignore okay + } + +// try +// { +// mac.Init(null); +// } +// catch (InvalidKeyException) +// { +// // ignore okay +// } + } + + public override void PerformTest() + { + doTestHMac("HMac-SHA1", output1); + doTestHMac("HMac-MD5", outputMD5); + doTestHMac("HMac-MD4", outputMD4); + doTestHMac("HMac-MD2", outputMD2); + doTestHMac("HMac-SHA224", output224); + doTestHMac("HMac-SHA256", output256); + doTestHMac("HMac-SHA384", output384); + doTestHMac("HMac-SHA512", output512); + doTestHMac("HMac-SHA512/224", output512_224); + doTestHMac("HMac-SHA512/256", output512_256); + doTestHMac("HMac-RIPEMD128", outputRipeMD128); + doTestHMac("HMac-RIPEMD160", outputRipeMD160); + doTestHMac("HMac-TIGER", outputTiger); + + doTestHMac("HMac/SHA1", output1); + doTestHMac("HMac/MD5", outputMD5); + doTestHMac("HMac/MD4", outputMD4); + doTestHMac("HMac/MD2", outputMD2); + doTestHMac("HMac/SHA224", output224); + doTestHMac("HMac/SHA256", output256); + doTestHMac("HMac/SHA384", output384); + doTestHMac("HMac/SHA512", output512); + doTestHMac("HMac/RIPEMD128", outputRipeMD128); + doTestHMac("HMac/RIPEMD160", outputRipeMD160); + doTestHMac("HMac/TIGER", outputTiger); + + doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha1.Id, output1); + doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha224.Id, output224); + doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha256.Id, output256); + doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha384.Id, output384); + doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha512.Id, output512); + doTestHMac(IanaObjectIdentifiers.HmacSha1.Id, output1); + doTestHMac(IanaObjectIdentifiers.HmacMD5.Id, outputMD5); + doTestHMac(IanaObjectIdentifiers.HmacRipeMD160.Id, outputRipeMD160); + doTestHMac(IanaObjectIdentifiers.HmacTiger.Id, outputTiger); + +// // test for compatibility with broken HMac. +// doTestHMac("OldHMacSHA384", outputOld384); +// doTestHMac("OldHMacSHA512", outputOld512); + + doTestExceptions(); + } + + public override string Name + { + get { return "HMac"; } + } + + public static void Main( + string[] args) + { + RunTest(new HMacTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/IESTest.cs b/crypto/test/src/test/IESTest.cs new file mode 100644 index 000000000..193fe1ae9 --- /dev/null +++ b/crypto/test/src/test/IESTest.cs @@ -0,0 +1,245 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /** + * test for ECIES - Elliptic Curve Integrated Encryption Scheme + */ + [TestFixture] + public class IesTest + : SimpleTest + { + private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); + private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); + + public override string Name + { + get { return "IES"; } + } + + public override void PerformTest() + { + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECIES"); + + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + g.Init( + new ECKeyGenerationParameters( + ecSpec, + new SecureRandom())); + + IBufferedCipher c1 = CipherUtilities.GetCipher("ECIES"); + IBufferedCipher c2 = CipherUtilities.GetCipher("ECIES"); + + doTest(g, c1, c2); + + g = GeneratorUtilities.GetKeyPairGenerator("ECIES"); + + g.Init(new KeyGenerationParameters(new SecureRandom(), 192)); + + doTest(g, c1, c2); + + g = GeneratorUtilities.GetKeyPairGenerator("ECIES"); + + g.Init(new KeyGenerationParameters(new SecureRandom(), 239)); + + doTest(g, c1, c2); + + g = GeneratorUtilities.GetKeyPairGenerator("ECIES"); + + g.Init(new KeyGenerationParameters(new SecureRandom(), 256)); + + doTest(g, c1, c2); + + doDefTest(g, c1, c2); + + c1 = CipherUtilities.GetCipher("IES"); + c2 = CipherUtilities.GetCipher("IES"); + + g = GeneratorUtilities.GetKeyPairGenerator("DH"); + +// DHParameterSpec dhParams = new DHParameterSpec(p512, g512); +// g.initialize(dhParams); + g.Init( + new DHKeyGenerationParameters( + new SecureRandom(), + new DHParameters(p512, g512))); + + doTest(g, c1, c2); + + doDefTest(g, c1, c2); + } + + public void doTest( + IAsymmetricCipherKeyPairGenerator g, + IBufferedCipher c1, + IBufferedCipher c2) + { + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair(); + AsymmetricKeyParameter aPub = aKeyPair.Public; + AsymmetricKeyParameter aPriv = aKeyPair.Private; + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair(); + AsymmetricKeyParameter bPub = bKeyPair.Public; + AsymmetricKeyParameter bPriv = bKeyPair.Private; + + // TODO Put back in +// // +// // stream test +// // +// IEKeySpec c1Key = new IEKeySpec(aPriv, bPub); +// IEKeySpec c2Key = new IEKeySpec(bPriv, aPub); +// +// byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; +// byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 }; +// +// IESParameterSpec param = new IESParameterSpec(d, e, 128); +// +// c1.Init(true, c1Key, param); +// +// c2.Init(false, c2Key, param); +// +// byte[] message = Hex.Decode("1234567890abcdef"); +// +// byte[] out1 = c1.DoFinal(message, 0, message.Length); +// +// byte[] out2 = c2.DoFinal(out1, 0, out1.Length); +// +// if (!AreEqual(out2, message)) +// { +// Fail("stream cipher test failed"); +// } + } + + public void doDefTest( + IAsymmetricCipherKeyPairGenerator g, + IBufferedCipher c1, + IBufferedCipher c2) + { + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair(); + AsymmetricKeyParameter aPub = aKeyPair.Public; + AsymmetricKeyParameter aPriv = aKeyPair.Private; + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair(); + AsymmetricKeyParameter bPub = bKeyPair.Public; + AsymmetricKeyParameter bPriv = bKeyPair.Private; + + // TODO Put back in +// // +// // stream test +// // +// IEKeySpec c1Key = new IEKeySpec(aPriv, bPub); +// IEKeySpec c2Key = new IEKeySpec(bPriv, aPub); +// +// c1.Init(true, c1Key); +// +// AlgorithmParameters param = c1.getParameters(); +// +// c2.Init(false, c2Key, param); +// +// byte[] message = Hex.Decode("1234567890abcdef"); +// +// byte[] out1 = c1.DoFinal(message, 0, message.Length); +// +// byte[] out2 = c2.DoFinal(out1, 0, out1.Length); +// +// if (!AreEqual(out2, message)) +// { +// Fail("stream cipher test failed"); +// } +// +// // +// // int DoFinal +// // +// int len1 = c1.DoFinal(message, 0, message.Length, out1, 0); +// +// if (len1 != out1.Length) +// { +// Fail("encryption length wrong"); +// } +// +// int len2 = c2.DoFinal(out1, 0, out1.Length, out2, 0); +// +// if (len2 != out2.Length) +// { +// Fail("decryption length wrong"); +// } +// +// if (!AreEqual(out2, message)) +// { +// Fail("stream cipher test failed"); +// } +// +// // +// // int DoFinal with update +// // +// len1 = c1.ProcessBytes(message, 0, 2, out1, 0); +// +// len1 += c1.DoFinal(message, 2, message.Length - 2, out1, len1); +// +// if (len1 != out1.Length) +// { +// Fail("update encryption length wrong"); +// } +// +// len2 = c2.ProcessBytes(out1, 0, 2, out2, 0); +// +// len2 += c2.DoFinal(out1, 2, out1.Length - 2, out2, len2); +// +// if (len2 != out2.Length) +// { +// Fail("update decryption length wrong"); +// } +// +// if (!AreEqual(out2, message)) +// { +// Fail("update stream cipher test failed"); +// } + } + + public static void Main( + string[] args) + { + RunTest(new IesTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/MacTest.cs b/crypto/test/src/test/MacTest.cs new file mode 100644 index 000000000..d4b3188bd --- /dev/null +++ b/crypto/test/src/test/MacTest.cs @@ -0,0 +1,216 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// + /// MAC tester - vectors from + /// FIP 81 and + /// FIP 113. + /// + [TestFixture] + public class MacTest + : SimpleTest + { + private static readonly byte[] keyBytes = Hex.Decode("0123456789abcdef"); + private static readonly byte[] ivBytes = Hex.Decode("1234567890abcdef"); + + private static readonly byte[] input = Hex.Decode("37363534333231204e6f77206973207468652074696d6520666f7220"); + + private static readonly byte[] output1 = Hex.Decode("f1d30f68"); + private static readonly byte[] output2 = Hex.Decode("58d2e77e"); + private static readonly byte[] output3 = Hex.Decode("cd647403"); + + private static readonly byte[] keyBytesISO9797 = Hex.Decode("7CA110454A1A6E570131D9619DC1376E"); + + private static readonly byte[] inputISO9797 = Encoding.ASCII.GetBytes("Hello World !!!!"); + + private static readonly byte[] outputISO9797 = Hex.Decode("F09B856213BAB83B"); + + private static readonly byte[] inputDesEDE64 = Encoding.ASCII.GetBytes("Hello World !!!!"); + + private static readonly byte[] outputDesEDE64 = Hex.Decode("862304d33af01096"); + + private void aliasTest( + KeyParameter key, + string primary, + params string[] aliases) + { + IMac mac = MacUtilities.GetMac(primary); + + // + // standard DAC - zero IV + // + mac.Init(key); + + mac.BlockUpdate(input, 0, input.Length); + + byte[] refBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(refBytes, 0); + + for (int i = 0; i != aliases.Length; i++) + { + mac = MacUtilities.GetMac(aliases[i]); + + mac.Init(key); + + mac.BlockUpdate(input, 0, input.Length); + + byte[] outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, refBytes)) + { + Fail("Failed - expected " + + Hex.ToHexString(refBytes) + " got " + + Hex.ToHexString(outBytes)); + } + } + } + + public override void PerformTest() + { + KeyParameter key = new DesParameters(keyBytes); + IMac mac = MacUtilities.GetMac("DESMac"); + + // + // standard DAC - zero IV + // + mac.Init(key); + + mac.BlockUpdate(input, 0, input.Length); + + //byte[] outBytes = mac.DoFinal(); + byte[] outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output1)) + { + Fail("Failed - expected " + + Hex.ToHexString(output1) + " got " + + Hex.ToHexString(outBytes)); + } + + // + // mac with IV. + // + mac.Init(new ParametersWithIV(key, ivBytes)); + + mac.BlockUpdate(input, 0, input.Length); + + //outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output2)) + { + Fail("Failed - expected " + + Hex.ToHexString(output2) + " got " + + Hex.ToHexString(outBytes)); + } + + // + // CFB mac with IV - 8 bit CFB mode + // + mac = MacUtilities.GetMac("DESMac/CFB8"); + + mac.Init(new ParametersWithIV(key, ivBytes)); + + mac.BlockUpdate(input, 0, input.Length); + + //outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output3)) + { + Fail("Failed - expected " + + Hex.ToHexString(output3) + " got " + + Hex.ToHexString(outBytes)); + } + + // + // ISO9797 algorithm 3 using DESEDE + // + key = new DesEdeParameters(keyBytesISO9797); + + mac = MacUtilities.GetMac("ISO9797ALG3"); + + mac.Init(key); + + mac.BlockUpdate(inputISO9797, 0, inputISO9797.Length); + + //outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, outputISO9797)) + { + Fail("Failed - expected " + + Hex.ToHexString(outputISO9797) + " got " + + Hex.ToHexString(outBytes)); + } + + // + // 64bit DESede Mac + // + key = new DesEdeParameters(keyBytesISO9797); + + mac = MacUtilities.GetMac("DESEDE64"); + + mac.Init(key); + + mac.BlockUpdate(inputDesEDE64, 0, inputDesEDE64.Length); + + //outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, outputDesEDE64)) + { + Fail("Failed - expected " + + Hex.ToHexString(outputDesEDE64) + " got " + + Hex.ToHexString(outBytes)); + } + + aliasTest( + ParameterUtilities.CreateKeyParameter("DESede", keyBytesISO9797), + "DESedeMac64withISO7816-4Padding", + "DESEDE64WITHISO7816-4PADDING", + "DESEDEISO9797ALG1MACWITHISO7816-4PADDING", + "DESEDEISO9797ALG1WITHISO7816-4PADDING"); + + aliasTest( + ParameterUtilities.CreateKeyParameter("DESede", keyBytesISO9797), + "ISO9797ALG3WITHISO7816-4PADDING", + "ISO9797ALG3MACWITHISO7816-4PADDING"); + } + + public override string Name + { + get { return "Mac"; } + } + + public static void Main( + string[] args) + { + RunTest(new MacTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/MqvTest.cs b/crypto/test/src/test/MqvTest.cs new file mode 100644 index 000000000..ef36e1a23 --- /dev/null +++ b/crypto/test/src/test/MqvTest.cs @@ -0,0 +1,99 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class MqvTest + : SimpleTest + { + public override string Name + { + get { return "MQV"; } + } + + public override void PerformTest() + { + TestECMqv(); + } + + [Test] + public void TestECMqv() + { + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECMQV"); + +// EllipticCurve curve = new EllipticCurve( +// new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q +// new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a +// new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, +// ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n + BigInteger.One); //1); // h + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + // + // U side + // + AsymmetricCipherKeyPair U1 = g.GenerateKeyPair(); + AsymmetricCipherKeyPair U2 = g.GenerateKeyPair(); + + IBasicAgreement uAgree = AgreementUtilities.GetBasicAgreement("ECMQV"); + uAgree.Init(new MqvPrivateParameters( + (ECPrivateKeyParameters)U1.Private, + (ECPrivateKeyParameters)U2.Private, + (ECPublicKeyParameters)U2.Public)); + + // + // V side + // + AsymmetricCipherKeyPair V1 = g.GenerateKeyPair(); + AsymmetricCipherKeyPair V2 = g.GenerateKeyPair(); + + IBasicAgreement vAgree = AgreementUtilities.GetBasicAgreement("ECMQV"); + vAgree.Init(new MqvPrivateParameters( + (ECPrivateKeyParameters)V1.Private, + (ECPrivateKeyParameters)V2.Private, + (ECPublicKeyParameters)V2.Public)); + + // + // agreement + // + BigInteger ux = uAgree.CalculateAgreement(new MqvPublicParameters( + (ECPublicKeyParameters)V1.Public, + (ECPublicKeyParameters)V2.Public)); + BigInteger vx = vAgree.CalculateAgreement(new MqvPublicParameters( + (ECPublicKeyParameters)U1.Public, + (ECPublicKeyParameters)U2.Public)); + + if (!ux.Equals(vx)) + { + Fail("Agreement failed"); + } + } + + public static void Main( + string[] args) + { + RunTest(new MqvTest()); + } + } +} diff --git a/crypto/test/src/test/NamedCurveTest.cs b/crypto/test/src/test/NamedCurveTest.cs new file mode 100644 index 000000000..e90c049cf --- /dev/null +++ b/crypto/test/src/test/NamedCurveTest.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class NamedCurveTest + : SimpleTest + { +// private static readonly Hashtable CurveNames = new Hashtable(); +// private static readonly Hashtable CurveAliases = new Hashtable(); +// +// static NamedCurveTest() +// { +// CurveNames.Add("prime192v1", "prime192v1"); // X9.62 +// CurveNames.Add("sect571r1", "sect571r1"); // sec +// CurveNames.Add("secp224r1", "secp224r1"); +// CurveNames.Add("B-409", SecNamedCurves.GetName(NistNamedCurves.GetOid("B-409"))); // nist +// CurveNames.Add("P-521", SecNamedCurves.GetName(NistNamedCurves.GetOid("P-521"))); +// CurveNames.Add("brainpoolp160r1", "brainpoolp160r1"); // TeleTrusT +// +// CurveAliases.Add("secp192r1", "prime192v1"); +// CurveAliases.Add("secp256r1", "prime256v1"); +// } + + private static ECDomainParameters GetCurveParameters( + string name) + { + ECDomainParameters ecdp = ECGost3410NamedCurves.GetByName(name); + + if (ecdp != null) + return ecdp; + + X9ECParameters ecP = X962NamedCurves.GetByName(name); + + if (ecP == null) + { + ecP = SecNamedCurves.GetByName(name); + if (ecP == null) + { + ecP = NistNamedCurves.GetByName(name); + if (ecP == null) + { + ecP = TeleTrusTNamedCurves.GetByName(name); + + if (ecP == null) + throw new Exception("unknown curve name: " + name); + } + } + } + + return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed()); + } + + public void doTestCurve( + string name) + { +// ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); + ECDomainParameters ecSpec = GetCurveParameters(name); + + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH"); + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + // + // a side + // + AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair(); + +// KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDHC"); + IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDHC"); + + aKeyAgree.Init(aKeyPair.Private); + + // + // b side + // + AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair(); + +// KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDHC"); + IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement("ECDHC"); + + bKeyAgree.Init(bKeyPair.Private); + + // + // agreement + // +// aKeyAgree.doPhase(bKeyPair.Public, true); +// bKeyAgree.doPhase(aKeyPair.Public, true); +// +// BigInteger k1 = new BigInteger(aKeyAgree.generateSecret()); +// BigInteger k2 = new BigInteger(bKeyAgree.generateSecret()); + BigInteger k1 = aKeyAgree.CalculateAgreement(bKeyPair.Public); + BigInteger k2 = bKeyAgree.CalculateAgreement(aKeyPair.Public); + + if (!k1.Equals(k2)) + { + Fail("2-way test failed"); + } + + // + // public key encoding test + // +// byte[] pubEnc = aKeyPair.Public.getEncoded(); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded(); + +// KeyFactory keyFac = KeyFactory.getInstance("ECDH"); +// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +// ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc); + +// if (!pubKey.getW().Equals(((ECPublicKey)aKeyPair.Public).getW())) + if (!pubKey.Q.Equals(((ECPublicKeyParameters)aKeyPair.Public).Q)) + { + Fail("public key encoding (Q test) failed"); + } + + // TODO Put back in? +// if (!(pubKey.getParams() is ECNamedCurveSpec)) +// { +// Fail("public key encoding not named curve"); +// } + + // + // private key encoding test + // +// byte[] privEnc = aKeyPair.Private.getEncoded(); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded(); + +// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +// ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); + ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc); + +// if (!privKey.getS().Equals(((ECPrivateKey)aKeyPair.Private).getS())) + if (!privKey.D.Equals(((ECPrivateKeyParameters)aKeyPair.Private).D)) + { + Fail("private key encoding (S test) failed"); + } + + // TODO Put back in? +// if (!(privKey.getParams() is ECNamedCurveSpec)) +// { +// Fail("private key encoding not named curve"); +// } +// +// ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); +// if (!(privSpec.GetName().Equals(name) || privSpec.GetName().Equals(CurveNames.get(name)))) +// { +// Fail("private key encoding wrong named curve. Expected: " +// + CurveNames[name] + " got " + privSpec.GetName()); +// } + } + + public void doTestECDsa( + string name) + { +// ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); + ECDomainParameters ecSpec = GetCurveParameters(name); + + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + ISigner sgr = SignerUtilities.GetSigner("ECDSA"); + AsymmetricCipherKeyPair pair = g.GenerateKeyPair(); + AsymmetricKeyParameter sKey = pair.Private; + AsymmetricKeyParameter vKey = pair.Public; + + sgr.Init(true, sKey); + + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail(name + " verification failed"); + } + + // + // public key encoding test + // +// byte[] pubEnc = vKey.getEncoded(); + byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded(); + +// KeyFactory keyFac = KeyFactory.getInstance("ECDH"); +// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +// ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc); + +// if (!pubKey.getW().Equals(((ECPublicKey)vKey).getW())) + if (!pubKey.Q.Equals(((ECPublicKeyParameters)vKey).Q)) + { + Fail("public key encoding (Q test) failed"); + } + + // TODO Put back in? +// if (!(pubKey.Parameters is ECNamedCurveSpec)) +// { +// Fail("public key encoding not named curve"); +// } + + // + // private key encoding test + // +// byte[] privEnc = sKey.getEncoded(); + byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded(); + +// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +// ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); + ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc); + +// if (!privKey.getS().Equals(((ECPrivateKey)sKey).getS())) + if (!privKey.D.Equals(((ECPrivateKeyParameters)sKey).D)) + { + Fail("private key encoding (D test) failed"); + } + + // TODO Put back in? +// if (!(privKey.Parameters is ECNamedCurveSpec)) +// { +// Fail("private key encoding not named curve"); +// } +// +// ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); +// if (!privSpec.GetName().EqualsIgnoreCase(name) +// && !privSpec.GetName().EqualsIgnoreCase((string) CurveAliases[name])) +// { +// Fail("private key encoding wrong named curve. Expected: " + name + " got " + privSpec.GetName()); +// } + } + + public void doTestECGost( + string name) + { +// ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); + ECDomainParameters ecSpec = GetCurveParameters(name); + + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410"); + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + ISigner sgr = SignerUtilities.GetSigner("ECGOST3410"); + AsymmetricCipherKeyPair pair = g.GenerateKeyPair(); + AsymmetricKeyParameter sKey = pair.Private; + AsymmetricKeyParameter vKey = pair.Public; + + sgr.Init(true, sKey); + + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.BlockUpdate(message, 0, message.Length); + + byte[] sigBytes = sgr.GenerateSignature(); + + sgr.Init(false, vKey); + + sgr.BlockUpdate(message, 0, message.Length); + + if (!sgr.VerifySignature(sigBytes)) + { + Fail(name + " verification failed"); + } + + // TODO Get this working? +// // +// // public key encoding test +// // +//// byte[] pubEnc = vKey.getEncoded(); +// byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded(); +// +//// KeyFactory keyFac = KeyFactory.getInstance("ECGOST3410"); +//// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); +//// ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); +// ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc); +// +//// if (!pubKey.getW().equals(((ECPublicKey)vKey).getW())) +// if (!pubKey.Q.Equals(((ECPublicKeyParameters)vKey).Q)) +// { +// Fail("public key encoding (Q test) failed"); +// } + + // TODO Put back in? +// if (!(pubKey.Parameters is ECNamedCurveSpec)) +// { +// Fail("public key encoding not named curve"); +// } + + // TODO Get this working? +// // +// // private key encoding test +// // +//// byte[] privEnc = sKey.getEncoded(); +// byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded(); +// +//// PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); +//// ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); +// ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc); +// +//// if (!privKey.getS().Equals(((ECPrivateKey)sKey).getS())) +// if (!privKey.D.Equals(((ECPrivateKeyParameters)sKey).D)) +// { +// Fail("GOST private key encoding (D test) failed"); +// } + + // TODO Put back in? +// if (!(privKey.Parameters is ECNamedCurveSpec)) +// { +// Fail("GOST private key encoding not named curve"); +// } +// +// ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); +// if (!privSpec.getName().equalsIgnoreCase(name) +// && !privSpec.getName().equalsIgnoreCase((String)CURVE_ALIASES[name])) +// { +// Fail("GOST private key encoding wrong named curve. Expected: " + name + " got " + privSpec.getName()); +// } + } + + public override string Name + { + get { return "NamedCurve"; } + } + + public override void PerformTest() + { + doTestCurve("prime192v1"); // X9.62 + doTestCurve("sect571r1"); // sec + doTestCurve("secp224r1"); + doTestCurve("B-409"); // nist + doTestCurve("P-521"); + doTestCurve("brainpoolp160r1"); // TeleTrusT + + foreach (string name in X962NamedCurves.Names) + { + doTestECDsa(name); + } + + foreach (string name in SecNamedCurves.Names) + { + doTestECDsa(name); + } + + foreach (string name in TeleTrusTNamedCurves.Names) + { + doTestECDsa(name); + } + + foreach (string name in ECGost3410NamedCurves.Names) + { + doTestECGost(name); + } + } + + public static void Main( + string[] args) + { + RunTest(new NamedCurveTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/NistCertPathTest.cs b/crypto/test/src/test/NistCertPathTest.cs new file mode 100644 index 000000000..0f42e24d0 --- /dev/null +++ b/crypto/test/src/test/NistCertPathTest.cs @@ -0,0 +1,5192 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class NistCertPathTest + : SimpleTest + { + /* + * These tests are taken from the NIST X.509 Validation Test Suite + * available at: http://csrc.nist.gov/pki/testing/x509paths.html + * + * Only the relevant certificate and crl data has been kept, in order + * to keep the class size to a minimum. + * + */ + private const string TEST_POLICY_1 = "2.16.840.1.101.3.1.48.1"; + private const string TEST_POLICY_2 = "2.16.840.1.101.3.1.48.2"; + private const string TEST_POLICY_3 = "2.16.840.1.101.3.1.48.3"; + private const string TEST_POLICY_4 = "2.16.840.1.101.3.1.48.4"; + private const string TEST_POLICY_5 = "2.16.840.1.101.3.1.48.5"; + + private static ISet ANY; + private static ISet TP1; + private static ISet TP2; + private static ISet TP3; + private static ISet TP4; + private static ISet TP1_TP2; + + static NistCertPathTest() + { + ANY = new HashSet(); + + TP1 = new HashSet(); + TP1.Add(TEST_POLICY_1); + + TP2 = new HashSet(); + TP2.Add(TEST_POLICY_2); + + TP3 = new HashSet(); + TP3.Add(TEST_POLICY_3); + + TP4 = new HashSet(); + TP4.Add(TEST_POLICY_4); + + TP1_TP2 = new HashSet(); + TP1_TP2.Add(TEST_POLICY_1); + TP1_TP2.Add(TEST_POLICY_2); + } + + /* + * FIELDS + */ + private X509CertificateParser certParser = new X509CertificateParser(); + private X509CrlParser crlParser = new X509CrlParser(); + + private X509Certificate trustedCert; + private X509Crl trustedCRL; + private ISet trustedSet; + private int testCount; + private IList testFail; + private StringBuilder resultBuf; + + public override string Name + { + get { return "NistCertPathTest"; } + } + + public override void PerformTest() + { + Init(); + + Test(" 1", TEST_1_DATA, true, false); + Test(" 2", TEST_2_DATA, false, false); + Test(" 3", TEST_3_DATA, false, false); + Test(" 4", TEST_4_DATA, true, false); + Test(" 5", TEST_5_DATA, false, false); + Test(" 6", TEST_6_DATA, false, false); + Test(" 7", TEST_7_DATA, true, false); + Test(" 8", TEST_8_DATA, false, false); + Test(" 9", TEST_9_DATA, false, false); + + Test("10", TEST_10_DATA, false, false); + Test("11", TEST_11_DATA, false, false); + Test("12", TEST_12_DATA, true, false); + Test("13", TEST_13_DATA, false, false); + Test("14", TEST_14_DATA, false, false); + Test("15", TEST_15_DATA, true, false); + Test("16", TEST_16_DATA, true, false); + Test("17", TEST_17_DATA, true, false); + Test("18", TEST_18_DATA, true, false); + Test("19", TEST_19_DATA, false, false); + + Test("20", TEST_20_DATA, false, false); + Test("21", TEST_21_DATA, false, false); + Test("22", TEST_22_DATA, false, false); + Test("23", TEST_23_DATA, false, false); + Test("24", TEST_24_DATA, true, false); + Test("25", TEST_25_DATA, false, false); + Test("26", TEST_26_DATA, true, false); + Test("27", TEST_27_DATA, true, false); + Test("28", TEST_28_DATA, false, false); + Test("29", TEST_29_DATA, false, false); + + Test("30", TEST_30_DATA, true, false); + Test("31", TEST_31_DATA, false, false); + Test("32", TEST_32_DATA, false, false); + Test("33", TEST_33_DATA, true, false); + + Test("34a", TEST_34_DATA, ANY, true, true, false); + Test("34b", TEST_34_DATA, ANY, false, true, false); + Test("34c", TEST_34_DATA, TP1, true, true, false); + Test("34d", TEST_34_DATA, TP1, false, true, false); + Test("34e", TEST_34_DATA, TP2, true, false, false); + Test("34f", TEST_34_DATA, TP2, false, true, false); + + Test("35a", TEST_35_DATA, false, true, false); + Test("35b", TEST_35_DATA, true, false, false); + + Test("36a", TEST_36_DATA, false, true, false); + Test("36b", TEST_36_DATA, true, false, false); + + Test("37a", TEST_37_DATA, false, true, false); + Test("37b", TEST_37_DATA, true, false, false); + + Test("38a", TEST_38_DATA, false, true, false); + Test("38b", TEST_38_DATA, true, false, false); + + Test("39a", TEST_39_DATA, ANY, true, true, false); + Test("39b", TEST_39_DATA, ANY, false, true, false); + Test("39c", TEST_39_DATA, TP1, true, true, false); + Test("39d", TEST_39_DATA, TP1, false, true, false); + Test("39e", TEST_39_DATA, TP2, true, false, false); + Test("39f", TEST_39_DATA, TP2, false, true, false); + + Test("40a", TEST_40_DATA, false, true, false); + Test("40b", TEST_40_DATA, true, false, false); + + Test("41a", TEST_41_DATA, false, true, false); + Test("41b", TEST_41_DATA, true, false, false); + + Test("42a", TEST_42_DATA, false, true, false); + Test("42b", TEST_42_DATA, true, false, false); + + Test("43a", TEST_43_DATA, false, true, false); + Test("43b", TEST_43_DATA, true, false, false); + + Test("44a", TEST_44_DATA, false, true, false); + Test("44b", TEST_44_DATA, true, false, false); + + Test("45a", TEST_45_DATA, false, false, false); + Test("45b", TEST_45_DATA, true, false, false); + + Test("46a", TEST_46_DATA, ANY, false, true, false); + Test("46b", TEST_46_DATA, ANY, true, true, false); + Test("46c", TEST_46_DATA, TP1, true, true, false); + Test("46d", TEST_46_DATA, TP1, false, true, false); + Test("46e", TEST_46_DATA, TP2, true, false, false); + Test("46f", TEST_46_DATA, TP2, false, false, false); + + Test("47a", TEST_47_DATA, false, false, false); + Test("47b", TEST_47_DATA, true, false, false); + + Test("48a", TEST_48_DATA, TP1, false, true, false); + Test("48b", TEST_48_DATA, TP1, true, true, false); + Test("48c", TEST_48_DATA, ANY, false, true, false); + Test("48d", TEST_48_DATA, ANY, true, true, false); + Test("48e", TEST_48_DATA, TP2, false, true, false); + Test("48f", TEST_48_DATA, TP2, true, false, false); + + Test("49a", TEST_49_DATA, TP1, false, true, false); + Test("49b", TEST_49_DATA, TP1, true, true, false); + Test("49c", TEST_49_DATA, TP3, false, true, false); + Test("49d", TEST_49_DATA, TP3, true, false, false); + Test("49e", TEST_49_DATA, ANY, false, true, false); + Test("49f", TEST_49_DATA, ANY, true, true, false); + + Test("50a", TEST_50_DATA, TP1, false, true, false); + Test("50b", TEST_50_DATA, TP1, true, true, false); + Test("50c", TEST_50_DATA, TP1_TP2, false, true, false); + Test("50d", TEST_50_DATA, TP1_TP2, true, true, false); + Test("50e", TEST_50_DATA, ANY, false, true, false); + Test("50f", TEST_50_DATA, ANY, true, true, false); + + Test("51a", TEST_51_DATA, false, true, false); + Test("51b", TEST_51_DATA, true, false, false); + + Test("52a", TEST_52_DATA, TP1, false, true, false); + Test("52b", TEST_52_DATA, TP1, true, false, false); + Test("52c", TEST_52_DATA, TP1_TP2, false, true, false); + Test("52d", TEST_52_DATA, TP1_TP2, true, false, false); + Test("52e", TEST_52_DATA, ANY, false, true, false); + Test("52f", TEST_52_DATA, ANY, true, true, false); + + Test("53a", TEST_53_DATA, TP1, false, true, false); + Test("53b", TEST_53_DATA, TP1, true, true, false); + Test("53c", TEST_53_DATA, TP1_TP2, false, true, false); + Test("53d", TEST_53_DATA, TP1_TP2, true, true, false); + Test("53e", TEST_53_DATA, TP4, false, true, false); + Test("53f", TEST_53_DATA, TP4, true, false, false); + Test("53g", TEST_53_DATA, ANY, false, true, false); + Test("53h", TEST_53_DATA, ANY, true, true, false); + + Test("54", TEST_54_DATA, false, false); + Test("55", TEST_55_DATA, false, false); + Test("56", TEST_56_DATA, true, false); + Test("57", TEST_57_DATA, true, false); + Test("58", TEST_58_DATA, false, false); + Test("59", TEST_59_DATA, false, false); + + Test("60", TEST_60_DATA, false, false); + Test("61", TEST_61_DATA, false, false); + Test("62", TEST_62_DATA, true, false); + Test("63", TEST_63_DATA, true, false); + Test("64", TEST_64_DATA, false, false); + Test("65", TEST_65_DATA, false, false); + Test("66", TEST_66_DATA, false, false); + Test("67", TEST_67_DATA, true, false); + Test("68", TEST_68_DATA, false, false); + Test("69", TEST_69_DATA, false, false); + + Test("70", TEST_70_DATA, false, false); + Test("71", TEST_71_DATA, false, false); + Test("72", TEST_72_DATA, false, false); + Test("73", TEST_73_DATA, false, false); + Test("74", TEST_74_DATA, true, false); + Test("75", TEST_75_DATA, false, false); + Test("76", TEST_76_DATA, false, false); + + resultBuf.Append("NISTCertPathTest -- Failed: "); + resultBuf.Append(testFail.Count).Append('/').Append(testCount).Append("\n"); + + if (testFail.Count != 0) + { + resultBuf.Append("\n"); + Fail(resultBuf.ToString()); + } + } + + private void Init() + { + try + { + trustedCert = certParser.ReadCertificate(Base64.Decode(Trust_Anchor_CP_01_01_crt)); + trustedCRL = crlParser.ReadCrl(Base64.Decode(Trust_Anchor_CRL_CP_01_01_crl)); + trustedSet = new HashSet(); + + byte[] _ncBytes = null; + Asn1OctetString _oct = trustedCert.GetExtensionValue(X509Extensions.NameConstraints); + if (_oct != null) + { + _ncBytes = _oct.GetOctets(); + } + + trustedSet.Add(new TrustAnchor(trustedCert, _ncBytes)); + testCount = 0; + testFail = new ArrayList(); + resultBuf = new StringBuilder("\n"); + } + catch (Exception ex) + { + throw new Exception(ex.Message); + } + } + + private X509Certificate DecodeCertificate(string _str) + { + return certParser.ReadCertificate(Base64.Decode(_str)); + } + + private X509Crl DecodeCRL(string _str) + { + return crlParser.ReadCrl(Base64.Decode(_str)); + } + + private void MakeCertStore(string[] _strs, out IX509Store certStore, out IX509Store crlStore) + { + ArrayList certs = new ArrayList(); + ArrayList crls = new ArrayList(); + crls.Add(trustedCRL); + + for (int i = 0; i < _strs.Length; i++) + { + if (_strs[i].StartsWith("MIIC")) + { + certs.Add(certParser.ReadCertificate(Base64.Decode(_strs[i]))); + } + else if (_strs[i].StartsWith("MIIB")) + { + crls.Add(crlParser.ReadCrl(Base64.Decode(_strs[i]))); + } + else + { + throw new ArgumentException("Invalid certificate or crl"); + } + } + + // Insert elements backwards to muck up forward ordering dependency +// IList _vec2 = new ArrayList(); +// for (int i = _vec.Count - 1; i >= 0; i--) +// { +// _vec2.Add(_vec[i]); +// } + certs.Reverse(); + crls.Reverse(); + + certStore = X509StoreFactory.Create("Certificate/Collection", + new X509CollectionStoreParameters(certs)); + crlStore = X509StoreFactory.Create("CRL/Collection", + new X509CollectionStoreParameters(crls)); + } + + private void Test(string _name, string[] _data, bool _accept, + bool _debug) + { + Test(_name, _data, null, false, _accept, _debug); + } + + private void Test(string _name, string[] _data, bool _explicit, + bool _accept, bool _debug) + { + Test(_name, _data, null, _explicit, _accept, _debug); + } + + private void Test(string _name, string[] _data, ISet _ipolset, + bool _explicit, bool _accept, bool _debug) + { + testCount++; + bool _pass = true; + + try + { +// CertPathBuilder _cpb = CertPathBuilder.GetInstance("PKIX"); + PkixCertPathBuilder _cpb = new PkixCertPathBuilder(); + + X509Certificate _ee = DecodeCertificate(_data[_data.Length - 1]); + X509CertStoreSelector _select = new X509CertStoreSelector(); + _select.Subject = _ee.SubjectDN; + + IX509Store certStore, crlStore; + MakeCertStore(_data, out certStore, out crlStore); + + PkixBuilderParameters _param = new PkixBuilderParameters( + trustedSet, _select); + _param.IsExplicitPolicyRequired = _explicit; + _param.AddStore(certStore); + _param.AddStore(crlStore); + _param.IsRevocationEnabled = true; + + if (_ipolset != null) + { + _param.SetInitialPolicies(_ipolset); + } + + PkixCertPathBuilderResult _result = _cpb.Build(_param); + + if (!_accept) + { + _pass = false; + testFail.Add(_name); + } + } + catch (Exception) + { + if (_accept) + { + _pass = false; + testFail.Add(_name); + } + } + + resultBuf.Append("NISTCertPathTest -- ").Append(_name).Append(": ") + .Append(_pass ? "\n" : "Failed.\n"); + } + + /* + * Trust Anchor + * + */ + public const string Trust_Anchor_CP_01_01_crt = + "MIICbDCCAdWgAwIBAgIDAYafMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMRgwFg" + + "YDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEQMA4GA1UECxMHVGVzdGlu" + + "ZzEVMBMGA1UEAxMMVHJ1c3QgQW5jaG9yMB4XDTk5MDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" + + "EwMFowXjELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" + + "CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANPzucEztz+nJ/ZBHVyceZ2q0pUQt4TO2qPlWAw+" + + "TotWvz6qIS1QE/7zGS56yxHP89O4X1efnZeArx2VVxLfNNS9865N53ymINQETtpjYT49Ko" + + "03z8U8yfn68DlIBHi9sN31JEYzoUafF58Eu883lAwTQ6qQrJF4HbrzGIQqgitHAgMBAAGj" + + "ODA2MBEGA1UdDgQKBAirmuv5wudUjzAMBgNVHRMEBTADAQH/MBMGA1UdIwQMMAqACKua6/" + + "nC51SPMA0GCSqGSIb3DQEBBQUAA4GBABZWD2Gsh4tP62QSG8OFWUpo4TulIcFZLpGsaP4T" + + "/2Nt7lXUoIJMN7wWjqkmYf5/Rvo4HxNcimq3EkeYcrm1VoDueJUYGvRjcCY5mxkghI27Yl" + + "/fLKE9/BvQOrvYzBs2EqKrrT7m4VK0dRMR7CeVpmPP08z0Tti6uK2tzBplp1pF"; + public const string Trust_Anchor_CRL_CP_01_01_crl = + "MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDFRydXN0IEFuY2hvchcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAiMCACAS" + + "cXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEwCgYDVR0UBAMCAQEwEwYDVR0j" + + "BAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAC7lqZwejJRW7QvzH11/7cYcL3r" + + "acgMxH3PSU/ufvyLk7ahR++RtHary/WeCvRdyznLiIOA8ZBiguWtVPqsNysNn7WLofQIVa" + + "+/TD3T+lece4e1NwGQvj5Q+e2wRtGXg+gCuTjTKUFfKRnWz7O7RyiJKKim0jtAF4RkCpLe" + + "bNChY="; + + + /* + * test1 + * + */ + + public const string End_Certificate_CP_01_01_crt = + "MIIChjCCAe+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMY07G8M4FkOvF+6LpO7BKcDuXCKudfl1+bKSowj" + + "2GCza8uIiMfYSH5k+fYb43lGQeRh9yVHcfNQlE7yfGo3tgxGv5yWpeKvDMqL8Iy6Q0oIjm" + + "qH80ZOz21dUkermcckzTEOfe/R2fNpJPv8M24pq29SdYAqu+CpLDHFtws9O+q1AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIrNv88bwFLtIwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAK4hP" + + "goWtZbHf6qWfRfmrPrz9hDH1644NrJop2Y7MXzuTtpo1zp4NCG4+ii0CSOfvhugc8yOmq3" + + "I6olgE0V16VtC5br2892UHYZ55Q4oQ9BWouVVlOyY9rogOB160BnsqBELFhT0Wf6mnbsdD" + + "G+BB5fFyeK61aYDWV84kS7cSX5w="; + public readonly string[] TEST_1_DATA = new string[] + { + End_Certificate_CP_01_01_crt, + }; + + /* + * test2 + * + */ + public const string Intermediate_Certificate_CP_01_02_crt = + "MIIClTCCAf6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAxLjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDWOZ4hk+K6NX/l+OiHC4pfKCWFt+XM2n/TxwkqY+mt" + + "j9Co77rPPPtVA7mDKU4OiYT74mIWH52HQBZr+PRmOFh0Z9S1oTpLbxNLCDc6OmQKBo6iex" + + "SIt/jOatFFmzmTZ78Kq9s3nfrOVA83ggmPDTPkuG5GwcxPgFq0vRmAJ0CESQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI5o5Am09NlOYwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEA3C7Ye5/Te14LIwo/LK2fnpobbQA3dhOn5UgqZ8lKbQ/HV1D8/eU9dK" + + "2v5gW43XvFq4whK0WKLBvBFchKtp9T1QX3CI2WCqdJRyqla6TkQsS36T17/ww2nzy1853Y" + + "hfDYNsge5XW8YZNfNjjVxcR3RnyFxPax1YIlISiGdI0dnag="; + public const string Intermediate_CRL_CP_01_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI5o5Am09NlOYwDQYJKoZIhvcNAQEFBQADgYEAl26W" + + "g1Gqq3R93XPjghABVocfeIi8zcSJ0YAKqbifh5V3JCC8Piy19GzZdL244GqBDls44IAhKj" + + "YuXN2mSohdqwULbye4agAgfl37XhhwsBDTYwaJiv3njFQ6Ml7KJ3STmoIpmlLvrXibDuHX" + + "ocuNGo72ckhOdBpXd+PhgGuoTis="; + public const string End_Certificate_CP_01_02_crt = + "MIIChjCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALwJrZT6bJXQnZzc3socZ/mNsEag4BTdym99ZCP2" + + "3PGsTCfV2z7+p4DehIFrn/N/a1d1nvyqRqpQGPU86tl1CWgFtXS+zCctDR71P76bjd6yef" + + "5vxxdO/SBIRHfQTjM8F3BTLkrC+PVl5wbaLcEXRORXrFvBvsj0oqwZ4C8ZObh/AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIf5mSjuNhs/gwEwYDVR0jBAwwCoAI5o5Am09NlOYwDQYJKoZIhvcNAQEFBQADgYEAK7wd" + + "MyLlIZ/Qsqj3/A3Gat0d5BORtFTZH0VdlVVOWN1JCZxrnjeIFB92NNzUROemxgBxzneuWN" + + "SlYlcpTk25pAbs6RMdbT8dovKQkQkF2TXeQ+4qktFaLQntVT8UsEzHR4Diw0/gH8tseGqF" + + "F7FyiW8ni6zInSO+embUKiibj9I="; + public readonly string[] TEST_2_DATA = new string[] + { + Intermediate_Certificate_CP_01_02_crt, + Intermediate_CRL_CP_01_02_crl, + End_Certificate_CP_01_02_crt + }; + + /* + * test3 + * + */ + public const string Intermediate_Certificate_CP_01_03_crt = + "MIIClTCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAxLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC4RZ0R82sA+BfyynFeoIDG7c5IlZ8HorEv+O4Ij3Oy" + + "7FR1MB4no8hDEBPBf5fCrAR/8PVxCZjVj2HOwnSAqUQgxo6WPcmkabux12k8kK6yeKq3b7" + + "u5fL6tb7eKElQzsz8Je4z4rCDkI10vV+X0VZ5Ip/Es428dw2KoN8eyGmw3+QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIz08WhMpG2JswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAQ+iqlFvbvDejO/m+RCHh2UuUau1FuABObkPOu2Tv9yTWvTSWDRygdO" + + "LQRiOLsjgrdXPdbDutVGjllBoTN8cdz3SWjCpampg5TBikArxmNEYMDQvL6n2lkUcetRJR" + + "gQ7TYLvFj9+SycKXfM5CUXAyCfcU/QwDghhZgc99AuDZtJc="; + public const string Intermediate_CRL_CP_01_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIz08WhMpG2JswDQYJKoZIhvcNAQEFBQADgYEAoyO/" + + "xcpJ0Obj4rTXhHFd7XMzslt79njkEgdwnon9BaYB3xSmkEXCMwLMurrjVYKaB6SWAiPeUv" + + "G7ScDHJE6UFVJwIt4vP/M7gTOJ7uak33aWi9e5DeIuLqE6pFqTGu+uoBkkd82SHg2GhJhZ" + + "VXDtJ3UcO/3JQPbslc02s9HiRBg="; + public const string End_Certificate_CP_01_03_crt = + "MIIChjCCAe+gAwIBAgIBBTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANAD1vQj//4BGEXW1Q7HX/AUyFJFyHoYcvg5y4u/" + + "8Sj6okriXj3knnBKDiJLpKfcsO5p5MQS5QzAc+lxErXD+duiw8lm61hj0StsRzhDFsaC1g" + + "akjzU70R2Tmz/djUnqO3aa2wICc4NVAXnIMMsH/b6XXFZpC0/C32TPTv9aa9mrAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIPw2wltiRqz4wEwYDVR0jBAwwCoAIz08WhMpG2JswDQYJKoZIhvcNAQEFBQADgYEAln42" + + "iR3eHyazF8CRjS9Jnas/26MaBtjUyDtcSjTVDWFlccwrQ7TgtzjkNm9fCmgSyvryDnUYGM" + + "DoEjwYNLIgtCAkVIEBTmJvlqiPHH+tV5oJvIav+Fn8okHpuuK44umDcdKiFWlOyxrShxzV" + + "3Bez/eHklaPTw/VsVhyh+Uru5zM="; + public readonly string[] TEST_3_DATA = new string[] + { + Intermediate_Certificate_CP_01_03_crt, + Intermediate_CRL_CP_01_03_crl, + End_Certificate_CP_01_03_crt + }; + + /* + * test4 + * + */ + public const string Intermediate_Certificate_1_CP_02_01_crt = + "MIIClTCCAf6gAwIBAgIBBjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC/lQLtWKzklgYuzhjMiK2CzFmzODsEY/JIVNdn9T8M" + + "W4ufpGwnfIV62EUHCFeMYydKBm8Hyjbjrz1otINJmrGL5WSAX1/UPtHy1chgXOsFYD6nAH" + + "jZAJJGw74nUbKw5+L1wUHU8qXABaaTrRpS1UdKSq4TCZ18NCjC4Oxcf/yDdQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQINsJcxaBqdugwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAOQP3iUX7FtJlL9nvu4F+8o/N5vr+OB28OsbYtW+Q1FzEfjkUGtT9Ri" + + "teradpN/xUnS/oj3BfqFtNANkYKrBeqRtm2VeOC3kdCVFnWFME2aoRAQZbWvOwCFc3yLA7" + + "JBdENtDNI54yYHMHPA4/2CuNQq1Iu1ektAS95DIe7ddxL18="; + public const string Intermediate_Certificate_2_CP_02_01_crt = + "MIIClTCCAf6gAwIBAgIBBzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMi4wMTAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLUNQLjAyLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCx/mIo1Ma/IN8OR7KOjclvIwsv0JFXD/T258DruDZU" + + "uGoYiEbAc/ZN7R8OHI7dnv9pBfsvyEl7m2DVoLZnP0eXJTHjdZxb1TwPHoSIysi9u3xWlP" + + "Rg+v+GGfKLB9pL0m8SZh97SngerZI14w7vQy0kkXziGatSpBoXtWNmsHJNuQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIoI0mSmDmzZUwEwYDVR0jBAwwCoAINsJcxaBqdugwDQYJKoZI" + + "hvcNAQEFBQADgYEAcfs1pH12Qwdhv4NOJO2xxgMZZo8+A9Zl9c7RxsvuoZOOyCxoE9wT/l" + + "PdUpGoGxtIPoWQs1qXEXnAlXJCXjLCJUHIG1/E6gQUXW0Ty6Ztpc5Dz06pPTN2gt+41B3J" + + "sL/Klqc4iyCaWr8sYgEPQ8nColWRmIwk9gAasPNkNhyxA3Y="; + public const string Intermediate_CRL_1_CP_02_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAINsJcxaBqdugwDQYJKoZIhvcNAQEFBQADgYEAlBaV" + + "VfrZqvyRhGXNYFik169nBHiNfKpw8k1YgFAQeNYdmfScq1KHmKzDhsx9kQteczBL7ltviK" + + "TN3CKlZW82c16mfd4yYx0l5tkU80lwKCHSUzx92+qrvYjSMup+bqSsi8JhqByBf6b0JbKf" + + "yx53Vpw1OCzjxrVHcfHPx8Q/vR4="; + public const string Intermediate_CRL_2_CP_02_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1DUC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoI0mSmDmzZUwDQYJKoZIhvcNAQEFBQADgYEAhAHP" + + "QxpcrTTN0GXeOwoMXuQUoHMvezEpM0BYOVLzI3KbRXWa9iWZINr99cRQvonMtOGkhIH3iS" + + "wSNbsjmF9HX5UvNzrofOWataVP+macpCuNlK0NS3xxJjKRWOB9C1Ib7tiSSrQqIPcchlF6" + + "vofy2ALEL6Usa1UTVYMhzGYnVZU="; + public const string End_Certificate_CP_02_01_crt = + "MIIChjCCAe+gAwIBAgIBCDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1DUC4wMi4wMTAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOzYq2murB5ZjQd4wReI51Lc1F5VwK90OMGRfi71" + + "YvwdRjgCudeDXZGW5ayid82y+eTDKFSzo1Li/BPTUXMpeqHHMCmLeefqxAWmz3aDoilF8I" + + "Q53PlejnXJdntsal44w6WdP6ssiXlwzcZDnobAfuDTPgsnWWfzAkr1/LqEw/QZAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIP5tVdEyxotcwEwYDVR0jBAwwCoAIoI0mSmDmzZUwDQYJKoZIhvcNAQEFBQADgYEAkVx9" + + "S/20Hir8qMnfMpMGTgMKoVeWoljxim83IkNs1Xqe1oLGHdyDUA66uF8wPkoTqGrfDYvgBa" + + "5Mi0iJREnMWoiWvCe467+L1b2gtvRBMl9bcRj40bvelk0Wn4lBl3VuKXarP5M0PKT5OWvN" + + "2cPLNeXHvV6ZIrC4rmK2ISpIXX4="; + public readonly string[] TEST_4_DATA = new string[] + { + Intermediate_Certificate_1_CP_02_01_crt, + Intermediate_Certificate_2_CP_02_01_crt, + Intermediate_CRL_1_CP_02_01_crl, + Intermediate_CRL_2_CP_02_01_crl, + End_Certificate_CP_02_01_crt + }; + + /* + * test5 + * + */ + public const string Intermediate_Certificate_CP_02_02_crt = + "MIIClTCCAf6gAwIBAgIBCTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw00NzAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDHJmlRKb+mjc61iiqGe9gx/VUMLNmGrXGRYKMmYSxO" + + "Q5sGLoztd2XtEgtZEPwvzd9KLKGP3XmgTrc4BGohqoFoG9Qb+w2ZGFwVC22GpeSoXc+J2u" + + "2t3uRKYgboHpB0Jk42XLy+2wSEtS+/er7cFu2ufdPsvT4J1AqiuZSco96vtQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIBvoP1E6PGiMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAmOyFq2vZrUNDVWRcyzYvZhs1uQ4zgXtfqnPE0V19RgaYffCrSCI86z" + + "5kyDUyZwbGABMxBaVxEw536MesyDTdZdEVw6lN5RRtxr8/WEiSH6oI6t0xNxuNOkSNpz4d" + + "28HA4UfUvtXK8RK2YZnPAd6UXsRUPBPXKEpzy4v/9RyihSg="; + public const string Intermediate_CRL_CP_02_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIBvoP1E6PGiMwDQYJKoZIhvcNAQEFBQADgYEAALlA" + + "f3IDWexcdkMQHWTdGeFe+bG5dBvVPL5ZyQUw9DWbLwrjw/Jm4v9t+HLjETLSymsFT4bW21" + + "OwnEiAAdaKT96k5t+sTyU5QQ6HL/jRXLHLGdCQgMFCglm5iNqaCLIFoMAVCaFkYtFUE3m/" + + "iVt+319JOh5UyshMuWrAEW0IGGQ="; + public const string End_Certificate_CP_02_02_crt = + "MIIChjCCAe+gAwIBAgIBCjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL/Src6e8qXwL+KJs5+v+JsakZdSDqMAFJUMfA2O" + + "OO2TIqcvDFHzqesX+G+28MUwy6++ux07CD3FCaapgzBN4zO4RfKcamxFReKMKcEvNVVCOO" + + "wO4Lvku1Sad14oYyGLOMzZwZFjRp8paaz5g87k70EOPBLeDlFMcch36czw53sLAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIPoHc2Sfk6XUwEwYDVR0jBAwwCoAIBvoP1E6PGiMwDQYJKoZIhvcNAQEFBQADgYEAFHhm" + + "o6QRFdO1x1wp7Jb1QQAlChFfP8MrGVNK04Ur8f+wfkwIypTDifJ0AoFpjcM3Ohu9Ixvb9q" + + "3kCSIWKDnWtDWw1/dN8mPL5If5gGqPA0+wRbUKVKvduOg7hKr4mWjKw7oYiaJuIIoN9RRZ" + + "ejzltd0NEaODNPW/JaKeQUVgZbY="; + public readonly string[] TEST_5_DATA = new string[] + { + Intermediate_Certificate_CP_02_02_crt, + Intermediate_CRL_CP_02_02_crl, + End_Certificate_CP_02_02_crt + }; + + /* + * test6 + * + */ + public const string Intermediate_Certificate_CP_02_03_crt = + "MIIClTCCAf6gAwIBAgIBCzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCaJ7NcOvb22F6HjMF1R/AORa4+pKFfFfd9teXPpVWC" + + "9InTq+alY11QaSj27Qg0znOIItmf2W/8Dub9sjnbg+SgAkoV5+CAkplodRNC8AbD4x8rh/" + + "fioQ8lb0Qb4Dn9I0n2wjOgitmMRdE2uW4uwVpH52vsMyenbDVxVI7jA4NS/wIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIC2T+/BkG93AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEApr6kDXVY5jYt23wC9n3LmhoxDoWh8cBQxcWmr1wpVxIrCbaP0/y00a" + + "29wbewKfucUoh/W2OfjNcohjpKRrnVmOpi5vN7SmbZIHaxbKLzyQ7JwF17aznyCSZVrGpF" + + "A/S49T5rlCm8KDBcc2ym7gRJzwUApbC0Wws4Pg46czrpQlg="; + public const string Intermediate_CRL_CP_02_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIC2T+/BkG93AwDQYJKoZIhvcNAQEFBQADgYEAlBFY" + + "vPxhFYsjFOIfQkd7MwKIi7vgPgoWTP5f+QlI0ison5n4N3rYJv31hTZRRRP99JZce1hY6J" + + "Qiv1OtkpG7VfQIhr0FAGxTNaJD6F6rLbGjG8cap4+VibFQf5gZv0XQcyW4akYiRqSXImYn" + + "NVlNyaxiJja+5GA9XVqvWOjjz4o="; + public const string End_Certificate_CP_02_03_crt = + "MIIChjCCAe+gAwIBAgIBDDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMi4wMzAeFw00NzAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMlW6FOLwhRsKZM6p0ww4QEWjQzjpjYhKnz3BnLw" + + "SdGZqMe4wzZnDWc/0eyDOMCSYXIWQhlDMqQn2zCVPbDKzMRkdEeRSvE6ghhYP/hn3ipjSw" + + "D8QwaqofCp0sFkbDPke+xD2tMhLdUyNKynPjpSQmYtfoA98PD7so3cSAtrYuSDAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIc/X6kp7teCQwEwYDVR0jBAwwCoAIC2T+/BkG93AwDQYJKoZIhvcNAQEFBQADgYEAStub" + + "g3DzhJgzYO+ZmRc0acldZGwZFm6F1Ckc1JzQDgVHU0bnCANgBcJj49UV2MwbNKPQdVzdwo" + + "c91rfwrSY/PrvVQ9tUonZ28y/esFRBAdJTLf4u++p/gI3vfCvEXa5xVTIz1Hc+iKzAGKrI" + + "cveDHy3ZZluQ3J6tbHs2BhnQFXM="; + public readonly string[] TEST_6_DATA = new string[] + { + Intermediate_Certificate_CP_02_03_crt, + Intermediate_CRL_CP_02_03_crl, + End_Certificate_CP_02_03_crt + }; + + /* + * test7 + * + */ + public const string Intermediate_Certificate_CP_02_04_crt = + "MIIClTCCAf6gAwIBAgIBDTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDgZy2Xs5pIoJrT7GuagmKLrn8F9rj8p8w2wELorGhM" + + "1HJMVOurH+o+y6RXd0oMGJkKNrhjEnbHKm3PBYiLgpCjVEcFNhQF1OOxJ7RdahvA9ifsuw" + + "jV1TxTGq35jeaJYASRXb2TiNfzuPWSVm0MWr5zz+YB6NNuvjxwEBgZvNiV8QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIWAOnkHkwSVkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAMiHozz92EOhSXU/krwQVs0GNEWoAUH3LHt70Zr01dFzEF6QhA/wUa4" + + "+V4XwbMob+q4zGnTHj+tL9ChGWi3NDGELQ4cN64OMPsToGKkepLy+sDwdm9LaUP1bDvPxd" + + "v2hjlskJ7TEu4+6ltXSG/k36Jk8C0/I/ayNGbYcEcLyes3s="; + public const string Intermediate_CRL_CP_02_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIWAOnkHkwSVkwDQYJKoZIhvcNAQEFBQADgYEAVtCi" + + "IocktnWOwWiaOc7tTUJvvH5+IYVyB/XhmMhF7cDbL292gyrnuh1+3+lHwZQBPoF9kzF0vt" + + "WaweG7mDvYKxENQODdph/VcnypgUiFTWRTIPB1ZXfCTMWYf2QSalpHRDR4vVsqF748QbcG" + + "E9mbzvLUz6NDA+Vf8wEwZehqSDM="; + public const string End_Certificate_CP_02_04_crt = + "MIIChjCCAe+gAwIBAgIBDjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMi4wNDAeFw01MDAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDQwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALBX5GIQtvwswWwMDDPnphIk1rJSbcq7iClXLM2E" + + "kgvBu+hbOzb0v9mtl0KJB71TWJCfwceVQiXc3Gk+YduujAbZRVTkROf9UOWD9bfrI7g+52" + + "g4ms2n7evCO33b+kGEf4I014xl8dJDWtHK9Bhr+569RW9TzO06IeVeTD7whxMXAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIuKXv5WkUTWAwEwYDVR0jBAwwCoAIWAOnkHkwSVkwDQYJKoZIhvcNAQEFBQADgYEAiu0B" + + "yR5Ru8qVsgRqkOpCvrJnkqBAImbbR6+BUYH0juRxxKzKnbFOjU6a9WvkKpEBB8Q2xLynPN" + + "68ecLpnOynx3xj2sWWSVbsRKPy0iOesQblKrq3yHAm4lhzoWA8t1Xz29Ko1WxylDhyxGpR" + + "QAWsyGVCfJFlsZE0ibw3erlWTnA="; + public readonly string[] TEST_7_DATA = new string[] + { + Intermediate_Certificate_CP_02_04_crt, + Intermediate_CRL_CP_02_04_crl, + End_Certificate_CP_02_04_crt + }; + + /* + * test8 + * + */ + public const string Intermediate_Certificate_CP_02_05_crt = + "MIIClTCCAf6gAwIBAgIBDzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC2d80bD1RounqjKizkZJYPFUuVWZQ8W2nZDkEp8qR9" + + "fRWCAGOZGs84tgHj5gasmxy1mxJc9ogyQ2mcZhJRitRm5LVNuGevO6JmfqYtJxbW54aZGE" + + "5AWSRXqjJKJEih4VmPjA3vjQaSZSZJnu0DSnO82qWfu1ZUDlvIG6dfKJWRQQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI3uNhI+QuI4owEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAG/+Rpk8dYrSFdaEO8Ch5tuvvKTOMi7W/DRA4B4xR7WyRJmosPB+37c" + + "teGKVzqFND22Xc8xQH/b/nxYW08sCSLAfN0cRusoSWwWSRtPO2f9fyC/BqCy2B2kQLFNPM" + + "Bk22jNFwLqPUeZn1UHN05RFAqVx325kpl2m1V7tw/mrXATI="; + public const string Intermediate_CRL_CP_02_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI3uNhI+QuI4owDQYJKoZIhvcNAQEFBQADgYEAWZUI" + + "2VGY4pak0kICONP/CKvamYFs5txJfR69AC5tEJ+Fy3PmSeHkLUZf/oc9d8EEyr0MsIjRHj" + + "N4X4MquMlk4FflZcc8GblQK8LdXBK4Dy1SiXHA5GB3U1AmgzAzEQGwGRZnzWP5+rJ65upX" + + "vksAYyPQmruRM0O5sElctPn6B+Y="; + public const string End_Certificate_CP_02_05_crt = + "MIICiDCCAfGgAwIBAgIBEDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMi4wNTAgGA8yMDUwMDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" + + "EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" + + "CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wMi4wNTCBnz" + + "ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAviLKpW4iblWNLQfmBJJ+ruMgygmjRWfoFGya" + + "Ndv2ma0Ugqm5xXq8c0orbnezwSp+tnzZZhG5KDNZr5+z3krCkqOGGzuUvVLqeJxPOLu7Js" + + "y472nAA7+FhwfZrXUI+Vg9F4qF+Ye81ivDrYVAEmalCpCyHOAKdvwkwQjRucifu90CAwEA" + + "AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" + + "QKBAjgph7BA5L7dzATBgNVHSMEDDAKgAje42Ej5C4jijANBgkqhkiG9w0BAQUFAAOBgQBr" + + "MDMv9NWCTIQ3blMEqPiEyjiBhSJl88Cu797P4lIn+gc6E+0vZp61X7B2k5CHgsnxyVLK5e" + + "bwl0bYAPKwRI9yzHLrj71RNw8HA7PCRPn1GNrtBBbIpLE0/sqLo51UPu/377+CnzYhIycL" + + "tvS0KDLUTDSY/OowDcplF6Xwnt8cUQ=="; + public readonly string[] TEST_8_DATA = new string[] + { + Intermediate_Certificate_CP_02_05_crt, + Intermediate_CRL_CP_02_05_crl, + End_Certificate_CP_02_05_crt + }; + + /* + * test9 + * + */ + public const string Intermediate_Certificate_CP_03_01_crt = + "MIIClTCCAf6gAwIBAgIBETANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw0wMDAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCuF8mub5cgUYZytrRjJ5Rhc2fgazGxWIj6EIKzeSpo" + + "FwScItRX9KxnTIXEBTguBk7eQUsbN8yu49/Mlq45EAnemyZRBWzLFLYLPCco7pyTsWm7Ps" + + "2FAGJ3vE9pC9xaZC+KrwF3Ho+DZNDwhj5InXTP8pChAIPfB8/7V/2mk0lN0wIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI4mI6Ojs0onswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAMVGzU6f4YOHpHla+YuGCjHOUZYrA9J25G3UFFoPr2JZEG+Fb5hRQUh" + + "4S1qUQKXn6dpVua+qTJDk3Tg2N8OdIHG/gy0hvYHsxhLCSDQBsfPN7p3FClM7r/VHOqgAN" + + "vzT+KYvxx6gwn6O+n7ERkrBIfkyrGFhnmjx3+VOCc9P4SDE="; + public const string Intermediate_CRL_CP_03_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMy4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI4mI6Ojs0onswDQYJKoZIhvcNAQEFBQADgYEAfwYf" + + "4kAG4srB2VxWimJs1HwXTaPDooellQclZ5hP/EluT7oe03+ReFef6uXbHt/xRdeaoQhJGy" + + "SP8dWf6UIbL82oaSYqChIvAZD6zTMavEgSET0PlUsK1aEMTpMEtKPvedFSOTNBaMNvMzSW" + + "t5xwurn63qyXTOxHf4m2L4w8+i0="; + public const string End_Certificate_CP_03_01_crt = + "MIIChjCCAe+gAwIBAgIBEjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMy4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ/ALaZ+MdNxKDH49+7jUm+17DII5QQEfjk8IaEU" + + "syApOhsByOG06HPItiBEnnfDDxU5kjsZDtw/9LlouBocNXAJt+ZmL3QYyOgeH4SQ4f21rw" + + "7j8fw57gUkP5oWhEc0loXr/hB92hoKbsBoRpv8F1zPZcPNLUnyUzqLH5+CeIibAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QI822isg/wPCowEwYDVR0jBAwwCoAI4mI6Ojs0onswDQYJKoZIhvcNAQEFBQADgYEAilIn" + + "OD0iQrLrHRkO4zr9S9VXAJXJV3l9wfbLBweXM3q/zt4HGKBw4Wq1Yn+AfDxXrBtJA5hP5e" + + "d7CDd4eM93yeKozdZCLNZfUM8sJ2/MRh07tvwJ19e2STklED8b/ndmr5my8H8jjJDaaYww" + + "qTSnXqpcqsUsj+kV4Mk0DvVWT3w="; + public readonly string[] TEST_9_DATA = new string[] + { + Intermediate_Certificate_CP_03_01_crt, + Intermediate_CRL_CP_03_01_crl, + End_Certificate_CP_03_01_crt + }; + + /* + * test10 + * + */ + public const string Intermediate_Certificate_CP_03_02_crt = + "MIIClTCCAf6gAwIBAgIBEzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC4AbP8gDUUcIa8w4pEsGgbYH2sz08QMUXd4xwx691i" + + "9QCcyWSovQO4Jozeb9JwtyN2+f3T+JqZL/gwUHuLO2IEXpzE2C8FzQg6Ma+TiSrlvGJfec" + + "TlSooFmEtD3Xh6I6N5PM1fpyyY2sOOhARN5S6qR9BOuxkBAqrAT0fgqD2TswIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI97nJCqq6+kIwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAWwpfh9oOOvj9xHS0zcczaUIHTkpjgk09I+pERlu0Z0+rHvpZGge4Ov" + + "NDFtMc4TgthGcydbIwiKogjtGBM2/sNHIO2jcpNeOtNKLxrzD4Y0Ve164kXBu9Mmsxx4sG" + + "7XUXZWgiOPfu/HmyPVdzbIReJdQO515SNx7JdgVyUkyhBxM="; + public const string Intermediate_CRL_CP_03_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMy4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI97nJCqq6+kIwDQYJKoZIhvcNAQEFBQADgYEAC9Hv" + + "NevV6/Oz3wcgEbDgZYRKJRdr4OW4Es7R4ahjz3sH6GXZ1HiEjx2+frmp8LMshQ4D+hpjRk" + + "drSPko1M4a/fQCYxbonZ0xjpYw067dwLmr56+GPJAxkzcSmFKXx+ejyQpG+9+qCR+zm98V" + + "lop6besAaGUjZKnYShIQOfNzDZk="; + public const string End_Certificate_CP_03_02_crt = + "MIIChjCCAe+gAwIBAgIBFDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMy4wMjAeFw05ODAxMDExMjAxMDBaFw0wMDAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMJMiW+G4bgoRaYz2OUu/+PQ/yp4JgFOB3Vegf5/" + + "vIrF4gsnoQxOCCsO5JTLrbS5fi3COjvM5w9/SZpNHtSfyWb9afmx4DdrT1bNjma7I6PCid" + + "yxMzX4iTLeaMRnqBk4A+/0Wf2+4VzCqr8aViIiQ7u2JfZiTQ4dZxDoUW6G8lrbAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIEjny2GzFXGQwEwYDVR0jBAwwCoAI97nJCqq6+kIwDQYJKoZIhvcNAQEFBQADgYEAJw3T" + + "3aL3pYbZhswgshOvJ9Y1qv65R6rClSxB5lqBw6+Qki4ZpW57NK8LwaGS03XzDUPaDi4/9R" + + "hGCHpP24fIskS4n4jNZgKpGtt6VEVorUH7cOLNCw2cuwMlKbkyZnNdx2JqTMMlHzNJ3cmy" + + "aX3F70IY0OZbwCKdUo/uMVC6hss="; + public readonly string[] TEST_10_DATA = new string[] + { + Intermediate_Certificate_CP_03_02_crt, + Intermediate_CRL_CP_03_02_crl, + End_Certificate_CP_03_02_crt + }; + + /* + * test11 + * + */ + public const string Intermediate_Certificate_CP_03_03_crt = + "MIIClTCCAf6gAwIBAgIBFTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCjLYKGKEMJgC/r0NH7vubQZ5qPEFEEN6QdLUWWqf/O" + + "Yqo9hboQq6S8dFHp3DVR5x/4NOdNRjsTABbXsnz8U+L7+4CorhDhXj29weGMYIIfJ3XSIb" + + "T7sE/GOPmXeGhrTv2zucI1j80sN5nTEoiGFm10LQqAgoyV46BxDltf3/D7wwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIhCIOyzfScpAwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAA18kQijoJebmTQS7n/q/fQx2iblOJaJAWQLHeGCCGqKxCjUpOxuD+y" + + "xMspmTKdQqEkqQ5vpHdFYQ5MYuecqAdp6woWUNQGVd4HHPmHsAW3Oppwb0yLggYs8IVHjm" + + "dNO1pYb+YYciCKBtX8D1OnedIRcrQmDMJUjbfmAEv/4b0EM="; + public const string Intermediate_CRL_CP_03_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMy4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhCIOyzfScpAwDQYJKoZIhvcNAQEFBQADgYEAk34j" + + "SxMr8p1h1qJWlfoh4er9pu1AkkHujovan6Ctx89VwFdOS5Kw82OCvD+nmJAHrFuncNlClf" + + "51G8FCEAFLhMNwic4WAxrBX15hcUTaWk8Wj00dfUFwjG8/Kv3QUCDBN8f3KC8/oBeORRX9" + + "dHW5ei2IUKuD1ITCeIoyRDBxQIg="; + public const string End_Certificate_CP_03_03_crt = + "MIIChjCCAe+gAwIBAgIBFjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMy4wMzAeFw05ODAxMDExMjAxMDBaFw01MDA3MDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALSw1Ey7kzFzzjMS4oTSrZH/95NMHLxtUSaVGMCy" + + "0q2iLfGZ79eTS9megQUranYlIuK411yvFtskbFKf0idMKBtM8nX3Rxubm5EnbnpgvNrBEg" + + "0FbOPqpSaR+8pxZ6lweB45tkzLU3OZeAZSpGOY1UvT/htn6Ae8JQAVajSvYyfNAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIF014kOHikvcwEwYDVR0jBAwwCoAIhCIOyzfScpAwDQYJKoZIhvcNAQEFBQADgYEAdLMM" + + "zGPPvBLgPbhn2tba/7HiaZaayHIxTXmpW0KAhP+8hwapOitrtLGPwqVtxQ3GoSMZJPMDCV" + + "WsrT3OZm27G6ytqqNZ2ZO49UC7WwQ49TVlN79Ui9RZIBnRzlMIDNKsyuohfSRhFZTkWdoH" + + "/y8ulY8k4xBThV8e8IRgtYj3nhc="; + public readonly string[] TEST_11_DATA = new string[] + { + Intermediate_Certificate_CP_03_03_crt, + Intermediate_CRL_CP_03_03_crl, + End_Certificate_CP_03_03_crt + }; + + /* + * test12 + * + */ + public const string Intermediate_Certificate_CP_03_04_crt = + "MIIClTCCAf6gAwIBAgIBFzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDbUii3czeUQ2zNlxvrhnJ0LcBGxCDHFr3xx+plDg3f" + + "uasDKCY/VjCLEfQ5a2oqcovvGKsd2CPXbCFJtimW1R7Dvt+a0y95fppsdseorYDikiBlOj" + + "ja6LR3Cz3bslYc133C+W/MKHMJ0tdvtTk+SJrq7lqs+iv/b/xHC3k/gDjIswIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIFNw3o1kc4XkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAn/pr7/noYyjXSKEe/eLk3l4Rb6PEhNAnzySmxGkjIjWKAgh5IVYSGV" + + "KFO/FaNOiYkRFHwXZFNj71q7gbM+HwALurN0Mr/MUA1TSpPy7YhFL0SWq3C3XsC/dVJ50b" + + "HmTW+dGcxboX0h9HeKFxp3VyOY/dUut2oc+s/TnmqQII1CU="; + public const string Intermediate_CRL_CP_03_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wMy4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIFNw3o1kc4XkwDQYJKoZIhvcNAQEFBQADgYEAMoJ5" + + "jGE1AxxfluixG8Sk7H4W2rqSEkQyNHfnlKSMbh9KZA3evI8HGKGGfkbBNoe4/HauZ4NVFw" + + "FXgllCp+TI8Qd+HafFoDv6ff1K7T86p6r7tE3AEM1XmbnfohP3/ivpIzustv/f2rqjxILK" + + "Ldvrth2/OlNygwY+D54lcWH1DX8="; + public const string End_Certificate_CP_03_04_crt = + "MIICiDCCAfGgAwIBAgIBGDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wMy4wNDAgFw05ODAxMDExMjAxMDBaGA8yMDUwMDEwMTEyMD" + + "EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" + + "CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wMy4wNDCBnz" + + "ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuSL9tB1JW6JPUO2Xw6TMYkPX41lru3EPyYko" + + "YgXy4giy6LGoqbgtskHehD22v3rfWjqOd9iV2PBio/vYE4zEz0H0n84dpnBvog6A1AlE19" + + "PkQ1txjzIA52FQIRwRfZ38LaulQEfJ0a+fiRHQiM960O3YvHXV+GEbNcw4jo8b0sUCAwEA" + + "AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" + + "QKBAh9/WgM+UT6bTATBgNVHSMEDDAKgAgU3DejWRzheTANBgkqhkiG9w0BAQUFAAOBgQDR" + + "I6PKUGg876/fSljtqxXCR4CoGAAurNFOcM4EWeoc6ZvuDOi3P7rNYiYAXXlmp7epOAgvZP" + + "EV4vS16ODaJO6qIMR1YsaGEPo0ecT2pEStvP37X6pb5TdyjyKYF3586IN6TJdFMFsW/Lqg" + + "tucl9bGlWmfTVwxTexq6+D8diK48KQ=="; + public readonly string[] TEST_12_DATA = new string[] + { + Intermediate_Certificate_CP_03_04_crt, + Intermediate_CRL_CP_03_04_crl, + End_Certificate_CP_03_04_crt + }; + + /* + * test13 + * + */ + public const string Intermediate_Certificate_CP_04_01_crt = + "MIIClTCCAf6gAwIBAgIBGTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC5UJ+KMj8tAmzr3OGYL2gSFcNTf8ik+ZVxlaPVGHyS" + + "KjYQBAEbefhfg5Ps2aIuqBwYkbtFXuHif5GEhgObA4InCyESeRjYLGcVMqwSZzAOFAR0dP" + + "1LzgzQs3ZgG9JX5MO5wEZ8IMnVN4Otu4XIlWSgIpUNS2vyet8Zi7t9fX+JewIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIOZvfph4Uu9YwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAXMyscmGpKSLG3hQltMQLegy0+g5wzgOrbFOWxZmiVNR+zSsHDD3UAH" + + "H4SyTozlooC0jAY4yAhZ5RX6SSJKx9fHsOZD9ldCmst14qLk3pkI+M0QiPBZkVTx5/7dR2" + + "wGkuNKSVWH6woOq7BbEzpO7xMlrUr6tgHt4Dc6Evt1pVZls="; + public const string Intermediate_CRL_CP_04_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wNC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIOZvfph4Uu9YwDQYJKoZIhvcNAQEFBQADgYEAe79z" + + "iEUgP/mvouJ9ufit1y4SjnHQWik75W65eGn/XGArRrBqJ8jZVJE4/rpDBbzm2V0hQoWU8z" + + "zchZFlesUyqQZ9KUlT0YGR0YPcNw/V+58RonWWfmU3M2DvWDrXgCOXPm61+AYq4+kTowsG" + + "0stmeML6NxjDzWpfAgI/MpXqe80="; + public const string End_Certificate_CP_04_01_crt = + "MIIChjCCAe+gAwIBAgIBGjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC45OS45OTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPiAZKXPjK8jvaNj34VynyKPK7dQtFysBPKFW5Y1" + + "Bc+OMsyd2pPpQoJYcQTMMomlAqoBvSXUJCMNly/BxVuvn7l6I9crtx6PjBBUlEzdcsscaa" + + "EaHuCCVl+Msnr66cSV3GqVGAhujun81+lyurcTEog3ftsohwbQnfA76qNU/N3/AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIJZPDbf2xNv8wEwYDVR0jBAwwCoAIOZvfph4Uu9YwDQYJKoZIhvcNAQEFBQADgYEAZf4L" + + "1RDHDXwwA2CgcIhM4CAfZ72CR2zOan0at38VVFB3u9vs4VLwFcrOQCIjDbdLijc0XWLima" + + "4vCD1qrsv6Hk5+6113HfFNmD8mp6X5jAwoNPa/I4kmFOA8iIm4TTk7M75vQyCQTPG0VzbU" + + "Nu3uwTbXKm5ME9C5MFMf7z347CM="; + public readonly string[] TEST_13_DATA = new string[] + { + Intermediate_Certificate_CP_04_01_crt, + Intermediate_CRL_CP_04_01_crl, + End_Certificate_CP_04_01_crt + }; + + /* + * test14 + * + */ + public const string Intermediate_Certificate_CP_04_02_crt = + "MIIClTCCAf6gAwIBAgIBGzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCteErspc5ekSOel/wmjn/XQ0HUy4XzxB5Zj0nGn9FD" + + "PbjF2LERCHOn5aBnIMHYhyr7PDynwbvSx2egzGC6wGe9Zrri1MteirQ9Ppw7062IIleloy" + + "UAiuwvD+s0npKsvboarQsCMfOB1hOB1tGG1bjXP6B5B187SZXuR3KawggyJwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIUjnGp96itUMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAR6fmN+9p5AWy/asEAiVBnbY9q7EQXyB8WuZK9FtFmupe3hlfcTq84E" + + "A+TGvXOlNr05/1iLRv82GsWXDif7DlGVPN8CS1+0kb5Ve8Pmv2ziiWVREqWx916ioPjDRp" + + "wvdGcCNC26+fyvv5TrP8uzojurl1ZlVRRqi2sIbopVX5r8w="; + public const string Intermediate_CRL_CP_04_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wNC4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUjnGp96itUMwDQYJKoZIhvcNAQEFBQADgYEAZkXJ" + + "aJG4QDE02wFURwaxWuv2VyD7m+N/2B0/9KR+6UKVpsMd2XHq+G3SlFOa6dA/fHUdhtUs2D" + + "gpx3SfQYbcgKFrryZHqJDK230eP3F41S9g5XJTRaNR5iZvxvh4bmSf4l6a5MXsKEoBoJoT" + + "j8cU4qg6j7Xk4NpIR1JbWiSIYQc="; + public const string End_Certificate_CP_04_02_crt = + "MIIChjCCAe+gAwIBAgIBHDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MRAwDgYDVQQLEwdUZXN0aW5nMQwwCgYDVQQLEwNEb0Qx" + + "FTATBgNVBAMTDENBMS1DUC4wNC4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALM7mfq+hpLfvQdqZUJfIx/2gFcgHS2AsgZn0An+" + + "Yn61WtG8K2+lt/a8aypa/q+J93RVkRYKWKFQcJHiRgx7DMlXElVnfQbSFuLX46ng4hqmQL" + + "sSOKmXDld2BlyMZ41B3rfdhJT8P12RMR6uAwvc9CH3b0UTcsc498Kj+JeaRbzxAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIo7S64S6t5nswEwYDVR0jBAwwCoAIUjnGp96itUMwDQYJKoZIhvcNAQEFBQADgYEApNT5" + + "Y+9Jc28m5Qwjm+/8SKk83iCPnIW3BsAvQUB9Wmd1+kMZvqLySQjm1tBBbcGYuSERMJ2Et5" + + "eoTdL9B6EG2CZYnPqu1vk0TVugRxs7IJm4h5z4MCInf2g1KTt0AMEasQW6ZTj7DIkkU48Z" + + "EKLPoBGXfD9t9Y9cmdj1e1RQbog="; + public readonly string[] TEST_14_DATA = new string[] + { + Intermediate_Certificate_CP_04_02_crt, + Intermediate_CRL_CP_04_02_crl, + End_Certificate_CP_04_02_crt + }; + + /* + * test15 + * + */ + public const string Intermediate_Certificate_CP_04_03_crt = + "MIICmzCCAgSgAwIBAgIBHTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGQxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEbMBkGA1UEAxMSICBDQTEgLSAgIENQLjA0LjAzMI" + + "GfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD11QBcw4P2rTUfPmbVNYqdo0AMmcB3Yxsx" + + "Iz5me/S1I2PJLtRh9KP7lUV20SMEFsFKtE1C+9O7ODtOUCJA/6ECeXbyj20SbG1E2oQrZe" + + "gkcn7IQDUgnuedzdFj4kTevok6ao9hycg+qeZrL6oeBD2XQCd9nqMmzhihNu/QOSnp5wID" + + "AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMA" + + "sGCWCGSAFlAwEwATARBgNVHQ4ECgQInx+ELo31rJMwEwYDVR0jBAwwCoAIq5rr+cLnVI8w" + + "DQYJKoZIhvcNAQEFBQADgYEAriYMoRDpSPI4HWrxN1rjqWIzggz8p1wpbEFgK5o/Fi2KT3" + + "jCd6bfCcIFDpoXNqlsc+dvzc4XB1Eg/Qbcror8HP8LSxrbFw/y7VhC+wCaDCmhcqQn3rp/" + + "WaOWnR7/H7HlKM9m1u7MBtwlxHINnLKwPHIA1XwmAnItAXIL2yHRJhU="; + public const string Intermediate_CRL_CP_04_03_crl = + "MIIBUTCBuwIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxGzAZBgNV" + + "BAMTEiAgQ0ExIC0gICBDUC4wNC4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWq" + + "AjMCEwCgYDVR0UBAMCAQEwEwYDVR0jBAwwCoAInx+ELo31rJMwDQYJKoZIhvcNAQEFBQAD" + + "gYEAvJgOX6tewnRbC9Ch+Fe4KjkB9IAhe5anQKGfnDHuLfga6JEjOzyfhonWZeppJwvYpl" + + "1rZbsKICNphMDkd/eaWnn8Q9w02ah4kzIb0LuzrNBrxpFv9AAidfGU2VeF0gRi02jtAZsh" + + "gUNbrdC+ovA8mAsBigy+HMzCi61+wrumwvo="; + public const string End_Certificate_CP_04_03_crt = + "MIICijCCAfOgAwIBAgIBHjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "GTAXBgNVBAMTEGNhMSAtIENQLjA0LjAzICAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMT" + + "IwMTAwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYD" + + "VQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLUNQLjA0LjAzMI" + + "GfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2Rd0VKnTIrME7hzpnpIPGXGXZCjpf5lSO" + + "19zvB3WdZumLGdwUBXpIQTrl5teYgL62PpOwNC93URZDEUt+rqoqvs8E7MpF3IulStp2+H" + + "/xa6Ihf4OmkgKjpHNTWOIFXeRJ4sVgWuH6cqQ+6GL+0fa1sed1crsEgTTAGYNhFi6ebwID" + + "AQABo1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR" + + "0OBAoECBNwCFdDgPCqMBMGA1UdIwQMMAqACJ8fhC6N9ayTMA0GCSqGSIb3DQEBBQUAA4GB" + + "ABAjSPg794yiVz9RqdNxic8TGnApNrZui/vwr1U8ZkETZfx8W1fWgQ0z7KjryML5IOmvps" + + "zycM7by6jb2kMmxI1SQCwjiNQ1fb1osrNAj2bRfpp2YgjjbHx1XkddommtVc0V8kvyQBcb" + + "7NdxfbwKr8AtpiWTWIajc2uqUlELsLzr"; + public readonly string[] TEST_15_DATA = new string[] + { + Intermediate_Certificate_CP_04_03_crt, + Intermediate_CRL_CP_04_03_crl, + End_Certificate_CP_04_03_crt + }; + + /* + * test16 + * + */ + public const string Intermediate_Certificate_CP_04_04_crt = + "MIIClzCCAgCgAwIBAgIBHzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOQ0ExIC0gQ1AuMDQuMDQwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOFf5hr4R8IqTp53qQSiBEjOFQ3Q3ICcafl+FLzm" + + "K3xIFqERjyXARsTM4gDQ9yntFeNp2TiIi98xBrz7D8TlrbTAmxO/PUfAQ68tXpz9Id/XrU" + + "WeAKxMZULPL9nPFcGQoh0qq3JKpFRSb3Iobryfysblm7cCDDCJOI7uK14XZtTFAgMBAAGj" + + "YzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBYGA1UdIAQPMA0wCwYJYI" + + "ZIAWUDATABMBEGA1UdDgQKBAjior7qCuLBljATBgNVHSMEDDAKgAirmuv5wudUjzANBgkq" + + "hkiG9w0BAQUFAAOBgQBhh55gTy5htqjxW1Ch2hRrRikhBH7LJz1PmDuzwiIOtnWL+EiQOY" + + "T6h3NV1j8Kn5S4KhUOrhnvrPXRi22HdqRzEPl7y/wXm6G0XcgYlyy2ofZKdYVWCVStKAMW" + + "5SwV2wC5RPK2KphdhnlEqss6QVRUsliDDjnf9Saiey9nzJAfNw=="; + public const string Intermediate_CRL_CP_04_04_crl = + "MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNV" + + "BAMTDkNBMSAtIENQLjA0LjA0Fw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMDBaoCMwIT" + + "AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAjior7qCuLBljANBgkqhkiG9w0BAQUFAAOBgQBI" + + "VlXD5FnIiO8tavLJ8qo/qRhbBNgUbFBdAgAY6yVnFNP6YN4qPineYPN6NV1XdqNDrZh2Nz" + + "GHzX3YDo1Uv9yABVR0NvXCaMIW5/raqZp/on6bPuQLgJe9UisOPKunzehTm/NmO1RW9dwU" + + "37UzC0XnVHyVipDVh07DrTKBUtQJQw=="; + public const string End_Certificate_CP_04_04_crt = + "MIICjTCCAfagAwIBAgIBIDANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJVUzEZMBcGA1" + + "UEChMQVS5TLiAgR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRswGQYDVQQDExJDQTEgICAgLSAgQ1AuMDQuMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMT" + + "AxMTIwMTAwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQww" + + "CgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLUNQLjA0Lj" + + "A0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCegy6qOnM14CS7+enBElgh2DLtF5bn" + + "ah0yfA18/hbqnmUaWOWJQllyXa8QFawnvdXOOEXJm1ErIm3rDYihkbUTP+ybOBH9dprWtl" + + "1cSGL9CkoxwzkJRLQTu5xG72EhET3S3kwqZsmYbgy4MduGKv9VGFbv75Wr17Vo9K4Lz6QK" + + "vQIDAQABo1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQ" + + "YDVR0OBAoECEc4b3BP059HMBMGA1UdIwQMMAqACOKivuoK4sGWMA0GCSqGSIb3DQEBBQUA" + + "A4GBADj73jXpPLev5crwZIoXCJd/nXXp1fJzEEbByWggsR9cFHN4wnp7N6gpIxQbLQwjmo" + + "cLPC1pHQ3A5VHVrCbxAk6nifmSvnKFWHTBftZGpfTGkrXbURFF64T/CB4O+JXr1eBUGheN" + + "Q0T8L17UNgi3oBENKjASWnpjxvD2QrOnH0rb"; + public readonly string[] TEST_16_DATA = new string[] + { + Intermediate_Certificate_CP_04_04_crt, + Intermediate_CRL_CP_04_04_crl, + End_Certificate_CP_04_04_crt + }; + + /* + * test17 + * + */ + public const string Intermediate_Certificate_CP_04_05_crt = + "MIIClzCCAgCgAwIBAgIBITANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOICBDQTEtQ1AuMDQuMDUwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBsWmrcKH0J9bkI3zHthZ0S3904f3fMUSasY5qp" + + "7CSQ0sbXTwP947sfAPK4Dso6Bpwl0WExRCdFHd6qfY9wR+NtfuI/DkFEY8WveoqM4Vskpi" + + "cutWghCx14PiPY5YGFn8VvXu7wbuHp4TnHtUCMEUt3EfYO5oqm+/I8y0eTKMNHAgMBAAGj" + + "YzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBYGA1UdIAQPMA0wCwYJYI" + + "ZIAWUDATABMBEGA1UdDgQKBAjOoKlp+BfGqTATBgNVHSMEDDAKgAirmuv5wudUjzANBgkq" + + "hkiG9w0BAQUFAAOBgQDLhQ/RJFqMDNRonAHZ30DYyphf8do4q6ARikhhXSSa6G2G/PzbpS" + + "x3T+3G8ot+NnFhtf9ZWo7KfwmFEbUA/B/X2vJaJbNImkMDT1aTY5sPXtA69B3QKQVz7HST" + + "f5XH6DjuoV0/m1M153A4vf1Z783dOPw1MzOq19t+6tYFeELEHQ=="; + public const string Intermediate_CRL_CP_04_05_crl = + "MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNV" + + "BAMTDiAgQ0ExLUNQLjA0LjA1Fw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMDBaoCMwIT" + + "AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAjOoKlp+BfGqTANBgkqhkiG9w0BAQUFAAOBgQAp" + + "6gLCdPQw7Hisnr1i3QbD7GybqfD6b1s10GQ3c/j59RYDe1Fk47Srs9ol/baleasWjcdt8M" + + "SlTc66KvK9YPFAqIdYoOW4FidpJBF/1cvSc2hGYwVsxLnXKr9CJ5Py5vBCCjovIRiLdzoL" + + "ZoteOKFIEHkV7V8V2OTFawxpW9hkiA=="; + public const string End_Certificate_CP_04_05_crt = + "MIICiDCCAfGgAwIBAgIBIjANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FzAVBgNVBAMTDkNBMS1DUC4wNC4wNSAgMB4XDTk4MDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" + + "EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" + + "CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wNC4wNTCBnz" + + "ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwZsiUhXiFHN9dfJb0Yyy+rYtV8gx+d0+8WkW" + + "5C68nQgSqqk2uSTpvZbx0bpHF+s+LKppj2M2tt/AfZgVQHTsp5rO0IftZE2iLwqejj0rYU" + + "Poprq1PE3vVhs818ZlDS0PTUP97YxLysQjq2jS/d/9lF5pS3sMlP4Usp24gXX0vG0CAwEA" + + "AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" + + "QKBAjpC0ZvCXrvBTATBgNVHSMEDDAKgAjOoKlp+BfGqTANBgkqhkiG9w0BAQUFAAOBgQB7" + + "YwJWcx+PU1sUZUOVleoB5amHFu0GT+Hy7cRa82UJMHFkz0bmnyEV8CBNcnn0xa5iVfwe2y" + + "5ZKwy61DLR3MPTar9eKITL67uZag9w+1tnIf594XRbEiUzn20uxuDFX3oPoZCemtWdVanj" + + "2T+9TVQKfrp15+qzOCObNNRHZw29EA=="; + public readonly string[] TEST_17_DATA = new string[] + { + Intermediate_Certificate_CP_04_05_crt, + Intermediate_CRL_CP_04_05_crl, + End_Certificate_CP_04_05_crt + }; + + /* + * test18 + * + */ + public const string Intermediate_Certificate_CP_04_06_crt = + "MIIClTCCAf6gAwIBAgIBIzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjA2MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQD0t0dfe82Su58bJdn4dh7E3OCam1AUPTzPnt7DwT2w" + + "1XwD76OCUYP7SBBjsLYDDfUCb2ek96pSK4jpzyE6/4IOtfObe7OW+iBT9YAB5WeW+SmvEO" + + "TIX+xo13sbz6rG6j9svcOxtth98yv7mxzV/ZwTNBSO72CcfDXIIq20TVunlwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI0AufZEn1f9AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAbfhxuNBYizxfMZNcyiN61j+7LXZZo3SmMU21UmOhPBTmdTbIkuVCI+" + + "F1jSWdu3eGShVNJ3jmkidDvojMm+E8ZZ1YGHYfgeG16dDQudaGUjGmOfYzzlkFmsaf0paG" + + "4y4sBerPsZCmhN7BanGh3qYPFvadSmp3OapGfEmDtS+BbVQ="; + public const string Intermediate_CRL_CP_04_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wNC4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI0AufZEn1f9AwDQYJKoZIhvcNAQEFBQADgYEAIAI7" + + "W6K69twJZnHx6CoIMs5+P9DrJ2yKHptmntlOCTSJirC/xdj0Zv2k5FW84VrTtdCSZDT1Ce" + + "4Dh69fT2sUUexJb/4IcDtzloiuASSJzKWCeVIj9A8e6+coNUJVKtRKRX8bHJ5Un7xpFrY6" + + "t1hdxt8gUecAAdXEFGuZ3QEHHN0="; + public const string End_Certificate_CP_04_06_crt = + "MIIChjCCAe+gAwIBAgIBJDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPdS5zLiBHT1ZFUk5NRU5UMQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1RFU1RJTkcx" + + "FTATBgNVBAMTDGNhMS1DUC4wNC4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDYwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKq8rAPXsu1RVm3vT7od7CDLn8k/C3x3wvfzoWrm" + + "W0cmlhp9xRy5a3HWiJATD8yCKY1psBgnrOpv37sdtUX4P2kf668HrYOaGo365fKPeT5Wjm" + + "gp0pL3sXKNNsCuJPd3wKAXGHAi1R9arZFYPsKJlfQl1774dwAvzxSOMr5+pbnzAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QI33MEYdo5YX4wEwYDVR0jBAwwCoAI0AufZEn1f9AwDQYJKoZIhvcNAQEFBQADgYEAo8Ge" + + "ADBoJFEIRzdO37uasuyIBhClTUgyFhEKemMBN6aelYeiJMX6FZIL3DgZOce4dg7Zg3Ak/w" + + "B5m8XlGQLW9xIbpEzY/Iq9kr+qK6k9YmvtcOiHFbnudCFNZngTQZpxjiDaj4eA48uqKIxs" + + "51taC5gOv9LYWPnugN8TsUUFZ1s="; + public readonly string[] TEST_18_DATA = new string[] + { + Intermediate_Certificate_CP_04_06_crt, + Intermediate_CRL_CP_04_06_crl, + End_Certificate_CP_04_06_crt + }; + + /* + * test19 + * + */ + public const string Intermediate_Certificate_CP_05_01_crt = + "MIIClTCCAf6gAwIBAgIBJTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA1LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCshocJtyGsxeEd2ouVTVKp+HuhDjnDk9eXtaLQIKaB" + + "7aTODHYbq1mC+1LO5DmRV5PBVd8NuuCA+1DmzFrfYl+nMCjjgOkC0//Gf9O85Hi/n21q0T" + + "F+oVa1j9fc7nAgLIziexaXrflYSbaeNWkwHHftGUninKPuNGM2re0krEeurQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIaUi/P20o4LcwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAWBLeJl4qlAPKxmBM5QZ2JYsbCV3VBeYGAKQ+4L7ehS63VQMCwIjBCI" + + "LaHGIFfCqecDNd6cpYIArdx4tY7X2/Zxm3j5ocngpI1Tv8zydQcFeraILglsHf2UZUuK/N" + + "6jKGjwL68C8YwmA+u6ZhcQFD2Xg4wSMC/xxzAs9zEAQGBPo="; + public const string End_Certificate_CP_05_01_crt = + "MIIChjCCAe+gAwIBAgIBJjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wNS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDUuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO9ODA12Fky/Md5AELkaOvOwB31UlfZq3SHAOvs0" + + "Y4NYoA7Q5KDIwW8RNzMSKD30z51VlgOAaBVR6HLo6rkcWB4wGiV7EPelewdSOdk72IrnYR" + + "npJEm2KEuLkHB+gejgk+paw8CejxMsrvT6loN8Pz0btBKxWaCfknTIyXVyQsolAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QI5LtSKs/inGMwEwYDVR0jBAwwCoAIaUi/P20o4LcwDQYJKoZIhvcNAQEFBQADgYEAOMrC" + + "38uzHckKMkiawXhPUHtDQfyR7bLweS2qro7GyndfxPpeMJwjzVxqvQBtMuHON+al8jyXpy" + + "BsEryV6qvdFC1vczLzJHAJZmLe5np27zQIXOObsyYcOG+aPq727/pKoD90DAlBvrxNW0ox" + + "x7citflEYpmOEv9Do5xiO3MuCFw="; + public readonly string[] TEST_19_DATA = new string[] + { + Intermediate_Certificate_CP_05_01_crt, + End_Certificate_CP_05_01_crt + }; + + /* + * test20 + * + */ + public const string Intermediate_Certificate_CP_06_01_crt = + "MIIClTCCAf6gAwIBAgIBJzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDI4MXZB08BfUHxo//4Re7Ax0qWkHgy6nb+/XaLQ2Fw" + + "Pbvpb5mkhLhqDZBSX3KQL0YiJ8p81tmdvRQH/LbFzX/3OKBTUfV5imYy979A2NEb4otFp6" + + "EDSskZhttY3d2IzUICoCWUXhObnmkHJ2jEc81bggFkK5Lir1m/tKq2IOPFJQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQICIAmlz6+Cc0wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEA0ZvIG2cnk32p6uxqGw8Bu40NrfHu9gNkJL5MhDHJXA6OxU5BX5bWZp" + + "LnKXLoHiqSdtEdmy5cLZw3kggxndxjsnRFMyCawaYupJBhlgquFbuvBtA8rMtkc5H4zudP" + + "ZcOcvXu7Xw58K+1caSGURL+A6uXFPnMUBd1+k+ejbtO8Pto="; + public const string Intermediate_CRL_CP_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJKoZIhvcNAQEFBQADgYEAbkJe" + + "jfc1rztCbtC6xJZ3iZEDDMW2CxFvOvSwhmCjPqVY3lrCPNSQzdjmqepioCnu7ongP+HAA7" + + "hM7bm+SoN7KzXKufQ7C2ONoAwvoPZgnoidg7RVECxUByD6AJu04yd2wCLYRpCfS2tDtXLh" + + "HEDpe+ELwv35pbkCMlCO2u7J+Tc="; + public const string End_Certificate_CP_06_01_crt = + "MIIChjCCAe+gAwIBAgIBKDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDYuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOh7lUwMRet7t/ABI6mo27CsnRzQ64Xx7f1dqxrJ" + + "NuuSRslVShaWnwiGHjc+5/TS7Urfj9VO0dseBCzPsyYFoIX1q7Q5zlArwy24qpXTGMmlpE" + + "GByzi7jkXO8w5+wqh3+8RFrQQzr71zLtAVV/qPUyleuF8M8jzkwfPvawunmwdLAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIayC0PPU9zyswEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJKoZIhvcNAQEFBQADgYEAPz7b" + + "UvaEV7Myjhe8LJO/soj84X71rvVPtBPrhYjWTJ6p69GCfJRyho3vAUIt8RFal1GFb72c45" + + "DQGkcVzLLJw8cDP3ajtWac5HZ9dNPJkW+Kh12l9gqjn061XAjQ4XnbbwQDYCuXhguPE9v3" + + "kzDbimwVwIEOB/4SARX37y7TUWk="; + public readonly string[] TEST_20_DATA = new string[] + { + Intermediate_Certificate_CP_06_01_crt, + Intermediate_CRL_CP_06_01_crl, + End_Certificate_CP_06_01_crt + }; + + /* + * test21 + * + */ + public const string Intermediate_Certificate_CP_06_02_crt = + "MIIClTCCAf6gAwIBAgIBKTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC/IejV3DmeaLW8OwMfAGyr5+8NOxM1C+UBYslbOfWj" + + "KUGdhlX6TxFc5AOJVJBpS/QjeA+RWoUCxnxKb9QSlOrBmADrcnGz8zV0/c0JDLaU3oSgsV" + + "EWZE0SexBVWrKcl1j7wN0RuxMeAp342/YoyvBwea3VeqJkmSCc7Y2TjruWEQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIaHxWOdHsLbUwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAuzeq/lqp0qs62krK6EA81Silhy42l/KmynE3mVu9GPBgQS0BUDi7+r" + + "QQ+m0UxYElzj2SNO4J5aBYeC98lVJFCHX7QE8yVOoPBQd5rA+rrz4HD9QoP7glxTqLU6Tc" + + "9VFd+iaFpqsVtSh2bxH2BtUB2ARgebTklaNl5VPbu0+yc2I="; + public const string Intermediate_CRL_CP_06_02_crl = + "MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1DUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAiMCACAS" + + "oXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEwCgYDVR0UBAMCAQEwEwYDVR0j" + + "BAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQADgYEAYGaAzVoUdlSZ3uGKiRPfHAFIoK" + + "T79hNOvtOxaGA0aIek9OypDrDqYAh/s2jsXSheL0pr/v9WRIHvtCt7ytXDxVyn4Nxjpfv7" + + "BkAMMiccdUx1OH1VElTRkmmtMe7ROzUeHUGzXJNPex1Bc9BvSChH18bWYckyOZdYJBjctC" + + "KJFgw="; + public const string End_Certificate_CP_06_02_crt = + "MIIChjCCAe+gAwIBAgIBKjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1DUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDYuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK4D9H8JxeIrFuOmx0cSkIYNS0p7cDSBlcc57Na3" + + "+1k7lJD7mE9ZP6/47YsDVK2bwe4aTKCTXtPk/kGQ6bsLswJXbyW4k4+f5LeAYoXgbmZXjA" + + "WF+BKIl8uKetsqC3HkCeqhBaY1AGUqef4oOAkakEP+1jYFumNYtMaB+9x/0ncBAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIC9MiJNI71RMwEwYDVR0jBAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQADgYEAo/ib" + + "mIxteityjZlszjCc/s7yM/0snL78pYpMOZ3P2TPKkYh2Th4+Bw8JqX10+M/zwFBj5Bw7Im" + + "zCIRfS3GFuKmcVcyHB4OZLMcQZtXWA8GOZ94YvWq5TBINlVtThQtusQj15KBq2TJNNFUyD" + + "pBdvyo05AnEsRY0HbIQu6ZhNQ40="; + public readonly string[] TEST_21_DATA = new string[] + { + Intermediate_Certificate_CP_06_02_crt, + Intermediate_CRL_CP_06_02_crl, + End_Certificate_CP_06_02_crt + }; + + /* + * test22 + * + */ + public const string Intermediate_Certificate_IC_01_01_crt = + "MIIChDCCAe2gAwIBAgIBKzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAxLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDDOu1J/VIzbB4VcS2Dwf2fsHOmIj3iatM8y61V7CrN" + + "RCxCWTJ1Os8e/mFWOi/zN+0afizA0UzJDTe8L++/RlP68IFg5Ju2OhXqQC3HbUZmQ7ve9g" + + "QdWTfur3oEJV6/XoVE4WG0Ic7D1p7BENb3LUT+8MJdSboTvAggA1CiOI6zRQIDAQABo1Iw" + + "UDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBAoECP" + + "RyRiSV+4XrMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBAJlmJ9EW" + + "9ujUosqHZyZkniu2vX8VOL52OnxtLxw3LqxLyuxivjyYCaMAaJNr7/xfm3C2ozh9mQyZTQ" + + "6TpBapLFUH8QsEKUhy57MDUgIvZsyOvvjJh3AXfSkXDaMZ3ncLg6x0wwjN/Hxu9i+IhX1W" + + "1E7/5foGx7AEVfwY7Fo9S82d"; + public const string Intermediate_CRL_IC_01_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9HJGJJX7heswDQYJKoZIhvcNAQEFBQADgYEAV4DM" + + "F5gU8MZ6E/mnjAWS+dIRKUBJV1GZJ+hOysdbmK1hD0mj5Pd5qTzlcvLjuatIoIsB5DCpYd" + + "AcNRLVvF5EJFhVjqsPzRlfUZth0Xqa+U/DeHjVxHxYsLEOSt+v2bLkbGh88SmOAk6F8xj1" + + "l7YIfPX5cIkUBTVZlsUt51slMXc="; + public const string End_Certificate_IC_01_01_crt = + "MIIChjCCAe+gAwIBAgIBLDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wMS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDEuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPrk1fosBu0hemIKgTDCeV/RoFbbsm02X4LfZonX" + + "KeGRGYZXz4tpWgbNpjKBq1e/2bOO1DCn9I8I2kjvZdOkabk4MLeuRDo/sqlNndu4Ar5502" + + "pAo4A2V0QLR4IDHAJoDpxtSFrqELOiiyCx9O9V19ywe5pcBFrxVEWDqTnBUeDJAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIbI6BhABrmQ8wEwYDVR0jBAwwCoAI9HJGJJX7heswDQYJKoZIhvcNAQEFBQADgYEAYzYy" + + "M0wbzNhZftAWz7TfFi64uA9WmTmd4MeK9vga4ChswT4H1zlaV1Sr+3hqpGmOoP5AUd9XIq" + + "O/ui+/gFaeuOLI+ATmK+V2KHGAneMwzcw9qbXRc+xZqGGjbXMb3Bowe3qrj3mhyowfa1n7" + + "x5xB7XEOqO6sfWxLdDjLVo4sn88="; + public readonly string[] TEST_22_DATA = new string[] + { + Intermediate_Certificate_IC_01_01_crt, + Intermediate_CRL_IC_01_01_crl, + End_Certificate_IC_01_01_crt + }; + + /* + * test23 + * + */ + public const string Intermediate_Certificate_IC_02_01_crt = + "MIICkjCCAfugAwIBAgIBLTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDemJgZnOzXOwNGqRA3Xq9aMrAWQU4oFuhSELsEYfLZ" + + "GO3ntBjJLqCn+rs3FjR9N94cu63TduOAgqlXqrNbvyO1+SF9m35JXreqn/OS6KrK6c8W2I" + + "pDAWJcr89nGyyCXMoJeaOOtj8m2NjZblmCZvtAl5UMOew73GE7Z5fE+jtA2wIDAQABo2Aw" + + "XjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQIhT9GjaaHj68wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEAWhKJUujLapxpz/DoD/w48HMzkL6UQCxQPOAjwwHicX8wFcKmcrWLVBdVC3" + + "0+ywrzMraWhaq+QCOqsgtxCwTZrfUxbCNqhKS0lZijCMgNN4Jht+PAZ22tzEsw7nCwiMM2" + + "n1jeKF/3btoDEUvZn9SuzhkIyxy7Q8l2tbNOsANqpxE="; + public const string Intermediate_CRL_IC_02_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhT9GjaaHj68wDQYJKoZIhvcNAQEFBQADgYEAJsjf" + + "oS3F1KMpcVBOC1Z6P5N20TYLCCHG6KETlBA3Rjf8ehNxJKJW0lGd7qHpVHp4BGvkSfaOAa" + + "OrC0G59wjDEY+Ci4QS46OYzBcHXMFX5HF2xMq+y5SfQnyV6MQUVVkxJRjgsTLrYwP2JaYm" + + "BK/zExhqQgPfgcR+56swBPXqogo="; + public const string End_Certificate_IC_02_01_crt = + "MIIChjCCAe+gAwIBAgIBLjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wMi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANbTVeAxOibAO3KGqxxY3VqKXDr9tKJN+igpKb4w" + + "goR0ZnWGDusSVm4pvneZ9qfmi8A0sM0E91+B2hAwsU6Y9RoA7nPsTkFYi5F+hHGIF46Op6" + + "8blGrZraGf9bsWXCZFoLoxcgltwjGPQqyZ5mnnm8cxUbtaWmgo28MK1yBH/sS5AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QI3gkBNo/SISMwEwYDVR0jBAwwCoAIhT9GjaaHj68wDQYJKoZIhvcNAQEFBQADgYEAQGl1" + + "7uT2xxYDks6HolrQIpesIoPqEiZ8TkizEBuLG3sUKsC7klHwy2iyVvA6nRUDwf/XzDLpGW" + + "/Gn0KTW6ZYIX6snOC1+7HX5OJglQx8tDpDvcAgyocK8PvCrHfu9o33J49aSeLAVpoCHwne" + + "tTtJxVfTMmjYWKeDbHHHi8a2YTI="; + public readonly string[] TEST_23_DATA = new string[] + { + Intermediate_Certificate_IC_02_01_crt, + Intermediate_CRL_IC_02_01_crl, + End_Certificate_IC_02_01_crt + }; + + /* + * test24 + * + */ + public const string Intermediate_Certificate_IC_02_02_crt = + "MIIClTCCAf6gAwIBAgIBLzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDoeA32BPwgq8pLJoR/tbOSjHtAz6fmzvzJrhJMvl64" + + "ccVuIzGxzOneYsO/ZYWy3ZGtlCoMZJRnS83tw0ikU9vQUwBw7DEcfRlLKYkY68rp25N1V5" + + "JEjnlHw+RvubdGkonWzUNJFbY1GA24J3no2GZHiLPgWmGb1jsA8Ag32MUrCQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIKx4Ybzu2PaYwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAotGeNFzmktvcxpCRcpuARHkv1lW+LegvbDBnSPvGnr1+Cn9rZcuLup" + + "u8ex6VJ7KWtgWBtzdOelerO6ytfWQ67uNpTOuc0SDdk/f3tCagdx44LBVQywuq/Kj57ZuN" + + "jpe4J8UPZSBFFK+P3gTX3S/lIKsDi6xjRnqFLSQYGX2XiIE="; + public const string Intermediate_CRL_IC_02_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wMi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIKx4Ybzu2PaYwDQYJKoZIhvcNAQEFBQADgYEAOfuX" + + "wRv4skbPZAbOH/LVXdc/cA7vCSTAnWecN3ZKm/eCsxbyRxqn7fcDyHmqg5H3Ac5UOlMHR4" + + "FMe0Dp+Yu4Xg8xg3zRvE/3M/5jyRILGGi7olh4ikkOMD+UlreysvYvUX2MVP1iM9qAkXh8" + + "E8n/LZIlABN2GGkFEMRMJA6KTXg="; + public const string End_Certificate_IC_02_02_crt = + "MIIChjCCAe+gAwIBAgIBMDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wMi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKogqWGx9EpJ/0G7ORopyIQ4IZXYKKTE48WqOJbu" + + "nLD3txGjMUb5Xefl/QyTfd6J758ddGzPiKs1zWO6riffJLIBoOFDmt8tchPBJuIM3gKgXe" + + "VcZMyF5mebm5/GZekMOjbs8P/zbLdrlu1D9CZWZMXONYitdluSg2moMGbewS2NAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIP8N7OmNGshEwEwYDVR0jBAwwCoAIKx4Ybzu2PaYwDQYJKoZIhvcNAQEFBQADgYEAwkpF" + + "j6Kv+OcKrUtOgnH9QddB0Ej0oU6B5/5Hhhf3liAPKtllDHnhUj6nqfh4APNq/iqYFOkKMR" + + "RUZoaj6kakJNSOlgvRIiQfuFIgv3CqLZnhr85YFRnKgoluZE1pq3TvunoiKyJbCjbmyCos" + + "Rd32gVcJq024xvY2eVBTl6tfn5A="; + public readonly string[] TEST_24_DATA = new string[] + { + Intermediate_Certificate_IC_02_02_crt, + Intermediate_CRL_IC_02_02_crl, + End_Certificate_IC_02_02_crt + }; + + /* + * test25 + * + */ + public const string Intermediate_Certificate_IC_02_03_crt = + "MIICjzCCAfigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC7LFt+yGItQFqSEPi03ICIr5ydWnFPQHZdEMNu2tRU" + + "3XiOpfam1wl0xgAPGBkQK768OfidpP/i1hgYOU/isOB5dyALscvIQ9XJG1OWQXBBLgKuCb" + + "MS5fuDhBNa4KiFuGMbJ3/UjluRsD9qaXwGUavc436JwbRHvW8FomaBYYY1hQIDAQABo10w" + + "WzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAT" + + "ARBgNVHQ4ECgQIPsBg9tMABhAwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEF" + + "BQADgYEANZcayTTX+FGhtRUJ+XuYA7jR14CJL6qTHPvdSMgHNw9mGXI/7sO5I4v1vayOCI" + + "YQ9luBvrTYlMPmuej8+bhM8YTYpiiOjVFANwvSKArI9U2CAGBcoBMXydykkm8qYw4gtYQT" + + "neiOz7VqI9plLWA111IRMgayD3CAt4Ntpzd1VSE="; + public const string Intermediate_CRL_IC_02_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wMi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIPsBg9tMABhAwDQYJKoZIhvcNAQEFBQADgYEAVeQi" + + "tT1FRUaJlhfpkfjZr6VHmvGnqYapdo4DRT/pm8tsp1LbZZXpYW638ztwgZNgeBRPFlcb+x" + + "8naQjEkoaYzLbCYfdY+PPVDv7ym15PE48Kve8ImvANY0YnTGS8pcKdK1dpNKBnYYMOG9JN" + + "+H5K/4cSm/WMCKIuKdsiAWFYauE="; + public const string End_Certificate_IC_02_03_crt = + "MIIChjCCAe+gAwIBAgIBMjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wMi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALGbo9yEujZ9RFU+Vmxb5+Rx1VdIG/3E/5hXV/xI" + + "OFu4mEfYh2tBhP2qIMH2KbrR1tiW5t4DvTCBM3NKKqp75wpiuu7E3q6imt1pLbGW13NVL+" + + "81gYWXnCnzHpxYjMTIqqCkPIAeOG+SBJ1MgERbL+NBl+AK3WG4TeQ8vw7r2CGrAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIS/HbII+ki/kwEwYDVR0jBAwwCoAIPsBg9tMABhAwDQYJKoZIhvcNAQEFBQADgYEAWHy4" + + "sHrTkqY1XjDBY5XpNEyhP6htcnjYD9bos4wjxPlJUyxdIWACWrLDE+R5iRCOYsh/nDAJEt" + + "CUcVASukvP6VLJaFjyxUOaCp6JCVV+txk7Fh0S/Ur3Zyysfp5LllP1plOA3N/k1Hliljp0" + + "+bnSiDhA1+3hJh0gDMjWUdRq9yM="; + public readonly string[] TEST_25_DATA = new string[] + { + Intermediate_Certificate_IC_02_03_crt, + Intermediate_CRL_IC_02_03_crl, + End_Certificate_IC_02_03_crt + }; + + /* + * test26 + * + */ + public const string Intermediate_Certificate_IC_02_04_crt = + "MIICkjCCAfugAwIBAgIBMzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDf5u5ouGQlQmdNfc4ell3RXKWmtq+ar9VKMme3kp8D" + + "cbDbUaVwlvhWTkOKxb9I208wfGG2nQiArezIwutlASf7sWo16EPapmGdCF+rp1dpjAPBUu" + + "fruEyCZ8nu2ITD52wuPY9OAcKHQE2/bBpCJWkw97fYX6Q9PPW5uobWoUJtOwIDAQABo2Aw" + + "XjAMBgNVHRMEBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQIjDm8K5YcGakwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEAEQIJeZj/HE3HvjjJV7PdU+2Ze8OeCYeeWDocxrA647xpeOksVXBXKmq2OV" + + "NqoFk7YNtlSUqiS2TlqjGqLtKYetk7a17qS/8EIQct+H5KWdvkLkYMkfIAAMJvJZHPGxEv" + + "j+oVPAi9FITRbFdN8Jvdo9MAuU2q8d2x8MF236RmEds="; + public const string Intermediate_CRL_IC_02_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wMi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIjDm8K5YcGakwDQYJKoZIhvcNAQEFBQADgYEAV5bX" + + "7WsT8sWeA0iQ7V/+ZQESDzvyHA7Ziju0iRsvTL7qOVF/Nl5v+zND+ZNPhdJDKEM/Q0lEaA" + + "ybe0E73NMmM1qRX1daAwE++jHukF9TMeNl750HJaS667H6jcjeRrHUJDD0+AgqrZY52dL6" + + "CPM3V4QSvdfc1/xtKmNIZWSSoqY="; + public const string End_Certificate_IC_02_04_crt = + "MIIChjCCAe+gAwIBAgIBNDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wMi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDQwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMW45d5dPrzUJbuRIDeQ5gIJRYxi80PxPvxSmJe8" + + "ScG1A+l75SAtgLGWAxBqxPSzL+teBBUsnmf2Xsc8/qQHHev74uat0lxq9YrZ3npLW2YNo2" + + "CfxLK0M7F1/bhkHK2f9ttIvOrrKI67BeEjfACULdJEhl431uWINWV0pY+fHq+pAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QII61NnUvgvjYwEwYDVR0jBAwwCoAIjDm8K5YcGakwDQYJKoZIhvcNAQEFBQADgYEAjwgL" + + "6qMnnqUvNspsDaYpPQzTCqXkqshZhsy5G/nLk621H/YbNGlnZ6asHGljYVYMzjmcny16y6" + + "ntiv9QPB7YorAx27WT7pQPFla96s+nM/rfwWHPWI6QGDsquPriwJm/MwQC+1oDXEFKvdIL" + + "0urejfd5hgiXYbRRwMI7km97iHg="; + public readonly string[] TEST_26_DATA = new string[] + { + Intermediate_Certificate_IC_02_04_crt, + Intermediate_CRL_IC_02_04_crl, + End_Certificate_IC_02_04_crt + }; + + /* + * test27 + * + */ + public const string Intermediate_Certificate_IC_04_01_crt = + "MIICjzCCAfigAwIBAgIBNTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA0LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDBtNwpr9LZBF2LRtAp9Tb1FZnfM3b/Jv2sdO5zc/Bk" + + "sO4ByUgY+Mux9dEvFrkVWBK110TvXn+dj+85TuboILv4MDKlu+tI/rtuadXGwwDIg8TQnz" + + "uyC7LWhxM5JZs1/Is+sPKUY4PTCHs3+EHPBWf2tFiP3l6ZftkySEiL6+2LSQIDAQABo10w" + + "WzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAT" + + "ARBgNVHQ4ECgQIbMuZ73onuZswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEF" + + "BQADgYEAhaTSc2xafdP/QceMm9YJ/rZJ5gTgBR/SlmKQwd2BclHabG+Fozdg4delDjtRXS" + + "FKY3sFWBFZHVeprh4T93Oj6IVA5X4DIuUeBpprtS+psCnWZxdtcUWmbyYQwZNCifG5C5D0" + + "lRwxlMlv40xT2oCM1zPZpfmqemBDUPJ2OhkCjvo="; + public const string Intermediate_CRL_IC_04_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIbMuZ73onuZswDQYJKoZIhvcNAQEFBQADgYEAMk6D" + + "Rztz1AyFnFr1KAlbjLLwxtQplf2eIc//zUkDFVUHtX5TrEC/ijUaItjdkOoPGQfpnL0w8x" + + "wyqWndMh593QPCqIJTtv/iACoiJNZ90ZJS0adcdZ+AEmQpa0Zv0e1JOqRrPoAfTq4HrOfR" + + "vhBwhvKQNtTExupW/EBudznKC6Q="; + public const string End_Certificate_IC_04_01_crt = + "MIIChjCCAe+gAwIBAgIBNjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNC4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDQuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2dGkraKGdIi6EXxAu6/ekMqDloX5YSVBGh4Hp2" + + "faujr1u4j8Lp8afqjngRxFUpTqGbqH0ETgm4cVPXmc9rUvUzYTMdxTUmIZ+iW+ULZEvzNB" + + "712kxRPCD2kDFN2fH2ai8miXr434w+weLm8VQN4jJGo4nswhSs2w1gsUmWyn/ZAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QITsLx/sO1edwwEwYDVR0jBAwwCoAIbMuZ73onuZswDQYJKoZIhvcNAQEFBQADgYEAeKft" + + "0RM8/b3zQodaKrTdWiFyLg5fzoOsTecSfdFPXoqz9J5ejLVkvJevSmfXJrIUhKXySzsQi+" + + "GazuTh/hvWjwUTIvmupi+EiFudnMpXCro8bgi48+NkepNjXvjsSmOfzlrK3SxtpH5dqonL" + + "6LHjGyg+Xp0Nor1m5g1rLHyrcEk="; + public readonly string[] TEST_27_DATA = new string[] + { + Intermediate_Certificate_IC_04_01_crt, + Intermediate_CRL_IC_04_01_crl, + End_Certificate_IC_04_01_crt + }; + + /* + * test28 + * + */ + public const string Intermediate_Certificate_IC_05_01_crt = + "MIIClTCCAf6gAwIBAgIBNzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDM3aWmgX3OzAaBg6lnWjpFQ9ufeTOia3+lIUqn+Ypf" + + "5OH/s9dLRqg1ZynV3YIUyzaJPP/YlUEmrhheJn3Bjw25bHeIKdge73pfEbuBAugbUMS75D" + + "csBV7Ze9D+sVw8w/LtT3ZPcvM3Vju4d+c14Ip/8pC15jlgQPhwVQSf0x3V2QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBAjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIJ2DFtxoQnXkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEASvdcfBOh2d1dC10pGLZLI3T+oSPCup/U9riynIR3RxZsIaS/+Q2s81" + + "oeg++WQV6pyYvCLneZIp0efvqh5DThNV9lhBcJjlYwm/T8Hi2IaRGsSMwIvzrFN7zxA/zu" + + "tW98wigAKM2myk/nlYxmholgbQkQ7ZxYM3lD1TDRl69N66Q="; + public const string Intermediate_CRL_IC_05_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJ2DFtxoQnXkwDQYJKoZIhvcNAQEFBQADgYEAK7Ym" + + "Y9PjX5CpVewe2E9PNxj3dLYElghaQyapYoVtNq3jDqLMWspdmHdNdeaQoXsjlSJe0Zy8xH" + + "ZvpimwifnFZ5hq4yByzHjzNMpcA2yFtg2MtPWGEia+BmaZYZi3X0lR+OShKpNLFc4CfVM/" + + "aWG6W2BulHjIAThZhTg3uRekDzs="; + public const string End_Certificate_IC_05_01_crt = + "MIIChjCCAe+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALlcUtceuxDznvI3pVM7YddPcBOrNvrOtpuLOa1L" + + "Lj9LeNH6+8CzRZnMsUtt+bRGqCKMEJLUIIstWwGg4SskXWk2m+nDKm5Ai6Kyx4nldpgtgQ" + + "xZSEwNcwRhpy7TtmLkxDVM9DoTbIbK0dZ7aWw4bXVHPK/lnOMtOaJbFDq0sLfxAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIiXgrRBVcDf0wEwYDVR0jBAwwCoAIJ2DFtxoQnXkwDQYJKoZIhvcNAQEFBQADgYEAhyO6" + + "SP6brWDDKZwdQGULno4Om5+DuilJKamyEcvSqE666z1KhvOCdLicqwVa6tQiAL6akrt5Kv" + + "R+TT0xqHR4JGosGLGolvK4DLrMeD+PRK7m1a+nJl44luo5Mn48HrKI7jn7n8Lp9bNdCHvr" + + "NHaQksCIR/Q8xoucPa+8sCTVSj4="; + public readonly string[] TEST_28_DATA = new string[] + { + Intermediate_Certificate_IC_05_01_crt, + Intermediate_CRL_IC_05_01_crl, + End_Certificate_IC_05_01_crt + }; + + /* + * test29 + * + */ + public const string Intermediate_Certificate_IC_05_02_crt = + "MIICkjCCAfugAwIBAgIBOTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCrtIYqo2Is8Cd6Ld+fyWC755oA6hQiiruooaR/6O4z" + + "ikyhOUztnHkOGMF5H4CKWafwwVrfFtqe7iop3N6AToEIpNlJLVy3cj14A/IASVYSSNFeHd" + + "O44Id1NWhPiKx3paPTWslMEdKQV9BlXb7gu8pQpvqTa/38hNQ9vdil/4QZbQIDAQABo2Aw" + + "XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBAjAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQI9P78RavuWW8wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEA0sAEmWBYSazUav6RtuNFtZgNrlQ2i5i138VzRHoF/kq/CxeR/lINQqgJhC" + + "ZlUnlslUuM86g8OQGlR8SS0Wsi0MdCQCtPCKA2hStlTx9MMux2IZAGoyHy6P95UE9qINHE" + + "fYZUYjO9rh96fzNyJ5Oy2kJdJWdhFXtSh3BSOe0ZD+Y="; + public const string Intermediate_CRL_IC_05_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9P78RavuWW8wDQYJKoZIhvcNAQEFBQADgYEAlPLh" + + "+CMqRcbLgUKEAL2UlSY5tjsF8At0hf000kec93TnBf7f1NKYVJ5eyeoh/WK4s+k4paAA5E" + + "/P2C8JMlGXNTrqKZXMy2zIlufE1ymXAZCKLOLC5ezXRSpwIsBWxko2nfw8Bz/mZO/bCSCT" + + "nDwkH8BJIbFV51vJFlyyOmZnCz4="; + public const string End_Certificate_IC_05_02_crt = + "MIIChjCCAe+gAwIBAgIBOjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPsWBfT8HqaiLnoUCPAFniq502odL4uVqzOOxkx" + + "evZtjh7NaFlRjuYjTofdkj/IAgg7lkkBEW3auK47Td3TvqnHO401PqvOFNTlbhr5wDLmXS" + + "WWcR6XrvgYL3Z3wx15/z6eojcSgu07kdvKqzuLzcDs+noG8lbcruokX0A186pVAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QImgomUTkzwbEwEwYDVR0jBAwwCoAI9P78RavuWW8wDQYJKoZIhvcNAQEFBQADgYEATAEq" + + "YVV0iYdYomPqxbTapSCJFAMQO/WZhN9brCXP88+jRfk6cAHzTodQOYTOAVe8YXa904505e" + + "RA11NNTViP3s/AseGWuqbWjsom9mbR+tVkvufGqPQtm1JhfLgR/68e29AI7tj7zIJyFVYD" + + "nLRXGwMGnosqSHDle+WYyfok6a8="; + public readonly string[] TEST_29_DATA = new string[] + { + Intermediate_Certificate_IC_05_02_crt, + Intermediate_CRL_IC_05_02_crl, + End_Certificate_IC_05_02_crt + }; + + /* + * test30 + * + */ + public const string Intermediate_Certificate_IC_05_03_crt = + "MIICkjCCAfugAwIBAgIBOzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCajRjoRNL9HFTytLLx7C8WYouW0uONGsrtGS5tKMiW" + + "oLlQUkohqB2a2PhA1InNGQqnbDtNdqKbR1k6EzD6MyegvXK1sXs0ZE8gt0LZYio7Xp3k+Q" + + "7i4Rk5iTruAUrV8bFMYmeIXHXL/9rl5LQV8YRp/Ut3Bg3VECzfhQG4EavMlwIDAQABo2Aw" + + "XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQI9041oiwvHsgwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEAYwGYwLsA/kxYZG/RM+kvoH+mUebrBVZRBxjovYsYzNznD26fssjBFfiTmg" + + "zwZJfG7MZRsgDSRsS+bxuTlXMVeGRKH8fVj7PNq05sS18QZQOF0CCKzg9DLkCzkzkEWBxc" + + "5ersciPrL90UarOIPIJWUxQ/5sdMS/wZtYTU34rNNWE="; + public const string Intermediate_CRL_IC_05_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9041oiwvHsgwDQYJKoZIhvcNAQEFBQADgYEAJHTp" + + "k+RRsD0dUv59J1GQMWjQTjVz39Xaonx2sk38WHcrHBB78L0W6Skjvt082PwZg32sb7FQBt" + + "boAQ3PIKpXMnFnkjnkyaFihrnMdfa0abCPtQhFl3yra+w+1a2RDjQBZOOdq3xlFcLi9unT" + + "YYome7eS93wchIvNWFpgwF5A5XY="; + public const string End_Certificate_IC_05_03_crt = + "MIIChjCCAe+gAwIBAgIBPDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYxdSZq7qRBdPOz6H+l0GGAtymAWTshfZZCubHK" + + "lQjbVq98qudORfhCOZgOy83j/mo2KAecBhxaxB9YA5ggWNAgaKtFvknvjFemtBCZwt6cVK" + + "8LCyUGKzStwAV1+HSDlHxdWo7pRwP0beXFvFECrX418osGt6E/v7Cz++ZtvaDhAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIgTuCLfTVa+QwEwYDVR0jBAwwCoAI9041oiwvHsgwDQYJKoZIhvcNAQEFBQADgYEAQRuC" + + "rAx9zzu9QwOq9weNit9PNgFHBpo3Gh9jPVYGJjOQxeSqqou503xi82H3W30FT/3ESCO7IF" + + "hfpr/uQZVEmUQnvDsVwbKvED1QF9qkTp6ILk38ITJJgfb+sdSL3bsUeNqVXd0C9wzVoErc" + + "OuoCulwkZzfoIOlO2YAjAnR1nUc="; + public readonly string[] TEST_30_DATA = new string[] + { + Intermediate_Certificate_IC_05_03_crt, + Intermediate_CRL_IC_05_03_crl, + End_Certificate_IC_05_03_crt + }; + + /* + * test31 + * + */ + public const string Intermediate_Certificate_IC_06_01_crt = + "MIIClTCCAf6gAwIBAgIBPTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDmutL9PY/BLXvXMEDQLQnWE7dCOsrLNvJiuSjDdznF" + + "vBz6WS/RqUr9zsDFknpOWB3Epo2syV4ZFto+v4VWNo61uaClIEsw5x1y0saG19px34KVpQ" + + "wkpvLeRZySdCydKdE1rptYR/JbHvPo5TU4mxOo6L7JeEwAvjSI4tK4rwJ4MwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI1BB9j6Jyny4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAajWMbY8zL8jS2VUjCPBMuIjUvBfy55+92EXg5pZnyNNwN1diZfJFiB" + + "rrPWEg3Fa4NMLgaDKWZsYkOcDDo8I+Qb9FsU9LphCzQ1ubIEuxu6KPX9X29BscFOxUnZCz" + + "yuzVfadACxi5Y7Bz5pN5LfC/jEb2iXjkdN5Rm8AqT81syIo="; + public const string Intermediate_CRL_IC_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI1BB9j6Jyny4wDQYJKoZIhvcNAQEFBQADgYEAxH4/" + + "mgACT847PyufmF1nob9TSqBj+cM5ye2bgv83gTVd3B1Gopr75Tnu4iP10d0PpSXjySWCjB" + + "0HPJ7BdxzkKxSrcM5vcb/jLdk9PqMUS30ohexsx1xK+E38pDJdLX4kbJ3E62AgyXm9WQlD" + + "9xsDk7TMXwuxHT4fX070HL6lWGI="; + public const string End_Certificate_IC_06_01_crt = + "MIIChjCCAe+gAwIBAgIBPjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO1VOl25MTf068LOgzmQOmyh8MXunBrQ4t6UYuEj" + + "H7v+owR9JTDXpfzLPcYfkR+BH2jjISSHIJsUDesKVhpmhABNXcOI5tiRNkeDlV2zKCBXKC" + + "wFi5qkhrE8FUCP0hL8YzbybOrYZYSVEP8GgIgMSQcTvhN/Tor0o1jdJvRLmevXAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIFJA9XGd9UZUwEwYDVR0jBAwwCoAI1BB9j6Jyny4wDQYJKoZIhvcNAQEFBQADgYEApRQC" + + "OTU9cp16BHM2n0TdZThgj9kSAQ4wHk/dKNOjYNEWu6n/GQ0alxy1dyRzpsr058FOvft23Z" + + "Kp0YhdKG/7F1hkcoNvC2yN+Re44n7S+F/jcEPTWnOX6h1Nkw8OS7Uz2fZ8t61iHjqjX4sv" + + "M/cKP+AkC8g7p2tfdkP1fQ6ww5E="; + public readonly string[] TEST_31_DATA = new string[] + { + Intermediate_Certificate_IC_06_01_crt, + Intermediate_CRL_IC_06_01_crl, + End_Certificate_IC_06_01_crt + }; + + /* + * test32 + * + */ + public const string Intermediate_Certificate_IC_06_02_crt = + "MIICkjCCAfugAwIBAgIBPzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC0JoTnPaI/HT2eAqCW1204nRNjcA8EQSp87tvHLpWy" + + "5aafmxeJxvk5V9Ba7Ye8eY8yX9losbNUpHJFNdE46fD5qp/oS7Cn3NXA0dwIDQEn1X9vaz" + + "nqtZtMjt1S/yGv2xDOb2LKT9zRrqSvxGszCHFUBcJ4HDFJMAdhXPUZiLyXVQIDAQABo2Aw" + + "XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwICBDAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQI7j2LO1CcsE4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEAfXIh0oYlM2pagAWzTuYqTl0NavtfqibPgolvhgIG/XmmjswHOg/JVCLb7O" + + "jIYtEG2MAD0xQXwu0mc9Deufed2embP/wc0qVG7rj7lxUq6p0aMQJNndBw4m9KlSnjdzyG" + + "lwE9pNd2BgEeD516J2k7dspCZHDw3qLer4i2JYoCo2Y="; + public const string Intermediate_CRL_IC_06_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI7j2LO1CcsE4wDQYJKoZIhvcNAQEFBQADgYEAJej7" + + "23qVtwkcvCTPb6afTosYMnVppPXWbtvqn0N5mAFHQfE27x1YPOXOQHBrpQuTyiUdUmPXiH" + + "xMKbuR5o2lfdQgew9hbYVk6GegSu+DBC1JKv2YSTgzgRAlJfyByDZ7mbJwZWHVHys08oGk" + + "adG6zstavg5EkEeRuAp47T+7cZc="; + public const string End_Certificate_IC_06_02_crt = + "MIIChjCCAe+gAwIBAgIBQDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkIzl9+NRTZf/xaA8noiHRt65Zo6Zp57YvCKUe+" + + "YfoC8koMq12MBgrc0IyIfJoqEDEMfD1WbitZdGZMQZ7D9BP2Bk09NXLEAAuj+waFhYk0bW" + + "vHBH90O7HpMGmxwHmzOjDV3JHYsU8hq77/5gRFDNRkSCJe2A1Maj8Gcqi6tYf5AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIYDfThEjNL28wEwYDVR0jBAwwCoAI7j2LO1CcsE4wDQYJKoZIhvcNAQEFBQADgYEAJiHT" + + "CjLGZK5Lyw+7ICDHs3eS1OGJH/wfsLcBP5sLER41qJfrXGTl2XdKvBMIpriUmJYzjkjof4" + + "bvS/VPDNlhI9AJadicW8LM4L3qpy7/YV4Dd/C/BJphJ6cZcT+hjaRKeC7gQVjMeC/npu/p" + + "jLgIgzf7HC4WYnaS3h9oYl0cMJk="; + public readonly string[] TEST_32_DATA = new string[] + { + Intermediate_Certificate_IC_06_02_crt, + Intermediate_CRL_IC_06_02_crl, + End_Certificate_IC_06_02_crt + }; + + /* + * test33 + * + */ + public const string Intermediate_Certificate_IC_06_03_crt = + "MIICkjCCAfugAwIBAgIBQTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCuUtIYFbVjg8VLLUqIEQ6r7hjTaqYVs8DJnJPHUWPA" + + "JW9HEIV+d6hj/so76Bff4KJRX7MgoXbvq4ivmn8656N7YSGk9GPuJ25SXK7RJyoqzG/x2R" + + "AVUCx/wG99VXVDZhd5ZAVBG2JCkHImsWAei6/Tz8UgXmmLBM8rZNJ/hNtTBwIDAQABo2Aw" + + "XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" + + "EwATARBgNVHQ4ECgQIpwUlwG1W+sMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" + + "AQEFBQADgYEAqJhUfgar10fl5qG+oH34s/JS3ku0dRm4cTQvqUNOWA9ALnBhSkmOpoMMzH" + + "sE9FXXcZ072a8/ecpviP04X5mt5QSLreh3hPVvgWv1LiZ9YkS4Z2kcr+3Gx7zj4gQgT5vG" + + "QPpbIBAtBRH5xNHIYQsk6kOe2+t7b0Q82Wnj8UoznmQ="; + public const string Intermediate_CRL_IC_06_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1JQy4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIpwUlwG1W+sMwDQYJKoZIhvcNAQEFBQADgYEAKCp7" + + "ViY1cajXpbjCIqe8yo/98SQRIxoTNgp7EUaaV17FeHZ59nJhRtsF1XnLP4cK0lPBkKFhHK" + + "2XyDEWx2hK3X7Z3lSAtn12WFJHOP5T5i0DmYfMJYAFbuPD0JQEWCM3aYsgbXKbbFH1BURh" + + "L/uy3arVBP4FaJB8gH678K4J1p4="; + public const string End_Certificate_IC_06_03_crt = + "MIIChjCCAe+gAwIBAgIBQjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1JQy4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZw+GpvdleGlmdqZ/zEO2DUGhwgrsselBUNnEzR" + + "bcuzr5O1WwiG6aLjrPxIXeL1wLS1/u9AD9p3CQU0XFhi+bEI9+LLnt2y3707O+AQxy1PnQ" + + "6qmYE4jMwqDGHn8WVanN2joFT3isLH5wJD0Jh74eoG0tqCHUyOiXaZNo78qgB3AgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIJOeyCnvfJtAwEwYDVR0jBAwwCoAIpwUlwG1W+sMwDQYJKoZIhvcNAQEFBQADgYEAJbz1" + + "RipbW6uu7B+f2Ol1iq4AVOUuET2S9vi9ojReyAIka3q1XUceZCm5Et0KqpOoOLiu8IRuNB" + + "bvKwRcZ4hcVEXv5bRMqaPEK2B0VrRAV/Llj5A+RGn6yc1ZdkJeBRhoSsaHn5whfICaiJX6" + + "j3lMpo/CiMRViL+gZLU3SdKqvdY="; + public readonly string[] TEST_33_DATA = new string[] + { + Intermediate_Certificate_IC_06_03_crt, + Intermediate_CRL_IC_06_03_crl, + End_Certificate_IC_06_03_crt + }; + + /* + * test34 + * + */ + + public const string Intermediate_Certificate_PP_01_01_crt = + "MIIClTCCAf6gAwIBAgIBQzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDRkBhJJVgOXHjydAHAnokd/XfEiW+bnWd2ZPJrMBmP" + + "7TlvVpxOGqLd6lGdbelbSyAzut1i8lyYn9NSDR0PcyehCSS+MsKS2uNKsTEuH3mlMK/7C5" + + "B1qggKqE8f7opyl9+U+Qyi1WQj01gY6XYXaCxksCB0Oqx2737d7QWMvl15dQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIO1U69B4DBHQwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAcHWV4Q4z7C+IC4bWgIf1+BzkszCN+LSb4JquR7GgICESbwF2JzR+xL" + + "7yoKvB/NBcCqtMY4Hi1DHACbIGJwRe68vVHzz4CmYEK50UUCbAtiAiy9Od6wwrTyFyacBd" + + "CBjiO6mkFEp6jOsoIgXRfxK4kDNcMkGUUwMbSR/wZKFuImc="; + public const string Intermediate_CRL_PP_01_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIO1U69B4DBHQwDQYJKoZIhvcNAQEFBQADgYEAHtbX" + + "MUofQlCnbJhgLQw96jsBRu0Kdx/Rk4LWxEbZQOWNaD7aukASjEv63d1qZIDgpefuUNTz5s" + + "3eascdtI6iyWFtBO3r6tihtkkSbxocN2Rz7OlR4rW9VwuUirxP0145nMd5CEL03/CNABP5" + + "zUo1bNgswHW3z/RaH6h0j0yTkbo="; + public const string End_Certificate_PP_01_01_crt = + "MIIChjCCAe+gAwIBAgIBRDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALQaTS1wvv551g3BP9JYBMM+KXXLzxtOwPlO5NR4" + + "LwuJJB2WuO4vmbn8AG35in/0JqwjZeroLQvbCPxZseXsyA0+7cMO0qcjRJ5l5WdFsahT6g" + + "z1YW8pYYY5i2eDUkIRsM7roHMiNjt3zpkuUGX0xZQfAxhuWnRIvlGg5J4r7UOdAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIeyLSANVaTpQwEwYDVR0jBAwwCoAIO1U69B4DBHQwDQYJKoZIhvcNAQEFBQADgYEAvZ4a" + + "SQMNl+Q++D9yVaGr+37XJyxs4yow5e5YM9LXn1qBASQ+GNfqPWoe2cPCPYKj32yulxyFEu" + + "RHrbhpEQe+nrKWJgO9W1bmfwgQDin29ne/JCQPlznhd3EPFvCkmPLnTyJmSLR6B2VxvndM" + + "GO8JEbj3KCf51uf3VnC/Qj11mX8="; + public readonly string[] TEST_34_DATA = new string[] + { + Intermediate_Certificate_PP_01_01_crt, + Intermediate_CRL_PP_01_01_crl, + End_Certificate_PP_01_01_crt + }; + + /* + * test35 + * + */ + + public const string Intermediate_Certificate_PP_01_02_crt = + "MIICfTCCAeagAwIBAgIBRTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCkQQXRO+dnU2v7EbaqQNmfPD8v0s5Wa50hl9M1Gfr5" + + "5nuVUZs/RI//1VksTNrW10MVh11nsxpA/XRPntEIbHiH1OoECd4dnZBiA/2xEueM02fTjj" + + "fb/t7g+pr9dSU/TzCVZDVWFBcPn4VNz7BBqIrTAOXaJkyBZ8hh7vyiE1Y2VQIDAQABo0sw" + + "STAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHQ4ECgQIoTKVlZ8YCR" + + "AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEADhtnd6ifr6kyfC5D" + + "UWuAXLtoccMj8Jaur/1YT1DgnH1XbBsEeZwm9Jkzr1a3cXPIHgaHYgXvBeGUtZ3XhbCSGp" + + "8U6clJz3lm3qKPKkb5rdDrpdTaPnEJJjS3C4ZK1L7UZtQga2Enlelm5vIkhjsF3Sexe1kY" + + "mzqiLZZ8yLxJ/Tg="; + public const string Intermediate_CRL_PP_01_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoTKVlZ8YCRAwDQYJKoZIhvcNAQEFBQADgYEAn94u" + + "sT8ZYNzfHIdnx0+fV0jglL0Kn1duz+ehKHow+RGqH+J9opMYuXVD+rVQnLdZl5LbFBcv+5" + + "TSP9WR9QtyoXar4/jmY2FFdBjfgO9w7p7OHD4WxblJmfPVOvrzFm/slZE39Oe5Qn4KlS03" + + "9tttEFTKDH3qREQbT6g4k4ExxYM="; + public const string End_Certificate_PP_01_02_crt = + "MIICbjCCAdegAwIBAgIBRjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANBwkwTWdZ977UAx6CCpXc9T4MX9T3/Tt6LbtY9I" + + "eXxI9W15eXm/aqrKiXhULB+oF9/qNeUi2fAtrURZ7hgHbTaswr8CZ3Uwc6Rbkyj2GGiM6Z" + + "8sKFztYZfFyGBiNEwfTT0yaUUQ6etIFqPuL/6qLvqXmvNPxFb9gjTH/azs/MdNAgMBAAGj" + + "OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIW1/BRCbe3c0wEwYDVR0jBAwwCoAIoT" + + "KVlZ8YCRAwDQYJKoZIhvcNAQEFBQADgYEAPJg24q7wCU8CVlxFLchoe7txhkzApkVMIJ9G" + + "+QTnraHDn0CZS6undCsJw8mrTNBQPHFn2Ixa5lrPfJvwW4Med1bcJKbwR4TveL1WeYYq6+" + + "9k1kS/7KmqyKAKC/s504jAc7qgMd4b08oLxbGVfFVjWG/ZMbO770FrsyRHHs2rTOU="; + public readonly string[] TEST_35_DATA = new string[] + { + Intermediate_Certificate_PP_01_02_crt, + Intermediate_CRL_PP_01_02_crl, + End_Certificate_PP_01_02_crt + }; + + /* + * test36 + * + */ + + public const string Intermediate_Certificate_1_PP_01_03_crt = + "MIIClTCCAf6gAwIBAgIBRzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDL/XgMvoeszcAzZqMYnv1At5u83Gb/CEX3fv6O1jL4" + + "W3XbdvBNIZpuTwQhTH4Iofk9rIuQdkR7xOmbk4AqZINuas3Y1CPdzss7teraK0CNralNl1" + + "jPYK+ClDBHt32Iw3bAl7RqWX73hl3YH6/7cvG4XCo1HqeeFFHUGa7HXGXq9QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQITMu5Qbn1Cm4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAuCnzXbHg87PIYYRbCCiXKDKA3MOcEKuxpNaSbtm12DQWpnvzmaK5nB" + + "D/Ebko97CS7u9Tpwa7TmTyi39bYzY0dmVaotCDzfSTpzw6qHZl/w8riS+cKr0mimnjW1cq" + + "kGPyHf0zBBqh0liGbd7EOLIBln0ASrn8V+G4Tj0Q6aQVcko="; + public const string Intermediate_Certificate_2_PP_01_03_crt = + "MIIClTCCAf6gAwIBAgIBSDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCu1Fq+gBJsBf5EjKKtNIxgdtgPMObby7tKH7fTJxYE" + + "5LPyPi/IiWQ5Mi/8BCG3zmQhu9ZdBbpal350qCGVTbaMlnpi98D4WwXSw7e8oHIJIK689p" + + "Q6Z5cf8hgwPnwDpYLeEaqxwhd4bu0x1lG1fUISA0ZZIQaEeNSJfdh15IkAswIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQILRhQwULcyPYwEwYDVR0jBAwwCoAITMu5Qbn1Cm4wDQYJKoZI" + + "hvcNAQEFBQADgYEAlEVOqXcdeTU7wT0l+/BJhlG5iaAcanAsOaJFZsXPjLMSjhldQe11/z" + + "BsrrqjcpdctcmBarKO4MnwqVU9DN2RZ/v5Gps6OcPxj3T8wlrCGe4l6s9d1FncBMJ0RAUe" + + "QEn2JLkQW5JWRBQ00+RXJYFuIM6Ger2MipWj1oOciv9MMoc="; + public const string Intermediate_CRL_1_PP_01_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAITMu5Qbn1Cm4wDQYJKoZIhvcNAQEFBQADgYEAycux" + + "rzvy2IiYfFkTw7QgGuBhxIQPbSIbfudqyUumuviHJkIMZpPwYj2wltjyiRaozrDAWq8mlc" + + "PsFYNr2lUYN5Cj4BhNQCNZlyBw7LLdzRgza55zVjmYkHWedyZm3kPWe7Y0w8xc/XIvi3iC" + + "qlwV+X85cgHNJarx3GEYdb7Yos4="; + public const string Intermediate_CRL_2_PP_01_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAILRhQwULcyPYwDQYJKoZIhvcNAQEFBQADgYEAbcjU" + + "+8l6pSik8PcuIzWndAg/w8uRfAgR5W9hPSXZChlx7uM+48wK98DGEXuTkJcbeclZia+Mpi" + + "J5u3qG1zhoL1aHr+RqyJrjiWKC4/rDBuiUk/ftU54mrYn0qev3aSjf/GLtpcC8kC3gpqD+" + + "20bvxLjBG3Vc9ZrxDvzfj8cD9K4="; + public const string End_Certificate_PP_01_03_crt = + "MIIChjCCAe+gAwIBAgIBSTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMO0l0+X6jfT8cY4DumtseTryyIJ7h+nraogXmYo" + + "uhFGvMUWEAZVGD4x9QTTVEL/UCqNfzpI//Pp/uZpDudSgOX0ZdAbykObqCAEO85msK+eie" + + "8baS1cW1XGjCuWDqNZko3Uo3c5lLPlRMbZ3hjvA1zmYh3prYnOh032GZAArVcVAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIMh2aWvtm0mgwEwYDVR0jBAwwCoAILRhQwULcyPYwDQYJKoZIhvcNAQEFBQADgYEAigVE" + + "FlCgbgKLR9FWIiwnz1bZ0MKsfhytllCI+jGx0Q3o3CxCGXs9PvL6BPDdMOxNIT/oU2uG64" + + "EhZEjcZCnUknGx9OkkSSVq44P/pGuUx1g4Kx4i8gsJ/UPrPpYv/3heuMcKWCr92l33cxPT" + + "IU+kmAtqy0MBvBKL4p635+MSIVA="; + public readonly string[] TEST_36_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_03_crt, + Intermediate_Certificate_2_PP_01_03_crt, + Intermediate_CRL_1_PP_01_03_crl, + Intermediate_CRL_2_PP_01_03_crl, + End_Certificate_PP_01_03_crt + }; + + /* + * test37 + * + */ + + public const string Intermediate_Certificate_1_PP_01_04_crt = + "MIIClTCCAf6gAwIBAgIBSjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC9gxMP8j4L+ISffY9wkislQ/V5sO9LzZOncYK93lZf" + + "HXJG1MPSQzFPNzDLSc2zsilA03v6q+zr4NRrRWwWGmB34NGM4aqkoxox/7ngTn0MIq5gZ2" + + "eOx0FbjA9W9DHEceVDS6kgs9lFcN2W+muCG2/fGqQUED9Fzl9JSM/tE8XAKwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIgdUt9H4i6kwwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAxPe0vM0BvormJLF5HxkyFcTtoombfDGANoLoyj+PTWRD6z1/AcAx5K" + + "rn/0J1sZo13M2ezaZUABbbpNH9X0OS225IJF4mXNpfkYhsz/+jNPGjRpN2p0K+DhMSawUw" + + "QfGv2x6f31k6WCdy/769i1mwKP6Rpph2nkRyYW8MwO0N5HU="; + public const string Intermediate_Certificate_2_PP_01_04_crt = + "MIIClTCCAf6gAwIBAgIBSzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC7YCtN67S/ItOzaSGqTvfEE483HoQGiQZ0ob3+0beK" + + "kmbSGADBQVBKe/sLJEKddyV2Gl8S4x+cKaKBWUI8lMZViJwWqVnyAFd8ZiAB/BpXaKKgP5" + + "pFsg10Yo/EtsxGlLSTLurst0azNnFv7ca5Hb8te3T91eaI6y59IjbsRgilSQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIGazrt+QRNCkwEwYDVR0jBAwwCoAIgdUt9H4i6kwwDQYJKoZI" + + "hvcNAQEFBQADgYEAUIz/MSc6K5eaIAg8skaAgm6rSPvcU/711b9G0qsIs6YqvEz4zhGi5X" + + "nalYYXfaSQzomuRuABNvuR1Ydaw/B9OdPMro0DhX8VpY6NzCL5Qj60/I4is5a+Hzgk82ck" + + "eAC3okPHbVMd7R9kdFsWNE3Capnv7rriqXO3vwFw8b9vXD4="; + public const string Intermediate_CRL_1_PP_01_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIgdUt9H4i6kwwDQYJKoZIhvcNAQEFBQADgYEAkR24" + + "ebKfvEhDA0C7sawukQbv/q8mjSS3CrhA/oqeb8bML1IlW8rjHSXuRU/n3oeyAZuxLCAQMU" + + "TPG6Vq4dOu8XC1RY74xIm8ps4mE0xB8/nI5kadHUSDPtUZhNzc8tv+z7fUGRaVGL7CBEpq" + + "ICyQKYytCwxyf4xu2Ip71Uy2tuo="; + public const string Intermediate_CRL_2_PP_01_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIGazrt+QRNCkwDQYJKoZIhvcNAQEFBQADgYEAjpUo" + + "XSj0HX7Wm4w1FiRBBazInGOhSQX9VP2GcGb5lfr3GKt75Y+C+C9qd5X25DVkA4M1gPBK+u" + + "XjSMQoHAmFJychQG23rcGcuDJlzRMyfvPCF9dOGLFdmkuHSo5hQUyYsxnXV8cWLIkR1AUz" + + "PtUbTJL9g98R/OJFsCBiPi+By6w="; + public const string End_Certificate_PP_01_04_crt = + "MIIChjCCAe+gAwIBAgIBTDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDQwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOtf65MaydWM3bmMT8tAGCX8gZkx1JlgQyBlJT67" + + "2APIkfmKRFK/dBtSwwCVGHZG4JYBrrwMpzUPrkGKYI6ZVIvvPnPfadZns9i5SM5LZFS+a5" + + "JfbRnSJd8dXhZsKHxqkxIWwG6+VgnRKXE/Uc4m8TePQJZEOra5ezna5yhvqUwPAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAjARBgNVHQ4ECg" + + "QI4iNoMjKiXMkwEwYDVR0jBAwwCoAIGazrt+QRNCkwDQYJKoZIhvcNAQEFBQADgYEAmOjp" + + "2EupE1AmgjGfiGK1fk9kf39yQXK1EDsyO6KLdWL/bmWeYi/G7ZE57/+yVVADJuHI8xVIDZ" + + "LAC0u5p35OLgbcmmA5bs52KWJJfa0nbgGpVaUSMg9SkEGS997OsgExWMvYhdFIKXlq4Rwc" + + "ca89Hg1GlXdrpfD2OCDNBvcWB5Y="; + public readonly string[] TEST_37_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_04_crt, + Intermediate_Certificate_2_PP_01_04_crt, + Intermediate_CRL_1_PP_01_04_crl, + Intermediate_CRL_2_PP_01_04_crl, + End_Certificate_PP_01_04_crt + }; + + /* + * test38 + * + */ + + public const string Intermediate_Certificate_1_PP_01_05_crt = + "MIIClTCCAf6gAwIBAgIBTTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDFzEEzV/yUEORIOufyqpZzKpYz5aPyBbcDf8AMMCM5" + + "tEz7j39cf1f227cbrTcAaUfYFwkrb07RU4bTS2X+U2Ak7Q5OROz5rrZBbsfwF3yHhwHxCg" + + "KLjbwz7D+OJdNfv7x2HRckwfMUkmP4cEuJIIPwj1ieBbsnUi9dkWZePwl80QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIjsCjmszYCHMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAWMUBdOdHMB/SV5kPUk+zut9g/1v/GyxyB60mq9jGqjrIsk4a9JRqa5" + + "MWju+6kVfSLelAOCR24EQsXnZM/5Qqg3Wb/SFJXWDcBnfWQWgh8UmJfmPhD7jViG5QVIxn" + + "iALNCYtz373L+IDECLMO6S3wcTPsHdYv14jl6BKtabwIpE4="; + public const string Intermediate_Certificate_2_PP_01_05_crt = + "MIIClTCCAf6gAwIBAgIBTjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCZzdj+ixWCuxJGMjcoHUwSNqI9Wt9gYwXUTl+dWg/E" + + "lg2SPJP7lrBOibAhSmaTorhunUSEf2adhdxhuGrd5Ucp6G0oZAa6ZDWaID4rKYWsI7d5kv" + + "mrUhDEEdzk2s4PCoPiQm4dKwRg2rIvA5Dv+W1ldqSVSG376zVrQ5xdjDUX5QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQIUASviIKBmJgwEwYDVR0jBAwwCoAIjsCjmszYCHMwDQYJKoZI" + + "hvcNAQEFBQADgYEAa3c+0Drcq7iWP7K+gE6Mz/0ATQoiG87irXWfWBUGWtYnsh6K+1THMl" + + "ibmZjYhsztK1P5rm6qL6HAyw0PhrRE9imqZ16cgiMomh65BWQImOeiXx9YWIPvjXWsE6iV" + + "E31XShr9b9OZBA2+Zpydc3ID/SQzy9PiTAfL5yJiW/JZvFw="; + public const string Intermediate_CRL_1_PP_01_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIjsCjmszYCHMwDQYJKoZIhvcNAQEFBQADgYEAZIzN" + + "pXT89MplQgcXcA/K7YKlf62QCbw3rE+bUQiumJMlNGiVdaNJ8T66ObyoOWE+s+KN/Oetlu" + + "HglQ7r6RG68gHYtZZiO6kmxq+wor65dFGQyRggpD+D47yioEgR12wUUksL/8oBW1pfGW2B" + + "dR4sNWjzV5k5EWbLYu7wxj2/ubo="; + public const string Intermediate_CRL_2_PP_01_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUASviIKBmJgwDQYJKoZIhvcNAQEFBQADgYEAlZ06" + + "h2L/89GvCtU1K1VtbHPMN/LAUYJrWFID1Eo+Cf/5wKEGBr8hxRtvshTK436zqVQRQN/XTq" + + "7u0SLxvIixNRErlmUlGByi5vumN2OA77SxOyqYLCnBXTd5tWbFGz/udjaNk1MxOK0MQxPV" + + "9R+HHUUVojRnAIQvlcqx/sMzU5o="; + public const string End_Certificate_PP_01_05_crt = + "MIIChjCCAe+gAwIBAgIBTzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDUwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALyBn2GKvoKNHcu3AEJRCbWOyUpCc/onvRoQgWRr" + + "wE7vMI7vjqnoR8mXdWDW5u9DFu9V5pb/yHBWn1zpgFGNnLrqn8irwR9i6Q+qlu4lXL5WSr" + + "DqBqEKxrOBDPgkVz8Ldjt/Hy57qEukBarvpAwTc4XEJPAmxNrboMeGCEn2UShbAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIaV3Cd/83r08wEwYDVR0jBAwwCoAIUASviIKBmJgwDQYJKoZIhvcNAQEFBQADgYEAVJXz" + + "gooT1qd6rdehnLxJMf1HZ6JuqpyoQjzWF1jA3SkJmBDMXvAkMmIcQ7r5CZHaVF0iMQl5JW" + + "fxPtM9Bws6jZhVL0TkwJHmbnSvbzUkJYeXPCP7ags4bu5I32co1nFVF6wf3aQDZeLFj/TU" + + "1GCQ4rh80T5oknuazD4xXAYx9sE="; + public readonly string[] TEST_38_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_05_crt, + Intermediate_Certificate_2_PP_01_05_crt, + Intermediate_CRL_1_PP_01_05_crl, + Intermediate_CRL_2_PP_01_05_crl, + End_Certificate_PP_01_05_crt + }; + + /* + * test39 + * + */ + + public const string Intermediate_Certificate_1_PP_01_06_crt = + "MIICvjCCAiegAwIBAgIBUDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA2MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCjeJAwaZ0cw6O76hu15XadwJiTsIJcXZxGAETq8H9p" + + "VJs7kJh57oLpO/lG8zG89QS9g1ozxaaGDWsSyXsDzv1eqDVZg3ISQu6XcKdDu8EwgQDY3S" + + "EGkJ2AidFue3l0kEwR9+rtsuVKd/P+ULF1hWcoyLB/sQD5z8GvIiDKyRBiFwIDAQABo4GL" + + "MIGIMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMD0GA1UdIAQ2MDQwCwYJYI" + + "ZIAWUDATABMAsGCWCGSAFlAwEwAjALBglghkgBZQMBMAMwCwYJYIZIAWUDATAEMBEGA1Ud" + + "DgQKBAh9i6tKUsPTgTATBgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQ" + + "B/Gxsb5lxSTN21CrjBp2aE+U1oTP2MpIFWUD1q8KWhZZF1iCQ7orcDVITqJPdPxDu1YwKk" + + "zOegc4YBSJzHZqF/W4Kw4wisMfnWLTsUAeP/Ucz4vXk5rsf7IRssFG6PLxVmtRZizoxl9a" + + "DO9abTM/jV8Mgi1IB6LdWgmtosBGBzbQ=="; + public const string Intermediate_Certificate_2_PP_01_06_crt = + "MIICrzCCAhigAwIBAgIBUTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA2MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC8DbqYUf437toWlRkOQA5PloqYQjWYpiR67yGSjQHp" + + "j/HlduTYFS4qfUbLCjH4qsNUH8yQDvogImQw5M1IQOsUAqO6mYFxjqUWccuOaHT6XfUaOs" + + "DDHr/tQUvhz3LJryaILiPlNcQF8QiYpujM1utVRyFpmUrMAlOvWUB93c/xUQIDAQABo30w" + + "ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAgQxGVMTJml1TAT" + + "BgNVHSMEDDAKgAh9i6tKUsPTgTANBgkqhkiG9w0BAQUFAAOBgQALJtPqY5uROJ+2QYTekn" + + "fSUc0gC7j3/cngIvxGT385xDLTrd6TjYSi+12+vU7RNd3MIZoz1o7RpWQV6C751WtOFuZi" + + "iXeQ758aLqfhjYSVW/NHkO8vjrAMUzUbgjqb03k7q5JgtT6udB+9ySmou2/RxYW5p/IT17" + + "euMVGmQb/RFg=="; + public const string Intermediate_Certificate_3_PP_01_06_crt = + "MIICojCCAgugAwIBAgIBUjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA2MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCsQqIx0ayxpIE8NduclvK1ubbNkXyvr0RDqnGOoyTj" + + "yMtnfnwRbclkFCNBdalZYofuTWP0reqvqGqsBj+RS3uazvDBqVmn0J0AGRiLILummgEFRJ" + + "ow8IB1hduDYJpDMrHRpfXpbG2H3fzN1XeX/B0hUZgdQ86GyK2qrmyIcyqZXwIDAQABo3Aw" + + "bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECNKJMmEWCA+jMBMGA1UdIwQMMAqACBDE" + + "ZUxMmaXVMA0GCSqGSIb3DQEBBQUAA4GBAKv9F3+Y4N8RX4bRZ4fFTKri2rrB4BsVrBFpOr" + + "SLzKnuyO1O5gg45d70pSHUAVBn3pz0f/6WwWLECq9tB7/Fphi0TyqeFmkRnysygZGlvLgs" + + "L19bpIgVPkjFFziMGuzdAFIGy8vnV19yJ2euMygEHr20yiGBUaHHnKyuOGbDg4i7"; + public const string Intermediate_CRL_1_PP_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIfYurSlLD04EwDQYJKoZIhvcNAQEFBQADgYEARL4u" + + "DZvfcQDYanTfwU/hWAJDdDO7m7oQZLy3o0PTqXkk2Jd2v3+M2U8UN2PcuqZXT1lwS/piiW" + + "Sc1x1YndD0qUtV4bOZ9SESPhCeOc1lQTk5mMf/zqFxQqYv8rfDB5O3QY4bjS7QQzSsvmal" + + "TGCnoHmUJ4skmZJrQAzYnXyD9G4="; + public const string Intermediate_CRL_2_PP_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIEMRlTEyZpdUwDQYJKoZIhvcNAQEFBQADgYEAcEyr" + + "sgLhVq0L6N5fww/U6TW4lqaVAEtjqxluWRyZnL3AJLEHfwh1lllCG5dNM5fahGDOW/53fV" + + "+gW5l92bsi2D/lAkDfNUdQdi5ZpQG9y2zhTArUlx9z1+KXklCi2Gg1X22gi+cYbK2hfzk6" + + "kNGP1v42bjrkF/ECczpy3e41rEg="; + public const string Intermediate_CRL_3_PP_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI0okyYRYID6MwDQYJKoZIhvcNAQEFBQADgYEAp3uQ" + + "Tn2HC65TFmSjzvjuStIJwJcVahNcTWiGdtfTalZrMtuC9vUgQq0K1QIa7QNC9C3hQlzb5e" + + "bO7JhJDs+5GZnnsqHN3pvdKEoueRfWBjUGpPnSGFD61ysf9aDFY2j9Amf3zcBFsXZs4+DM" + + "dIENndbjkwqCV4zRTajAqCsIy20="; + public const string End_Certificate_PP_01_06_crt = + "MIIClTCCAf6gAwIBAgIBUzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA2MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC+IxiNJMOQG2gx1xd9ELNuzs9LrVJVRLvgP0lpWrx2" + + "2HTEXPDB6YmrEg/YgyptmQ5Z4K6CEgJz3EdDOarCSGcL7DmcSEwEw46MV3piS5DrHwQ4GH" + + "a2/ENSh3lF+6dliBwbQR2necmQ5g8ekqkWNb65pLl6RCNGkntJpdu8w5GWbwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIMf/eRyakKwgwEwYDVR0jBAwwCoAI0okyYRYID6MwDQYJKoZI" + + "hvcNAQEFBQADgYEADgpHRDgyPuK4dc+m2p0IELHUAK3qsdTZzBXsaA0rkkk1aRjI6DQ2qg" + + "b4crRU3spQgYwBC7KQYd/hp8Lk17iX6fdV/9wol0DxTGhamOJA0uRl768awRArf4cEUElF" + + "uWPN8D3wJEfL6BWgReUJWg8V9HEtdvXZZgzFN/CgHRkQ2RM="; + public readonly string[] TEST_39_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_06_crt, + Intermediate_Certificate_2_PP_01_06_crt, + Intermediate_Certificate_3_PP_01_06_crt, + Intermediate_CRL_1_PP_01_06_crl, + Intermediate_CRL_2_PP_01_06_crl, + Intermediate_CRL_3_PP_01_06_crl, + End_Certificate_PP_01_06_crt + }; + + /* + * test40 + * + */ + + public const string Intermediate_Certificate_1_PP_01_07_crt = + "MIICrzCCAhigAwIBAgIBVDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA3MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDs3Z/FfgJOyKp+Ds8xiQBM053cWylYbD+g+zuWDz3d" + + "nD0eF77TLPITL7hwI058Pn3tXHlveuKMFqbvzWUgFXaBoHmmRohIj1eqfJQhlmKLjlSYyC" + + "N4xhLVi7vg71ZjFdRk1k8ME1HDfpb2WXqXh9LyRYY8b/aqL+NHe1PUDbT6FQIDAQABo30w" + + "ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAgvehPxsTfSBDAT" + + "BgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQBpdMBEONGcpFitMN1ihf" + + "W441E4HVTQwtF+h56aagVFndUF1gQsVEdDNmvvN/jdlzXotcfdEj1lOahmcwWbPOlNx3PB" + + "LUPAcaNM9SCrXWi1gKJK3gXC2OAxj0mT5XhfPlAdfhZXTBZLqMqebmk6kVwa+VyPPZFHGy" + + "BW0fV2ClJ69Q=="; + public const string Intermediate_Certificate_2_PP_01_07_crt = + "MIICojCCAgugAwIBAgIBVTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA3MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCrO/98w96Bg5YTTmtdc9sL8AOABGcYx5J8E1Y7/GhU" + + "2sInc/j0dtBbE0Tj4KFIKpVLD0m2mTyHVCUA0/QGiS1Tq6DzmZW/V36Clya3CoX9rDTJyU" + + "cKHpgntV19fFAK58aksyKCdP9jjLpbSspzOlIc+mVW+hkjgw3NcuY6fAOQvQIDAQABo3Aw" + + "bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECEmeATXRkM5EMBMGA1UdIwQMMAqACC96" + + "E/GxN9IEMA0GCSqGSIb3DQEBBQUAA4GBAG/Qv60jyImedUXtCYl0QpQ1Ne2ZLxvUHRLms8" + + "B1nXC/Rze7zfz5cwiyQn+6XN2rhuYFdTMDEFZDIjeeCLNllfan4GUAdRGtoJnfoLOGLlQf" + + "RW1ONc80cxd1NTxHqxOtqpWdoJQEn8070WLqQPACEs88XYKBZ00sF9ZdSg5vhHUu"; + public const string Intermediate_Certificate_3_PP_01_07_crt = + "MIIClTCCAf6gAwIBAgIBVjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA3MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC+5b7o4iWl80ntDMKGcnquLQDTGlf6Gy/8y34Vw08/" + + "8ij+nuHMiKpo6UCF0OpDcnkJ2ovvMsY5dAb5ErhH64UbnMlKbghnGv0sVidtipoC8u7ey1" + + "YUIzDCdmbNvTfho6IXKzH8ev//K+FJd3qBuKHl9u2Kk5+igsyb+bPSid7d/QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIUDKu7h5EQ70wEwYDVR0jBAwwCoAISZ4BNdGQzkQwDQYJKoZI" + + "hvcNAQEFBQADgYEAnKhR3OvdgtVtmio7ikCvjxlSoKVbUleazxONOxHUAKdXEv0/mSOTwp" + + "hPPIoE2xAqPOOHvXPmzmJpPADjrfhU6afJ7ThDRFTMk4ZLOkT1SvRlymK7uWhj5bhUgi6S" + + "UQ2LUmrY2hIN4cTrrzZvDw2Q/6UIuqpmySXEOHDL5T5MXEo="; + public const string Intermediate_CRL_1_PP_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIL3oT8bE30gQwDQYJKoZIhvcNAQEFBQADgYEA4gZR" + + "71wRXNdxWe7kaQPAw44UUw+cN1bDBU0RV7nwYAFDYxDIaDGOfjhUVTMBq4rb51S7uqIqYS" + + "F6j7BdLXl9WVRJobfkRH0t0cBnuSeQRz3ckrZrCuvyxb3PEL3pbf0UH1i/BfoG+EHJAY7R" + + "OVOL/dyoXeX6ehH6ImGhucDixS0="; + public const string Intermediate_CRL_2_PP_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAISZ4BNdGQzkQwDQYJKoZIhvcNAQEFBQADgYEAfzKw" + + "NHrl10PJDHa3olBYXYzXi94zxDsEQSIb+W4pPXUfDZijPqL1NzapLqc/uL1Sl28GmLDrbm" + + "nCrlMn1Kt/gI6XndOnSyC9Sg6WDxAI3HTHxlG5MHLBn9Lb36CHobnwep1BMo8zl2clh0Kz" + + "PIxQSGXM1BDpHkwF5eoFAolDih4="; + public const string Intermediate_CRL_3_PP_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUDKu7h5EQ70wDQYJKoZIhvcNAQEFBQADgYEAj7+M" + + "EeIe1GmJpbRUFqbNrDvT5tHjKQMNdbe5Y8F920U5t0ig1Up60kc7hs7LH57i6R/quPOpym" + + "a9Eo9Bql+P2Bg9FELih5/a4B021TZBmmdSI5fwQZ6Q5PjgG58Zl2cJitNYvGi7tVUBojA5" + + "CSN7KBMyipia9ivxm9a/llJPrQY="; + public const string End_Certificate_PP_01_07_crt = + "MIIClTCCAf6gAwIBAgIBVzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA3MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC/RmUcYHxgQRHCUh5cMug/J2o8DzYbT+2pIehJkNCr" + + "zfqemV3qshLdMct5GV73oEkG5b6n7tj3/hI1TLh/A3LQpKROAGZybdo9fk4Pa0+6V6ql/U" + + "NnSpcAKct/f3IvchGo9nBGdi9aE+j+xKhMM6E8xj1+Jc7Z0xz7zE4+qRbeZQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQI/y572lfRyH4wEwYDVR0jBAwwCoAIUDKu7h5EQ70wDQYJKoZI" + + "hvcNAQEFBQADgYEANl9zdMKbaq14OP45PeK9D4ftOSuliW2di1qAX38FQoWPYLLoaDU0Q1" + + "9I54PDY/UYRR9jKDl1WPhV6cD+65eadtiOZVr/h1CaW/HxTloouzN4z1zCXMC7AxZKo+EI" + + "XLN8f4w7hKLFYgf6gP9+iVi+T2gKfH5Ch2zjRhlmGFRgsBQ="; + public readonly string[] TEST_40_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_07_crt, + Intermediate_Certificate_2_PP_01_07_crt, + Intermediate_Certificate_3_PP_01_07_crt, + Intermediate_CRL_1_PP_01_07_crl, + Intermediate_CRL_2_PP_01_07_crl, + Intermediate_CRL_3_PP_01_07_crl, + End_Certificate_PP_01_07_crt + }; + + /* + * test41 + * + */ + + public const string Intermediate_Certificate_1_PP_01_08_crt = + "MIICojCCAgugAwIBAgIBWDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA4MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDDe20HLq7R8b0fWTsEiNV3Z5IbQseZ8QCW+1cb6yM+" + + "ArKLJDnXx8zmTHSHQCpw3G7xhGsxA1btm0cSC5P/1bw/kFWsSLRe2NFF6oKU+7c+cgIUMB" + + "kzyXk+kpWAQRb7hcb50iKdKFtO8gMNGMAxlHRI05/1tThyAs9suI4TrxTS9QIDAQABo3Aw" + + "bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECFxr9vgF31fKMBMGA1UdIwQMMAqACKua" + + "6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBABaX7TYfmSyVmzGCVbTFweUuPilo4wzy7z/w0x" + + "y4uSaM/YMtixUdDPpTHOJNYDdeV85v+w9oezdL2ZYAaGn7tldC6k8ouq/6hOGGST+ziHJS" + + "gTOD8UVBQPRPvWEwgmDIprnzrVRz8rG6uqslXNiBDnO9BMGpRo4dy8YpOmV6BPCD"; + public const string Intermediate_Certificate_2_PP_01_08_crt = + "MIIClTCCAf6gAwIBAgIBWTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA4MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC8nLZcMLHYKxVqbhwJiqQbAYhf7S6ck2O9AhNor935" + + "Bfm7/8qVZbBAotQy1PoCjSW0UYdknDolWvi8aAtO0f9XVrAv6BZVVW9j3osIGN/XUThaN+" + + "9dZ83kGpyjeoitpGK4wbFNDteuBFYp+8gFNupnX7JQwUK3aGwBUucbe7puRQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIL0xyFYBk4OcwEwYDVR0jBAwwCoAIXGv2+AXfV8owDQYJKoZI" + + "hvcNAQEFBQADgYEAPk+Lys0Ueoyhp544EH9Hqy9+gY+l/+N99v7KvBlZWKuhkwZDE+qAYT" + + "P/SOPsWe8ADZE2iQ4pOlpK8jSqtJSdK69RgGL9omLnR04L9c/zKLArBE+VmoV7mohcQp8x" + + "aB4q/g3QnAqwfFYDjIWW3H6gRAeQ5MOtKdz/4042fJxc5L8="; + public const string Intermediate_Certificate_3_PP_01_08_crt = + "MIIClTCCAf6gAwIBAgIBWjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA4MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCvy6bNOyVaP8JTwiySFa3Sj+rdSqzkalK5gA7DLk4q" + + "AyvnAK64HgbCsb8dpnSi94WBDsocrQ4C1Ltoahc/AZyRVLA/REsAh1r3/0FALZgYiIxvSF" + + "m3ihKb3P9URBbotzhl1ahRZPSrcxKwNXEmxB0gjixGW7GZTARq3Il5ressRwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQIwFtfZBe/KqUwEwYDVR0jBAwwCoAIL0xyFYBk4OcwDQYJKoZI" + + "hvcNAQEFBQADgYEAeZhpIDEYyV/LkOtUf1TryemJExQ1jdfirJ3AUtoFIoWz1p9aqnV6Po" + + "GAMozjtdyotfSA2O8c065DwD+CvUXPmdD+2vWpX/2hJPj+x++UvvntAokD2UE9HCeEvBHK" + + "rr59hvKKd6GChyhAjLris202eTLIiMEoyZy9X/Wt1nXF8/g="; + public const string Intermediate_CRL_1_PP_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIXGv2+AXfV8owDQYJKoZIhvcNAQEFBQADgYEAhkwT" + + "E/EGAe32J883qVrh1wG5xQzO/GGfp/zuDYGL2k1zZ2zq7MajKfzBoXXQ3WPh5dTK1sy5o5" + + "boPHG0pge0B4/2JvuDVS539+9HAPansUNsrMXzOblg1acjdKtuk4oS8PIYkM/lbA6yJl6F" + + "QMbdIthWqa2gjaWKll3R8fVUjxI="; + public const string Intermediate_CRL_2_PP_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIL0xyFYBk4OcwDQYJKoZIhvcNAQEFBQADgYEAN6BQ" + + "sEQT5YCvs9vlUSdG4gjTgNkyQTCdmSIcufpK4MG/AoW/Fn5zJXxiMyHmvT/dkk/UOf82/s" + + "41YI/Inz4qRmGF4IL7jo+l7V+OI1n+Vf4ClgZU6ocb9d1dFoBkJu3xI9dcWK6ExpzaBUXw" + + "rPJilV4M5luGbszdDCs9cLjmiRA="; + public const string Intermediate_CRL_3_PP_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIwFtfZBe/KqUwDQYJKoZIhvcNAQEFBQADgYEAkmDx" + + "t+r59llppKmm9mSTof9/BX2rNyG9LfIH7wweoDi9be2vYOLy0NU1kJ8f3/muEw2v7hWDri" + + "k9ROLDFnb/S8MYVT0l4rymRhpshPF1uMTOZmfJUCfTX9jIaShztSScqcGSP0a3EUfDD14R" + + "1yMu2pdlMM35llE0lV3uf/eUNr0="; + public const string End_Certificate_PP_01_08_crt = + "MIIClTCCAf6gAwIBAgIBWzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA4MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDTWNp6Oz39wwU8AFDzYVs3UfVvXg+t6j/qFavnvllI" + + "NO6aU1o4Hnk1wfmTPZPErc00/MfizMSumTYYRl21hEZWhjNO5uQIHrF9V/4OToo2iOfsPd" + + "gxwpSokwxcl7CJyadwUxhRDYCLhSORXoCK1CPQZjwb+uQz799O5ozb0WVNYQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQIO1TNJtWwaiIwEwYDVR0jBAwwCoAIwFtfZBe/KqUwDQYJKoZI" + + "hvcNAQEFBQADgYEANmP9hyFnYvi8gdtRe8ERoEG90NwoyPTsB8sXd40f+Sm1QxKqMPzKPL" + + "7bOtY12JGwZ55a6HFVgpw4PnU+0iOcCMHS5OQQLtyirxX2HfioiXEmcmRJT6FvLHrGIHGv" + + "KNcfc3rUiksdOb6+j2k8x4IwQ6pBEHQwY8U4Y4DgqALlqM0="; + public readonly string[] TEST_41_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_08_crt, + Intermediate_Certificate_2_PP_01_08_crt, + Intermediate_Certificate_3_PP_01_08_crt, + Intermediate_CRL_1_PP_01_08_crl, + Intermediate_CRL_2_PP_01_08_crl, + Intermediate_CRL_3_PP_01_08_crl, + End_Certificate_PP_01_08_crt + }; + + /* + * test42 + * + */ + + public const string Intermediate_Certificate_1_PP_01_09_crt = + "MIICrzCCAhigAwIBAgIBXDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA5MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDJqSSqGjgI3JUJfA/XkloAOg2QtZeAGp2nCq1Oiply" + + "MTjJpMpEOSRYrEIgKMGnBPq33seP7X/obCT2jgexmbFT2TmPirM+h1aqbGQ7QAqsx80BdE" + + "ofdcfiNosLbbzli9qFrbarO7fJfBhzraBFGDJj3N8nLi2YtP9IieFYJ/MhKwIDAQABo30w" + + "ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAiVRMrZuHQ7VjAT" + + "BgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQCetZy9JMzUVveSPE2fQY" + + "4fRVChyvIc9nCE4wbzhnRl3zduBGmAwTFr7dRWSFTnEq1c2b6B5nJtCzmt4Ovapf69sIlM" + + "s3iV16eBB1WTNCY8YlAsnmZ7q/AR0t0vX+hh6QV6zN5xqulOM4Y8csZEx3RWJzV/LjE5w7" + + "mKvofBEUoqQA=="; + public const string Intermediate_Certificate_2_PP_01_09_crt = + "MIICojCCAgugAwIBAgIBXTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA5MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDWUTlTieoi7aLGUYOAgqUC2J/6JarOWfv4vobpwjAA" + + "DjvQGqg/GCZP7FgD/72Z4YefZKJEFZTDnYfmy2qh6iBYxcvLsJ+PJGzPCObNSmyq8gpeXy" + + "KKEeCZtEev1tSywTT6E5Dhee4dX0QHE4ydZEliMMXGRW/8ffT6x54CPwVylQIDAQABo3Aw" + + "bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECAMhmGN8+qXoMBMGA1UdIwQMMAqACJVE" + + "ytm4dDtWMA0GCSqGSIb3DQEBBQUAA4GBALNjokGrTnWsPn5KrlO+g3R8tAGM90JQDjfrap" + + "xWM+nN+dUVVdGU6w2pAOAq2UhfySiP42qiFChnPK9oOqPF2Or7/kcmXZzBfZkE/FnJGNUA" + + "gs9je1nZvTPQYsF094OqE7QdJi2k3seA1tqejA1kihMHpwQNmIp8bFpqn4dPO6ys"; + public const string Intermediate_Certificate_3_PP_01_09_crt = + "MIIClTCCAf6gAwIBAgIBXjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA5MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDHUpHhF4ANNLOywnvpqyDgzLMtatW3ZxgLBBRYk6TE" + + "jMgTVKmRasVRTA9uatGG4b2f70YWs9cOd4ylQDqPEDdKNZ47bqZdX6RAU3j1dO9LBwWDbp" + + "NvZ3zuDBRDoCZClIcBESDYweaZ9nUgKl/WxTeCnMwqkfSJGYBBcHIonRPnGwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwAjARBgNVHQ4ECgQIyppef22OmjEwEwYDVR0jBAwwCoAIAyGYY3z6pegwDQYJKoZI" + + "hvcNAQEFBQADgYEAOySUCY+PZxomhWgTRSKRodOIe/QSfCMSC+0iw24a2TuJzFLjN9pSm9" + + "0C2PqWbfwD1uDjrteO1NK+1yhtIDySiptR9GmR/fhL7NJ+z7M4fEJBjjeeI9/aEIuHuBFT" + + "TVHfwsJxnZtjujtOdl56B825LsKW8Otumd2A43N9wIgSyBg="; + public const string Intermediate_Certificate_4_PP_01_09_crt = + "MIIClTCCAf6gAwIBAgIBXzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA5MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDR8/c35YqAswoRMgQswlTbKB9oYEzrFSC0G4dt8ydP" + + "O4PyQs+J8wUVrRVMiVDTLO9rUnzR1T3iA0dqM+SvWMIA8pMWKyNV58f73ZPJIejhxMmOZa" + + "sSLHceMmmMRy1zyk38i3ZJP3YhvxffTjWyTZ9k2xSDX+6KNnkiKkJSKpl6nwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIpcWcVIIu63kwEwYDVR0jBAwwCoAIyppef22OmjEwDQYJKoZI" + + "hvcNAQEFBQADgYEAckgV11ND/D1vfPEMUbDGUvtmsziHiSuEoDLJqSAhOmcX+evKWOfoVo" + + "f7og+0ajuul7yuB+7YX1AakOw+33k++Rsgg4o+ImZq3+VScpgnIQ037OOhgH3umwFRC0r3" + + "NpWqhmQuz+mHnKiK3X+IDsQOFkhnpNs06CQSZzmrzbYlQU0="; + public const string Intermediate_CRL_1_PP_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIlUTK2bh0O1YwDQYJKoZIhvcNAQEFBQADgYEAkEc6" + + "qHGOWZXYTQ5fsWyJgEtuJyl8uJ+gMcikcMut5SIJTTtOz+q3wclYDevT8z1MM25kNdgwyg" + + "b1bwHNAG8I72eIDtGfLrChFwU3qpvVMTG9gPYJb05Q8On56nsBu/PnnzJervzxjViaeOuv" + + "kjwwfmWqGkyiK433WxzgPqE48eA="; + public const string Intermediate_CRL_2_PP_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIAyGYY3z6pegwDQYJKoZIhvcNAQEFBQADgYEAV9Md" + + "8PaNoIlT7WIwnelqrbwsR66vAaT8w3gu8XDYXu+MOYThfyERUvtH6AUrHWfiRvWEzKljHH" + + "3BQB0Zsa9Zz3U5cLzJcqtqDc1lH53aIA8MflrfMVrYSF684s28FikcukmA5Fw3+7S3TJ18" + + "Hq7plHwTCidVD6yG35hsPwcjTrE="; + public const string Intermediate_CRL_3_PP_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyppef22OmjEwDQYJKoZIhvcNAQEFBQADgYEAjBaP" + + "V/TFQtDLxQFIBCbfqhlgpOfvJBatjNuvB0TuD2rsGS1eaLNfTfyVKlOLpxoKwKYMu36kIO" + + "l/+KEPDq+ofy7uDZ6GLK3KZ/WiJyriqBQjFCvlhNTW1cjA7Ejk2lOM/A46mrUS9xC+aITh" + + "d+/UYGt6O/e256cOwQCUaF2z328="; + public const string Intermediate_CRL_4_PP_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIpcWcVIIu63kwDQYJKoZIhvcNAQEFBQADgYEApZ1l" + + "w5SJoU8zeKwX5jpVWiFFFomDgKsNlkkX5mF88l0B6MiYbGqJIowJRfeIlxvPOf20imN7Z8" + + "l38DRXFacDQP4y5kxM420dp+ljQL5q9RsrC1+OS7I7TGgGwPoZTO4mHVk8nx9MyT+kW1OU" + + "x9qRYWN0CLmP22kutYBndny222Y="; + public const string End_Certificate_PP_01_09_crt = + "MIIChjCCAe+gAwIBAgIBYDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDkwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALiOjwwwUk1HNwf2rdzPL2okKTgL+lMdzhC7cbq3" + + "6A409EY7iipPCcsDsheo9EaTNOHV9xjWDqOhqjA38h4hGNkRUVOlTW2r8SoHISn3gDXfrh" + + "aHbU3owscAmt1nuA7rzo7L1eBPsisIIxAY16uAmVN5RdiAAaP8VUdshcNI4/1jAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIGZIY3nffEXowEwYDVR0jBAwwCoAIpcWcVIIu63kwDQYJKoZIhvcNAQEFBQADgYEA0Svm" + + "aqjaeQx/lnF223xlCTsU7XzOxbHetRWfeCTw0QrWQaTrKjWTS/TNyzLhGuPBFg+NTTvWML" + + "gzteo/WWdF8+d2rOis9FVRCe/Euok6ZCL/xgzaE86ZSQg0jj6458TpuC2cszSaifRSlhL5" + + "ogy4ADWgJxdVcBrgADo6QZXkXXw="; + public readonly string[] TEST_42_DATA = new string[] + { + Intermediate_Certificate_1_PP_01_09_crt, + Intermediate_Certificate_2_PP_01_09_crt, + Intermediate_Certificate_3_PP_01_09_crt, + Intermediate_Certificate_4_PP_01_09_crt, + Intermediate_CRL_1_PP_01_09_crl, + Intermediate_CRL_2_PP_01_09_crl, + Intermediate_CRL_3_PP_01_09_crl, + Intermediate_CRL_4_PP_01_09_crl, + End_Certificate_PP_01_09_crt + }; + + /* + * test43 + * + */ + + public const string Intermediate_Certificate_1_PP_06_01_crt = + "MIICozCCAgygAwIBAgIBYTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC4mu1oBHB9BeorCFJIuSw5tszmmYBD4bjTklsAfjrz" + + "OknQsYxEoHfifpdgivh1fMUk+mK5YWUz0G8/edquKbJhPBTTWp8opsGzTATsTLSEzkKbVM" + + "DQ84ttxrhJWlrVRlouZTnD5HoLUvujY4EdydmKsjj6UBt/tGL5EKodymcEtwIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEKMBEGA1UdDgQKBAiGRi8YRte8PzATBgNVHSMEDDAKgAir" + + "muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQDHOaIki9TogVJn54FRPl+7FyzBJ2DnR4RTM/" + + "q1K3COWRdtvmGqtBBtAccxWziQJ5TnAQn1XA0cFPoCgymGPRcUz+0+C+3VhJ/m9LggVP3/" + + "pjJEG0fsmJtUYPyphUlXeUzf4qSj34SlJws3DIHTR8ozAR75HZmlMRnxyZBLl+jAng=="; + public const string Intermediate_Certificate_2_PP_06_01_crt = + "MIIClTCCAf6gAwIBAgIBYjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC2rptuREzhGfEJ3U8ILPBq+z0s+aafMvBRHpqkipDq" + + "bC7v9zpwg1K18F4MYiATpPAEfdEeprKs0mWfdusF93BoMBVm1y0zRgDRUNdyB5GFO8g8+2" + + "yNEO6L37c1PwrMLnvJakaqwbbnwlcMcKtLHoX19fyveQQg5DNj8WcKZj397wIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIJPt6qKdFeYEwEwYDVR0jBAwwCoAIhkYvGEbXvD8wDQYJKoZI" + + "hvcNAQEFBQADgYEAkFJGNze9/6YX7Rv8FR9obFGACIJ7Om4YQQRW9WM9pEDgKls7g9b9El" + + "dJxLKOlWoRoYZIrbEam19traE2O3dxqRevPoYvfAqkR089BkxH/cFYyfqw64IpjDG84dsY" + + "XieajI/Ov/HjgF0VQKF3+Y1ZiDjb2OHNgMkqs9VmUHaE+94="; + public const string Intermediate_Certificate_3_PP_06_01_crt = + "MIIClTCCAf6gAwIBAgIBYzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCzxfyi52gw/5tt6/9aNAXdY3wZYH1GifzGoN4cg8Mt" + + "++5xmTdrc2A9/5biaTUVC0x/Ml6mm940NA9mM/EoEu4SdnP2crNCIFHWNlYz3cJtYJ68rE" + + "rEU+S0gnYaYRiwNGhVpAjV+FPDr0Ghgp5rYQ61evAhmRuNAFwYocUw80G6JQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIZ9yMlboxCIEwEwYDVR0jBAwwCoAIJPt6qKdFeYEwDQYJKoZI" + + "hvcNAQEFBQADgYEATNnRMQmvTxRcSMUL4pa5bejuX2Ixy/OfZIAlJWt9AfLW2tHmdAaGpD" + + "GhTHKfyQQ+HrIMQ+lXau8Yu6nzWXAY8pKpKD1Hbd355VE4dYZ7aPvcAulZHeV0F2EFn09x" + + "qQ1frHDRoCOc11B5qV5hnwgDE/ByZh1+OWUcR4tBQKyEF4g="; + public const string Intermediate_Certificate_4_PP_06_01_crt = + "MIIClTCCAf6gAwIBAgIBZDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDB66hLZx1WGcCqmOxHK/rotXOpccJQOB2L3kpWP1M2" + + "ZiWufUguLw45XShdqu31OgmGw0/w9ugwy96aRL+Tiluj4xjIAxJCav5cXF8Dt2Ex7hjIHm" + + "XV0rHbJUiduHEh3fQphgtzlR4QxG6i/i4SbcsoJzsws8x3qOqRPaWDtyWs0QIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIyZsLNvyyIZEwEwYDVR0jBAwwCoAIZ9yMlboxCIEwDQYJKoZI" + + "hvcNAQEFBQADgYEAc7G4BAUsQeqNp/Kv8TKJckfxWygz54PrkBICNw/eGuGamVJMRkYCP3" + + "yJ8NW4jY/rfxzKKyjVB09XuNBLDwYdR5Z5UHSg6Ijes3j8tehZ+9DwEQrR+WQf/adHIsxn" + + "/347MHrSQF7CJzE9tAu6AOu53lKxLeH6C/5YI611or2Ql1I="; + public const string Intermediate_CRL_1_PP_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhkYvGEbXvD8wDQYJKoZIhvcNAQEFBQADgYEAC7ev" + + "Pqe0veUX+zF51d/NiG6VwgEwOP1HlzD/saDn/FYXStTQDwoIyFjmZ9z0yLGIaVI1O9BWVD" + + "CTU3bCU1dBg61Blo3rI3TlNqmGrYRUSJ857QM9c/G+/+V0XJ/HgId39Pufd9Tob150XNMs" + + "9h0PvqjhYjG1bARMRa8JB4KTBU4="; + public const string Intermediate_CRL_2_PP_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJPt6qKdFeYEwDQYJKoZIhvcNAQEFBQADgYEAiUbi" + + "qQ3X/hTgjhpQGDZi/7EnZcqSgiAFMreV30/mav2NtXDITE9DqZzCS9x1vHBp4BBsQwYVvp" + + "XvLVSgns4pFwR+0Whc+tPo2j9ScePq3sICsqleWTN1DvuoP9rBe8w7pDN4guA59Kbeku75" + + "5CMA5YjiTUomK4UaqI3htwkBlWo="; + public const string Intermediate_CRL_3_PP_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZ9yMlboxCIEwDQYJKoZIhvcNAQEFBQADgYEANowv" + + "f/scWT6FFT393XEpWcTnA18hBT5Nkddw6mHjKBq7ndtBQkydMO8Wym1IeQ2qYbAqu3ifNZ" + + "SKF3PfgJjYPBKImzJdHTKfcclMC5H8Y9JDN0voeyONr9NiXcoj+p24YNYjb+PFI6avRYo7" + + "Xyrqvwnvng/IY9zLtc7SYYUIODk="; + public const string Intermediate_CRL_4_PP_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyZsLNvyyIZEwDQYJKoZIhvcNAQEFBQADgYEAsnA9" + + "ERwsi2mK540oPL45mLdOjGnet7+HhNk14q0hvALTYGB1vEjijc+Yvf6mHJGRbiG207BpJ1" + + "DWeWBY8TLe4YJXlSrWwx1jD46rCt7gdqXAdLpMo+i35yfQ19ZqeWcRLkspmczoUJLJaJza" + + "eLRrnjv62GLJ09KVKpZBGhV3SUM="; + public const string End_Certificate_PP_06_01_crt = + "MIICbjCCAdegAwIBAgIBZTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKrLB7XA0PKY0qtSC5lMBvvIvbyjBM8XmANrN9Wx" + + "66QxEuloRAz0D5uAu7TnJBv6qNuIPGFl74yusKCSkjEkBMdVpBCfDvpG1/Tz3sALSlxmnz" + + "xbK2ytOncbYuYrzvXttx6wkhLrBLlnfuwpZwGZOr/Pt6WwQJWjXxgTNJ6dcgXbAgMBAAGj" + + "OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIv0gg7LxDM+swEwYDVR0jBAwwCoAIyZ" + + "sLNvyyIZEwDQYJKoZIhvcNAQEFBQADgYEAgzlxBGGOBvHw20eOzSswMqrHopNMcvwuEO+Z" + + "Mr0h8U2/HIiRqKWQaxMyM8A0oULGJny3B/0WtkfVQ2EIibZGiKIjC1RPAB3QmL0vgSyUmF" + + "s/LZbzugpJW6jvfov7N4O+u0J5rYniRxa4bgrXa89TY9kwDMbr6/z4oiI8bq3gEsw="; + public readonly string[] TEST_43_DATA = new string[] + { + Intermediate_Certificate_1_PP_06_01_crt, + Intermediate_Certificate_2_PP_06_01_crt, + Intermediate_Certificate_3_PP_06_01_crt, + Intermediate_Certificate_4_PP_06_01_crt, + Intermediate_CRL_1_PP_06_01_crl, + Intermediate_CRL_2_PP_06_01_crl, + Intermediate_CRL_3_PP_06_01_crl, + Intermediate_CRL_4_PP_06_01_crl, + End_Certificate_PP_06_01_crt + }; + + /* + * test44 + * + */ + + public const string Intermediate_Certificate_1_PP_06_02_crt = + "MIICozCCAgygAwIBAgIBZjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDjg5+XWZwW1gLAOldsRshbCXmUCmt1Vs+oZsvyH+6d" + + "2PwKs8ydrz+oD0/D8V7cRXucj7q7cJSLhEY1wJoTTgrWeRg1hQioAXzPW3ZkaZuzhpi+cC" + + "qeZzN5nPvqK18GWvpffNbUUVfOuaHzzHmhmhgQyZaNG7JHwpWM10UMzMawOwIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEFMBEGA1UdDgQKBAh5am+tkndt5zATBgNVHSMEDDAKgAir" + + "muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQAF0h1iaxxZUp43AjP5gSvbW6JfFRW/ugH9SU" + + "n3e1B29LMH3F/ML0joVhPx5CIVpX4nfaYzdeje9+E2/bHMBGSCFeHz9S/KoBLLiI0GNhzh" + + "I6MytvPMPRx7hkuROouQ69TnslJiGCcoo+MD0fA2YwO1bCtyLdeVHYhJZWQ2Sg8PHQ=="; + public const string Intermediate_Certificate_2_PP_06_02_crt = + "MIIClTCCAf6gAwIBAgIBZzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDF4KSKxo8HvQ59E77LcuLpZ7ujNDjb30KB+EbIuRmy" + + "khXAkhq2Rp2Iqd3OhC0AXmhSF+enJq3h0dqyxNWP08SIuK5ia3OIeatl1UgEyukuAnrLuI" + + "A7PFUQAGZmDG4OuHv28zza4n/SwfCaKfi8qatIwpwF/29ycB8wYBrHThQD0wIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIKFZV4vjfOOQwEwYDVR0jBAwwCoAIeWpvrZJ3becwDQYJKoZI" + + "hvcNAQEFBQADgYEAuj8P5ga8Xv9eFjk4AdRMx/Fj/doRAOLZfs+OnrduRXPLe7CFKDxhFx" + + "xYOma8In08cgXVVnRR+2nZ54h5qjCYpskGNx+yZRY8+HW3XXE3KpS7QgTnc/1XshUy9VGm" + + "2qX0k661f2d3KnSKiKVKtM/y/j/nNyxPugDz1Yy50NtzQOE="; + public const string Intermediate_Certificate_3_PP_06_02_crt = + "MIIClTCCAf6gAwIBAgIBaDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCitrzXkbO4hAQpBRQE880MFBPq84umX9pyKbV3iMqK" + + "Z7HBYwZOvEwGQxG+TX1PIj0Jz27oyvoqpLeMkbn9L3K0BuS0AZKlWIOGPPHWpYTDoQCCs9" + + "Mba1evVT/1CMxESsv2kgf49YHMs/6TtxQX0qj5TQzXrkM6CMBc5zyPBDWORQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIxLES0WIVZQYwEwYDVR0jBAwwCoAIKFZV4vjfOOQwDQYJKoZI" + + "hvcNAQEFBQADgYEAdQeDAOFys//2xUFwBilhqr32/jh4gT/ijxRjG0msKTYXmWcCQv9Tms" + + "smtIMtiwwnByhjTdQAtOmEyDm/CFW0/NBnxlRvqZKt+PRtscpExVy7xnnm2MBITTa+9xkC" + + "A361jSDPnRPEOZoKdMRRzNnW4f59m0huibeFNRYJ7y8BnHs="; + public const string Intermediate_Certificate_4_PP_06_02_crt = + "MIIClTCCAf6gAwIBAgIBaTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCg0yQG7oewLD2eFfPuj2DPBgT47iEri2IVeS/r5hUD" + + "nZhxzT2/+UsQfiS+ufdC2Xq+QAcXFcAifPbvRs9xo2q0uLz26mwSq1TH8ilHLKatKwJ/Yf" + + "hcRAfEWDwhLJGRhZ7YrKu8xczZgyxwaeu5m38lEaLIRyaVfVSrw8WhN4z4ewIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQI/dKmuI1u6I0wEwYDVR0jBAwwCoAIxLES0WIVZQYwDQYJKoZI" + + "hvcNAQEFBQADgYEAOEcMpdSAVKUzQ1A7LJnWOh5Tul6yXw6qMsdZNGOZ3vYBXH3vHnSHvp" + + "MqJQ1JIX/4XSiKF8En5dVI/ooNabgyORpPnLGDvrshvO/09iaDlQXxWRsoGAFhcIe7Ibp+" + + "3g6hnBO5U+0pbInioKVYf/1VyZSUK1QQMutshMIye/8gyZw="; + public const string Intermediate_CRL_1_PP_06_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIeWpvrZJ3becwDQYJKoZIhvcNAQEFBQADgYEAEJ28" + + "g5iyw3ZOqs5ly7O2X0YWtgKK3BnPztxygCUWO1xVy/QbMM5ybAU/UPbJC2pUnkOZMX+h30" + + "RYp/kV9w2o15V1hxj2M0tR8fQ0WXudwi20pZO56uHb+WSaETOmPVoNH5efeXsTvtbHQR5w" + + "95L2vNeEzJEy1l7S/sasUUoQvqY="; + public const string Intermediate_CRL_2_PP_06_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIKFZV4vjfOOQwDQYJKoZIhvcNAQEFBQADgYEApLIK" + + "X/YJYhSfn7yLTAlKjnhpH1QDlFeaE6/+uj6j7ZgpK6HBjHOvfwbrjurl+L3ZTLrY1FCL4/" + + "SUgXrJxbAyMANlg4Z8u6o73F9cur2gi3sgv5d6FjJ8VwuKYWY2dwZNeXwlWE/W0h01Vd9H" + + "QVuctFxzQaJQdQBadw/XqzvLlyw="; + public const string Intermediate_CRL_3_PP_06_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIxLES0WIVZQYwDQYJKoZIhvcNAQEFBQADgYEAE5J9" + + "wJKAb3veF4GhHeoIgy6JvMsrjv7d7dhT+ZIKq+wPNk1909X/Zo1GXxJSjMaMgkLlXa0QN6" + + "LtSJxbyMRCKSJfqTKOezFXirZ7MEQ04FT0z6Hp0m+E2Q7dGs52ZOV3YZBhQUlH+aQ8WNu2" + + "6clf4VqBiUYgGhkE95PhN5AAnOU="; + public const string Intermediate_CRL_4_PP_06_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI/dKmuI1u6I0wDQYJKoZIhvcNAQEFBQADgYEAKgk1" + + "HJ7OW203z9H7jNGxoLCN9bGDKOFcWlWuruzXWOAn+AomjSZpqZkZU1qyKrFaKM320sfn8C" + + "ZJPnVWaVMLBLNddDRWUjJrUHtNdnnZEuYPYlRVb0MmwaxHHR0ZBUIaniqoLuvtQIB9N++T" + + "bu4cjx33mN6MX0oWr4Bbq7ovPnE="; + public const string End_Certificate_PP_06_02_crt = + "MIICbjCCAdegAwIBAgIBajANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANAr4hFku3Y6jI+vD6JTRFc7ZLL9tIxT7Mq+QcDd" + + "rRHgSEXhPL3MM//3ZFXca3w4rXOUVQyANQncywNM3uwl7T9jC0MD2kJ9PsNGQL2bQcSajX" + + "jrxT403PVFsa6ZrLMU0hwomSO4nJBLCJj3i1rlX9esYbRNCqzep2OMWgAWRUsrAgMBAAGj" + + "OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIMBvQP4Q8w2UwEwYDVR0jBAwwCoAI/d" + + "KmuI1u6I0wDQYJKoZIhvcNAQEFBQADgYEAnmNf+3jJp4mo4YDznASTMnrBBdXuskhnRXSQ" + + "Gj5dNq6PxEXM+CmBhaNlnFYcr7UCtcD8XwampfyO52tvAZW5kWQKsxyowVtsxtwkAtj6/f" + + "trIeulIM0B1xjyXJshmVST5u6gZ3OegsAyuqyAbo9B1IvkNFOldt624aEG43jq7ho="; + public readonly string[] TEST_44_DATA = new string[] + { + Intermediate_Certificate_1_PP_06_02_crt, + Intermediate_Certificate_2_PP_06_02_crt, + Intermediate_Certificate_3_PP_06_02_crt, + Intermediate_Certificate_4_PP_06_02_crt, + Intermediate_CRL_1_PP_06_02_crl, + Intermediate_CRL_2_PP_06_02_crl, + Intermediate_CRL_3_PP_06_02_crl, + Intermediate_CRL_4_PP_06_02_crl, + End_Certificate_PP_06_02_crt + }; + + /* + * test45 + * + */ + + public const string Intermediate_Certificate_1_PP_06_03_crt = + "MIICozCCAgygAwIBAgIBazANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCrUMqMxZ4sSrH6sKv2y6nYKagLvUHaforCnf4z/5O1" + + "PeldaW4ANtNPA8SkVBES/zoKgvrLJUmqRi4b+BGhCVqLU77PvWyiPOS40tpJfw7m9pPK53" + + "aeaLC9M6rarjdOvF8MkdtytCMU/Ef1NsuJULwEP+XB90k4lHr9EzbgKhXvoQIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEEMBEGA1UdDgQKBAhF0iXZmlIKsTATBgNVHSMEDDAKgAir" + + "muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQCmab7noekyx5TzxAqWoQiC9S/aZJtvLkuH1p" + + "KiZnclMpRvIL1CVOukkzLTZXY0EcCHnXuVGjw+9vmiQWGGw8t6TGCXo/CtCo934HGBxOfQ" + + "MVysEjst7L7TDQsqxk4j9O8cU/TFWsghW9Ihu7SVIn8RJmknKMB2xkIhcDe8S8dmxw=="; + public const string Intermediate_Certificate_2_PP_06_03_crt = + "MIIClTCCAf6gAwIBAgIBbDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCmT7wL9WwWBr1oY9bHIq4IrJOkbOARK3zOeyZSbBBB" + + "zxcky5kjC9pamMpyZjga+q0CGd2rq9eUjQ2FXZsBSgf/X9B0/g9trNMebYgGnYmHHX2JK+" + + "doyAX+h3afDbZzZ696S0Hw7yRx00+teQe/Gx4h4qKPwbJIW5Bep9SBysikJQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQInXHgY/+onu4wEwYDVR0jBAwwCoAIRdIl2ZpSCrEwDQYJKoZI" + + "hvcNAQEFBQADgYEAhlboR5gzYWluWIaFM5R1Ko0/rprrv5BHONRiXjLfAPkzZmd7FLDE2j" + + "BlU7s7IenICeST4c7HG5zqBigK1814GG75nq5htCGUnM6pn8/gvc58+ckKeWgbJxC5I/0u" + + "olCCs8ORbWIEGWmghGg1USxeI1RQwXGgE8XwtabVibJOVBk="; + public const string Intermediate_Certificate_3_PP_06_03_crt = + "MIIClTCCAf6gAwIBAgIBbTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDEouRlqTFQiJQSwc+yhjpvA0dUIbRrNwLF+EPfUWq0" + + "FV1UV0a5lb5BGPW4RGUEbFwsgGCHsfLiY7WmUpC1e6332PZPnrnoJbf28paeiZ8KqcAKZE" + + "pGPWKCmFBwBW23q1w/v/CxcXJoBx5OC1yxG3fGH7CZSzc+4Z/+PxLk9yoASwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIc24GzUM6/LswEwYDVR0jBAwwCoAInXHgY/+onu4wDQYJKoZI" + + "hvcNAQEFBQADgYEANLxcLvJqjyu94HN+X6tTxGcN1s43kQh8yRGotW2ptuA2jmGlAhI8QQ" + + "sXHO0o0bFLBC/Uv0L0YlEJhK1w0ct7Awwn4UYgqupxug2f84yamcvFa1es3osIMJoi0GPz" + + "1WDBM711efRtbzvK6t/4fJ01nG2BlMeEbctVqrehuAip4p4="; + public const string Intermediate_Certificate_4_PP_06_03_crt = + "MIIClTCCAf6gAwIBAgIBbjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDNuzSN3BiT84M3Dy6KeTQkMqWNuYGTENWPP8WvQ0Ot" + + "ggue/lemC+IqYBtIEYtk3A30eKKnF28WIbPlB3oSykrPVV5dMhYGF9ysOtp4wyETHtzdv0" + + "7HyqlMHOCPiFplbwjUSo0uEIRVgS3luBJi9onTpcn97/i0S7VsM2nooooaowIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIDjpr8w0dRq0wEwYDVR0jBAwwCoAIc24GzUM6/LswDQYJKoZI" + + "hvcNAQEFBQADgYEArE6qUMnjXiB5eKiAFc9Elw1dYsQArtnDQAfFGtShDulxYKq9+pxory" + + "4kTMUZZCJc7awEC11tdJp7xJGcpjCJl4I2wBcHiCcVcnwQijqM719PqoQKydXB9MSrXqmU" + + "2CyakSzBpb82VooVNx0IZ3h0nXQSE3V0qSXXCaImJcOIGMo="; + public const string Intermediate_CRL_1_PP_06_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIRdIl2ZpSCrEwDQYJKoZIhvcNAQEFBQADgYEAQrHK" + + "VV2MJPJLNdPoEuqFXRTEclSmYhUWC5lthK0JnKUbCUj2cMAku2UdN5sRgVG0475dXV2nvn" + + "huxy+IQVt5OJ+PNZ9MYZlC2CfYsBiW9DEYMA603XhVvX/bxx80MwxNby18oyo/V9ycSyJw" + + "XzUmzYRUtohHk39r3eUSAt5H7zM="; + public const string Intermediate_CRL_2_PP_06_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAInXHgY/+onu4wDQYJKoZIhvcNAQEFBQADgYEADOEh" + + "jV8V8y17mFstkVwigOAKURbi7sD24RkLd1QG0Bn21JiwpkGY8Z4vetQps+VX586xKzz6v6" + + "Sj+TJk3jfHCiEAk6a7PLxRcVCCi6y70mzEBCwn6fS5NDfxzxYYLgq+dlUiVwqXsHksEvUz" + + "2Z5dpuLhbUGxHiqazNE9iq9pEEE="; + public const string Intermediate_CRL_3_PP_06_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIc24GzUM6/LswDQYJKoZIhvcNAQEFBQADgYEAK/zi" + + "r7ASgtWA0xGQVrqhHsXH9bdaj+FceW6ivoXo3z6xCFLvzu2uenEu5g849+YI0KMomHsDAY" + + "tX8qO3XEaLGchbhIfywgRVDlSF8ytMKhJTS05R/vZSZAl+eoT3mC92Grihsd3wublyNZ7a" + + "d925Py/oFp3J+geUkKJQK+RVu4M="; + public const string Intermediate_CRL_4_PP_06_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIDjpr8w0dRq0wDQYJKoZIhvcNAQEFBQADgYEAcBag" + + "81RFYMBAf8aRP5VXPcfu0OxgJvVE25ZHGLCkLD4TPKAXMjZMHWrf34+5FW7aigDO1YhGA+" + + "2zVtVj8k71DichiCCGXQvH50AqFgeNXNQwn9WcpQ8rRkfmyhlccfeM+MzHI1giRw/RjvCN" + + "0dfJL9g3c7peW+VCKn85REZ1ne4="; + public const string End_Certificate_PP_06_03_crt = + "MIICbjCCAdegAwIBAgIBbzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKBSOacrUg5H5yuISkqmJuQcK2ao+Ib0FmIKCuek" + + "8mm2HEiux+K5/yIAYsQnz9eDKzKWaS73exPniKOXABHaL6dxsptbdBqWB6II2kIl0BFz9P" + + "82qjz6DMwpUhj5Pwfy5q0Bz8grTe31ZYP19y8AHgcWna+eiY4fNVXVkIEJOJ6tAgMBAAGj" + + "OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIaZQ3Q55so58wEwYDVR0jBAwwCoAIDj" + + "pr8w0dRq0wDQYJKoZIhvcNAQEFBQADgYEAnNYKc2pSFZ9PtR4gQyVI3j+gQ97tcWu6Alxm" + + "4T48fSb2KtFGuozJyCv0aYjtuZ9ava9r4v04lyFPoAjWYbALHC9F+vz7JLNr4VstuMdy5O" + + "ax+PvJjKGACSXD7QjXJ48qvm+v8OnMbkzf8+rY3LoTJ2KhXo9Ey4+UmU/YuZ0PXuY="; + public readonly string[] TEST_45_DATA = new string[] + { + Intermediate_Certificate_1_PP_06_03_crt, + Intermediate_Certificate_2_PP_06_03_crt, + Intermediate_Certificate_3_PP_06_03_crt, + Intermediate_Certificate_4_PP_06_03_crt, + Intermediate_CRL_1_PP_06_03_crl, + Intermediate_CRL_2_PP_06_03_crl, + Intermediate_CRL_3_PP_06_03_crl, + Intermediate_CRL_4_PP_06_03_crl, + End_Certificate_PP_06_03_crt + }; + + /* + * test46 + * + */ + + public const string Intermediate_Certificate_1_PP_06_04_crt = + "MIICozCCAgygAwIBAgIBcDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDFoR/YTJlGYenu2IRsTiT6jwIA7yOnFbM9JXcqYIP5" + + "jSgtn/wVztPHgVWP+582foXJ+oEcThQVZ+RBXYt6VU5o7eVCsGJjqMd0DbRzTO+poelVoY" + + "1UEJMrKG0xSEex0T6XLQ+jPU9o5tlXoLYsXvpvbIrCJ0o8kuk4MWTzenDKJwIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEAMBEGA1UdDgQKBAgVwXynYDSYEDATBgNVHSMEDDAKgAir" + + "muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQC6MnYM9cY3CNb7/KKZvoaSwF/Se5iZYnbdPn" + + "WCnKydnN1AhlDN3kEw0gjTmZo/MkvPqku2aPzg5EiZ0eyeJaR6a4aiICU9z/Hiet19mBF6" + + "BtAUdt0fJ7aL5WPAc4BKXUbONd6vkQNv8uLcBmsqZ4wXDj7ZVBMGKcuDq7uClb0xYw=="; + public const string Intermediate_Certificate_2_PP_06_04_crt = + "MIIClTCCAf6gAwIBAgIBcTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDHqX/4IZpOCsHWgdJ6mICN94nXz/KqsXPNymadVdZA" + + "nVU0fHdMcxehAvsBKju5d791Psly1Xyyda8KQ0BKPgGed6jNKb89JzuEtPBov0VMzskqwR" + + "irjaDCwYKtibiDe+T/kEN9Sq5pbexHcaTbAIeQrAIoSUmGdQ/Up6PYplb0jwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQISKcQDqdBecUwEwYDVR0jBAwwCoAIFcF8p2A0mBAwDQYJKoZI" + + "hvcNAQEFBQADgYEAkAQaOoZYAZOCk881Ro+SIclAj2lp+arAkWPP/gwN4/0lpH62eWqlmY" + + "okWRBjk6+iwCgRxQ56uUjJhE08p5juZ5V32ie3RW+S1ZBPtL/T/+Tqp9HNQQ3GjW1yc/yI" + + "sWQxrd7QKzTER37HBiOr5WjEjn+dzuWlJtClcQetqMLtMgM="; + public const string Intermediate_Certificate_3_PP_06_04_crt = + "MIIClTCCAf6gAwIBAgIBcjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC2tnVj8KHGCm8XBPvDYWZMp3yOKQxuORze6a764qIC" + + "hkdO7hQbgJ9YiuAF/y62W17FnbhKPX6ninaZG0N77bznKvivSC3+T1jIVhw+kpxRh9MRya" + + "L2p+zHJEyO/9JaKWzJZiVi4kebW+hwNgSZc7FSYsAbW7lr4ujDei/yn/AJEwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIaAEiWf4JpfQwEwYDVR0jBAwwCoAISKcQDqdBecUwDQYJKoZI" + + "hvcNAQEFBQADgYEAHNsZDCWtOqt741IJNA9OwpymTA4ES1BRJquEvGj5+4RH2pxi67bYd1" + + "kWTPF1qFC2R1sugSNhbU0wOBMdKUJtKWNacPsK0HbD7CPqt4THOcMXFO36b/2gqHqy9rc/" + + "slWuIwbtT/tEC+Mk67GEATWNPifoPT7TjWHM3RhsDnagZXw="; + public const string Intermediate_Certificate_4_PP_06_04_crt = + "MIIClTCCAf6gAwIBAgIBczANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjA0MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDgdk/smDJ5yZYJDH4SG7pIDCzGNZeLO9RI3ybOx4/B" + + "M3YQu3DDFSOv8kq6PgL8ThC8Dk6t1jSbT8QVzaGgx0KMV3p6pIMdaVNkOjVjUb+L0nXVfr" + + "XYpFLON6tZLgh8oIbiz4KznKmsxo6VdYwyUeHmkpGcL5y+8qLspCNdRJnDGwIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIgSY376EamQowEwYDVR0jBAwwCoAIaAEiWf4JpfQwDQYJKoZI" + + "hvcNAQEFBQADgYEAEztvmGSVnDGGeNlIoR+wfRM8ndJogvUxLBZm4N96mDZ9Y+Nr99Dqvw" + + "+mMI3BU0miA5kDO9aFrKIgow3cpruoedhnBUsxTfhrNaFEwp+ORUb3tWn7sSxLfnTim4Vq" + + "y6j/EfUK2CS4ZAy7J5BADWSqDezPnrb5UaY1JFKMuLyGRac="; + public const string Intermediate_CRL_1_PP_06_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIFcF8p2A0mBAwDQYJKoZIhvcNAQEFBQADgYEAPlIW" + + "SxwW2LE8qxeD+M+HypNwai7j9XxUA2MhBbGVnsrhH+DKX5VeyP/nyZn2hBoGWhs05IpG2P" + + "S0odnyhbgGSXSj+IOfkZkVT0BmuEJmqv75R15LBzeyONks+eSEhoOIGAaIN4WgJ5mzjSrI" + + "ddDu3c4s6QO/OFVrNF1F6e4laSU="; + public const string Intermediate_CRL_2_PP_06_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAISKcQDqdBecUwDQYJKoZIhvcNAQEFBQADgYEAE5wt" + + "y3+jVnr8de/Yi0LV70v3JDHimwG2pQcuDRhR1NLPr4oC+2uxMqwxVzdHITDb3yI2ZT9pVh" + + "PV3UvX85avMdA0/JyaMWSKNpbSah1eNfMwMBY2vzh1Q7f5n+7HYYM+I2kz7HARPvwsLP9d" + + "j4mY7Kq7uiOFdnQzJ6LWjm8qEMs="; + public const string Intermediate_CRL_3_PP_06_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIaAEiWf4JpfQwDQYJKoZIhvcNAQEFBQADgYEAOm2f" + + "m3IdcDnIS915tEZzDmIbTFPBkIn0wjUreZKb9uNxE2a8Jixq+UP2uiyYWiWmXnRdVB1Gsb" + + "ofc5f8ctNgSPVTSYB0U5apIauXjV0y7WMUrLNrDFa5m9lxLRhF9kvXVL8zPhVfMpujnXre" + + "A8WS4UjDMuveyQL6yASGoZvB+Ps="; + public const string Intermediate_CRL_4_PP_06_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIgSY376EamQowDQYJKoZIhvcNAQEFBQADgYEAznK9" + + "ekskl4uWU+2Xqp3Pj14wvXuzfPAqFlHR0jl5By7T82JRiRa6LGX6T953vcwwJBsYG1hMqH" + + "pgbnUGB8APQ6YNXN+7ZkudaG6fMVX6bCr8zT+nVSj7PHIK2VFsC1Jpm5SoQMHH6DFit/oH" + + "tm4tdV8+nupMBQn1ZtxQHgUUF14="; + public const string End_Certificate_PP_06_04_crt = + "MIIChjCCAe+gAwIBAgIBdDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDQwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCVJmtrW8Z2WGGRNjEgyp2NJn1xaIVDwlxL4C0n" + + "UAPpo1WM/rarQTYejT2Yo8H39TdRfiAlggF0Qsce0W//atey8WewGsFlUem6a4OFwg1X2h" + + "CN/COL0eC4a6lwkdOKmqgxSyWNWeKxXRTM8+EYQIem78uY7A8XuzVUmOpzYWoLAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QION6UOZ2Eky4wEwYDVR0jBAwwCoAIgSY376EamQowDQYJKoZIhvcNAQEFBQADgYEAXota" + + "1N1UrMxj2a/vdII92Wi8uEetcHo9vmiJVYxwPFkp+qo1q93Ww8Qnfp7xzaZwLgVoUOAF8U" + + "TRUVnzqoSwmRrfyEMfrgej3eiBjcU+zS9mNlx9mUUSLmlY+xMeejyVDCntRn6YJWWLesVq" + + "eFOjyNux97/XnGT3T1w0J+wShu4="; + public readonly string[] TEST_46_DATA = new string[] + { + Intermediate_Certificate_1_PP_06_04_crt, + Intermediate_Certificate_2_PP_06_04_crt, + Intermediate_Certificate_3_PP_06_04_crt, + Intermediate_Certificate_4_PP_06_04_crt, + Intermediate_CRL_1_PP_06_04_crl, + Intermediate_CRL_2_PP_06_04_crl, + Intermediate_CRL_3_PP_06_04_crl, + Intermediate_CRL_4_PP_06_04_crl, + End_Certificate_PP_06_04_crt + }; + + /* + * test47 + * + */ + + public const string Intermediate_Certificate_1_PP_06_05_crt = + "MIICozCCAgygAwIBAgIBdTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDMIUtQ/CgudxHAwAAn8jUsdAY8u7WDslOC4nNbWn5C" + + "tILgZ2hGIZhEnhzP+VCV8ke8zLo1DX0hCRYAgzk5XTGAimExHFv/yDdhpJWEnqMRljkCHx" + + "Hg3XE1439qutBdmWvGUlRF0hQrd9Q/Ubr+PjEzP3a0EUmXo7LYuQKMcFsC4wIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEHMBEGA1UdDgQKBAgha8GqGbO1nDATBgNVHSMEDDAKgAir" + + "muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQAEG5C3P1A/MYpNJ0qvi26v04GGUWDQWRW1q9" + + "1392XpAxDdv7kODf1FUMpfBpcUblagxrX7Npthv6/6W8poBTjvJuq5BfnnOMQrCwnsNfRy" + + "Y7b1mAZIvcOBhWe+bFVqRLUqZ+JseWkw0YgZIGtX41Znwl0VcFQKJ4lNkuaBgXXdGw=="; + public const string Intermediate_Certificate_2_PP_06_05_crt = + "MIICozCCAgygAwIBAgIBdjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQC36j0YkXZZSw3qQaxD0g2BfrKYperkGjVAfLwOtOxB" + + "0A3Ufx2ECl/MqNOvi/QWlTkKwnrqw0aEnD25iS1DFM4jMZBmdfJg80oa+y6TJoZcIb+3bv" + + "SK5o3ArCFWkhTHHggIIY3H9dQOgAeYQF57Vb0iu59GPfnYJO8y8ZpxGIYcjQIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAECMBEGA1UdDgQKBAhUpoGZzfV7EjATBgNVHSMEDDAKgAgh" + + "a8GqGbO1nDANBgkqhkiG9w0BAQUFAAOBgQAjrFHzC1FLvssJTfV5YsGfw7Luj4EqLDQd6b" + + "MgtBSwPnXqMTUAZpDETyeYvcgM+L2tasB26MSy6IttSKsaJpHPCP+BIs0jji5xosuCX6Cs" + + "wI2gE/LjF85rjZnldrlDShw01DlcmWlWwudit/ieO71Xc8i0F4EhSaTUJX12po5Xkg=="; + public const string Intermediate_Certificate_3_PP_06_05_crt = + "MIICozCCAgygAwIBAgIBdzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMi1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDFWhChPQNFYQpLBmVmXSGF2py1wcfhZgZurv0E5AgE" + + "BZwBo2bxSeC36lBQyR3OABGI4nQoEegSQWwuS2Pk3+emG2MZ8R5QINAkMlAKTp5Gj7KTlm" + + "3VVJRx7/VduoFx8sZPjkpvF1bSL+KOH4UZny1xqqTj4bJ+oGu58INeSNVa+wIDAQABo3Ew" + + "bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATAMBgNVHSQEBTADgAEEMBEGA1UdDgQKBAjN4PvsHY9+YzATBgNVHSMEDDAKgAhU" + + "poGZzfV7EjANBgkqhkiG9w0BAQUFAAOBgQA8KmWbAQOnM59zry9TNtLbA2P5y8R/sO771S" + + "yQYcu6undt9t7UEiOepDp/z3CGsITm9RdtXAobZ5ZqhW+3Ll+UnML1itiCytOPbfC7iiUO" + + "S5jviQnpgJncZD2Lp65yNAB7lMmMleFO15Bsk8VNmzMDMsFtzo508Bs6T33ZW69/vg=="; + public const string Intermediate_Certificate_4_PP_06_05_crt = + "MIIClTCCAf6gAwIBAgIBeDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMy1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjA1MIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDxx57R4j64xdbjpTl7reLby/T2ym4rESC90aBkC2/E" + + "/YUSjsuGG9GiHEVgoGzoQGQNQV0v9ZMIvuoI6q7Fd6VZhIVGE0MGzTFNA9QEEDGPc10ZxC" + + "Gyh9mZYp77PMuhQ12Iv3aDW9KNTr09+HyhK7d3Se7toXLwjE5pKt+A4ZvBFQIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIwmq0fugIX0kwEwYDVR0jBAwwCoAIzeD77B2PfmMwDQYJKoZI" + + "hvcNAQEFBQADgYEAbAbRorTyh6zfAmdg0lfeZyCyW9k4NWfhUs46iSOl6lkZH8c1eoAF5/" + + "q0pOF+CtI3F9VMhfUXChEbVj7QENctU7kDiFe8300OWD5h1VUi+WTK4CG7B36/BjkrVOuG" + + "Os76P9l1WaC+/WRZdcqgFMfPjpn3R179dImBDwZiCMMbVqc="; + public const string Intermediate_CRL_1_PP_06_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIIWvBqhmztZwwDQYJKoZIhvcNAQEFBQADgYEADX3u" + + "wxpN+p8N2HqmhFw8w9LCeoR3Xa/uaqgqh4i/VkDuAC4Bi7VbIO6rcxDO2uAdZgNhb/hnRq" + + "cvKLcy0vrovCa2EPHcFo7dJl7si2q09EeuHT4+lZt/Ek/VOkwHhvh2o6yEvKOGXCnF9hZr" + + "8YbOIknboEz+tRfxoJArRBwpJkE="; + public const string Intermediate_CRL_2_PP_06_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIVKaBmc31exIwDQYJKoZIhvcNAQEFBQADgYEAQz7u" + + "dfU4yAHFLH5BgeZkYh0l2lZ95af+E/67MSCjQSF7RWWWTffbDMc4HmiRlZLvQdltyGCKmi" + + "kuzcPP8vyYOBQmoIKQ6c2LItBjXVavLdpe91yCOhCWXVVlnMFq5ztrvBEpfO0GVUOnPWfG" + + "1Ugit3SEd4DbhYFTBYHbbOKRWsU="; + public const string Intermediate_CRL_3_PP_06_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIzeD77B2PfmMwDQYJKoZIhvcNAQEFBQADgYEAkiW6" + + "h9a8v+IITd+p0jxukj2FYfmED59ZXAlYhQdQAGlPE71rOXn6ZPURYoGf7qlmBwQffpksOb" + + "Byb+PX+CBTUNXzhgTzD7ifM9xOhCEKVKai9acQfvokU56OHwfq5AnkRykLZ7IdvdYCP57k" + + "ynrNNV35dsMZXg23/PpreumlOkE="; + public const string Intermediate_CRL_4_PP_06_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIwmq0fugIX0kwDQYJKoZIhvcNAQEFBQADgYEAnTbS" + + "MBWyoPaslaLpAMmJ+D6kmmKAdRYurA0okU/QP+0W+YNPV4DducAQUDy8Cg3RkpRK2ze0ad" + + "l6TUW8g83hj9TXSBp+XZuVvzerMCjOeBqhskZN4Ly8101ZZmMmdYdSc3PEhqkme6iZzjwB" + + "ZooAN2dIYjuBj1c1/t5qH80CMAI="; + public const string End_Certificate_PP_06_05_crt = + "MIICbjCCAdegAwIBAgIBeTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBNC1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDUwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALyVMklPv3uwTPzLG70sXIwKSEt65yiU71ibHyhH" + + "wJ/6dXy3HK2UETkRBK7UVSOYq005EbO9s/3oR3zt7QTFifvRTsIjl1L4TCLC2a8ApBr3BH" + + "xmBWcJDf427Pk1fm5qDdEmZnpyIlpKaKIiBcdtwZfjr0lROL8RNcvgtJPdu/ndAgMBAAGj" + + "OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQISjAUfyAwSA0wEwYDVR0jBAwwCoAIwm" + + "q0fugIX0kwDQYJKoZIhvcNAQEFBQADgYEAC6Af3cJUh/IQgWdbC2Vmk96sYjDlAsbA2keY" + + "J0bgBcNaIVoJ/W0B3rSawqSU+Vv64p7kcuAl6cbvIXPB++19V23jj6HUs1JxtPJZ9IWkS/" + + "FRakv6lD7+j1OdzJvDR8AMZWmPFHJdQnJwQ+I1YOU/O/ShawOnGCmihpIULUINFhk="; + public readonly string[] TEST_47_DATA = new string[] + { + Intermediate_Certificate_1_PP_06_05_crt, + Intermediate_Certificate_2_PP_06_05_crt, + Intermediate_Certificate_3_PP_06_05_crt, + Intermediate_Certificate_4_PP_06_05_crt, + Intermediate_CRL_1_PP_06_05_crl, + Intermediate_CRL_2_PP_06_05_crl, + Intermediate_CRL_3_PP_06_05_crl, + Intermediate_CRL_4_PP_06_05_crl, + End_Certificate_PP_06_05_crt + }; + + /* + * test48 + * + */ + + public const string Intermediate_Certificate_PP_08_01_crt = + "MIIClTCCAf6gAwIBAgIBejANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAxMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCp2vHVX08nyKe+S8NPkNJOZ9Xng22TbYXhUHtXw9yv" + + "ZmPkRhwDrZfBLXZcdZFixidkky3kCzv8Q3aPyPByM2ozH+AHJzEMbwifhyvUbANcS+Jts3" + + "lsZHarN7VyiXO+8J2OtYqX9qzmrAOHGleB2cJopEcmAMdrzgt1JIo98SUs4wIDAQABo2Mw" + + "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" + + "FlAwEwATARBgNVHQ4ECgQIoRYqHNcbLacwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" + + "hvcNAQEFBQADgYEAXchRFC94Pl25d3Kl4wBcueQLyWPRuH9zS0ZPLAqKLcWVdcg3fYMuJ5" + + "SypMMpxLaVjN7xq0KjML1gLiPQPk18iA2TOAUMblvjUl1uFzDdD6SqQidEZh2h3wxFtbLP" + + "U7qBBki7i1+Xn072Bpn2paw/vlh4K+ut0tFQ2BAhqVnQGJ8="; + public const string Intermediate_CRL_PP_08_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoRYqHNcbLacwDQYJKoZIhvcNAQEFBQADgYEARyX9" + + "2+LoXD2fIAACBMPDgds6m3Equ+Aawlr0kuppPO4ydCU4kiEgtVGK+kY5GzP6fUpAKjC8mh" + + "BrozojhAbkJekDoN0BIJ42Iab70VmdWXRQhPsUDhQwEt+9eSgy+HfiFfpcL1VJx8uY4XMh" + + "VB3hmapIe99P/T2QkZ+Pl8j0MgY="; + public const string End_Certificate_PP_08_01_crt = + "MIIChjCCAe+gAwIBAgIBezANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wOC4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDEwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYtrtpgxNl+9jF3TN1B9bSEGQci+cQOKpFsmrtF" + + "AyiGBxKONgGSgSFFuFIhyBKZF5ROaKX1P8lsQkrpnuybUi+Z9ADdyoaLUDD/z/kp5sebAZ" + + "ujmF8HVlqHYj5Ls2smS9EdSN1zgPTXIOTeZd/lv1iFppRZv6cBqlaoapQJsb1JAgMBAAGj" + + "UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" + + "QIZjcOdw0ZTCYwEwYDVR0jBAwwCoAIoRYqHNcbLacwDQYJKoZIhvcNAQEFBQADgYEAarsn" + + "13/g0vOKxy0okOp2JXEsPdsP7aWnCfR8N4+7gFD6dVnkgCIyc5Kbs7MbhB9gtIxYhHOV9W" + + "MaW9QAcBH+eXciFDfQBfaMBkL34ssE/TsZ92r/bhBwKRcH54f96G0QWUnoNMt4U/1j2mKn" + + "faFirltqEPUu9mv4FiQ0pNT9yH0="; + public readonly string[] TEST_48_DATA = new string[] + { + Intermediate_Certificate_PP_08_01_crt, + Intermediate_CRL_PP_08_01_crl, + End_Certificate_PP_08_01_crt + }; + + /* + * test49 + * + */ + + public const string Intermediate_Certificate_PP_08_02_crt = + "MIICojCCAgugAwIBAgIBfDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAyMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQCmAgNA68ABUEppM9Oo3guiGvguvtrWQzsQIJfMBrE4" + + "/Scwc4SPK4PiJD+kVwtXinXpVclBMQge10uZ48lSJTihfZscJw3RSHt70H4CpPQm44QS7P" + + "7fQqpcZKZvMWmY6A8jju3Phbuq2WgJCIxxVw886GNIAXW8C4ZFmXCjwiGGHwIDAQABo3Aw" + + "bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" + + "FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECOhZ4RAlqGGcMBMGA1UdIwQMMAqACKua" + + "6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBAGEVSOcNaUu50f6AgGBtz1MDdRiHe08W/nzCNn" + + "0K1/UqrIXVJ7IYgbOLkL3cdHy4PdngCyEblzl5Cwp9chh2zL0PTUbV1uJIBW32ks1HuAVQ" + + "FTZqx0iuopY5AqRCJVDJt4HB5PKObwnmLPNWicI4Juap13j/Tcnw1EP7E7n6OejC"; + public const string Intermediate_CRL_PP_08_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI6FnhECWoYZwwDQYJKoZIhvcNAQEFBQADgYEACLHw" + + "iDARFoF4GauIHnoZlfj6nlOHAFfNSXq06Vvl713bsoAiOSV+2goZjRG62uxhampE+gCdXx" + + "1nwhKQ5R5jOGGOxgLtBFNZwKmD0KiDOSvfIVJ0kYCcaB4mSm0a/7pcCPrrE5ofvkmTW6Wx" + + "k/YIuBZdDoqZC91v4tnu0fSch9Q="; + public const string End_Certificate_PP_08_02_crt = + "MIICkzCCAfygAwIBAgIBfTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wOC4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDIwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJsz8ys71e8UB+VDTBAocVQvADiqh0LjdML3pET" + + "B6VvikiHgbB1PJufxDses+v0WD74ChZEa/octNcMFqMgBlhVBEfvbyGTjiN97LzdZ7SPyd" + + "DsDulqwBG9sACryUGHqwHYnUbjOqsThOXFB8Sg/CGGawpZAosm2AuH2gqNvNuJAgMBAAGj" + + "XzBdMA4GA1UdDwEB/wQEAwIF4DAjBgNVHSAEHDAaMAsGCWCGSAFlAwEwATALBglghkgBZQ" + + "MBMAIwEQYDVR0OBAoECOiMLE2l5u16MBMGA1UdIwQMMAqACOhZ4RAlqGGcMA0GCSqGSIb3" + + "DQEBBQUAA4GBAFf4BCbNtduwn5InkfdtFbQOqhPLAn/5eIhxhVhUu7TekWT7ktdaVQFzGF" + + "G2h1+gXgFP+YKjJy7kGzEVQjlWtuC0l74EwybNHnYAoDg4itKe+0OSNNXdyOmn+i0tE0nx" + + "sWN19VvhLGFC8p38gd0oDr1ziYdg0z2Mx4IlMDxl7QhT"; + public readonly string[] TEST_49_DATA = new string[] + { + Intermediate_Certificate_PP_08_02_crt, + Intermediate_CRL_PP_08_02_crl, + End_Certificate_PP_08_02_crt + }; + + /* + * test50 + * + */ + + public const string Intermediate_Certificate_PP_08_03_crt = + "MIICkDCCAfmgAwIBAgIBfjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAzMIGfMA0GCS" + + "qGSIb3DQEBAQUAA4GNADCBiQKBgQDKZDgBum5Ud5i8HWlCKInJ1x9goZ7TQJ+LdfA9iGU1" + + "47xJL5eFcERWy4dr5wM5GNRW/DHXlnA/qsRVE29EuRh6qAVgcPGAfmJxz7s5yhmErfmiQ3" + + "0rh6+pma/EhcjntXqwIqnk1qt6mEk7x9UKO3ksFCVsDEA67/dvownjcZB59wIDAQABo14w" + + "XDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUdIA" + + "AwEQYDVR0OBAoECGtTrZIwYYHbMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqGSIb3DQEB" + + "BQUAA4GBAM3t13xJJraRiJDAwZFxhTNR570wMdSRiF3yWSRtOjEv8NTVFj/T1oJJ8h9Gqh" + + "hMpTTHU7uGCyVB9S1HCelmS+1zteKr0B+WVzBl9yuhvku3farz6zgIVK3v5hQ6xC4H4Lac" + + "NDhTTKBkRfDf9KskFoxJ/AGxPdZtIEC92DFSblQB"; + public const string Intermediate_CRL_PP_08_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIa1OtkjBhgdswDQYJKoZIhvcNAQEFBQADgYEAcUHo" + + "D00X/pd3D5KGa5C6dY18RsnUovkjUkegGTpbhQfmYZIdBatj7Kv75FeUJ9UpqCUjxHgdiE" + + "EVy60NLVGP2VRuJ1m8vfDz8hu5PaiVjneQoRw2M9ieBnz3PjSETDdBGJLWHyCBZbp/W2+0" + + "iqcZK7Fm9O5EL4PUO6QIwuH76q0="; + public const string End_Certificate_PP_08_03_crt = + "MIICgTCCAeqgAwIBAgIBfzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" + + "UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" + + "FTATBgNVBAMTDENBMS1QUC4wOC4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" + + "BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" + + "A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDMwgZ8wDQ" + + "YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsXEPrCg91CObTl5OrHIB5GshIDXgqBmjzxfWPK" + + "ih4STWeBe2eIFO9pONXcM5lstEu2XLBPP6QBMUMWOrphJejrJ3eDQHs404bBnt95O/x17i" + + "665CZtg1jUqoO1kOBOComx2AJGZ46RdBExbfd0tTtdHWtRhMsnQchI+WtEyotdAgMBAAGj" + + "TTBLMA4GA1UdDwEB/wQEAwIF4DARBgNVHSAECjAIMAYGBFUdIAAwEQYDVR0OBAoECEWZkJ" + + "TYQ3z5MBMGA1UdIwQMMAqACGtTrZIwYYHbMA0GCSqGSIb3DQEBBQUAA4GBAHki/TrpHiKW" + + "gvERhguQ/uOqHHZNXsog+fgGVFFMOWwJ9bq4aHKd1fDZpyZF4vBxW7llbhuSt+ob2TNlkR" + + "wkqzfGL+3xOTKNRgzDwJcil8akC1N5uBftrQk+eL7rM1PezWRM7fIbpmv5ZieIVswtTPF5" + + "1Rl3G+JXUBy9E95espls"; + public readonly string[] TEST_50_DATA = new string[] + { + Intermediate_Certificate_PP_08_03_crt, + Intermediate_CRL_PP_08_03_crl, + End_Certificate_PP_08_03_crt + }; + + /* + * test51 + * + */ + + public const string Intermediate_Certificate_PP_08_04_crt = + "MIICljCCAf+gAwIBAgICAIAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsrM3A06j1zDz6VuZh+O2UrAPcKtwSA6KxTShUpgr" + + "t9UB5iIAEvxcDTwDlubEv/cJjDcFj9N57otzW4ppnuT2ztE4ROmkNb0xL6u00deS1yGjXB" + + "wy1G9g8bYDdAXOJlv0tjHOBqXlyKoMny82BOBL2vsCstiqxl14Q3/wBD1w29MCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAMwEQYDVR0OBAoECJiAkexK6/c7MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAL4xwcpXZQPTTPYIQ8CMoVla/5P1x6BPmPqSkvh1D/o4ds9Ll9kHBz" + + "//X1ZM8SzYcEO+1r75JUzoHsvDw9yYAk2oclLsCORAPqD8Owhv3jv0QQtYSmf0Sxt5FLx0" + + "MRP9keY/DURRf9KitO4glOawtRtYMq2BeeJk1xusY0KqEnQr"; + public const string Intermediate_CRL_PP_08_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAImICR7Err9zswDQYJKoZIhvcNAQEFBQADgYEAcN3a" + + "jIEcXsQatb0fvVcFnO7d7lzNtgbqL3MtaqJ/PjkRJ/rO7JAXQRwdajUZF4ECHylZKE2HUG" + + "Dk+vidV98T8mNmb0TEuuLV+J1G0q8ezMXRJtDt/2m3y1VBireXlEMd1DdgpsDdCQ4va+XJ" + + "qv0TvVhfxWry+LrVb6Bf5ItexXg="; + public const string End_Certificate_PP_08_04_crt = + "MIIChzCCAfCgAwIBAgICAIEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUFAuMDguMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA0MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPJWa/cB7WW7tkGxFhcwxqE+BycXe3Ru2qGbun" + + "NPQZ/j44UT2C6rl1wZwugCY0sR6mXR/P/NR7czZvg4Tt6lwcNtc8PeafFMUeu0u0Kg9uWn" + + "fzQQKeIgRVcEzGTGMPGWXS0ed6X/1+Dj8A+T/tqXKUtM3Jpe0pCmm9CIrYCXLPRQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAQwEQYDVR0OBA" + + "oECKm9IOyOM1h+MBMGA1UdIwQMMAqACJiAkexK6/c7MA0GCSqGSIb3DQEBBQUAA4GBAEXy" + + "dlTkkZaYK6sUJCiPeCPxfj5cdo/G4RGBImMJbTeDyVTvXSH9G2yWUMqBGnYLrwdJJeXjF3" + + "89miJgnJ+1r/r3r2/NeAUuJDsOHRMFh0KXFmgubyw/kGsZBe3279hDnND8ZjfQBmKQD17f" + + "PycWTTAC5p6GM8tGERiDSnMc5rmm"; + public readonly string[] TEST_51_DATA = new string[] + { + Intermediate_Certificate_PP_08_04_crt, + Intermediate_CRL_PP_08_04_crl, + End_Certificate_PP_08_04_crt + }; + + /* + * test52 + * + */ + + public const string Intermediate_Certificate_PP_08_05_crt = + "MIICljCCAf+gAwIBAgICAIIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwH2d+D0pH8y4QJAPpE0s2oWucV1jlE4pBMGNNPJ5" + + "FIRmyRCt90IpzmK/EuqT6iSZYd9hIB9wa180ByN67PK1z4loLFMUL2RmbWeAFlGy5eEFOy" + + "4d479qfy6JCOzt0TKhYzhukLUqGLa4DDTzvnnUx0o86aLvGq0K5s6DRlNyc08CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAMwEQYDVR0OBAoECDSeuxr4EVgaMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAKoGi6qlODB8Lc86PtGXfBhW769jB8xzgmENE59sqNBEvYa/oK9Xxm" + + "1JX1OGEQMq/mqwZXg6hSczpexCIO4tUH8QKTU68yvqcZoZCDV8FLM8aEUPtUoPIpluhAtN" + + "scGfb3uXoV9fg7q1Pi5YlKMnNrDIq1tH1CAGKMDRrjW63Q8C"; + public const string Intermediate_CRL_PP_08_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAINJ67GvgRWBowDQYJKoZIhvcNAQEFBQADgYEAv5Hs" + + "nYPZO1fGC/Z2lIbbUKjIv0+BrR9HbG+b76wXeJTVxfXMlZe0cpOR/KD29DyxI3G4IedHRy" + + "zL8iCDWYbA86arJzl5GZJ1MC2A586vNn/6wiiT6nP3iMj2z/nyvan8L30KNBm9IDXQExOu" + + "PNE/wOWYBxxCjg551fpXfJKqDIo="; + public const string End_Certificate_PP_08_05_crt = + "MIIChzCCAfCgAwIBAgICAIMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUFAuMDguMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA1MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4BZFTwOqI+71v8CdiYbe7x0qYveN524h6+iLh" + + "oEqvzuVKVqvQgVSaSLPcMhoCGDv3nqyP57Znl/3I09vLU6F4HKLtjO9E0PZu8EXOKLjeWP" + + "XmJQkdHfODj/TrrWSsrdorl7s7gdWEUFlbiWvUVUtkqLNbGLJZ5Q1xZvBRLS7loQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAMwEQYDVR0OBA" + + "oECBDaTXbN11BBMBMGA1UdIwQMMAqACDSeuxr4EVgaMA0GCSqGSIb3DQEBBQUAA4GBAGVa" + + "QNtd4LgoVZQ+Uy1lSr6sog4fsGaoQJCZcvrMJwGpMF0FJsGtOb0R2mfwHi1YXqPF5qZY2I" + + "7cVbwVtRQzbXunk1z12k0iIesMtYUncxb/SBstC7VNS8HNZm9ese+YM6Ac8mGT+IUZsPcP" + + "gI9fQ1L/2u+/3L4fweca1R45xm5M"; + public readonly string[] TEST_52_DATA = new string[] + { + Intermediate_Certificate_PP_08_05_crt, + Intermediate_CRL_PP_08_05_crl, + End_Certificate_PP_08_05_crt + }; + + /* + * test53 + * + */ + + public const string Intermediate_Certificate_PP_08_06_crt = + "MIICsDCCAhmgAwIBAgICAIQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlSIH/+6DEL1P9tkgbsI2PcW0w9dmqMTLP3jKYPsr" + + "sSWI5bcv55sk6RItVr3hGgkaskZoHeamUBAiGPksVyrqmRwSCJzQDLnLdMnjjudvPjp1ZZ" + + "9UCufTtMPFvnEuVBx5e8A13AQ4OyHqaJgWRVoRJd6vwTa5jzfYCCMJZHHKpcUCAwEAAaN9" + + "MHswDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwMAYDVR0gBCkwJzALBglghk" + + "gBZQMBMAEwCwYJYIZIAWUDATACMAsGCWCGSAFlAwEwAzARBgNVHQ4ECgQI8837JGF7vMAw" + + "EwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAKmgbxzWI6V2twYDp65" + + "Gu8zn883CnI08s2FEVupvrKduxYmg+ZDkTBE3ZJFxcOuxJf58MRfDWy8C4jJhLnT3JSSSg" + + "sY3n93jzc0s2h5y2wd1bUTDLqhqWCshisDG/88rpv938O8luiUEwltolzKTa+ScA6nXSQt" + + "LT4I6O3vbTx2g="; + public const string Intermediate_CRL_PP_08_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QUC4wOC4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8837JGF7vMAwDQYJKoZIhvcNAQEFBQADgYEAHua+" + + "lC3wP4G6796jjr6wuu7xEQqY1azsLVsGtL7YL8fm42rl7hgU40SuFIc7Kc+A7oEEkKgvmu" + + "SLMIv7q5O8J26fQOuduGWQAncPYB8w7sNWjCZbdjVbjp1XIApcAL3djCbLZ8/NYsCoOuwx" + + "hRQKX1hIn+rNDi1DMD4H99QdDGE="; + public const string End_Certificate_PP_08_06_crt = + "MIICoTCCAgqgAwIBAgICAIUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUFAuMDguMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA2MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnaYU/lu+u+LmLQwyACSsRyxQEEvgriE7ApmHj" + + "sNBcd3lovFQMfw9MyOOMsInOgQZU8p/invnhx11/pwi77ViQQ780unhHt5H/tteaYwcsDR" + + "cUxR/8jK0DBnbVWvm8S/NGb8BxfbRmDHBTWGZ70hDSCJypWRfHQj0I/SAqAW/VuwIDAQAB" + + "o2wwajAOBgNVHQ8BAf8EBAMCBeAwMAYDVR0gBCkwJzALBglghkgBZQMBMAEwCwYJYIZIAW" + + "UDATACMAsGCWCGSAFlAwEwAzARBgNVHQ4ECgQIhh/KikcKA7EwEwYDVR0jBAwwCoAI8837" + + "JGF7vMAwDQYJKoZIhvcNAQEFBQADgYEAbHK3lkqbGy61lu9d22uO2H3hzwvjmlccZo8pro" + + "ord45d2nRIxw2ag4dS1YRFrefVdxZtKeR9+5o+tQtvmTcDOer4u6NZ/sVVElTb1d6axtL0" + + "i4cmqv6bGWYECEwtwmPGqAavp9pPZjNRbkBGy9qhVNTXfDQYpA8yzXWO/xUrwNU="; + public readonly string[] TEST_53_DATA = new string[] + { + Intermediate_Certificate_PP_08_06_crt, + Intermediate_CRL_PP_08_06_crl, + End_Certificate_PP_08_06_crt + }; + + /* + * test54 + * + */ + + public const string Intermediate_Certificate_1_PL_01_01_crt = + "MIICmTCCAgKgAwIBAgICAIYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxDV2d7qXbpCvOzBimskBLsgexpEYaHv0s7gOaqhC" + + "4A3K8sxdjyW6QdGZhKX8tCMqnlPp9CNbpY4tQQ5oTSk5pj6HwAsTfGcDwXJnjKWx1FJ7rD" + + "meZZ8c2K7a8voBl6FoPGn8CMhO0WmM9Eyb/vDUPdCZzScb+z/BxTcV1BPFdq0CAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECBpj0+Gcq32oMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBAB/9veHrkLeu8jkwXggJtwqPTmkrIBcX+pz85BTSETYeLOzF46" + + "onk+qt+IHptlrm3D7ny2Y5M0dQQ6tPzhGZxCEg9RoDibZGtsx+qeAh1ZjeEpEcQyp/idWY" + + "asH+EIuEIOZA9c1ySxI/3v3ZfzaSGS8jsgSDkLB4JumrE9ZkLNd1"; + public const string Intermediate_Certificate_2_PL_01_01_crt = + "MIICljCCAf+gAwIBAgICAIcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3B3UKG3tEL6FQz6dL6iqSvzgGsm1Fg5uzK8npkEq" + + "g2caUM7huYFfXeur1mu6iKiROcGX8ZYxrPi9Orh39YVrSu2EUWvqQui4QScf4dIlzAOunv" + + "0gAa/lIVTHgZhIomKND6/tZLU251dJiFhoV6bXx2tor83vWFVPx2oVd5LL5S0CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECJmK3jFTIl6lMBMGA1UdIwQMMAqACBpj0+Gcq32oMA0GCSqG" + + "SIb3DQEBBQUAA4GBADkYLTg4RncTpAFmpUy7WGOMvoFV15nDoi91OMxhxVkbGSE0DJFxi3" + + "hPKcfUNvzy0bEUUTaqOXdbIkoLTG77NTckJxurSRyam0jA0+6SUYZ6F9fVotwMul2EiVl9" + + "XP5oCt7LkgqVgMASuwfzMnQozB6Oi/YP2OdSPXLipI6rl2dx"; + public const string Intermediate_CRL_1_PL_01_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIGmPT4ZyrfagwDQYJKoZIhvcNAQEFBQADgYEAd8YZ" + + "8jibr8yjcGYSDicJuyUvHBZntTVQ1sP5XVmtCZcYcQCVjbC0auYTEP5snXbGPW5qeEaaXB" + + "MhekMr776hP4Kl3g4AjguFl3XQGcURlgNd8LsTpMMdNWC7XwooOF2FzFjD1ru0BSEWabzW" + + "NNaVeuMMbu2N0lc6NDJvRC8LkhA="; + public const string Intermediate_CRL_2_PL_01_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAImYreMVMiXqUwDQYJKoZIhvcNAQEFBQADgYEAZFec" + + "GtjOfp8pT0n1dMF/x9n8y5tM+G3LLnZvDJspLc/sqP3E3B/sHBiis81caEkQQAOTBU5goJ" + + "0KOFAUOfEq+IX5uvNhuPuinx0OsSak+2Annvi12zodMQKPNm1uMVt2bMHHHZVEVTqcv36g" + + "xgdbp0YKTmuvSy6s8NtGFpkNmnU="; + public const string End_Certificate_PL_01_01_crt = + "MIIChzCCAfCgAwIBAgICAIgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCAUPp5j4V5XTA44Ra1EWkp9HgS4w3uXJ7/Vhi" + + "K5bARFrDOOxjV8nmr5hoUYr4jwdi2Rl+60TQK/F08gdcGxdyc9p/yiU5HyAP6i+4iqmvaW" + + "9b2egNyZ5tOmpl/Q9FSFWa9d/PYBKM5Sj/r73RtA+/chc4uq3uyLekSRQGh1MieQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECAiL3A4CkaFyMBMGA1UdIwQMMAqACJmK3jFTIl6lMA0GCSqGSIb3DQEBBQUAA4GBAJtH" + + "mNNvCt/0uFbHdvUvCuBeZ9cggfpTyUS4X8zgcLDPFbw6VvX65umOZpceZI6hwcre+LZahi" + + "gUEPvXppncEObkeVTcYdOTSDoxh5tZyee1P4sbD9H+suGWeewqUDvFs2ymHtxlkpOttitR" + + "xQc2U6VlCuZ4XU8SwucyhW0z51e4"; + public readonly string[] TEST_54_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_01_crt, + Intermediate_Certificate_2_PL_01_01_crt, + Intermediate_CRL_1_PL_01_01_crl, + Intermediate_CRL_2_PL_01_01_crl, + End_Certificate_PL_01_01_crt + }; + + /* + * test55 + * + */ + + public const string Intermediate_Certificate_1_PL_01_02_crt = + "MIICmTCCAgKgAwIBAgICAIkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4QmGXEeVKCn1aQx27r+EBuQqfi8fP7gyV5JLkaSu" + + "DOUrqXg8dQxHsBNCf3XilGIvjNFZjVUPdS8FNqC+if9D164VyGQlv/JUor/GlvwVfyotUO" + + "U1PqSzFrAALYTmfm/ZqhMvGYloStSDxlzjDmyKadskzOxZZDNSe5s8dvUpYn0CAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECGk7qDbbBgRbMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBAD+eI+jg4jmeC3pJRGEF/hbPPYvL6aocjqqbZyNKN5FWItccQo" + + "PWg/GK1GpusDZadesZBDo6fLIUJzL+OumrIYJLB3HxQsmyOXB1gRg1hcva71RWFJYzx01U" + + "eB8lCbk8Zu24HzLzqjfVuwKOFFELWDEq7bd6Re/aKSHtNnDbsgSE"; + public const string Intermediate_Certificate_2_PL_01_02_crt = + "MIICljCCAf+gAwIBAgICAIowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAl/HiHoos7eHaDIFhMmvIPk63UT33Z+0iiCIuKLW7" + + "tgkT8ia1Yg++np1pC3oqYVeKkXqMcjgonPGQhcek12vLt3/+2PYyYirOTVZaiO9pKQ5An8" + + "ZMWXIJmCEAMHabPO1RnetvRv5JZFxZY9jIUnD2fUADzzUh/eHN6Pur0DDrI6sCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECPk0C10KQLZuMBMGA1UdIwQMMAqACGk7qDbbBgRbMA0GCSqG" + + "SIb3DQEBBQUAA4GBAMJ4+BZQxpxWhNbo8bpGkbbcKT3kfKYrHjHsZADC+/gAJSVL854b1W" + + "VKsGr1YcCX10V1Gcqb6Jgziy+AzRLhcJngszcz0A7LxrMH+FIyWEPgZnOyQCa8B/9bnsh9" + + "bC1gEmXGOVtWboIFOEdGghEbm/ENnQyj+HbIk3jhF3QYbXhw"; + public const string Intermediate_CRL_1_PL_01_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIaTuoNtsGBFswDQYJKoZIhvcNAQEFBQADgYEAZEt+" + + "FjRuXgnOZg70geqS4hVsF1VWWawlAVGmjPsbRH7rADXPUE2bYL54wLdwt/6QYwHqy2KwCf" + + "d4OkWkwn9xwGS4j+XBCw9Y4nbWI+wrsZ9W7vgbeIaVUUUZu6hoin1GxrGDcfbM+bhYzQAA" + + "gNmKIWdlJ4tKD2KNgg0KmZPoj/k="; + public const string Intermediate_CRL_2_PL_01_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI+TQLXQpAtm4wDQYJKoZIhvcNAQEFBQADgYEAXwZO" + + "wr9mrO6yUOoopNjcIcDssCUksYco1PFgWx9O/hGq9ktdoGoGcECGhdkHTLe2ab3WFl9jzW" + + "1/lkysD9Jl3VjbnbRB3dPQlrSfiv7cYBLnfKvyF/CxQg/wCtWo46GJJQgOx/WHzi9aF08m" + + "tQuJEtl7RgoByUSvLtmvKjQWEnc="; + public const string End_Certificate_PL_01_02_crt = + "MIICljCCAf+gAwIBAgICAIswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/rXOZwUebRaHcPPFeKTB2OWIzIAgavqb5HerPAe" + + "c3sJCdNOSLc0OX0dFblso97WR8uueF9I7QeGg3ayQjzDVqm5Tu77ZaCuyb6UU8+fY2eqwD" + + "5lCVuLfJr9U2JD5b2TcdvAD9RqfhefclVjDj9rObLjvzLg3AefO3drsfBtAIMCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECDBWCFTOp3evMBMGA1UdIwQMMAqACPk0C10KQLZuMA0GCSqG" + + "SIb3DQEBBQUAA4GBAI/JpU3gHo8Izsbjlx6bkQo/e/hD634N5lSMtVHIGnoVLu99dvroRu" + + "2DO8Fhnv6VZpMvYoAc5oEgUqx9hw3bfS/XN9GXaeMssjwN/qM6lzCsvMG7DA9sf59xjf4Y" + + "2+u4KTye4PdpmWaseDDJ1wAihTHEaofnQdaoUffxQgw5UcAf"; + public readonly string[] TEST_55_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_02_crt, + Intermediate_Certificate_2_PL_01_02_crt, + Intermediate_CRL_1_PL_01_02_crl, + Intermediate_CRL_2_PL_01_02_crl, + End_Certificate_PL_01_02_crt + }; + + /* + * test56 + * + */ + + public const string Intermediate_Certificate_PL_01_03_crt = + "MIICmTCCAgKgAwIBAgICAIwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA60y6V2WkNCB34dcGfu+Jo3YHQZXzgp76+HgnyFmP" + + "DLj9DjZHqifD3gW8Zk7L+yK4PfLDSHjbrXM9GY1ser6XwhaJQDPUBBYW5X3XTOmDWmV63J" + + "YeRF5r7cfF2h3eEZ460GRLK5tt0Zr8V+hA9oOvwqynrIhDYC/tCzE28ciqA+sCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECPE2FCetVerZMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBABUOUWwyfyrRIw7dRIVfLlWyp5R1I+Kmq5e8st0AEMVpPAmLoy" + + "0s+46Xf+THXZy5em1P3bSVTSUhTs+XD6tbFFUcTrX0mQJlshR7yD/A0siMDUNzzt9LJQvP" + + "dwNjQSA2keOrV9q/2CAGce4daL4Wz54jfh33YVqJ8sHT4E8CxQb7"; + public const string Intermediate_CRL_PL_01_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8TYUJ61V6tkwDQYJKoZIhvcNAQEFBQADgYEA6FnB" + + "LXWt4B/3oP0PXERYh7ZV39yu/tm9DHBQGcGDF8JIspU7F+mH/+37U/lT6BQxpKOpgOgGeP" + + "nTQeQzN9sRsXxFO22SkHbdPCao84qvv485epgzqFcVsCRBwBBLcnNLMg891q0EYsTW9vSw" + + "Dx7V4CawyYAYGz1MqYuY6SSs6Q0="; + public const string End_Certificate_PL_01_03_crt = + "MIIChzCCAfCgAwIBAgICAI0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjAzMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwt6B9gpDz/x/vnowXf1MdkAPeaCWZ3pYikgxE" + + "ZLrMuulFaI1UDnAzgSuSvoHE80VKGKjSkrzIX9OFfeilW5rNZAXoZrjtkaJd1Q8l5AtjFn" + + "0tlLytDzIMYo5Tiq/n3IiTdbEzGYzEOCcSyVaQdB7K1WgYI/z/UAaWV/GbqCX1zQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECMQHLiufEm0IMBMGA1UdIwQMMAqACPE2FCetVerZMA0GCSqGSIb3DQEBBQUAA4GBAD5/" + + "vGn/rpoHvny/mfh6n2zVNNQLTEBiddfAdCWpeBFcwxS5lpxfm4dAWgHhprZTMirF9yS+wO" + + "wWQ4G9/wiqfAtoaNN1qkHMlUMOAPsOSff6ClgP+1uzKVqQa9NTd5HAeMdYfYjMa/fcF/37" + + "plCs5ZsJjb9lhEjNd/tq4/aALQmt"; + public readonly string[] TEST_56_DATA = new string[] + { + Intermediate_Certificate_PL_01_03_crt, + Intermediate_CRL_PL_01_03_crl, + End_Certificate_PL_01_03_crt + }; + + /* + * test57 + * + */ + + public const string Intermediate_Certificate_PL_01_04_crt = + "MIICmTCCAgKgAwIBAgICAI4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA06yd2NQEAgpv0kQQEOzhHHU4YqHgtvJgkdLYxb2W" + + "Zordrm4b/43UDnLmsI0790V76y9Aa+Y8SIMBBRBJgnlppFJrFsPaOMO98M3/mXkQotVbY1" + + "59P/AjWMxpzP9h8Bs8KuoPqnl5jN0UZAF4kRoNXHzyS445VBp4DtWz/jcCPm8CAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECHxLORDZ1KKNMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBACHmDOaoC0Hr2cmfuQvdyGDF7/RlvTUJ7cvGypCa724SwAZGZk" + + "Tf5GwxgjVcLHY5RlX2kDm9vjneDzP88U3587qA2ZRwxhheK0RGp1kudNQ5y2gAGKZ7YSc0" + + "SENMDxUAa6HUkn9Rfo4rf5ULuGNJZXQZ3DtP+lZSwzkUeCVjKhyQ"; + public const string Intermediate_CRL_PL_01_04_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIfEs5ENnUoo0wDQYJKoZIhvcNAQEFBQADgYEAb8lX" + + "19SlVNRkc9SKNpRLZQom67djZfMSIPIDkBALfMepdevbquzgO7AufTuiDn5Zqe6J6odTv6" + + "RrQReo64XB4+Lx2pXOe8bZEbzZk0HvzLl9DjN7zxyNglNK+Hd2xS4yT4ps4fBdvXvWAXEx" + + "6DfvWHbGFDoH2auomCKJtCVXxCI="; + public const string End_Certificate_PL_01_04_crt = + "MIICljCCAf+gAwIBAgICAI8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA14bXc39XiWvb4r1jzbADzrpfbg2Y9sGBkefSQHsM" + + "QZ1SRLR7uexWD7MuDYh4ZYBL+WPhaJJr3a1jnAIp54h68m8mwS13DgrxBF2/hrVKEm9IRG" + + "s13hoM4Mjjogn/Lvc1xLvB5lctHjZrNRZjyrt+PqDDmqZqgCOmcD61PhrfAoECAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECB9hXgJfzBvTMBMGA1UdIwQMMAqACHxLORDZ1KKNMA0GCSqG" + + "SIb3DQEBBQUAA4GBAB0HgiURRd/REVfc5DenIPhMu8riVcwVgTUwatsCWragUhXpCtvJmf" + + "z4vGo1rKYai2dltVX6am+NDvN5tROcM0bvC8lOCc/iPfI5eWTy9SJ2nxvs1+q809Rj0rno" + + "zS77TIE8rD7Q8ZUd3qNUiBwdjBoc9misgyN7zUulg4Ueebvv"; + public readonly string[] TEST_57_DATA = new string[] + { + Intermediate_Certificate_PL_01_04_crt, + Intermediate_CRL_PL_01_04_crl, + End_Certificate_PL_01_04_crt + }; + + /* + * test58 + * + */ + + public const string Intermediate_Certificate_1_PL_01_05_crt = + "MIICmTCCAgKgAwIBAgICAJAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA/rVBEGZ4jibDhREeRGV3jPnv05esRL8/En1Bu35y" + + "QrAHi32+kBu42vwwDbeuiTZd/B90bn5srJZoW83rxXxNnpxqbnjN3GgIcRiUVyaVRTp9/U" + + "IT8B9h09b9yT8gpQ5qR0+JDcOHCfJwpogAsyJJa6AM5p/q3TeF39ugfVOWt/cCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECJ7/mkuLuEIGMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBADC0A2KMMSSmGI9p85WG7XZVMBX/xdDYOHO0e3ORTRFS3kj9rK" + + "a0yUjc1X+p22AA8kUyOLpYIulfDjPrLKN2E/hWSf3+XWMiC7JfX01F+BBl/avEZoymaZB4" + + "dkH1Hym4IMJoSaEOgf5HFKBnFEA6aUcr+oDYGUP+Sc1dmJMjBW72"; + public const string Intermediate_Certificate_2_PL_01_05_crt = + "MIICmTCCAgKgAwIBAgICAJEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEArir4GaS6r0Tv9PMbaOXYdPKADNpVbJe79G5t/F6x" + + "7Tz1rwUR+m10E+Jq9RsV+fU/nUzzjJXHbPLZnfodUVVmrXgzvQ8+B2N4jJtdNLG66j2PZG" + + "+P8GQzVK9drDh54VHXdvxAYCXs7GaIprWmCQsxZOKjhFU3YDiRRK8qJGpBG/cCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECMmrFr30fUzZMBMGA1UdIwQMMAqACJ7/mkuLuEIGMA0G" + + "CSqGSIb3DQEBBQUAA4GBAI4qJF6STCi+elUbpZIP7YmcaQsS0PE4G3+LJoMg1LT3rSeobK" + + "Aj/yUetmA7y0B5i0svKjRChLOpfClNPVPCx/+mc75+LG+dh1eVG/qk2UH/lrqLN0XLl8tA" + + "IwZeoPaegBQAIp9oEjhDN1fWtKIkOe6A6wYdH2VPvsqC8g02VcwD"; + public const string Intermediate_Certificate_3_PL_01_05_crt = + "MIICmTCCAgKgAwIBAgICAJIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtRC2/PDG3kx8LpzfWC0yJph5h3LXZJZW0W2voss1" + + "HYPP1/MBoQY067dfbALilVRh9asCNL4F45uu0lT24qS9vjW8SzBOLA18GsVYRmWO7EP+Cd" + + "9f3mgPIMJ5n+UjW+yhBwh0Z2pzVElkX9CxECrs1Mt2ulyuwWA1lR8nRMaTUeMCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECAlV3mzXYPyuMBMGA1UdIwQMMAqACMmrFr30fUzZMA0G" + + "CSqGSIb3DQEBBQUAA4GBAG28iHdlA+nTs/b9pi+m9eMy7niELjIWL9fMgn1r4iXQ0TsPYi" + + "tgpoip+BB4G/jz7MPx/N4nwyAPV+C9wN8cAHALf/ka2MxAORYFVFI+5PDgXzm78ILqj91f" + + "vOFN4jemizTES4/dHxfmdctnsTRpU9ALQgfJLhxEQISOPwuemKB0"; + public const string Intermediate_CRL_1_PL_01_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAInv+aS4u4QgYwDQYJKoZIhvcNAQEFBQADgYEA5i45" + + "gETFAw6l9Awex9IAVIqYTA1dnbDyrUYDRdzd0x6OxSPODvNfQCwqwlTJXrHidCPO8jRhMS" + + "Zcdn/MTlIeHa6OERFcjOiwOpeTgtchvpTdDchs5ve8Ik+myue+cfgpEVKOE+ZQ2T2tcyz/" + + "+DbeMptECfJ0lVfCKIY7ZOzBPaQ="; + public const string Intermediate_CRL_2_PL_01_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyasWvfR9TNkwDQYJKoZIhvcNAQEFBQADgYEAdsNe" + + "ugM8sd8bmIDkYXce2WmS5Zx6QUQ0yT6Ij4OR5/F4CG4Vl+k3JkNPuAiNSs2Z9HeML+F/W8" + + "3yEPe/mdLV4nLw4B/b1/8DmgZN4r1ojaWuHAg+KrA3Zz3Rc/hwQfvBy49mf4NGtY4ArbeB" + + "DYKz5sVlrwR+gOCR5jm4IC7WEDs="; + public const string Intermediate_CRL_3_PL_01_05_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAICVXebNdg/K4wDQYJKoZIhvcNAQEFBQADgYEAqYex" + + "FaIykZo17O2URpofe8x04L/VsfA9jV28zUgNFruAGld/kUh4rYvgwrdbNZ8NmEFDp9J9aL" + + "93af3bzoNvWCik2VrQLd5nccCFiC04B+LUH9Y2p+7vV2ojrtBks5SMW0q4HaNyPSQu8Fst" + + "4mYVf+QIYZC3iVAF4rsKnaxwzIU="; + public const string End_Certificate_PL_01_05_crt = + "MIIChzCCAfCgAwIBAgICAJMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA1MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXJjzKGcLyONTyOa6sQHvIKZIAh0pWdteUiXf" + + "b7yjCn6Z52SCHxB9GZERHwR7fbJpoE3oDcYUY+8pH65bIVm1p3zr5deo4v85DEZQ50cU9a" + + "WEUAO/5X57P7pYb9/47abu0cdsLIWeE+O94HpZS8vz8mxRQKLj27gPY1KzzTbrZQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECG8ILlM9oqZwMBMGA1UdIwQMMAqACAlV3mzXYPyuMA0GCSqGSIb3DQEBBQUAA4GBAF6S" + + "x3aunfgnDmo42aPOzDh536WSkTTbX9bmUNyg3IQHl/3xhVqjS76bMqreYhx5nh4VNx/Z3N" + + "LD0W75XmASCk0wtW9S1MoxzJMFIozRruaE3oykrbyMMOt0Br5CV12ofUd0WybDkXfNAIze" + + "IRgps3nORHWjV1GwXe8uNoUn6/z7"; + public readonly string[] TEST_58_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_05_crt, + Intermediate_Certificate_2_PL_01_05_crt, + Intermediate_Certificate_3_PL_01_05_crt, + Intermediate_CRL_1_PL_01_05_crl, + Intermediate_CRL_2_PL_01_05_crl, + Intermediate_CRL_3_PL_01_05_crl, + End_Certificate_PL_01_05_crt + }; + + /* + * test59 + * + */ + + public const string Intermediate_Certificate_1_PL_01_06_crt = + "MIICmTCCAgKgAwIBAgICAJQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAweCAiEGMLycmodjrUMIWEEFshkvhX2r90wGl+/pU" + + "Ia9NSdT23zYzE4Uo8Is1ywyV+YfvgR22j/RXF6j8OK+XZ8jlgfjVTAhjCnTWY9LDR7qAyk" + + "8zuuITxJrYpiPoxqZs9BXLfGkDbye5VpVJXvQdbJNxgKO0hkBBDfe+T9+qw6ECAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECG1DiuoAwV6aMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBAMFvtFiMDMP6n3CrqQLSzhpK5Qu0uxa56ARXIKSIqi0OUZAu9v" + + "sCXxMvaG/R5bElwi7ybYZ5KUSN+PnDmlUxWWL5Ib5RZdXgj7L83oyLTQmbDMvka6rSWHgw" + + "Jq8qHVslhh+l+YNOb4fzs8x9ctCrs/BgjX8wkORpQbigU0BUJ9sX"; + public const string Intermediate_Certificate_2_PL_01_06_crt = + "MIICmTCCAgKgAwIBAgICAJUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwf6Nf0+r7JvE6BO4MbDbS1T1SCzn78haBAmqGZLS" + + "Ac4xQTydvmzr9PwiWlU0xjFfKItqRMt7rfzTTPfvvnwxsAfQNPtxKzi30yCNq/VotMA7j5" + + "iQYaVe2OWVHu13agbXLEZ0pL/ZkmQ3Gvo6UhF4dRmCnjFbd5cMTxQVHUrwgyECAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECE3tS4AYmwZDMBMGA1UdIwQMMAqACG1DiuoAwV6aMA0G" + + "CSqGSIb3DQEBBQUAA4GBADcBTKbhx8PCunjRVJkcLBCcVGHs9HfkChDafwBO51fe5uhHE2" + + "QBpW3J8ZsevuFQiEZvuy2RVFktE6ZoKD8wxwBFhs+OIxe2mergQPy6jHuxoSUiPzr3CVXZ" + + "UsNxe7j3IcJLqbJ15UqGFH5yph7Sa4Ym6x747miF6W9knNkjcx3K"; + public const string Intermediate_Certificate_3_PL_01_06_crt = + "MIICmTCCAgKgAwIBAgICAJYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwq2YlDLHX4KktKnzLCYjnk079IDgXENrkRBuZHTB" + + "IQyZoiBH4ZWHreZKs3LvznP8uSd8eEL8keNw4PwZ6aT1LF/Jr/UlrFQNnpLzQVXwGGAuzh" + + "tFJYRlOfI5cCZYAcpjnyUV4GW+MuwBdoqDycMjmqIv/8A8vupjahffcmBAassCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECB+qYFJjEkJ5MBMGA1UdIwQMMAqACE3tS4AYmwZDMA0G" + + "CSqGSIb3DQEBBQUAA4GBADiXredACtRQTV2TKgu5SDdPlczj7cZZUARJiJKiRfjmxHCc1q" + + "m/Oh7sHkqRvlHqjoX8qp4iSchoZWdOAE5O/q4Ef6rViejDFVyN2ZmlhP6KIiRxznrvYfF1" + + "n08K7CHgHWvDaumm4pNmWeF03nuasHrY0W9h1uk5poVuzaWDpx3A"; + public const string Intermediate_CRL_1_PL_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIbUOK6gDBXpowDQYJKoZIhvcNAQEFBQADgYEAiHM1" + + "xFuYt6tDscqzwj0mLHPHULnR44/vNyPUg0KnV03Dd4XbFHz0FtwDKgVTBZ8x7ybp83ubJH" + + "tE/p8nPW5kN25WQOlYkZoAcMpEXjTzlo9evU0W3nyzJjmlT8YEI7vnmWFz/ahzy6WFwPue" + + "h862EKh2zVO4hoqZYEuDQI33fOc="; + public const string Intermediate_CRL_2_PL_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAITe1LgBibBkMwDQYJKoZIhvcNAQEFBQADgYEAuDSF" + + "W1KOc4x41HGvdRaw/NtipD2y6zSh3mtRoo7Q6J2BvJvunymZNEziozBOiUgT8zMgbdbm4a" + + "PEwlHRaoJP8+yxJIlKaHa9Hc7Yz4SOwSrLicf7EnBSct3Mze0b48UYqbn1q+lf/zKaUGrP" + + "M6oqtE8Fam06T+WUfutU53zTtSs="; + public const string Intermediate_CRL_3_PL_01_06_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIH6pgUmMSQnkwDQYJKoZIhvcNAQEFBQADgYEAcPfO" + + "+Rj2KmO1CxjuKLEiOUAIq5YmR4U06IcCBGMxlrdHVXHM3vepBKUlMDaT4UGcleABMPX9Iz" + + "/31ofyXlZ/fQJOoTZt0CI7SOPQE5ZkUsR3BDuUqf1+sWwBYyBHkrC95JhJkM4LfGS5K19p" + + "fp0j0bguzNCXSBRTfjSZhy80tcs="; + public const string End_Certificate_PL_01_06_crt = + "MIICljCCAf+gAwIBAgICAJcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wNjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3asAqJcjXngEuyM/W3+TAE+Qr4JtNUdwBtmrpGlo" + + "fAvJdmXHARyiN/Zn6Si8bGI8Wz8J4Y+Ll7zLdaMU4MCZo6hwZiaQwkh9a+ZecCpLpjs4mz" + + "MSf5zHSwTYiXKMazlmnGEITVyKLmAiLSyGeeJvOJVqVo/NZXRGVlmnPxZFfgsCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECLZuS770NcDsMBMGA1UdIwQMMAqACB+qYFJjEkJ5MA0GCSqG" + + "SIb3DQEBBQUAA4GBAGM18aR2i8vSywsWhcLrRN1Xckl/HiBPNphobfKoER4NG29cFjUPQX" + + "zukjQcJl2clAXNCVtcsKCoYRP3YUyAB6At+yskuuJXtES7FIzM3rt/UpDS5ktVC3gh+jgE" + + "pPhMILYIXFzYY1hifkpagfO+mkcr7RqHU3tHAr6LCWjqrB9g"; + public readonly string[] TEST_59_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_06_crt, + Intermediate_Certificate_2_PL_01_06_crt, + Intermediate_Certificate_3_PL_01_06_crt, + Intermediate_CRL_1_PL_01_06_crl, + Intermediate_CRL_2_PL_01_06_crl, + Intermediate_CRL_3_PL_01_06_crl, + End_Certificate_PL_01_06_crt + }; + + /* + * test60 + * + */ + + public const string Intermediate_Certificate_1_PL_01_07_crt = + "MIICmTCCAgKgAwIBAgICAJgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5HkS45NLuqq9ZwF79+pTGtQnGWO7DFdetYeQTbeD" + + "sisjZMsK0sCCR5xAKYQsJSS4v/8LQUdxlQR30LMV0SQUKFMJyFsMiSsO8subb6sVINWn8A" + + "tL4zcQK0WiASUZOEkybAFJtP31PahzI5wfD1cikE1M4BlDij5WeaIjt/RTHKUCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECLSUEn5d8YywMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBANLO+kEiswkGzEh4ZcF5LtfnPZlnG4gTPSNugeWJc+Xedqmttp" + + "jZ35fr1hiRe2Q1UcyTd4ThkPknawwZednbsZVPqw8u1mo7kuAeL9KrCk199vL4bV8Ag/kj" + + "HJ8TAy40UDB6hMm7l4j8mEKwV03THVrz1Vvz59CQXj+iseH6yUNO"; + public const string Intermediate_Certificate_2_PL_01_07_crt = + "MIICmTCCAgKgAwIBAgICAJkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu78gmT5HwmBHEe+K8fLLgGaPpcv13ZjrgL4twTBS" + + "OkZn5LL9GcfkPuA5WIAZkVYfCWSDPqcAGoOWUIDADfBfdcyLteUH+xI01rHKiLDVexMvU9" + + "vqCmcBKhxK3S6wraW5YhOO0bx4oPrZXVIjyG8fh4e5WTEykzvUWJ8ZbzSJ9JsCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECCT+fDEaN7GaMBMGA1UdIwQMMAqACLSUEn5d8YywMA0G" + + "CSqGSIb3DQEBBQUAA4GBANpKr98PiXAdcXlbgSgif0213H+tg3WwUNKZTw8MpqPyrN2/DZ" + + "HBi6e2KWXLTxttV9AZBRvcKwsveS6oc31eulMe8nHxRNRfadvF6dL3Tsig6HAQkartcJMI" + + "yfW4V3EhXbCdziQkre7XcR9WK5bpQoX04HWeew6YTxjG/cL9MIJR"; + public const string Intermediate_Certificate_3_PL_01_07_crt = + "MIICmTCCAgKgAwIBAgICAJowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr7YezMXvnkSuNCdXch2HRAEVuCqfzpVRCj6laJI9" + + "Q+NxgXwzaOwnImvwER3Hblh1l0MAt5/I/9hhqCN+918ueME50MkoM1wPbcmrRIlwWLGSVZ" + + "yBKeyPHrLbdPqVIexUlQk7PasLm/Qx4SvRGVe9IMLrEzPV3MFJtrJoWaMobQkCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECKw8JlHMvVfuMBMGA1UdIwQMMAqACCT+fDEaN7GaMA0G" + + "CSqGSIb3DQEBBQUAA4GBAA5JEDEDyqfZzTGzOoMV+8RVke+a4qgOo7rnOEdletgGFEwz8A" + + "tiMHBxR+UMxuHS82Hz3+F8XlyYIwlrG9wWVcB/tOyzgVyA28Yux9Q/meU7T6dco/AnmOdr" + + "2XL6Xm5iLnARG+PkUPHOsxuweyB/sSUSA8ZJPowNRWTik57ul/bO"; + public const string Intermediate_Certificate_4_PL_01_07_crt = + "MIICljCCAf+gAwIBAgICAJswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wNzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7mNS8dGz0gkXDbBRzP2ypdNMahJbM3cSMHO0hYpn" + + "uRsiXGUhIB0K4WVbnz6tr7Hch3yltK4H1Y12Lf8cXEETR2sE9lCY2A3r8/VM5OUbou5Y8k" + + "wIf03VhP7cGKonaFtlj/WD77fidDePVp1Nk28gV0T2F/l4pM5TEJrq5C9PSUcCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECJBEcZsMRq6CMBMGA1UdIwQMMAqACKw8JlHMvVfuMA0GCSqG" + + "SIb3DQEBBQUAA4GBACfbHKpuRJnZ5UU0sih8RuywhUo6Getwl/p6fsi87wYI61pvYru+hm" + + "4R4eAMZvg7MrAarS3Iu3zKBU1HKeq1i+hpwTIXrngR8eL2fU/X6GPzdte3+3tjhah38bqF" + + "zDon+N6ap4MKWRk033SsFYo1K88Mena2tGuFForJlV9DOF1l"; + public const string Intermediate_CRL_1_PL_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAItJQSfl3xjLAwDQYJKoZIhvcNAQEFBQADgYEAJtaE" + + "I1+PCNL1/bgEVKWUIwvh58ugnWhxzbFW6hNJwNEz9/yt+FLZfNrT/Ezort4VVQFLQg7+Gj" + + "KrkIujqfRJG4LXrXAV8ZsvSPuwyQ+hM1GdHGDPhj9x6DkjFusxJYUEs5BzlX7ovpnaIPSW" + + "RPsatheSzu48pMOCmyTKE3MpuZg="; + public const string Intermediate_CRL_2_PL_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJP58MRo3sZowDQYJKoZIhvcNAQEFBQADgYEALiV+" + + "BFpXhgTjiMZBYLVuc/fqhHcXeXOGOmJZoKUnIXjETH3rzkkt5k4tMN00ycZVgpRwn3ZyQs" + + "cFLcW8taau1J7iQOmGY/7qIT0eFx2OlgNmxqirmwx4OM5VSH5mEpnp9NOr1rfut1GDRzw0" + + "tZ+nhD/PGDXYPu+QPX6jii0vdHo="; + public const string Intermediate_CRL_3_PL_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIrDwmUcy9V+4wDQYJKoZIhvcNAQEFBQADgYEASY47" + + "p94jEh9FZ1TrPS82nWC3Z6ZKdaD9pUbaJpRnAId59QdBaD2Cxq+SfM3HTlz8grCAPKwulv" + + "jDDhXhp4H/m63Q/pJbyl3bbMxnphMOoDwB9wwKIUQPM5wagMovF/UYtC8MoC++m2kuZ1eb" + + "fR/OIJuQr+k/kD5Axhw/xolKPdE="; + public const string Intermediate_CRL_4_PL_01_07_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIkERxmwxGroIwDQYJKoZIhvcNAQEFBQADgYEAMhIQ" + + "lE+BdCO6NBz+YgcH+tjP0n4OCdQ+7uxUxUYmPtPbsLwbDDEEZUjykgwiA6P47Cqh5fXB6G" + + "tfInh1cmQi3y2IEHK+bRSx321qczOh34Yx2hw5vp+JFttbQAEl/BHixklrFBrXjN0UsWGC" + + "ibXcZy0YjerWTp/yceoABz9p94U="; + public const string End_Certificate_PL_01_07_crt = + "MIIChzCCAfCgAwIBAgICAJwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA3MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdH60mBM1eInACvOB83zLrtiebq9B5UBlAAVS8" + + "9ucDwGx1HOJwhwk2AmvhN7pYuDc+BFzuNtgHojqZSDpRMA3rVsGlgOkZ3sOQzvxB73w+/X" + + "XmCYpwcEGLpK4egl8r1aOYm0Zm4OxqWhNu9+Do7nrJczDLi8k/qh8/+Rfdtvt4kwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECEmVurZ+7UXFMBMGA1UdIwQMMAqACJBEcZsMRq6CMA0GCSqGSIb3DQEBBQUAA4GBAANe" + + "AbvpAHwBu9+FlI4DOb65Z+h5f2Ok59FVbVqAj3zkMRkawppngK3CMY/1BQlGXOlHvE+CGz" + + "x/7DsiV0O3rxOUjutt00PNxCyIM2pcOZeGUaAu5DJWn0SRwzTMJa4M5K+7wh/4sSPWyxKi" + + "ueDq2VXvIgAfEVC8Lv44sxcOduSZ"; + public readonly string[] TEST_60_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_07_crt, + Intermediate_Certificate_2_PL_01_07_crt, + Intermediate_Certificate_3_PL_01_07_crt, + Intermediate_Certificate_4_PL_01_07_crt, + Intermediate_CRL_1_PL_01_07_crl, + Intermediate_CRL_2_PL_01_07_crl, + Intermediate_CRL_3_PL_01_07_crl, + Intermediate_CRL_4_PL_01_07_crl, + End_Certificate_PL_01_07_crt + }; + + /* + * test61 + * + */ + + public const string Intermediate_Certificate_1_PL_01_08_crt = + "MIICmTCCAgKgAwIBAgICAJ0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wODCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsr+i9HxgO6LnOa6xOHfe9BeLVTo4iZd8rp6UTc02" + + "C0MmsSjvIgn3UiayU7aoHcTH8tAXSV5bn0CIH4B46qLym//oE69hUFImy6d1kKgNoaUKWB" + + "HztKVtswSSPjIUf7pbyp0wasYMN6fIKYyLpLXUxzA2DrD0kP2Y8ElQJKl2HocCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECPMW3WMPtaowMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBAH2N6S9ggfmRJkzhs82uOPXaHF62YEg1pbNxaCyJJbSt2iIIyy" + + "NPSlE1OufPPH3pO7p5xcYi90LCI//0tlUL8y7aULFNygbshFY3B8MSgCz3KPA3UKdtIZYe" + + "7lqP9/ob5wmkjtLpx6oZ4/38jxqe37pH1IwVjaUnoeElSo3EkCI5"; + public const string Intermediate_Certificate_2_PL_01_08_crt = + "MIICmTCCAgKgAwIBAgICAJ4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wODCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqZZolrig33i1rEwdP1pin8a5PgzSk7fT+qhrJRCg" + + "UTOW5WyPtakrLTUipDcR07t8tIe0NsjRoph7+fAwbjWBfbJdydndHHGx5BqWg8Xi4zFhFd" + + "6Mc5O6KO7Yqxs8lmthv/RAdL4Eiir9d9hqskKOtQKbLWz+Bz3+9NwfLGzwzPcCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECFjxM3RkbbhNMBMGA1UdIwQMMAqACPMW3WMPtaowMA0G" + + "CSqGSIb3DQEBBQUAA4GBAJOJKBubTS/kLnfXN5YbQfggxbO2c7DTxx2LhrnPiyVDEow+Xf" + + "lMv4YK5olH6UUm02D8cv6Wxg4NeTtBBnwKQG/GV4Ssgc/rrpEzM7jFRQcUzPu0jfya2fX8" + + "ZNBnSDjovlN6vmZHtiksjh66h3a0aVusEuOQXD29ogMR8qAGYQaZ"; + public const string Intermediate_Certificate_3_PL_01_08_crt = + "MIICmTCCAgKgAwIBAgICAJ8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wODCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAogLtEcWxzzkkIYe+KrwKhaQjjGQqy2KDsW00U5lx" + + "+XJoT8eKd5pxFdCa0SPn/jkNILVeh07mIHec1WF8SOeveVT4Ewd3nG/6ZGoVVq6l0j+3RM" + + "jpJbp26BPR69nFn6rmFUMoSNq0VG8Zl+UBqnjq83G3umJCJMMRekUTULSFEGUCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECGAFYeJIhrRzMBMGA1UdIwQMMAqACFjxM3RkbbhNMA0G" + + "CSqGSIb3DQEBBQUAA4GBABHamiW7sPLQ83nXt3LZemcAp4QaDB8X94EuJGBwshEcKLoOHb" + + "/3cZkPRbOiRQUh/YdpfyApndGFSi0DtwM2Z7yup+MzdrR0wzQoNS95A51nHE7XdCuVFemc" + + "LTJ5rdd2BLK3OB5lQagVLzAY9Bs1vaeXKT2Cy+gSUkTIekWcsH3K"; + public const string Intermediate_Certificate_4_PL_01_08_crt = + "MIICljCCAf+gAwIBAgICAKAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wODCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxVjjKlLlZzeZhamPO2NDnRtWM1oWZ3/kdwdBRn50" + + "o1NRXb60Ir2HjniK1dRdbijAvR5uItLe9tmj4nusBiaPUGM0HNlEdQWSzble8rvUsP0apw" + + "uJusV7zLvzwwbgLbMYT+8lMhxWXM34xszP+dgjWASQOVao1Uqs/MLLibOuueUCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECFMFrvh2hQ18MBMGA1UdIwQMMAqACGAFYeJIhrRzMA0GCSqG" + + "SIb3DQEBBQUAA4GBAFsCOJ4DzuMOKti5PvF71ZKOtcTHSv123ZNdPIbK6OatT9YhVuUOYB" + + "AjMavggywrb+QOXOFfJMctQlS3y/JE9YyoNNt/4UTdx1jQ3I2ablonmzjt8eN5GJ9jUXth" + + "fHjxnmGUeWlAvwMjEdzdigkyuWCi9LJfjyHtTjSf9n7w2rU+"; + public const string Intermediate_CRL_1_PL_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8xbdYw+1qjAwDQYJKoZIhvcNAQEFBQADgYEAG2Aq" + + "R1oelnrTgh56m6Mm+Lsm0Sf+Ot1W7LzZmMDwoZgmGLcTduVktx+XrtiDDWsf58hmneT1q0" + + "5wl4yNH8y/VCAA3SM/gOq4ddOEiS8GbuEYo5P/julH/U3g6M0vfPUZ5y+7V0s35jIbTkjX" + + "76n3Rhf88nvTscYvMdqrYyUhAmg="; + public const string Intermediate_CRL_2_PL_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIWPEzdGRtuE0wDQYJKoZIhvcNAQEFBQADgYEAX/+I" + + "DkAx7PLTi2x6aYbLacPRaUSjMne84MDaEkYiA64Vo3eL6FbKe14z2mBsM2W7x8xDnxjZ0N" + + "RbhcFZ2E6A1ct6HMunuKxjoROIsdWhrYMqJfKKMTWMviz1UjtupsGUWS0dVQCquAr6DJmr" + + "W88P8wgiVH2VZsc+edDmCGDunrI="; + public const string Intermediate_CRL_3_PL_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIYAVh4kiGtHMwDQYJKoZIhvcNAQEFBQADgYEASw1+" + + "6rGDKgpUtXcCziQCjy8mHFD2zV6x/Ppxm2Gj0U+5eFnIbMPmr4TUYwfSOROUycsiJX/Wa8" + + "HEuqWJhIdcsHMA7TYf0iSXK597Bljjg4F/1Rgz0wqLjgMuA59eFbKjJ6zP1E6Sv2Ck0Ea9" + + "HJsv5zFA1ljVnNWoQwoHsuLk/wk="; + public const string Intermediate_CRL_4_PL_01_08_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUwWu+HaFDXwwDQYJKoZIhvcNAQEFBQADgYEAHHKd" + + "U1SccTsK99BUDrvF930ejNRAvHQM9xv80wcUAy18x+TLwBH8vDTmP210/C5Zk9pQs+rLDd" + + "doQQbWJrQkznyB1OSK0T41KZ9L0UE+YmFGJjz0PEzYHV0Kc57j5uc7Fsi8Xu20Y8JeTaJs" + + "FUXVsvnCuoSxYmwY1futFWHJG7Q="; + public const string End_Certificate_PL_01_08_crt = + "MIICljCCAf+gAwIBAgICAKEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNS1QTC4wMS4wODCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwgNkhQrcqmjhkES6DNAW3uQLKILcFlrFvOlWfDPo" + + "ngXzCKeed85npqL+Enxo4sLarEiywuDLrDgPf0gKnZXQWBmzWViZhvTsiAemH7iNsNS68s" + + "hhb0vnLzlPpDUJDv7KVKW8VbM7nvplKptlEE6g5kmj3iEmM4l2u8Z/pmQoTsMCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECLfApJ09y/ZNMBMGA1UdIwQMMAqACFMFrvh2hQ18MA0GCSqG" + + "SIb3DQEBBQUAA4GBAG2ANLc/ib9ayz0B0L6/XQf/xuwETEq8kb5vWml/PbcFD1b/uwRHI8" + + "vTvM559nZgtzkhS5ZAvNBTh1CB9Ox/nugHc4srbH6/Wcd94pMQx/sfCB/C6zZ5Tbm7Y4jp" + + "hkjnxwGUYTvgNzxmaAPLyCfqY7KwhCSzns2M+yuncEKqlzuT"; + public readonly string[] TEST_61_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_08_crt, + Intermediate_Certificate_2_PL_01_08_crt, + Intermediate_Certificate_3_PL_01_08_crt, + Intermediate_Certificate_4_PL_01_08_crt, + Intermediate_CRL_1_PL_01_08_crl, + Intermediate_CRL_2_PL_01_08_crl, + Intermediate_CRL_3_PL_01_08_crl, + Intermediate_CRL_4_PL_01_08_crl, + End_Certificate_PL_01_08_crt + }; + + /* + * test62 + * + */ + + public const string Intermediate_Certificate_1_PL_01_09_crt = + "MIICmTCCAgKgAwIBAgICAKIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wOTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4slldx8rhfz5l2i0rwib2McrCyQkadTjJRoEGQCV" + + "xT0dmw7GhDa6wJg2ozXLLk5y7ZCwlmBOTEoNbigHvcKSnJT8R/S+F4KqBz5d5dbRMNEKYz" + + "jdbD7Sm7id+eyfq1s5cpmta2lBJ5gTaC9YPSOY2mucGcJ1muYzdOc6h+PCCNMCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECO7tq4dJC8OgMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBAHbth0HjAygIoWVrz59ZBPntOn5nzgUGpH60aSDOS6i9ZOKSoC" + + "7wCOEt6IpKO7M7SNznxaX2uhFTYotneyq3qENvqZVXKhE6wQRsdK4kG10cxSB5AXPHJRgk" + + "W9+p+Nb0iYVKwHdDCW8KHYIroGhSkKxuflwxhK6DcwQuA7y5q7r7"; + public const string Intermediate_Certificate_2_PL_01_09_crt = + "MIICmTCCAgKgAwIBAgICAKMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wOTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA70v7BFxmToZHF5M29JK6N0Ha6n729cv1U912mH9O" + + "NTz9tafa+jv4W7njScv21CJbNlUO5rlAFcTlXY0U9vbqHEufhtwRQqi7+pkfa+Ig8bwl26" + + "4U8L5rgmSvZJpEiiKfkmF2Rz9+zPPhHjk58ZcKoAcyhOdZ60KqmaaU/TVtEq8CAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECKOwR13+P/BlMBMGA1UdIwQMMAqACO7tq4dJC8OgMA0G" + + "CSqGSIb3DQEBBQUAA4GBAN71oLHr0+uf6zCOC5L7oeCOGMUwvZyROu8eTztZrPYGjaamSm" + + "Z0ZmUPOJP3g5nO6tHf34Tb9CTkwPdPicEaXuxflkSbJBV3mUFQ1BUDlyYTuaL8uT2N61dg" + + "xt5RgYTIGsW3/2XrRvXsH91gSiEkccoUyjKnQcX3oZmEeITb6H8m"; + public const string Intermediate_Certificate_3_PL_01_09_crt = + "MIICmTCCAgKgAwIBAgICAKQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wOTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwMLmDs63ai7i4xC/1ufMFWeigJAlbKWMti/PeEKi" + + "7LBfNJDRaO+1kde6QIo1vhkhKtokNu9ue3Rfo1+xGuZVohjRbHnmamEm5G3jihegPQgGCR" + + "fDZoJDI9HMbwBa0RWw1Nes5igIVjdSHQKO/XTul1yyF2Dt03K2qeLwes+2FyECAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECPEAjG80q0FoMBMGA1UdIwQMMAqACKOwR13+P/BlMA0G" + + "CSqGSIb3DQEBBQUAA4GBAN9eiZXma2n0XgzdvYrlV/IEqBIhpcZ7gycjDumVBVITZJD2sJ" + + "bkBi+N8dg7uovgxGxWGsyxqgAboLhMgbpbFzGh+HyIhQu/CeAx93PWYc5rP2l2Y8d7KJvk" + + "p1GZEcG/nTakpjxTQ5MQYFsOHVsnDDOyaZYvqPuMrwGYsfoUa1wq"; + public const string Intermediate_Certificate_4_PL_01_09_crt = + "MIICljCCAf+gAwIBAgICAKUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wOTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo4L9QEqzq2VXzkZI3cvUWR5v6vreKKQPfJPfEwNH" + + "nMS0cgDjC4Fnw9ySI7Eb4A/OJGLIyg84mzTl6JX3kGoYr9/bJ8jOD7pN6CljXuHpwwmd7L" + + "6Nf5Hy0ltjAIr5s67e33OWdPi4gApS4FN6nPSDkZotY73d1xqJYQQZWuNEsGUCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECLfU7BuxzXeCMBMGA1UdIwQMMAqACPEAjG80q0FoMA0GCSqG" + + "SIb3DQEBBQUAA4GBABmQZOvwRpVsTD8uazfQpLJUZkuTap4OOPHie5xJsvOhGend2k+LiP" + + "7btGoFrqmkyVV/+dNA8+45SRsnoOtgctiF2ubeqIvd7xf/J5C9Cmo+T89Mt7WEBEuDmEZm" + + "JPXvOvyh6lRcYVSBnvVW5ZSstNAQKa/8xuyN0OrE1hJWbucn"; + public const string Intermediate_CRL_1_PL_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI7u2rh0kLw6AwDQYJKoZIhvcNAQEFBQADgYEAbXc1" + + "QgR2TAvOPqJmRFFrDQkPVIVyEEDTwZy5aNnoAKK+AmJ5FZkBtbPJ8qt9UeYRh8lbX8+EIk" + + "tyrAKw/1Kc3h7RDqAQ/p8t8kFwVQh2l4KTIukV8hYcj5sMKlt5f49ZwzWPyoOaLDomiUfI" + + "OY/jaDMw293AjQXxGCDtnaTvh0o="; + public const string Intermediate_CRL_2_PL_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIo7BHXf4/8GUwDQYJKoZIhvcNAQEFBQADgYEAq6en" + + "XtvIdh/DifGzWn11hqJIZxLQDGJZPoMmwSOLyB6OzsPrIg1xkOWZYEOELTR8+qP6emmx+D" + + "CaEbUDLj60rso0gRQCBwTgHgjeMRpv8fGnV8MJgMv5BdzsGAGQbLSSY9FxtqeCPfZ6olHC" + + "iUIopdZJZP8ZvGKQ6QGaMnLpJ78="; + public const string Intermediate_CRL_3_PL_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8QCMbzSrQWgwDQYJKoZIhvcNAQEFBQADgYEAraCx" + + "ruxopFbKvxOx/CIF4niG27ABB2ZwU6n4NBGYHo1Y9NjuytjjMZvQjMHyoayqpnF5TA1vXL" + + "jXjI3VgQcK7A4ah/0FNLFGtczyY8kXXrpbmdg8+xdNJEG3/e5rDW5VSf7OY1XqU85ySUJQ" + + "ZR5uiy8LxlDdaIT4WT7X5ezs3wk="; + public const string Intermediate_CRL_4_PL_01_09_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIt9TsG7HNd4IwDQYJKoZIhvcNAQEFBQADgYEATtjA" + + "BdSZYnIbv1bCL+aSiioJg9S9yWGD1mjsA/CDzvkzSffeSpvqaSy+Zwwf+NDMMG6Cs+SgU+" + + "sxQdJALAbb4sYGEyXj/Exh9BYHvgoVahH4NWuhm6LIN8RTcMDAtGoGYFNGXGuT8XRBUJZ/" + + "tH9re3gpWaE1rjWeB/2ZBR5ONcM="; + public const string End_Certificate_PL_01_09_crt = + "MIIChzCCAfCgAwIBAgICAKYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA5MIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+g1Puqjn+/Of35mqVVUricIV5x+bpZRCAgBDh" + + "VYcmZFXLB/XnRd/mYTu0RR4ISEerC1km5tjGeCN2k3NGdZwz/wEh9kEL8WikSqpxUSUD/N" + + "vQbliz4f3YECLcpNXKzkCvszeB5ZGHa0sLYDg3r62wy+1y2rtcrHzFEoMFgnnruwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECANGcL2klYf7MBMGA1UdIwQMMAqACLfU7BuxzXeCMA0GCSqGSIb3DQEBBQUAA4GBAHm+" + + "/vQ7VxDry3VqiqKnNoOhAHTTIUphNWF4jddRqVc32IsjVaeTbcGwCIRflRm/lUplRvXXxb" + + "JEbW9mP3nfTCREUdm49hjmo/szsPjgosFoEmuEKXThC81/y2vQkb4/jqRoOHEknU++38EU" + + "Juv6Y6psZNa37x8Yn3i7S+b3TM2q"; + public readonly string[] TEST_62_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_09_crt, + Intermediate_Certificate_2_PL_01_09_crt, + Intermediate_Certificate_3_PL_01_09_crt, + Intermediate_Certificate_4_PL_01_09_crt, + Intermediate_CRL_1_PL_01_09_crl, + Intermediate_CRL_2_PL_01_09_crl, + Intermediate_CRL_3_PL_01_09_crl, + Intermediate_CRL_4_PL_01_09_crl, + End_Certificate_PL_01_09_crt + }; + + /* + * test63 + * + */ + + public const string Intermediate_Certificate_1_PL_01_10_crt = + "MIICmTCCAgKgAwIBAgICAKcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4xMDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr4LmuvhSms70CnuAHIHwz45csKvBPVtcDjA1tWNb" + + "NIvvNHBzyt6G8U4CTVKmsFAZOzrWJem3b/ZywM1WlDarGJAAa/SRIYZ/jQwaOIoPW4OUfK" + + "ZQI6MO7uAPcIQ4ugtPth10viVqZYLZn/6O26Q905YsFltuPFl64KrJVJJBlLECAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECGRn9ckrcsEdMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" + + "CSqGSIb3DQEBBQUAA4GBANK+1qalm7Nl+PJHT9nQLVJ3ruQNAoMlH9fN52Q9BZCr30iWCd" + + "+GhQIPRjxZ4GWojMnqbWzYQsxIR2PLdFc6SwjQrq+i2ES/LePDtaLQddS44/+GP/+qDpM9" + + "Mqp3/Nbe1MfOKRBT57qgrxa8eUVieysoKeYX6yQpa8bab3qDwOTH"; + public const string Intermediate_Certificate_2_PL_01_10_crt = + "MIICmTCCAgKgAwIBAgICAKgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4xMDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx5tMLJ3LRxi9jAzCSNkj8zyrSO0cImNGf6ZCIzEU" + + "V8LrmXjgiZboPTh9LWQ3msWDLpzaxVxDLBXG3eMO8ys46TfJKciyeoiB8wfuNGMKAccm8u" + + "43XjWs1KAdNikWEZupYPgdmA92oRlVcHshG9PqP4+xA6sydpu3V18Nyfa0n3MCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECDE3dDXkS7TxMBMGA1UdIwQMMAqACGRn9ckrcsEdMA0G" + + "CSqGSIb3DQEBBQUAA4GBAE+8cyOUQ7y4atc4BlZNZvGNRZ63dbGDCM2AItTEAf4ETM9v7j" + + "biUWTirJyoWsGxm2eIUk1V+EKxcuO3FotFUe7lS6thmVd6OYOSW+02RXMNklmptzK9I3AK" + + "DZNh82ugLNyrrd06BSiED+0MoGVVI4gi3wdFtRiai+MgQVeWIB4i"; + public const string Intermediate_Certificate_3_PL_01_10_crt = + "MIICmTCCAgKgAwIBAgICAKkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4xMDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmSUL/UZBYMdqU0PecjCd+9U+1Ld3mKkH303Fido" + + "K6k5S4ZObxVHKhYDJyp3CcVT2+nENjzIfQQQaA11UK7Uf/jmVs0IC8e2scWzq0W2BeOLef" + + "jVgNgXGsXyfLi9T4KJPPyGsKlIU2R2xKxgHmAOt/tw6OYX/OaEfM1jiQza5lkCAwEAAaNm" + + "MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" + + "lghkgBZQMBMAEwEQYDVR0OBAoECHYI07i4owpIMBMGA1UdIwQMMAqACDE3dDXkS7TxMA0G" + + "CSqGSIb3DQEBBQUAA4GBAK23Kx99Y9HtFBVnHWW/NfvNro7I5Wx/ZCko6ulHm84FPAjhnL" + + "tvc4jmfAZd0wYPKQKWwUKUDWNEwIU1qkxyJYACckue35GLzj8aLY/z+h037vGonFmNutMM" + + "rcRdiV7gVD17dYLVTt0RgxsDVDtut+twqHgIaKtKyJnl9dSgFFv1"; + public const string Intermediate_Certificate_4_PL_01_10_crt = + "MIICljCCAf+gAwIBAgICAKowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTMtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4xMDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEArgBnLCnqI6Sa7gXkZOvIKH4EL5i3CoG6eGG2R8aA" + + "kjBs78IKGYj9gY7rRajAKSpf19zvfcW8+2gBDDj5AoCy6uDnBICmqdu+hkdokVi8dJHiTU" + + "9LdS2TeuvFv47eiXoEBjMEAquCuSyHvW3lNrA+ESTnK3s7V4lBoO+o5mZD6dsCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECLTgYziQC9zmMBMGA1UdIwQMMAqACHYI07i4owpIMA0GCSqG" + + "SIb3DQEBBQUAA4GBAEx8wgBjBglU98rocddKAEKXkt4MNzrpUMq75C9HtnuOtFgM2oY/OC" + + "x67aZSTEph9ag6Hc+MyxWB5rzGD9j0y7OLsasE9AX8vjplUq50wq1xAFkGi1GnqRK/Oe7D" + + "S6R66+UFHW/3KAeNe96aaJuMcx0TRbfkGbW1ASSi/ixMd9Gi"; + public const string Intermediate_CRL_1_PL_01_10_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZGf1yStywR0wDQYJKoZIhvcNAQEFBQADgYEAjkY5" + + "nXjLst8CMz0fyEM7Ft2d9TOOJXV4TMAfSAP9QCnit8qzrdVdJ6TJIsJNZYBz9Ryr5K/iSw" + + "KbYk0g6y/pskcMoHG3vJwNAxBbkf+fV7Eyve+90Z6oWDXHKLGCQQpdZ0a0wAqYeiScok8+" + + "YHypEVLfbjWARR9fsci2Ps3tdvA="; + public const string Intermediate_CRL_2_PL_01_10_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIMTd0NeRLtPEwDQYJKoZIhvcNAQEFBQADgYEAdpTU" + + "xcywBjX2rD8Gu6zkDqlDmZfRXHDPtnf2RB4bHDx77kDEib6nH6DGoJdx8WnRTZsTjly3MG" + + "62LfVmjp/bJyKHUQqBDrilv21EWsaI9JOr673Nk5iTZa/645GdgyLzSmxvcVDN40BAH0py" + + "/2gvBQTPNzp2W1IR2mebuLdHwTI="; + public const string Intermediate_CRL_3_PL_01_10_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMy1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIdgjTuLijCkgwDQYJKoZIhvcNAQEFBQADgYEATVf2" + + "cEEGphsIe0AsqNJ5rENLe8DeDAV8R4XCKdeP5qmHmLMm9Z4pX8bIfU7bCoXiNIwGvIU6ag" + + "FmHPNHEj70cQFVqCX/ZESc02hit+Os9g7pcl7s9QgwVUCMZdCiF/+pSEp3eCL5tFoKmAZe" + + "nxkL0KOSuKmBzuqRtZufbhDvmbw="; + public const string Intermediate_CRL_4_PL_01_10_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBNC1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAItOBjOJAL3OYwDQYJKoZIhvcNAQEFBQADgYEAbG2B" + + "BhvRQ1pY/8VFeiCRFD8mBzq5iW5hWv2P7Zdp9zEbQo0fI4Kbis3OGemEttCxvAc/UPfogr" + + "UudImf3s8sLV9BS59xQUGQlxZ5XBNlripY8EjHNWrwgy7/x4hzlZ9yYBbqoNOqnHLy/gbM" + + "XZWoCbIK0co70lh1soOQ6eqLDKM="; + public const string End_Certificate_PL_01_10_crt = + "MIICljCCAf+gAwIBAgICAKswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTQtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNS1QTC4wMS4xMDCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3bx0qx8s4Zse6Ri6NqkLEKUPLIOhTFj/9Dh7sxvE" + + "HpemBlTjbp2in08WTxEb9n8iAIWuGs3Vqm82ttBQmayjIaWD5oE/BE0oV/e91NAv/aRLsl" + + "f7VtOb6vi8Ef6muOAjI2dUaUD6QONkqkJhnZ353uR3LZnsAEAW+InePGFNEGkCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECIokB8m8Vi4QMBMGA1UdIwQMMAqACLTgYziQC9zmMA0GCSqG" + + "SIb3DQEBBQUAA4GBAKBGQwZQLQFXb+/kjP5xAtq+1rRtrblytjpv3ujJrKH1v2VB2+9boB" + + "0YYYGJTy2Wuj0ZBEMeTzMO8Hol4Mq9pnYv5DCmfnZN3FuDidgnRsCjM3ZL7NcXXG9YwlKF" + + "G2SXj0YfkSwN9gnyN11W8i+F/OSjlm+TDKHB3ePMcY8EnnXy"; + public readonly string[] TEST_63_DATA = new string[] + { + Intermediate_Certificate_1_PL_01_10_crt, + Intermediate_Certificate_2_PL_01_10_crt, + Intermediate_Certificate_3_PL_01_10_crt, + Intermediate_Certificate_4_PL_01_10_crt, + Intermediate_CRL_1_PL_01_10_crl, + Intermediate_CRL_2_PL_01_10_crl, + Intermediate_CRL_3_PL_01_10_crl, + Intermediate_CRL_4_PL_01_10_crl, + End_Certificate_PL_01_10_crt + }; + + /* + * test64 + * + */ + + public const string Intermediate_Certificate_RL_02_01_crt = + "MIICljCCAf+gAwIBAgICAKwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMi4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3AN+Y3Hl/9V0nKXHQotb/cA2VfZc5vrRu+ZjwKgK" + + "6KasGegAorKSTybYX/fTbnaPwykDPfSscAnzAW5WdF9+wTLmvYc+6pkcx1ryKkGmofFMXi" + + "bZ5LUO/oK0iuNjBKfLdWoi+hpciKyPb9Bs8SO/svKSNqTEbn9ts3q6tpbngoECAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECGXQ07qiAqv2MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBADKtN3OOaRdte0X4xLC6nTGaK/u7IEKQ0DjduDHwJR5w27zefrx48Z" + + "dlq8t5lAfQJqWmfk7iCIW1QJPLcZOouWDP2S9Cb0YooGQRIEkMjpBn3Xufx0XUphtCDs3W" + + "9LAMVXqfuce1tpZ6Dvrh6/H2X8rJMU29Czsz949bh6tcsHJi"; + public const string Intermediate_CRL_RL_02_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZdDTuqICq/YwDQYJKoZIhvcNAQEFBQADgYEAxrDH" + + "zKno1mkJqPTub0c9To6jC3CGTilV1E12oD0kFjkXqL40+W251qQ2wMC+G7ZrzBIc5dRuJ9" + + "3feHZ7cc03/s3TziXDvSyfNOYpHzkPwT48HuSgBYgJ3uswwk+tDiA64NzbOJqssxxhFRok" + + "9OpwC8eQkzgpA3a6816v2I3XL9s="; + public const string End_Certificate_RL_02_01_crt = + "MIIChzCCAfCgAwIBAgICAK0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDIuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAyLjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCykRGcIKuxia47yRmJT8XpNNi2LTTbUUTteIBp" + + "DZBfz2ExeWLruO9Rn1/oB/EP+4apx4r9rQ2tGsvr/7qQYeQK8W7eJzZgvxFadY57IMfUNq" + + "1nEnj0ZvuWrOSf+K9v6FWX5Y2uyZS5Uvb1VVQv0Ev890+yXTtthPTjepk3JkkouwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECFIkVrx7NRAdMBMGA1UdIwQMMAqACGXQ07qiAqv2MA0GCSqGSIb3DQEBBQUAA4GBAI+B" + + "T6bFZruoeFHXsYVjkQ42jSdYB9JuQkG7JLKte5gGlhyR+jMlJBzxBgNIfvlmYSnbRFPbE8" + + "eqsGm90hJJoUuVMkm0i03H13uddlS494O6HhTGpaKcYwp3hbLhVcaY3wFTqTCuZk1T7Oxq" + + "ggTrCDYvNH+/ZpQuy6nB/FH3SAHS"; + public readonly string[] TEST_64_DATA = new string[] + { + Intermediate_Certificate_RL_02_01_crt, + Intermediate_CRL_RL_02_01_crl, + End_Certificate_RL_02_01_crt + }; + + /* + * test65 + * + */ + + public const string Intermediate_Certificate_1_RL_03_01_crt = + "MIICljCCAf+gAwIBAgICAK4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsZG8wsV3Kuo+jtnKxLYGBuAqQwUh6Cs7ioDTNUFI" + + "UDDJ0lOP1HVTMBA7DEcyTCGvnQ02dEVVuCddBTQvG5RvW7G7cCEW37cS56/3yPsU1bD/cp" + + "3C1pPJpoun04va91Sxtgcmx7jnz69QPVrucu6aI1sZyeOlvzb8K7DceaAfR98CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECMNzJ3SpyOLxMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBABo7oKmQilgji3w1tGz1cMrWxZxqGJqOAKcHywli+oxFo2oxSfEuFS" + + "tN2aEd2Ja5HU5a0ySztvByXF1TTNurGez7ARxmcS2kpoQtQXTloywza4A5N7iQwk0yyo/E" + + "J4lrXUfVRwZHr7FwA7qMODtFb0+Zivv9JLaq19GhnRhzZyWp"; + public const string Intermediate_Certificate_2_RL_03_01_crt = + "MIICljCCAf+gAwIBAgICAK8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wMy4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt7yNq1QZsV3p7OR8rgPuY7x7Bvs+nPhcLR7zFOgR" + + "+plQUwpWQ2PhuzReVV4jNasKtNK9MIWoeV+eV3pEiso5obb9+Byvha1F6gkYNZMPs9Iv86" + + "cJSMtownNJVGVAL9FEpof1QKLp7kfn08EjkoGmGy85xy9uFytd2S8n5TlrBqcCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECAVwoCPFqMtqMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAL9GufFieduzBJaMtsXtKHMf64O/KAGLSh1YDXS+a7Ku+EFw+WteKU" + + "Ob6+c1m7VH9P711eATQoACotCdKusPECqeYDEmT9keqA4f7cP4VcvGwhvSVQJsPuB3LL3S" + + "LIILE4zhT+O9G+5v+mkG/pEDirRYk6ZkdM91bsUuzsX40uyn"; + public const string Intermediate_CRL_RL_03_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1STC4wMy4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIBXCgI8Woy2owDQYJKoZIhvcNAQEFBQADgYEAkwyA" + + "I1rrz6tOmEpBHDzuJfqY2nbXCIXFN6dVuaKNZWHJ4ZNIc4/t29Wa5GgXYrVXyXRcXP/u5k" + + "NEhOX2/NwCm6vL8+tclYP5qPLrh/Dk4v3nvcTFLKCvclAbf4Il0zfMQx+RRnO5PPqPDu5i" + + "1tHHwOtA8Q+oO71lZEwPE+pX1Sc="; + public const string End_Certificate_RL_03_01_crt = + "MIIChzCCAfCgAwIBAgICALAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPGLfi8/T5p63cbGE98mqO5VzkeI1r2/2TLgvY" + + "RpL1h8i+CVYKoX37yYwNXf+HkHhj1OXJSNrm7853ctmDf2h1fv3f1+qJLg4VRVzlEgErNq" + + "74OR7XLXV77kGOmhip2g5BF5VKeqAdj0pCo1E5ZFHpRPFq/0DDmSda6GKJ6Dl8hwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECOHM3uWxFmcrMBMGA1UdIwQMMAqACMNzJ3SpyOLxMA0GCSqGSIb3DQEBBQUAA4GBAFBu" + + "doX0TZK/yoUcrSkP8AtFiv5c7QvyEtigFZTT+lbW/g4RX/oJGNZCu78yAxCczl+Z6ft+0V" + + "wInwahjyyAgw4QXxtw3b9CfqvT7HH7hcQ6r9ZA/NA9XpzNtxKfmXjzCZWdfmLJrd8KCnU/" + + "utKRAObRBKiaTGa178SEWvtkoIXd"; + public readonly string[] TEST_65_DATA = new string[] + { + Intermediate_Certificate_1_RL_03_01_crt, + Intermediate_Certificate_2_RL_03_01_crt, + Intermediate_CRL_RL_03_01_crl, + End_Certificate_RL_03_01_crt + }; + + /* + * test66 + * + */ + + public const string Intermediate_Certificate_RL_03_02_crt = + "MIICljCCAf+gAwIBAgICALEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvoTuc2LYBOhziBe02f6F8l9MwX74O1lknBcJjGvq" + + "JcirQx/6hQgBQT4hz4RRXNy7DSBr3swEw4eDNSeyd6kvG0h9oI3+SVmVyPPVi5eKDL1roI" + + "OBzmfx1+Nn/CnwOf8VroKDutBBQ0gJ24IEjwp6er/8hEAVN/yIjIi/MTFeoRkCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECKtCUOlmMPu6MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAI9x8O/JgJuZV/s4OBUy3AvcW9QP3HWWBQSdxUdjSosT2schjn7wrR" + + "gttL7vWjT1djsbATAHa5C3inG+VjGIq/NqWaPoHAucRNMs4oZX2ACZFuBLOb/qhywsKh5+" + + "bjv4QgtqkUedzEratY6yQiJSiMSJVJSMzHosTVMX7oOp+cll"; + public const string Intermediate_CRL_RL_03_02_crl = + "MIIBcDCB2gIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" + + "CyFw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgIzAhMAoGA1UdFAQDAgEBMBMGA1Ud" + + "IwQMMAqACKtCUOlmMPu6MA0GCSqGSIb3DQEBBQUAA4GBAAEZ0Hg6sKiVXIeK6zbQrKtMMz" + + "Vz2K68+SqN1LAjlNW6u+HSTlAvhRIFO1Hv5Zj7qbO226rLxas/X2XWXpMlm84NHN8T4dZU" + + "4Yo5rhhpCHckRxNYn3AFcfcV4ra1rrTtdx8e7e7/m0Ghog9Ny52ZuQThasL9caF0JxUx6d" + + "zbBHPm"; + public const string End_Certificate_RL_03_02_crt = + "MIIChzCCAfCgAwIBAgICALIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAyMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNb6HGPRDulLMCCyCq6w2X8rHPtm1gN68JXFkX" + + "j/BZsHhu29Z9hXj76hO//7O775EPVMSLyRy8t15yzYpXfZRHFaGB5bs8U2R5ClvsD2FR0H" + + "t0JVfU6Ggn1lhO+jOiguJtXVRjofsfvHuiOe75ctaJ9lBpgwiV8tk4VRKz2e5xVwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECI3Gy0TgXMrwMBMGA1UdIwQMMAqACKtCUOlmMPu6MA0GCSqGSIb3DQEBBQUAA4GBAISQ" + + "Qh9+7D6nk3FL5YQOzyZ0BSHQYjpbIVykJ+Lr4jBPKyGgCqW6jqWNg7X4waB77J2z/OkavY" + + "A6qtpsk8r2wmG9thi8JyZZNhYMxAszHzFbBmSoxGRMvI0XarxgIu8Ky6V7jKVDLz12C3o9" + + "H0yd+nZXilCD+p9BTjjg5bGUogJS"; + public readonly string[] TEST_66_DATA = new string[] + { + Intermediate_Certificate_RL_03_02_crt, + Intermediate_CRL_RL_03_02_crl, + End_Certificate_RL_03_02_crt + }; + + /* + * test67 + * + */ + + public const string Intermediate_Certificate_RL_03_03_crt = + "MIICljCCAf+gAwIBAgICALMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu/o0uxgTrAvNDrMNuG2eTla+AmkLVCIXBbsIo0gs" + + "tLm29tLwfBh/8l5OC0y6Xeh5lx+NLdelsiZGRNaaWmWHj9Ji5V6rclr8sXRDUjxe12zLeh" + + "0G+a0TfpL380cx9RItqQyA1ZRiUNymmJHnm13hwrf7LPirR9BMrtyTT2EI3cMCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECHYt39LYdEn0MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAIoSGa7MxnOuHoWM/BoJKsCeBmBHYCYDKmQ19JfsDHW8z8oAFiikFb" + + "Gtw1Qpc0GFfJgN0cppaXfe5lDS6BWL2dPorhu3URfXKu84ATLwGmNhqLDY7zh/zPvLtG2m" + + "izaMLC6ZwZL5KELpYpcP15EHPDquyP1xpV3fT17GjpG9IH8k"; + public const string Intermediate_CRL_1_RL_03_03_crl = + "MIIBcDCB2gIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" + + "C0Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgIzAhMAoGA1UdFAQDAgEBMBMGA1Ud" + + "IwQMMAqACHYt39LYdEn0MA0GCSqGSIb3DQEBBQUAA4GBAI3HsXanos/N6uO3QVUaBZzmCt" + + "w1HCHMrLVG614YlUQiEedQ/oEc7dwCeD1rUbGNVkFPIRvMkmUQo1klhKAlEUmrtW+aH+If" + + "6oqumifqxvaycWidacbgNLIAMQtlQmniPF6Pq0dv8sNeKq4CE0gjRHOPJ2zIqy3kJ3tZYB" + + "pTguwO"; + public const string Intermediate_CRL_2_RL_03_03_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wMy4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIdi3f0th0SfQwDQYJKoZIhvcNAQEFBQADgYEAXZSZ" + + "ySsD7U6ETy9ZRmiKUCJMUV9CIhCY0mEihHjW0DhFTyV1Hr01yN5zUr/IFVuP/Xcx36IX4l" + + "dVv6/MgR1GeM/BUGZhm4z6YwfAosZ1N3zayIy/pP3fa1rVRl8cgCxc/8qxg9nH9p6yPpxM" + + "AOOu6TLYquk/dA7wJPEW7MPixXY="; + public const string End_Certificate_RL_03_03_crt = + "MIIChzCCAfCgAwIBAgICALQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAzMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5LNxAB+lm514Hk2ykrFUb7fCX0ryIEMg0mgeT" + + "/z8Iw7xisht57koK4PTXY863aunfNNh+8oFTHZnoLB5dbkROj1nFRgcWPezzv1wNkZEpxn" + + "NINtTPBogW22NPznoZ/rSk9JRFe0sCOVazkW9tZbY2ARqyJsYU1ez5tQIkDS47kQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECMWddsi+qmxKMBMGA1UdIwQMMAqACHYt39LYdEn0MA0GCSqGSIb3DQEBBQUAA4GBAAv8" + + "nrJaqEycAyIKdPBYTUqaxjkv4SmonDDJG9OqvD78/o9hUKKteoMkNUp8eexTkWk0L72L4N" + + "/eXB30+m65E841V+Dy8L4bXh15n4qz4cyMt8Kvm7nbCqcgpiyBJmBxzfaXDLSthlmhcJ4X" + + "zDFnav1LEw5fZklt7cnMl4YvLD8d"; + public readonly string[] TEST_67_DATA = new string[] + { + Intermediate_Certificate_RL_03_03_crt, + Intermediate_CRL_1_RL_03_03_crl, + Intermediate_CRL_2_RL_03_03_crl, + End_Certificate_RL_03_03_crt + }; + + /* + * test68 + * + */ + + public const string Intermediate_Certificate_1_RL_05_01_crt = + "MIICljCCAf+gAwIBAgICALUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNS4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA59vHTe5A9AcT237mW7HdSfh8Pu4P2wJNLT7RXczN" + + "7DD/P6mAkugSgPTXwwlE1oSB/hCxAtEPhwONYZFYlRClFJidHDdVApalB7UbosTghsUzAg" + + "Lqw7NL+w9i3Un2G7JM2oWwugozQn/1hzr2Cii2TIB6K0RWKoPBJvaWUURS/G8CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECP55Cc4eBca8MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBALX594y5uF4Rt7CoRHeKZ5h8QiG7mc+kQDMjaSU4KJwNVVL0mJatQG" + + "w90yFfhvprlgDt9UIAvpF6z5gysbrjHXJaEhVlXeg9D5mcxsL4THEc8f6oU1GjfT/SOD9l" + + "QrT/keX3D9lcFEaTOgi0HIZ7aFIJgoWjXF/9kNNMEAs8sJNI"; + public const string Intermediate_Certificate_2_RL_05_01_crt = + "MIICljCCAf+gAwIBAgICALYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDUuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wNS4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtl4hX6HlF0M+lSBTG8jHiB06hOy87LL81yAE2JQt" + + "/6F+LZjuOBTCIc2yO2bVM3XzUnjyYDBYGnBFp/7XpRoiADuPJSfmkzmezpyJc+hm96UR1g" + + "Bpo+pPKbRTWuM+FYy+vPtaDk5wKOrmyNx440PwbzxTN3JeWz17xeYE98bXMc0CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECJOjtwEYV9VSMBMGA1UdIwQMMAqACP55Cc4eBca8MA0GCSqG" + + "SIb3DQEBBQUAA4GBAFbkOffoIjWSfxEuKszoK7Fj27Hf5jlV92xqXtBLURjNGi9jCLUIUd" + + "QLnONZLJYo70Z6XaGjpAK1EtZKVWsz11JDq5egE1zNES//9Tz8xDtJ7Lcq0mwneVFxmBuL" + + "gxkw4GKbBFKz10FoSP7VJWaeW080WwKnp96Me5GtZRe260N1"; + public const string Intermediate_CRL_1_RL_05_01_crl = + "MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjA4MDYCAg" + + "C2Fw05OTAxMDExMjAwMDBaMCEwCgYDVR0VBAMKAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQCg" + + "IzAhMAoGA1UdFAQDAgEBMBMGA1UdIwQMMAqACP55Cc4eBca8MA0GCSqGSIb3DQEBBQUAA4" + + "GBAIdOaBfpAEKWLrSvepVjk3UTfEfsSP6y+kFMl33YXy18xUvVpLarGu6YjQIpXiL+ulkP" + + "eF8TAc9AarUjvDf0kcslIOt3NhdMxR4/F614Ds/rPEXs4c7n4kCkvAlFg/19iIFeCaynx3" + + "X0s/v1SwzgAUHi3P+OwAGDApDTyKbnmzvt"; + public const string Intermediate_CRL_2_RL_05_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1STC4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIk6O3ARhX1VIwDQYJKoZIhvcNAQEFBQADgYEAfOOd" + + "JiLUCFSurAafQEBfxE9KVrgFC+W9m64cmERicO1QL9aDVIDGJAIY1pdvWVdhLBIKwSugwB" + + "ZH3ToptY+VizvFN1gkKGL2OuvDsXPHn1+QgmqvxYFPmvwDcwuxZ/3zD1VeHgEIKo9ugRnW" + + "F8G2Ph6SWUxJCjJQpB7WIbydowI="; + public const string End_Certificate_RL_05_01_crt = + "MIIChzCCAfCgAwIBAgICALcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUkwuMDUuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA1LjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9NWkW/mia20c5gM3DpcTsBWTNC/d/Cob+OVrS" + + "lYytMjK4htO3MavavMZNTLAYFCXWhZ+Uo/uiAF0ddE4HaFI418eKJMSSbQyed0TG5Udw/t" + + "3dhYeLzLEmVc0r00q5v+CLINsCNQAKaPV71UvoHrE092zZjmtacuAetBS1Q2ufpwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECGNPOXdCLpZ3MBMGA1UdIwQMMAqACJOjtwEYV9VSMA0GCSqGSIb3DQEBBQUAA4GBALTo" + + "hfBEPdzZ6A9QNStakOhmhHYox70xOPuWqzSbIugZv4chKXNQGiUAoOGImTw1mcun/uPNtd" + + "0bT+O+a9yX5gzW55CSmR/teHkTkND1mJhOMuYOmaCaBHnqgIIe1iEhMZQgag70+/tSmmQm" + + "UpWGpxeK2c02tBK6gEmnqk75bKRT"; + public readonly string[] TEST_68_DATA = new string[] + { + Intermediate_Certificate_1_RL_05_01_crt, + Intermediate_Certificate_2_RL_05_01_crt, + Intermediate_CRL_1_RL_05_01_crl, + Intermediate_CRL_2_RL_05_01_crl, + End_Certificate_RL_05_01_crt + }; + + /* + * test69 + * + */ + public const string Intermediate_Certificate_RL_05_02_crt = + "MIICljCCAf+gAwIBAgICALgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNS4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAouNcO1wHvKHPR15L7Fohr/QbTkPWGr9QYp2MXEDy" + + "BRGHt63Ob+yNvsP/C74GJA+PzvcRELSnJxmBVbdRN5y/u4S6Zt4yTTcrvp4vl//luoGLOX" + + "NHhCXbrGavyoP/iKpbfP7fy948AN34i95HuZENoGPjG5stX0uk12P087S2tPcCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECFi86MGPmMsXMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAFVZVMZEsaVuL0qX5Ls94+x8gBklxPfxgfG5LeBR2/YcqW+7BhsVA1" + + "GQhjBtwqCU9SOL16oTrqgw2+YeWBjaYuNYVlxfdifd0pQydpE1iDQWxmoKLzSDmtWgRYhz" + + "v0TB6j8q+0x5Q0OOrHX0jdIiBnHrLmReCK8dY1x6fb6I0tTH"; + public const string Intermediate_CRL_RL_05_02_crl = + "MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjA4MDYCAg" + + "C5Fw05OTAxMDExMjAwMDBaMCEwCgYDVR0VBAMKAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQCg" + + "IzAhMAoGA1UdFAQDAgEBMBMGA1UdIwQMMAqACFi86MGPmMsXMA0GCSqGSIb3DQEBBQUAA4" + + "GBAFMN6PWjz2bA1RRySYNXde2rKiYkZYghbtT4ig2yDJBKOiPnjdx+jriFJxGYpt7BvcNx" + + "cDfijmDZ1clzprIvz0lFO6IwsQiWtLxOz4Doj6K2AD+7IxuGLceaXmubvi4e6VVC3xXGsu" + + "OYsNgFzsdUXIazi74+eOcj4dqrHAepbhXT"; + public const string End_Certificate_RL_05_02_crt = + "MIIChzCCAfCgAwIBAgICALkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDUuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA1LjAyMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuWE1aFx3Zjk6gM0Wy6ijcUegbiGvhjBgqIGwv" + + "YissT0v3KGAKoh5wGeKC+rePQNbZ91j4XDLvUNUdNw8HVNdNG/igIwsuaJ9teKSbqrAw9X" + + "aD2YjJz/I6X6WXFd/eQ+g9lY3eidOXJkglYSwWMxUV62RUZbGyqjR1so+XpmYxCQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECLLbuNyVkkK9MBMGA1UdIwQMMAqACFi86MGPmMsXMA0GCSqGSIb3DQEBBQUAA4GBACKt" + + "GgxIRXYHZGZgwYHjNzquM1pUJTbxxm3qYA4U6r44oAo1UzQTDpHOalflreGFvG05l1BCnQ" + + "olQ8rcXU25v/CDfyww7cl8l7IxjYz7PNht7R97vjfMVqqButbn+BmU6D5kR9YXDCDPzaQ5" + + "DrKNk+3tIjJNj6YhxhqC2tPG9RIN"; + public readonly string[] TEST_69_DATA = new string[] + { + Intermediate_Certificate_RL_05_02_crt, + Intermediate_CRL_RL_05_02_crl, + End_Certificate_RL_05_02_crt + }; + + /* + * test70 + * + */ + public const string Intermediate_Certificate_1_RL_06_01_crt = + "MIICljCCAf+gAwIBAgICALowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNi4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmhxr4ckU5C3E57odZjgcxl46ZF2QVy+K86YoLOGT" + + "mq34NSHTFxP93mrNqMYdFKFedUTNI68HkecFVvVKoXsDNBnhyyCTQ3xXhBcMUXFByB+55k" + + "W5LeQ8l1G2ugsyZ7Z+P8uylrpeGJt4RjOTilhcI2mnfZ7S+arFGe4KYgnsaFUCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECOS4X3XqhyJYMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBALCPtNwXGxVSUNGErkBHSYCHyqlA55jKQQvZ4P0PznWEQ/gBJx34hq" + + "LxiBO2G+iDomzHszeM77TXkQBpNxCUw26Jxv2HuvyBXuSprgjw5F1tvLqwsBAnD5vsb0uD" + + "NrkKIzJSIBFQ1SRhuCObaXnamfPJHBmkP25t4QqEvoXMtVHB"; + public const string Intermediate_Certificate_2_RL_06_01_crt = + "MIICljCCAf+gAwIBAgICALswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDYuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wNi4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2IKrW6HDZJVFw3e4cC7v/jPGXAexI4B88707NhAc" + + "qxSVfGTPJBdfWo5pkptZKN5/L5n6+rixLItHnei/uwBCHvhwzeEIGo1yVCgz6R2MoNB966" + + "Q5CHWfT43BUjp0rZLJkK4hVKNyXB78NVv2Fly+XWBDEnzQvgVPWbGOvzE3zh0CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECK/1z9Xbu2jGMBMGA1UdIwQMMAqACOS4X3XqhyJYMA0GCSqG" + + "SIb3DQEBBQUAA4GBAAa/MVC+8ozm9py40a4o/kHbkkmFNQr4s9yi3KXXuVxsNvquFMXm4a" + + "gC8GPoNjvV+RPRmU8wOM6I2/PPl2JEQRb7NDM8LkY/m/Au4GHVeln6FKlldiRm0A+YIr19" + + "ip2RHOldikAjUUYv7JT3SP34sjtq2e8bsXfWEPG5BA/wxtm7"; + public const string Intermediate_CRL_1_RL_06_01_crl = + "MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" + + "C7Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgODA2MAoGA1UdFAQDAgEBMBMGCWCG" + + "SAFlAgEMAgEB/wQDAgEAMBMGA1UdIwQMMAqACOS4X3XqhyJYMA0GCSqGSIb3DQEBBQUAA4" + + "GBAJSexboWDaqLVY6iiWt8ZX5GwuNwDBN1R2TgM95H7JqjMgoWML887dKk24p4eKACFMWI" + + "Ji9nwsqdZ/h1FtPhYpSoJ8l8vo4imMKr+tTnMngDNpMMZPQyRY1AK1jSrLhEtUdjiEtrTY" + + "rG56RNt4YyUtNxxfkEymvwJxmO/4YcAz/l"; + public const string Intermediate_CRL_2_RL_06_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMi1STC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIr/XP1du7aMYwDQYJKoZIhvcNAQEFBQADgYEAImRg" + + "n9A7px9exOJL4Se9jsSHzZ3sAd3y16LdAb+HLtYLl1swNB4KPE+OebtzEoYiSzVVwezdlm" + + "5WseZjfbd0q01srZI4FeACZe99iBSpKymdKxw2gRvfYZ8ZMwFpK2mQq9cmygFn53iOwP7j" + + "3KE+lllielu7sYyEnkliF9wsaG0="; + public const string End_Certificate_RL_06_01_crt = + "MIIChzCCAfCgAwIBAgICALwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTItUkwuMDYuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA2LjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZVBNzD7LZW6mC2GSbVPjpcJ7sWISYsL2eHqXb" + + "/PuxtbOneOjYqx0GeL9pxDGSSNl2NrlG0G1HTU2MaEOVA6h96W9e5ADV/pzGPMr97z+3BV" + + "unxLX+ciM3T7rUQm/LueQTEC2Ww19T6QOg2i8rEadYT0OoW6OcvyuomemspxgClQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECK5pHDrhL7xjMBMGA1UdIwQMMAqACK/1z9Xbu2jGMA0GCSqGSIb3DQEBBQUAA4GBAF3J" + + "Kskjs4jp+BBoei9YWYtmOupn9w3oGyhknNh2jz7api5Gtgk2SyKfYFvN6EhWZJEab0hPFe" + + "WuYwO7zNCLGHw0cFXT/R48ogd6JkH6xDwj4afZDkWVTu8oaVD4h1rTYS6WPRzizAozOzhi" + + "tmIo+MV/lCG8+jdVtFgeKycI8aX7"; + public readonly string[] TEST_70_DATA = new string[] + { + Intermediate_Certificate_1_RL_06_01_crt, + Intermediate_Certificate_2_RL_06_01_crt, + Intermediate_CRL_1_RL_06_01_crl, + Intermediate_CRL_2_RL_06_01_crl, + End_Certificate_RL_06_01_crt + }; + + /* + * test71 + * + */ + public const string Intermediate_Certificate_RL_06_02_crt = + "MIICljCCAf+gAwIBAgICAL0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNi4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxMlJ0vbkMRGzuEDTDGuPmwDzU1xn3dFDZ1Tx6ONP" + + "fwNN5gk6r9kYl5TZ8f5TbkQSnOzyhDSqX8dGumCSgukETXtYBU2+KiIAtliu5NJRbXe3La" + + "vn102HxaHDLGsR0FFLiFM9GVhOOXryJoXoGZqUwvqbWyaQQEzrV4RWmuOv7xMCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECFNaMo88Vb5MMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAJsjJG4/U1OWCJPB1u7UD3TPKRgOR9hT5l3LzFw5s0CEGt2Beg25LP" + + "GEGcr0sEdosVQI5m5CuPolpmlQv0FkZv5M1W+uXX+F/6edtMDEquDpdR97ihQSLZjFFqjE" + + "ytuaD4gqtL/BKBbz3e93mOmR9Wi+kWlXOYl0j8wpU9ePSjDV"; + public const string Intermediate_CRL_RL_06_02_crl = + "MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" + + "C+Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgODA2MAoGA1UdFAQDAgEBMBMGCWCG" + + "SAFlAgEMAgEB/wQDAgEAMBMGA1UdIwQMMAqACFNaMo88Vb5MMA0GCSqGSIb3DQEBBQUAA4" + + "GBAAKNj5xmtE7wzO1p5igiAmCDV6KuYsiPAQPHPEBlmo85vzvWv2hpEtmk4nDhehogl0QX" + + "rhvRRqR+cPE5vBLB8mAStW+ZR6FXQPnmU5qGHqCQ4Wh6TWZesd7oyftoS7bJD5Xdf5ErA9" + + "qijWoz8FgxZHVnAFmjA0rUINkdQ5JfE5oj"; + public const string End_Certificate_RL_06_02_crt = + "MIIChzCCAfCgAwIBAgICAL4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDYuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA2LjAyMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3UzwrnwKRlP00Pn49iI35S0wLn7c1I3rsmzdm" + + "YFicetxHNeOKXLg1CN1bqkbAJ+N39fKjrkusqb2T+R3zhAV5LeLT4fzbHYdU7f4r6xgW2/" + + "b2WLv+QVR+ldTsVxgPp/ZUgYi4/vAow4Q/6IT+zWtlawMBob/nLjVl+jQ9N4coFwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECPhq75noL+9WMBMGA1UdIwQMMAqACFNaMo88Vb5MMA0GCSqGSIb3DQEBBQUAA4GBAIU2" + + "5bLX/NyDC8dKUxRwVn8oc3YPQjK0zXGdUr15Ib+cLdRyFVCuAyxVdpTf/csuga6tDhGuTL" + + "B18mTE/fAjhUOiKiOLD6m4P77Nj67l2NTi86RimsI/Z6r5+bU31ahrls/7kr788+f4oEIY" + + "TyOJecojsJUOG3qzK9J50iszclxg"; + public readonly string[] TEST_71_DATA = new string[] + { + Intermediate_Certificate_RL_06_02_crt, + Intermediate_CRL_RL_06_02_crl, + End_Certificate_RL_06_02_crt + }; + + /* + * test72 + * + */ + public const string Intermediate_Certificate_RL_07_01_crt = + "MIICljCCAf+gAwIBAgICAL8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxjHxSRwJjEkLG9Al5uSQ22QI8N/hJ8hhkhh9qlaJ" + + "mHusM8sWpAp2vnuumlThTA2zZbptXZ8Krb7i/Kpym4wo3ZkEThwi/ijsM5QCunQJmESRGD" + + "yPZJjfhWjoC+lCjbmzsOGLMETpgSEMy+EyoXkRCnKmXcmCMS8HjLrqdnwiWBUCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECHPEkeIs8GuwMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBABCmgEnb8dfnG9lWQKT5BmQm459WqRQAiqdfqf9w0qRMuVrdfLMwqx" + + "oq4uh10A3d+auHohgT2fT9RzNaWnRoNaH9K6qLQsdCUZdqjbEGdyiIFzvWP9MkV9nhDlo2" + + "GgiU68HfnpKO/WA9EaRHyEzwT9o4SA7hAbz+3L12hB2WLSOg"; + public const string Intermediate_CRL_RL_07_01_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNy4wMRcNOTgwMTAxMDYwMTAwWhcNOTgwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIc8SR4izwa7AwDQYJKoZIhvcNAQEFBQADgYEAOyZr" + + "f1tRnuzoq7dgQo+eOYhb5JyRyrNaSwNnRy82wOP+/G3NH8V3NGonDFOOcd9SoLTbeW4o71" + + "vdOrKZgom5H2MZK5M4wTdfPAfXB1wBxOMzW5jXzsRtaha4l6EPI+GVL0eXN+aW3k/pscdA" + + "ToI+OxTmRRnCYS6yW3qL9RoTIXQ="; + public const string End_Certificate_RL_07_01_crt = + "MIIChzCCAfCgAwIBAgICAMAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrm/Zem9Tt2UJFUKdAhTNwvhLo03uOax74ZgbV" + + "YNTCpKeEWkV5d5d7DRC4mCTX1yjIlg6K4l7T+sRGI4XAcDRgYLuoyG1X958XCXSdIPTdbK" + + "Hxs/tFv4mrCwi1kU+zjyzDoqgjT6kUxgM39rfcvDMH6qSzHQKgTFp7Tj/DHiELqwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECGFR8c6rRbhcMBMGA1UdIwQMMAqACHPEkeIs8GuwMA0GCSqGSIb3DQEBBQUAA4GBAANZ" + + "TVR288mKpDDzm9XZMZ9+K1kPZ+eQYX+vUul11luVw27AIJGR8Fb4PIGl4+ALvqU3NQP/6v" + + "d+zvS7IfiR6q7aLS3w111BUCgDhTJAp3oSo12qfcp+2DB1M9QfjrM9nKgmh5bBJigdJwJM" + + "W8HHKStUMLdxg+qkZJgZpnyowCFM"; + public readonly string[] TEST_72_DATA = new string[] + { + Intermediate_Certificate_RL_07_01_crt, + Intermediate_CRL_RL_07_01_crl, + End_Certificate_RL_07_01_crt + }; + + /* + * test73 + * + */ + public const string Intermediate_Certificate_RL_07_02_crt = + "MIICljCCAf+gAwIBAgICAMEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNNTAwMTAxMDYwMDMwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMjCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0CvEneaAPtxZOTqlh/TXBM6V0bQgKbO58yEyURcO" + + "Zi7jzYsmNtN9Tsr0wAlD41/ZONsW4MMzZ13UCc0aGa+eE8XRULBe5cgaGxJKwVnEqz3W8z" + + "v1MjOk7Anb8TkxMSlWlptC6V3eRA85p5Id9gXbIrP3E3NuSfyx6246oLjNnbECAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECIb5Ia6wKcHtMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAAYEHQY+Z4qv4bYLmd+sz4aNGwZF7FT6ZIQ43OSeb+t+ibL7rZ0X0y" + + "4SCTMs1mAB44IA6RFurmeCFk0ladRCn3A1xaVI1HlHen13ovzDA9ogL4CWbYXvCUv/znQY" + + "yVSQCTKwT8iVam8xS1MsNCe408iVjhRfR6u9Hi31M+Pf+AUe"; + public const string Intermediate_CRL_RL_07_02_crl = + "MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNy4wMhcNNTAwMTAxMDYwMTAwWhcNNTAwMTAxMTIwMTAwWqAjMCEwCg" + + "YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhvkhrrApwe0wDQYJKoZIhvcNAQEFBQADgYEALVUq" + + "3Wq/Opvp9ifmQ4VXz4dgLNR+5Nz3muJ4RZt5R5b4R3RYllhgXNYw2EbEVCFjnfm97z73Ke" + + "wzVV+fo/u5GbqJHN2cAVEHarOpasLxySktNA1Cwq5OTzUF0dYISqYbyBvVcaOQBvU/Lwj7" + + "MQJJVVq96iDKnAJYBX03EHKbBeg="; + public const string End_Certificate_RL_07_02_crt = + "MIIChzCCAfCgAwIBAgICAMIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAyMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD6YgsbjW9IL7/SBORKssFUZBUxmluOpxJK/7d7" + + "JA2pxbg7L96xHFPWN36CYDJzTscNpbGrD3G2MPkg4GqoTo0rU28NYVzj4SwqYoSLIbXB+r" + + "SVgWcxNgbJ+4x9bK3YccNLR1PWEFxz1NckhCLBmb5pI4E34MCxQ6PvFO02I19FwQIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECIutV9ItCIbZMBMGA1UdIwQMMAqACIb5Ia6wKcHtMA0GCSqGSIb3DQEBBQUAA4GBALQE" + + "cBr31h3jKUHcuf3yztr9NWUkGMDM0NCXHOpQl7JbV3P5BjvaiRYWlUrN7+92G8EaUFORto" + + "zp8GG+d/MvFooVQOvpOzyhautYWyqq3AWpZLppnxNk1mRAdjUAvJaONtv37eLsma0bhtLM" + + "j62sQQ6CdoKbMtIEGuJgpwWqHYwY"; + public readonly string[] TEST_73_DATA = new string[] + { + Intermediate_Certificate_RL_07_02_crt, + Intermediate_CRL_RL_07_02_crl, + End_Certificate_RL_07_02_crt + }; + + /* + * test74 + * + */ + public const string Intermediate_Certificate_RL_07_03_crt = + "MIICljCCAf+gAwIBAgICAMMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMzCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8QzGjV0NVTNrOgkeqTkQFCOvl7M0qmjmYJjuw4R3" + + "YfQIXDN0m9HR2JKp5WKTSUedmWviGS7NbGSzLR7+6OkLwSoxN9PkA/fMko7O0KWBfduhvn" + + "jymlDMb2GPb1hBjScbq8fVJHwzqUm+BtEO2MXwXKYY2hZr+OEyEGhSEThp90MCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECFwl2XphEZRSMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAAb5GERgYVGuOb62gVZAAnhuk5K7CCkWZucOv6iI7pAgI6S7pvool/" + + "dXHC0tzgQ+/MkuWcr+22k/ya7f+iSfiYokjnQkgoYFYk3PkjyOXA3mzs5qhF0nOP6Gvmz4" + + "asONA+qZSqa4pjxF9Kn8L64f9yeyEXnckmbzdmbjAFCveQIP"; + public const string Intermediate_CRL_RL_07_03_crl = + "MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wNy4wMxcNOTkwMTAxMDYwMTAwWhgPMjA1MDAxMDExMjAxMDBaoCMwIT" + + "AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAhcJdl6YRGUUjANBgkqhkiG9w0BAQUFAAOBgQAz" + + "DMl8P16hylNkUEw4z9//PJFObNPZCYdmzBfp0K3tNRrOAouUVegyX0gDHi8O+bmmJNgcnC" + + "tMRXx+D4qP7bx5fDS2MVQhSsncf6u4UZ8pxbRc0JmwR5oGZLPQabrctgmEmg8ZKGApKtsf" + + "pGyvvTwaAzM+GaWXD68bBEN3VfVdeQ=="; + public const string End_Certificate_RL_07_03_crt = + "MIIChzCCAfCgAwIBAgICAMQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAzMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU6mec24uBaVip7fFWHas+o/lpZBOfj/IPHXQ9" + + "QaRZwmJZBB81AX3BJ60DD12o/+RXdHl7B2Eh9kYv/QEXOKmyhJFSPa0Lv7MQ/hCIcL4m1U" + + "FDGtJ3SUixZMqVBP0xjwXoNS88zzaCBL+co2TxhBrYMzeNQOX1eEkXMT4pvULmAwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECBBgFdYLuvk9MBMGA1UdIwQMMAqACFwl2XphEZRSMA0GCSqGSIb3DQEBBQUAA4GBAAof" + + "dPOGa4ZxRPcLw6zWM/NLzF3XYDqXAsZBsC75r0GRrogqEYn07tVUDNaQczDtjRLBRNmxWE" + + "+qCkJwc+wOBJqOFUxcuhK9oag6OE94+UIHdh3Td9i2ELZXj9RSNchnjyFohj5gk1dJSO41" + + "86Ls3mCT9JcssR0dSxxkF0ENfZCG"; + public readonly string[] TEST_74_DATA = new string[] + { + Intermediate_Certificate_RL_07_03_crt, + Intermediate_CRL_RL_07_03_crl, + End_Certificate_RL_07_03_crt + }; + + /* + * test75 + * + */ + public const string Intermediate_Certificate_RL_08_01_crt = + "MIICljCCAf+gAwIBAgICAMUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wOC4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs2YRTEl3C1TmmneJ6K110nSACn+KXxSOTGAGN5xv" + + "XW751StpE2iEQIbRVPQdMzmcQX0bcg/WpdrewPQld9NRjFj7it+9YNQh7vMKhZwoAPoDmv" + + "TnTdTEuV0c1FLVDVhiaAD9KMBa4fBLRfTKVzgzAr+oNqLhm3YBd2JWRHg+fA8CAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECB4we8+hIrkKMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBABTQI82uCMwQ4bgUWr9lawSI5DyWg3KY13F45rAlmKyckgne9SHbCH" + + "+Lvm3XkkIqKmeHfJ3QTf7bpz6eErn3CxRrGm5JWblcYbVT+smjboJ9A0BXifqINYLy3qGc" + + "AnNRkPq8OUREj2sU1qWKagUIgA/Vk2WyZhcUiApJPHI4fwv9"; + public const string Intermediate_CRL_RL_08_01_crl = + "MIIBWjCBxAIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wOC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAyMDAwCg" + + "YDVR0UBAMCAQEwDQYDVR0bAQH/BAMCAQEwEwYDVR0jBAwwCoAIHjB7z6EiuQowDQYJKoZI" + + "hvcNAQEFBQADgYEAkjF0oERt5XW2i70gyspkEYIHyGCHnqngky5yuwQSRrlW7t0vGdKV7W" + + "50evTeSVV41uhi1MBcccpx1MdRcB5vsatFSSKcKx4NF3PuHXxXCm2HkfXQy4K5zftE3jOZ" + + "5s+yTHiw3s/QSErtHRca+TQcEZwamI+p402TEa6e82l6xHI="; + public const string End_Certificate_RL_08_01_crt = + "MIIChzCCAfCgAwIBAgICAMYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDguMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA4LjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfEMqWMqk3Rre5m4ILtQIz45JImvU379Al/S6t" + + "2y/TzimJc4nhIKQp80VaZA/gwu/DcvMgJPM+FFz5U5rRkDaYASsc34tZUESF5LC6ZbtGqf" + + "J96IKdajvkGLsHyI7dseuwaQ0FlOwcmKMSR898MGNNbKxaQNLEXsIFypRDsN6JhwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECMT22ARjB1ABMBMGA1UdIwQMMAqACB4we8+hIrkKMA0GCSqGSIb3DQEBBQUAA4GBAIaP" + + "EqI7oHl/+h3MszG4VB1Va9NTN0kaysTyjQSVBi9jhOlPkzuXc2wI1bymBhatHEn6OrgP13" + + "vsOiH2BiyudYcYjKpwI4FUiyKLIc0CXzM0VYFoMzb91QtsK1EnvAPDKNYVVFXrL7ABVIK4" + + "hU6HfMMUbnpKWBxT5274iHScX8tL"; + public readonly string[] TEST_75_DATA = new string[] + { + Intermediate_Certificate_RL_08_01_crt, + Intermediate_CRL_RL_08_01_crl, + End_Certificate_RL_08_01_crt + }; + + /* + * test76 + * + */ + public const string Intermediate_Certificate_RL_09_01_crt = + "MIICljCCAf+gAwIBAgICAMcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wOS4wMTCBnzANBg" + + "kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsvkvLv5fMFYvohaXO8a7GgU4rDHe9iL7LP1VeNUg" + + "GIdJGqPEnuggQ/guhrBHafGh1NtmlEbmPJ4WQ99dBbPHHeO8sfCgkmWC0SqPODoI+t3qJE" + + "kf2z9dWoAij15RXPliywZz+S6bTtcEQAREyBQ6M8/HJ83wRXp/uCpdPOSxVPkCAwEAAaNj" + + "MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" + + "gBZQMBMAEwEQYDVR0OBAoECISY4bvGMEBTMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" + + "SIb3DQEBBQUAA4GBAAd7g+dWso4V/Vr+QIoNLueCBAYWdOF+Yz3VeomcsDAs2V8E+xcZaq" + + "jo2LrMygYCeMxVfXx/ZdhLPOaZ+ahNAbk+nWRwj35JdTNAAbMMWFdZUgR6N+uzx1v7i86p" + + "AWUpRJ9IYPgUoQ5pmjdf3Ru1nrLfRt4yp+kNHWp6IL/+MwcM"; + public const string Intermediate_CRL_RL_09_01_crl = + "MIIBXDCBxgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" + + "5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" + + "BAMTDENBMS1STC4wOS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqA0MDIwCg" + + "YDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4IB/zATBgNVHSMEDDAKgAiEmOG7xjBAUzANBgkq" + + "hkiG9w0BAQUFAAOBgQAKTXYgqlP+upFIwOSpdaVKDT8aqFzY9nSIsxHg5Wdl43U7p44LvQ" + + "lW8XKhw74oQl1ExU5s7mDaEqB0JIozGzmoNyKsErgWKNW+lpKSxR5+1EHOB6Oo2KijpTsv" + + "GFrHFCnF09f9JaTaMRIXOljx3rMO1UZsftKy/L9z3aUz8hQRnQ=="; + public const string End_Certificate_RL_09_01_crt = + "MIIChzCCAfCgAwIBAgICAMgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" + + "NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" + + "MRUwEwYDVQQDEwxDQTEtUkwuMDkuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" + + "AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" + + "EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA5LjAxMIGfMA" + + "0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpz09VCXzAhH4/ifMk0RAzaBqJCXaHHqAdO/TW" + + "6uvOVtl+fGvWXhXmSSCUfzg5xBqdUXrqcyxOME3vdgF1uOFZ4q2K6+Zuxmm+GCOCIpe+Gl" + + "Jzqz4WKXG0iaXXQOYa56itNc/6Z6D/aAjNJavI19w0lmb9l6U2WBfn3LywxHp4dwIDAQAB" + + "o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" + + "oECOri1JgnJfLjMBMGA1UdIwQMMAqACISY4bvGMEBTMA0GCSqGSIb3DQEBBQUAA4GBADmV" + + "Ee0xy25Z0HtmWwprKPjJDr/p7TgzbmNC58pUPkgtxnJFP4yrzNB9FQBWSfnjZpzQkLSU7i" + + "7O6cf5HkqjQqoPErDnJLWgGzjbF80v2IIyZk7rEpAAM4MwjIk7hFvJK8QkTht9F4N1zj2X" + + "0TQkmlbo9Z4SFj/3fsbl9h2GdKuU"; + + public readonly string[] TEST_76_DATA = new string[] + { + Intermediate_Certificate_RL_09_01_crt, + Intermediate_CRL_RL_09_01_crl, + End_Certificate_RL_09_01_crt + }; + + public static void Main( + string[] args) + { + RunTest(new NistCertPathTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/NoekeonTest.cs b/crypto/test/src/test/NoekeonTest.cs new file mode 100644 index 000000000..c3745da1c --- /dev/null +++ b/crypto/test/src/test/NoekeonTest.cs @@ -0,0 +1,157 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Tests +{ + /** + * basic test class for SEED + */ + [TestFixture] + public class NoekeonTest + : BaseBlockCipherTest + { + private static readonly string[] cipherTests = + { + "128", + "b1656851699e29fa24b70148503d2dfc", + "2a78421b87c7d0924f26113f1d1349b2", + "e2f687e07b75660ffc372233bc47532c" + }; + + public NoekeonTest() + : base("Noekeon") + { + } + + public void DoTest( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + KeyParameter key = ParameterUtilities.CreateKeyParameter("Noekeon", keyBytes); + + IBufferedCipher inCipher = CipherUtilities.GetCipher("Noekeon/ECB/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("Noekeon/ECB/NoPadding"); + + try + { + outCipher.Init(true, key); + } + catch (Exception e) + { + Fail("Noekeon failed initialisation - " + e.Message, e); + } + + try + { + inCipher.Init(false, key); + } + catch (Exception e) + { + Fail("Noekeoen failed initialisation - " + e.Message, e); + } + + // + // encryption pass + // + MemoryStream bOut = new MemoryStream(); + + CipherStream cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + Fail("Noekeon failed encryption - " + e.Message, e); + } + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("Noekeon failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + MemoryStream bIn = new MemoryStream(bytes, false); + + CipherStream cIn = new CipherStream(bIn, inCipher, null); + + try + { +// DataInputStream dIn = new DataInputStream(cIn); + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { +// bytes[i] = (byte)dIn.read(); + bytes[i] = dIn.ReadByte(); + } + int remaining = bytes.Length - input.Length / 2; +// dIn.readFully(bytes, input.Length / 2, remaining); + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail("Noekeon failed encryption - " + e.Message, e); + } + + if (!AreEqual(bytes, input)) + { + Fail("Noekeon failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + } + + public override void PerformTest() + { + for (int i = 0; i != cipherTests.Length; i += 4) + { + DoTest(int.Parse(cipherTests[i]), + Hex.Decode(cipherTests[i + 1]), + Hex.Decode(cipherTests[i + 2]), + Hex.Decode(cipherTests[i + 3])); + } + } + + public static void Main( + string[] args) + { + RunTest(new NoekeonTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PBETest.cs b/crypto/test/src/test/PBETest.cs new file mode 100644 index 000000000..ee61a027c --- /dev/null +++ b/crypto/test/src/test/PBETest.cs @@ -0,0 +1,527 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /** + * test out the various PBE modes, making sure the JCE implementations + * are compatible woth the light weight ones. + */ + [TestFixture] + public class PbeTest + : SimpleTest + { + private class OpenSslTest + : SimpleTest + { + private char[] password; + private string baseAlgorithm; + private string algorithm; + private int keySize; + private int ivSize; + + public OpenSslTest( + string baseAlgorithm, + string algorithm, + int keySize, + int ivSize) + { + this.password = algorithm.ToCharArray(); + this.baseAlgorithm = baseAlgorithm; + this.algorithm = algorithm; + this.keySize = keySize; + this.ivSize = ivSize; + } + + public override string Name + { + get { return "OpenSSLPBE"; } + } + + public override void PerformTest() + { + byte[] salt = new byte[16]; + int iCount = 100; + + for (int i = 0; i != salt.Length; i++) + { + salt[i] = (byte)i; + } + + PbeParametersGenerator pGen = new OpenSslPbeParametersGenerator(); + + pGen.Init( + PbeParametersGenerator.Pkcs5PasswordToBytes(password), + salt, + iCount); + + ParametersWithIV parameters = (ParametersWithIV) + pGen.GenerateDerivedParameters(baseAlgorithm, keySize, ivSize); + + KeyParameter encKey = (KeyParameter) parameters.Parameters; + + IBufferedCipher c; + if (baseAlgorithm.Equals("RC4")) + { + c = CipherUtilities.GetCipher(baseAlgorithm); + + c.Init(true, encKey); + } + else + { + c = CipherUtilities.GetCipher(baseAlgorithm + "/CBC/PKCS7Padding"); + + c.Init(true, parameters); + } + + byte[] enc = c.DoFinal(salt); + + c = CipherUtilities.GetCipher(algorithm); + +// PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount); +// SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm); +// +// c.Init(false, fact.generateSecret(keySpec)); + + Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters( + algorithm, salt, iCount); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + algorithm, password, algParams); + c.Init(false, cipherParams); + + byte[] dec = c.DoFinal(enc); + + if (!AreEqual(salt, dec)) + { + Fail("" + algorithm + "failed encryption/decryption test"); + } + } + } + + private class Pkcs12Test + : SimpleTest + { + private char[] password; + private string baseAlgorithm; + private string algorithm; + private IDigest digest; + private int keySize; + private int ivSize; + + public Pkcs12Test( + string baseAlgorithm, + string algorithm, + IDigest digest, + int keySize, + int ivSize) + { + this.password = algorithm.ToCharArray(); + this.baseAlgorithm = baseAlgorithm; + this.algorithm = algorithm; + this.digest = digest; + this.keySize = keySize; + this.ivSize = ivSize; + } + + public override string Name + { + get { return "PKCS12PBE"; } + } + + public override void PerformTest() + { + int iCount = 100; + byte[] salt = DigestUtilities.DoFinal(digest); + + PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(digest); + + pGen.Init( + PbeParametersGenerator.Pkcs12PasswordToBytes(password), + salt, + iCount); + + ParametersWithIV parameters = (ParametersWithIV) + pGen.GenerateDerivedParameters(baseAlgorithm, keySize, ivSize); + + KeyParameter encKey = (KeyParameter) parameters.Parameters; + + IBufferedCipher c; + if (baseAlgorithm.Equals("RC4")) + { + c = CipherUtilities.GetCipher(baseAlgorithm); + + c.Init(true, encKey); + } + else + { + c = CipherUtilities.GetCipher(baseAlgorithm + "/CBC/PKCS7Padding"); + + c.Init(true, parameters); + } + + byte[] enc = c.DoFinal(salt); + + c = CipherUtilities.GetCipher(algorithm); + +// PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount); +// SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm); +// +// c.Init(false, fact.generateSecret(keySpec)); + + Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters( + algorithm, salt, iCount); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + algorithm, password, algParams); + c.Init(false, cipherParams); + + byte[] dec = c.DoFinal(enc); + + if (!AreEqual(salt, dec)) + { + Fail("" + algorithm + "failed encryption/decryption test"); + } + + // NB: We don't support retrieving parameters from cipher +// // +// // get the parameters +// // +// AlgorithmParameters param = c.getParameters(); +// PBEParameterSpec spec = (PBEParameterSpec)param.getParameterSpec(PBEParameterSpec.class); +// +// if (!AreEqual(salt, spec.getSalt())) +// { +// Fail("" + algorithm + "failed salt test"); +// } +// +// if (iCount != spec.getIterationCount()) +// { +// Fail("" + algorithm + "failed count test"); +// } + + // NB: This section just repeats earlier test passing 'param' separately +// // +// // try using parameters +// // +// keySpec = new PBEKeySpec(password); +// +// c.Init(false, fact.generateSecret(keySpec), param); +// +// dec = c.DoFinal(enc); +// +// if (!AreEqual(salt, dec)) +// { +// Fail("" + algorithm + "failed encryption/decryption test"); +// } + } + } + + private Pkcs12Test[] pkcs12Tests = { + new Pkcs12Test("DESede", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC", new Sha1Digest(), 192, 64), + new Pkcs12Test("DESede", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", new Sha1Digest(), 128, 64), + new Pkcs12Test("RC4", "PBEWITHSHAAND128BITRC4", new Sha1Digest(), 128, 0), + new Pkcs12Test("RC4", "PBEWITHSHAAND40BITRC4", new Sha1Digest(), 40, 0), + new Pkcs12Test("RC2", "PBEWITHSHAAND128BITRC2-CBC", new Sha1Digest(), 128, 64), + new Pkcs12Test("RC2", "PBEWITHSHAAND40BITRC2-CBC", new Sha1Digest(), 40, 64), + new Pkcs12Test("AES", "PBEWithSHA1And128BitAES-CBC-BC", new Sha1Digest(), 128, 128), + new Pkcs12Test("AES", "PBEWithSHA1And192BitAES-CBC-BC", new Sha1Digest(), 192, 128), + new Pkcs12Test("AES", "PBEWithSHA1And256BitAES-CBC-BC", new Sha1Digest(), 256, 128), + new Pkcs12Test("AES", "PBEWithSHA256And128BitAES-CBC-BC", new Sha256Digest(), 128, 128), + new Pkcs12Test("AES", "PBEWithSHA256And192BitAES-CBC-BC", new Sha256Digest(), 192, 128), + new Pkcs12Test("AES", "PBEWithSHA256And256BitAES-CBC-BC", new Sha256Digest(), 256, 128) + }; + + private OpenSslTest[] openSSLTests = { + new OpenSslTest("AES", "PBEWITHMD5AND128BITAES-CBC-OPENSSL", 128, 128), + new OpenSslTest("AES", "PBEWITHMD5AND192BITAES-CBC-OPENSSL", 192, 128), + new OpenSslTest("AES", "PBEWITHMD5AND256BITAES-CBC-OPENSSL", 256, 128) + }; + + static byte[] message = Hex.Decode("4869205468657265"); + + private byte[] hMac1 = Hex.Decode("bcc42174ccb04f425d9a5c8c4a95d6fd7c372911"); + private byte[] hMac2 = Hex.Decode("cb1d8bdb6aca9e3fa8980d6eb41ab28a7eb2cfd6"); + + // NB: These two makePbeCipher... methods are same in .NET + private IBufferedCipher makePbeCipherUsingParam( + string algorithm, + bool forEncryption, + char[] password, + byte[] salt, + int iterationCount) + { +// PBEKeySpec pbeSpec = new PBEKeySpec(password); +// SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm); +// PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); + + Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters( + algorithm, salt, iterationCount); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + algorithm, password, algParams); + + IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm); + +// cipher.Init(forEncryption, keyFact.generateSecret(pbeSpec), defParams); + cipher.Init(forEncryption, cipherParams); + + return cipher; + } + + // NB: These two makePbeCipher... methods are same in .NET + private IBufferedCipher makePbeCipherWithoutParam( + string algorithm, + bool forEncryption, + char[] password, + byte[] salt, + int iterationCount) + { +// PBEKeySpec pbeSpec = new PBEKeySpec(password, salt, iterationCount); +// SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm); + + Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters( + algorithm, salt, iterationCount); + ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters( + algorithm, password, algParams); + + IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm); + +// cipher.Init(forEncryption, keyFact.generateSecret(pbeSpec)); + cipher.Init(forEncryption, cipherParams); + + return cipher; + } + + private void doTestPbeHMac( + string hmacName, + byte[] output) + { + ICipherParameters key = null; + byte[] outBytes; + IMac mac = null; + + try + { +// SecretKeyFactory fact = SecretKeyFactory.getInstance(hmacName); +// +// key = fact.generateSecret(new PBEKeySpec("hello".ToCharArray())); + + Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters( + hmacName, new byte[20], 100); + key = PbeUtilities.GenerateCipherParameters( + hmacName, "hello".ToCharArray(), algParams); + mac = MacUtilities.GetMac(hmacName); + } + catch (Exception e) + { + Fail("Failed - exception " + e.ToString(), e); + } + + try + { +// mac.Init(key, new PBEParameterSpec(new byte[20], 100)); + mac.Init(key); + } + catch (Exception e) + { + Fail("Failed - exception " + e.ToString(), e); + } + + mac.Reset(); + + mac.BlockUpdate(message, 0, message.Length); + +// outBytes = mac.DoFinal(); + outBytes = new byte[mac.GetMacSize()]; + mac.DoFinal(outBytes, 0); + + if (!AreEqual(outBytes, output)) + { + Fail("Failed - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(outBytes)); + } + } + + public override void PerformTest() + { + byte[] input = Hex.Decode("1234567890abcdefabcdef1234567890fedbca098765"); + + // + // DES + // + IBufferedCipher cEnc = CipherUtilities.GetCipher("DES/CBC/PKCS7Padding"); + + cEnc.Init( + true, + new ParametersWithIV( + new DesParameters(Hex.Decode("30e69252758e5346")), + Hex.Decode("7c1c1ab9c454a688"))); + + byte[] outBytes = cEnc.DoFinal(input); + char[] password = "password".ToCharArray(); + + IBufferedCipher cDec = makePbeCipherUsingParam( + "PBEWithSHA1AndDES", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + byte[] inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("DES failed"); + } + + cDec = makePbeCipherWithoutParam( + "PBEWithSHA1AndDES", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("DES failed without param"); + } + + // + // DESede + // + cEnc = CipherUtilities.GetCipher("DESede/CBC/PKCS7Padding"); + + cEnc.Init( + true, + new ParametersWithIV( + new DesParameters(Hex.Decode("732f2d33c801732b7206756cbd44f9c1c103ddd97c7cbe8e")), + Hex.Decode("b07bf522c8d608b8"))); + + outBytes = cEnc.DoFinal(input); + + cDec = makePbeCipherUsingParam( + "PBEWithSHAAnd3-KeyTripleDES-CBC", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("DESede failed"); + } + + // + // 40Bit RC2 + // + cEnc = CipherUtilities.GetCipher("RC2/CBC/PKCS7Padding"); + + cEnc.Init( + true, + new ParametersWithIV( + new RC2Parameters(Hex.Decode("732f2d33c8")), + Hex.Decode("b07bf522c8d608b8"))); + + outBytes = cEnc.DoFinal(input); + + cDec = makePbeCipherUsingParam( + "PBEWithSHAAnd40BitRC2-CBC", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("RC2 failed"); + } + + // + // 128bit RC4 + // + cEnc = CipherUtilities.GetCipher("RC4"); + + cEnc.Init( + true, + ParameterUtilities.CreateKeyParameter("RC4", Hex.Decode("732f2d33c801732b7206756cbd44f9c1"))); + + outBytes = cEnc.DoFinal(input); + + cDec = makePbeCipherUsingParam( + "PBEWithSHAAnd128BitRC4", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("RC4 failed"); + } + + cDec = makePbeCipherWithoutParam( + "PBEWithSHAAnd128BitRC4", + false, + password, + Hex.Decode("7d60435f02e9e0ae"), + 2048); + + inBytes = cDec.DoFinal(outBytes); + + if (!AreEqual(input, inBytes)) + { + Fail("RC4 failed without param"); + } + + for (int i = 0; i != pkcs12Tests.Length; i++) + { + pkcs12Tests[i].PerformTest(); + } + + for (int i = 0; i != openSSLTests.Length; i++) + { + openSSLTests[i].PerformTest(); + } + + doTestPbeHMac("PBEWithHMacSHA1", hMac1); + doTestPbeHMac("PBEWithHMacRIPEMD160", hMac2); + } + + public override string Name + { + get { return "PbeTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PbeTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PEMData.cs b/crypto/test/src/test/PEMData.cs new file mode 100644 index 000000000..ea783c88c --- /dev/null +++ b/crypto/test/src/test/PEMData.cs @@ -0,0 +1,117 @@ +using System; + +namespace Org.BouncyCastle.Tests +{ + class PemData + { + internal static readonly string CERTIFICATE_1 = + "-----BEGIN X509 CERTIFICATE-----\r" + + "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx\r" + + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY\r" + + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB\r" + + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ\r" + + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2\r" + + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW\r" + + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM\r" + + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l\r" + + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv\r" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re\r" + + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO\r" + + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE\r" + + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy\r" + + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0\r" + + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw\r" + + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL\r" + + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4\r" + + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF\r" + + "5/8=\r" + + "-----END X509 CERTIFICATE-----\r"; + + internal static readonly string CERTIFICATE_2 = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx\n" + + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY\n" + + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB\n" + + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ\n" + + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2\n" + + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW\n" + + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM\n" + + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l\n" + + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv\n" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re\n" + + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO\n" + + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE\n" + + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy\n" + + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0\n" + + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL\n" + + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4\n" + + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF\n" + + "5/8=\n" + + "-----END CERTIFICATE-----\n"; + + internal static readonly string CRL_1 = + "-----BEGIN X509 CRL-----\r\n" + + "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT\r\n" + + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy\r\n" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw\r\n" + + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw\r\n" + + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw\r\n" + + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw\r\n" + + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw\r\n" + + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw\r\n" + + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw\r\n" + + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw\r\n" + + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF\r\n" + + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ\r\n" + + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt\r\n" + + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v\r\n" + + "-----END X509 CRL-----\r\n"; + + internal static readonly string CRL_2 = + "-----BEGIN CRL-----\r\n" + + "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT\r\n" + + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy\r\n" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw\r\n" + + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw\r\n" + + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw\r\n" + + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw\r\n" + + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw\r\n" + + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw\r\n" + + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw\r\n" + + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw\r\n" + + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF\r\n" + + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ\r\n" + + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt\r\n" + + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v\r\n" + + "-----END CRL-----\r\n"; + + internal static readonly string ATTRIBUTE_CERTIFICATE_1 = + "-----BEGIN X509 ATTRIBUTE CERTIFICATE-----\r\n" + + "MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl\r\n" + + "IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy\r\n" + + "aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV\r\n" + + "BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv\r\n" + + "dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw\r\n" + + "MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV\r\n" + + "MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI\r\n" + + "NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7\r\n" + + "eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G\r\n" + + "odUBlSsJwPPQjZSU\r\n" + + "-----END X509 ATTRIBUTE CERTIFICATE-----\r\n"; + + internal static readonly string ATTRIBUTE_CERTIFICATE_2 = + "-----BEGIN ATTRIBUTE CERTIFICATE-----\r\n" + + "MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl\r\n" + + "IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy\r\n" + + "aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV\r\n" + + "BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv\r\n" + + "dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw\r\n" + + "MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV\r\n" + + "MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI\r\n" + + "NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7\r\n" + + "eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G\r\n" + + "odUBlSsJwPPQjZSU\r\n" + + "-----END ATTRIBUTE CERTIFICATE-----\r\n"; + } +} diff --git a/crypto/test/src/test/PKCS10CertRequestTest.cs b/crypto/test/src/test/PKCS10CertRequestTest.cs new file mode 100644 index 000000000..b1fe4f50f --- /dev/null +++ b/crypto/test/src/test/PKCS10CertRequestTest.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class Pkcs10CertRequestTest + : SimpleTest + { + private static readonly byte[] gost3410EC_A = Base64.Decode( + "MIIBOzCB6wIBADB/MQ0wCwYDVQQDEwR0ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBMdGQxHjAcBgNV" + +"BAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYDVQQGEwJydTEZ" + +"MBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMCAh4B" + +"A0MABEBYx0P2D7YuuZo5HgdIAUKAXcLBDZ+4LYFgbKjrfStVfH59lc40BQ2FZ7M703hLpXK8GiBQ" + +"GEYpKaAuQZnMIpByoAAwCAYGKoUDAgIDA0EAgXMcTrhdOY2Er2tHOSAgnMezqrYxocZTWhxmW5Rl" + +"JY6lbXH5rndCn4swFzXU+YhgAsJv1wQBaoZEWRl5WV4/nA=="); + + private static readonly byte[] gost3410EC_B = Base64.Decode( + "MIIBPTCB7QIBADCBgDENMAsGA1UEAxMEdGVzdDEWMBQGA1UEChMNRGVtb3MgQ28gTHRkLjEeMBwG" + +"A1UECxMVQ3J5cHRvZ3JhcGh5IGRpdmlzaW9uMQ8wDQYDVQQHEwZNb3Njb3cxCzAJBgNVBAYTAnJ1" + +"MRkwFwYJKoZIhvcNAQkBFgpzZGJAZG9sLnJ1MGMwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwIC" + +"HgEDQwAEQI5SLoWT7dZVilbV9j5B/fyIDuDs6x4pjqNC2TtFYbpRHrk/Wc5g/mcHvD80tsm5o1C7" + +"7cizNzkvAVUM4VT4Dz6gADAIBgYqhQMCAgMDQQAoT5TwJ8o+bSrxckymyo3diwG7ZbSytX4sRiKy" + +"wXPWRS9LlBvPO2NqwpS2HUnxSU8rzfL9fJcybATf7Yt1OEVq"); + + private static readonly byte[] gost3410EC_C = Base64.Decode( + "MIIBRDCB9AIBADCBhzEVMBMGA1UEAxMMdGVzdCByZXF1ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBM" + +"dGQxHjAcBgNVBAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYD" + +"VQQGEwJydTEZMBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiMD" + +"BgcqhQMCAh4BA0MABEBcmGh7OmR4iqqj+ycYo1S1fS7r5PhisSQU2Ezuz8wmmmR2zeTZkdMYCOBa" + +"UTMNms0msW3wuYDho7nTDNscHTB5oAAwCAYGKoUDAgIDA0EAVoOMbfyo1Un4Ss7WQrUjHJoiaYW8" + +"Ime5LeGGU2iW3ieAv6es/FdMrwTKkqn5dhd3aL/itFg5oQbhyfXw5yw/QQ=="); + + private static readonly byte[] gost3410EC_ExA = Base64.Decode( + "MIIBOzCB6wIBADB/MQ0wCwYDVQQDEwR0ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBMdGQxHjAcBgNV" + + "BAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYDVQQGEwJydTEZ" + + "MBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiQABgcqhQMCAh4B" + + "A0MABEDkqNT/3f8NHj6EUiWnK4JbVZBh31bEpkwq9z3jf0u8ZndG56Vt+K1ZB6EpFxLT7hSIos0w" + + "weZ2YuTZ4w43OgodoAAwCAYGKoUDAgIDA0EASk/IUXWxoi6NtcUGVF23VRV1L3undB4sRZLp4Vho" + + "gQ7m3CMbZFfJ2cPu6QyarseXGYHmazoirH5lGjEo535c1g=="); + + private static readonly byte[] gost3410EC_ExB = Base64.Decode( + "MIIBPTCB7QIBADCBgDENMAsGA1UEAxMEdGVzdDEWMBQGA1UEChMNRGVtb3MgQ28gTHRkLjEeMBwG" + + "A1UECxMVQ3J5cHRvZ3JhcGh5IGRpdmlzaW9uMQ8wDQYDVQQHEwZNb3Njb3cxCzAJBgNVBAYTAnJ1" + + "MRkwFwYJKoZIhvcNAQkBFgpzZGJAZG9sLnJ1MGMwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwIC" + + "HgEDQwAEQMBWYUKPy/1Kxad9ChAmgoSWSYOQxRnXo7KEGLU5RNSXA4qMUvArWzvhav+EYUfTbWLh" + + "09nELDyHt2XQcvgQHnSgADAIBgYqhQMCAgMDQQAdaNhgH/ElHp64mbMaEo1tPCg9Q22McxpH8rCz" + + "E0QBpF4H5mSSQVGI5OAXHToetnNuh7gHHSynyCupYDEHTbkZ"); + + public override string Name + { + get { return "PKCS10CertRequest"; } + } + + private void generationTest( + int keySize, + string keyName, + string sigName) + { + IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator(keyName); + +// kpg.initialize(keySize); + kpg.Init(new KeyGenerationParameters(new SecureRandom(), keySize)); + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + + IDictionary attrs = new Hashtable(); + attrs.Add(X509Name.C, "AU"); + attrs.Add(X509Name.O, "The Legion of the Bouncy Castle"); + attrs.Add(X509Name.L, "Melbourne"); + attrs.Add(X509Name.ST, "Victoria"); + attrs.Add(X509Name.EmailAddress, "feedback-crypto@bouncycastle.org"); + + IList order = new ArrayList(); + order.Add(X509Name.C); + order.Add(X509Name.O); + order.Add(X509Name.L); + order.Add(X509Name.ST); + order.Add(X509Name.EmailAddress); + + X509Name subject = new X509Name(order, attrs); + + Pkcs10CertificationRequest req1 = new Pkcs10CertificationRequest( + sigName, + subject, + kp.Public, + null, + kp.Private); + + byte[] bytes = req1.GetEncoded(); + + Pkcs10CertificationRequest req2 = new Pkcs10CertificationRequest(bytes); + + if (!req2.Verify()) + { + Fail(sigName + ": Failed Verify check."); + } + + if (!req2.GetPublicKey().Equals(req1.GetPublicKey())) + { + Fail(keyName + ": Failed public key check."); + } + } + + /* + * we generate a self signed certificate for the sake of testing - SHA224withECDSA + */ + private void createECRequest( + string algorithm, + DerObjectIdentifier algOid) + { + FpCurve curve = new FpCurve( + new BigInteger("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"), // q (or p) + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16), // a + new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)); // b + + ECDomainParameters spec = new ECDomainParameters( + curve, +// curve.DecodePoint(Hex.Decode("02C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G + curve.DecodePoint(Hex.Decode("0200C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16)); // n + + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters( + new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d + spec); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( +// curve.DecodePoint(Hex.Decode("026BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q + curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q + spec); + +// // +// // set up the keys +// // +// AsymmetricKeyParameter privKey; +// AsymmetricKeyParameter pubKey; +// +// KeyFactory fact = KeyFactory.getInstance("ECDSA"); +// +// privKey = fact.generatePrivate(privKeySpec); +// pubKey = fact.generatePublic(pubKeySpec); + + Pkcs10CertificationRequest req = new Pkcs10CertificationRequest( + algorithm, new X509Name("CN=XXX"), pubKey, null, privKey); + if (!req.Verify()) + { + Fail("Failed Verify check EC."); + } + + req = new Pkcs10CertificationRequest(req.GetEncoded()); + if (!req.Verify()) + { + Fail("Failed Verify check EC encoded."); + } + + // + // try with point compression turned off + // +// ((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED"); + FpPoint q = (FpPoint) pubKey.Q; + pubKey = new ECPublicKeyParameters( + pubKey.AlgorithmName, + new FpPoint(q.Curve, q.X, q.Y, false), + pubKey.Parameters); + + req = new Pkcs10CertificationRequest( + algorithm, new X509Name("CN=XXX"), pubKey, null, privKey); + if (!req.Verify()) + { + Fail("Failed Verify check EC uncompressed."); + } + + req = new Pkcs10CertificationRequest(req.GetEncoded()); + if (!req.Verify()) + { + Fail("Failed Verify check EC uncompressed encoded."); + } + + if (!req.SignatureAlgorithm.ObjectID.Equals(algOid)) + { + Fail("ECDSA oid incorrect."); + } + + if (req.SignatureAlgorithm.Parameters != null) + { + Fail("ECDSA parameters incorrect."); + } + + ISigner sig = SignerUtilities.GetSigner(algorithm); + + sig.Init(false, pubKey); + + byte[] b = req.GetCertificationRequestInfo().GetEncoded(); + sig.BlockUpdate(b, 0, b.Length); + + if (!sig.VerifySignature(req.Signature.GetBytes())) + { + Fail("signature not mapped correctly."); + } + } + + private void createECGostRequest() + { + string algorithm = "GOST3411withECGOST3410"; + IAsymmetricCipherKeyPairGenerator ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410"); + + ecGostKpg.Init( + new ECKeyGenerationParameters( + CryptoProObjectIdentifiers.GostR3410x2001CryptoProA, + new SecureRandom())); + + // + // set up the keys + // + AsymmetricCipherKeyPair pair = ecGostKpg.GenerateKeyPair(); + AsymmetricKeyParameter privKey = pair.Private; + AsymmetricKeyParameter pubKey = pair.Public; + + Pkcs10CertificationRequest req = new Pkcs10CertificationRequest( + algorithm, new X509Name("CN=XXX"), pubKey, null, privKey); + + if (!req.Verify()) + { + Fail("Failed Verify check EC."); + } + + req = new Pkcs10CertificationRequest(req.GetEncoded()); + if (!req.Verify()) + { + Fail("Failed Verify check EC encoded."); + } + + if (!req.SignatureAlgorithm.ObjectID.Equals(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001)) + { + Fail("ECGOST oid incorrect."); + } + + if (req.SignatureAlgorithm.Parameters != null) + { + Fail("ECGOST parameters incorrect."); + } + + ISigner sig = SignerUtilities.GetSigner(algorithm); + + sig.Init(false, pubKey); + + byte[] b = req.GetCertificationRequestInfo().GetEncoded(); + sig.BlockUpdate(b, 0, b.Length); + + if (!sig.VerifySignature(req.Signature.GetBytes())) + { + Fail("signature not mapped correctly."); + } + } + + private void createPssTest( + string algorithm) + { +// RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( + RsaKeyParameters pubKey = new RsaKeyParameters(false, + new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16), + new BigInteger("010001",16)); + +// RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( + RsaPrivateCrtKeyParameters privKey = 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)); + +// KeyFactory fact = KeyFactory.getInstance("RSA", "BC"); +// +// PrivateKey privKey = fact.generatePrivate(privKeySpec); +// PublicKey pubKey = fact.generatePublic(pubKeySpec); + + Pkcs10CertificationRequest req = new Pkcs10CertificationRequest( + algorithm, new X509Name("CN=XXX"), pubKey, null, privKey); + + if (!req.Verify()) + { + Fail("Failed verify check PSS."); + } + + req = new Pkcs10CertificationRequest(req.GetEncoded()); + if (!req.Verify()) + { + Fail("Failed verify check PSS encoded."); + } + + if (!req.SignatureAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss)) + { + Fail("PSS oid incorrect."); + } + + if (req.SignatureAlgorithm.Parameters == null) + { + Fail("PSS parameters incorrect."); + } + + ISigner sig = SignerUtilities.GetSigner(algorithm); + + sig.Init(false, pubKey); + + byte[] encoded = req.GetCertificationRequestInfo().GetEncoded(); + sig.BlockUpdate(encoded, 0, encoded.Length); + + if (!sig.VerifySignature(req.Signature.GetBytes())) + { + Fail("signature not mapped correctly."); + } + } + + // previous code found to cause a NullPointerException + private void nullPointerTest() + { + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); + + AsymmetricCipherKeyPair pair = keyGen.GenerateKeyPair(); + + IList oids = new ArrayList(); + IList values = new ArrayList(); + oids.Add(X509Extensions.BasicConstraints); + values.Add(new X509Extension(true, new DerOctetString(new BasicConstraints(true)))); + oids.Add(X509Extensions.KeyUsage); + values.Add(new X509Extension(true, new DerOctetString( + new KeyUsage(KeyUsage.KeyCertSign | KeyUsage.CrlSign)))); + SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pair.Public); + X509Extension ski = new X509Extension(false, new DerOctetString(subjectKeyIdentifier)); + oids.Add(X509Extensions.SubjectKeyIdentifier); + values.Add(ski); + + AttributePkcs attribute = new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, + new DerSet(new X509Extensions(oids, values))); + + Pkcs10CertificationRequest p1 = new Pkcs10CertificationRequest( + "SHA1WithRSA", new X509Name("cn=csr"), pair.Public, new DerSet(attribute), pair.Private); + Pkcs10CertificationRequest p2 = new Pkcs10CertificationRequest( + "SHA1WithRSA", new X509Name("cn=csr"), pair.Public, new DerSet(attribute), pair.Private); + + if (!p1.Equals(p2)) + { + Fail("cert request comparison failed"); + } + } + + public override void PerformTest() + { + generationTest(512, "RSA", "SHA1withRSA"); + generationTest(512, "GOST3410", "GOST3411withGOST3410"); + + // if (Security.getProvider("SunRsaSign") != null) + // { + // generationTest(512, "RSA", "SHA1withRSA", "SunRsaSign"); + // } + + // elliptic curve GOST A parameter set + Pkcs10CertificationRequest req = new Pkcs10CertificationRequest(gost3410EC_A); + if (!req.Verify()) + { + Fail("Failed Verify check gost3410EC_A."); + } + + // elliptic curve GOST B parameter set + req = new Pkcs10CertificationRequest(gost3410EC_B); + if (!req.Verify()) + { + Fail("Failed Verify check gost3410EC_B."); + } + + // elliptic curve GOST C parameter set + req = new Pkcs10CertificationRequest(gost3410EC_C); + if (!req.Verify()) + { + Fail("Failed Verify check gost3410EC_C."); + } + + // elliptic curve GOST ExA parameter set + req = new Pkcs10CertificationRequest(gost3410EC_ExA); + if (!req.Verify()) + { + Fail("Failed Verify check gost3410EC_ExA."); + } + + // elliptic curve GOST ExB parameter set + req = new Pkcs10CertificationRequest(gost3410EC_ExB); + if (!req.Verify()) + { + Fail("Failed Verify check gost3410EC_ExA."); + } + + // elliptic curve openSSL + IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA"); + + ECCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters ecSpec = new ECDomainParameters( + curve, + curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + +// g.initialize(ecSpec, new SecureRandom()); + g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); + + AsymmetricCipherKeyPair kp = g.GenerateKeyPair(); + + req = new Pkcs10CertificationRequest( + "ECDSAWITHSHA1", new X509Name("CN=XXX"), kp.Public, null, kp.Private); + + if (!req.Verify()) + { + Fail("Failed Verify check EC."); + } + + createECRequest("SHA1withECDSA", X9ObjectIdentifiers.ECDsaWithSha1); + createECRequest("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224); + createECRequest("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256); + createECRequest("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384); + createECRequest("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512); + + createECGostRequest(); + + // TODO The setting of parameters for MGF algorithms is not implemented +// createPssTest("SHA1withRSAandMGF1"); +// createPssTest("SHA224withRSAandMGF1"); +// createPssTest("SHA256withRSAandMGF1"); +// createPssTest("SHA384withRSAandMGF1"); + + nullPointerTest(); + } + + public static void Main( + string[] args) + { + RunTest(new Pkcs10CertRequestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PSSTest.cs b/crypto/test/src/test/PSSTest.cs new file mode 100644 index 000000000..677289e7c --- /dev/null +++ b/crypto/test/src/test/PSSTest.cs @@ -0,0 +1,253 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class PssTest + : SimpleTest + { + private class FixedRandom + : SecureRandom + { + private readonly byte[] vals; + + public FixedRandom( + byte[] vals) + { + this.vals = vals; + } + + public override void NextBytes( + byte[] bytes) + { + vals.CopyTo(bytes, 0); + } + } + + private RsaKeyParameters pubKey = new RsaKeyParameters(false, + new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16), + new BigInteger("010001",16)); + + private RsaPrivateCrtKeyParameters privKey = 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 static readonly byte[] msg1a = Hex.Decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0"); + + private static readonly byte[] slt1a = Hex.Decode("dee959c7e06411361420ff80185ed57f3e6776af"); + + private static readonly byte[] sig1a = Hex.Decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c"); + + private static readonly byte[] sig1b = Hex.Decode("96ea348db4db2947aee807bd687411a880913706f21b383a1002b97e43656e5450a9d1812efbedd1ed159f8307986adf48bada66a8efd14bd9e2f6f6f458e73b50c8ce6e3079011c5b4bd1600a2601a66198a1582574a43f13e0966c6c2337e6ca0886cd9e1b1037aeadef1382117d22b35e7e4403f90531c8cfccdf223f98e4"); + + private static readonly byte[] sig1c = Hex.Decode("9e64cc1062c537b142480bc5af407b55904ead970e20e0f8f6664279c96c6da6b03522160f224a85cc413dfe6bd00621485b665abac6d90ff38c9af06f4ddd6c7c81540439e5795601a1343d9feb465712ff8a5f5150391522fb5a9b8e2225a555f4efaa5e5c0ed7a19b27074c2d9f6dbbd0c893ba02c4a35b115d337bccd7a2"); + + public override void PerformTest() + { + ISigner s = SignerUtilities.GetSigner("SHA1withRSA/PSS"); + + s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a))); + s.BlockUpdate(msg1a, 0, msg1a.Length); + byte[] sig = s.GenerateSignature(); + + if (!Arrays.AreEqual(sig1a, sig)) + { + Fail("PSS Sign test expected " + + Hex.ToHexString(sig1a) + " got " + + Hex.ToHexString(sig)); + } + + s = SignerUtilities.GetSigner("SHA1withRSAandMGF1"); + + s.Init(false, pubKey); + s.BlockUpdate(msg1a, 0, msg1a.Length); + if (!s.VerifySignature(sig1a)) + { + Fail("SHA1 signature verification failed"); + } + + s = SignerUtilities.GetSigner("SHA1withRSAandMGF1"); + + s.Init(false, pubKey); + s.BlockUpdate(msg1a, 0, msg1a.Length); + if (!s.VerifySignature(sig1a)) + { + Fail("SHA1 signature verification with default parameters failed"); + } + +// AlgorithmParameters pss = s.getParameters(); + // TODO Can we do some equivalent check? +// if (!Arrays.AreEqual(pss.getEncoded(), new byte[] { 0x30, 0x00 })) +// { +// Fail("failed default encoding test."); +// } + + s = SignerUtilities.GetSigner("SHA256withRSA/PSS"); + + s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a))); + s.BlockUpdate(msg1a, 0, msg1a.Length); + sig = s.GenerateSignature(); + + if (!Arrays.AreEqual(sig1b, sig)) + { + Fail("PSS Sign test expected " + + Hex.ToHexString(sig1b) + " got " + + Hex.ToHexString(sig)); + } + + s = SignerUtilities.GetSigner("SHA256withRSAandMGF1"); + + s.Init(false, pubKey); + s.BlockUpdate(msg1a, 0, msg1a.Length); + if (!s.VerifySignature(sig1b)) + { + Fail("SHA256 signature verification failed"); + } + + // + // 512 test -with zero salt length + // + //s = SignerUtilities.GetSigner("SHA512withRSAandMGF1"); +// s.setParameter( +// new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-512"), 0, 1)); + + // TODO How to do this via SignerUtilities/Init + // trailerField=1 above means use default/implicit trailer?) + s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit); + s.Init(true, privKey); + + s.BlockUpdate(msg1a, 0, msg1a.Length); + sig = s.GenerateSignature(); + +// pss = s.getParameters(); + + if (!Arrays.AreEqual(sig1c, sig)) + { + Fail("PSS Sign test expected " + + Hex.ToHexString(sig1c) + " got " + + Hex.ToHexString(sig)); + } + + + +// s = SignerUtilities.GetSigner("SHA512withRSAandMGF1"); + + // TODO How to do this via SignerUtilities/Init + // trailerField=1 above means use default/implicit trailer?) + s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit); + s.Init(false, pubKey); + + s.BlockUpdate(msg1a, 0, msg1a.Length); + if (!s.VerifySignature(sig1c)) + { + Fail("SHA512 signature verification failed"); + } + + SecureRandom random = new SecureRandom(); + + // Note: PSS minimum key size determined by hash/salt lengths +// PrivateKey priv2048Key = fact.generatePrivate(RSATest.priv2048KeySpec); +// PublicKey pub2048Key = fact.generatePublic(RSATest.pub2048KeySpec); + AsymmetricKeyParameter priv2048Key = RsaTest.priv2048KeySpec; + AsymmetricKeyParameter pub2048Key = RsaTest.pub2048KeySpec; + + rawModeTest("SHA1withRSA/PSS", X509ObjectIdentifiers.IdSha1, priv2048Key, pub2048Key, random); + // FIXME +// rawModeTest("SHA224withRSA/PSS", NistObjectIdentifiers.IdSha224, priv2048Key, pub2048Key, random); +// rawModeTest("SHA256withRSA/PSS", NistObjectIdentifiers.IdSha256, priv2048Key, pub2048Key, random); +// rawModeTest("SHA384withRSA/PSS", NistObjectIdentifiers.IdSha384, priv2048Key, pub2048Key, random); +// rawModeTest("SHA512withRSA/PSS", NistObjectIdentifiers.IdSha512, priv2048Key, pub2048Key, random); + } + + private void rawModeTest(string sigName, DerObjectIdentifier digestOID, + AsymmetricKeyParameter privKey, AsymmetricKeyParameter pubKey, SecureRandom random) + { + byte[] sampleMessage = new byte[1000 + random.Next() % 100]; + random.NextBytes(sampleMessage); + + ISigner normalSig = SignerUtilities.GetSigner(sigName); + + // FIXME +// PSSParameterSpec spec = (PSSParameterSpec)normalSig.getParameters().getParameterSpec(PSSParameterSpec.class); + + // Make sure we generate the same 'random' salt for both normal and raw signers + // FIXME +// int saltLen = spec.getSaltLength(); +// byte[] fixedRandomBytes = new byte[saltLen]; + byte[] fixedRandomBytes = new byte[128]; + random.NextBytes(fixedRandomBytes); + + normalSig.Init(true, new ParametersWithRandom(privKey, FixedSecureRandom.From(fixedRandomBytes))); + normalSig.BlockUpdate(sampleMessage, 0, sampleMessage.Length); + byte[] normalResult = normalSig.GenerateSignature(); + + byte[] hash = DigestUtilities.CalculateDigest(digestOID.Id, sampleMessage); + + ISigner rawSig = SignerUtilities.GetSigner("RAWRSASSA-PSS"); + + // Need to init the params explicitly to avoid having a 'raw' variety of every PSS algorithm + // FIXME +// rawSig.setParameter(spec); + + rawSig.Init(true, new ParametersWithRandom(privKey, FixedSecureRandom.From(fixedRandomBytes))); + rawSig.BlockUpdate(hash, 0, hash.Length); + byte[] rawResult = rawSig.GenerateSignature(); + + if (!Arrays.AreEqual(normalResult, rawResult)) + { + Fail("raw mode signature differs from normal one"); + } + + rawSig.Init(false, pubKey); + rawSig.BlockUpdate(hash, 0, hash.Length); + + if (!rawSig.VerifySignature(rawResult)) + { + Fail("raw mode signature verification failed"); + } + } + + public override string Name + { + get { return "PSS"; } + } + + public static void Main( + string[] args) + { + RunTest(new PssTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PkixNameConstraintsTest.cs b/crypto/test/src/test/PkixNameConstraintsTest.cs new file mode 100644 index 000000000..a20fc33c4 --- /dev/null +++ b/crypto/test/src/test/PkixNameConstraintsTest.cs @@ -0,0 +1,433 @@ +using System; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + /// + /// Test class for {@link PkixNameConstraintValidator}. + /// The field testXYZ is the name to test. + /// The field testXYZIsConstraint must be tested if it is permitted and excluded. + /// The field testXYZIsNotConstraint must be tested if it is not permitted and + /// not excluded. + /// Furthermore there are tests for the intersection and union of test names. + /// + [TestFixture] + public class PkixNameConstraintsTest + : SimpleTest + { + private readonly string testEmail = "test@abc.test.com"; + + private readonly string[] testEmailIsConstraint = { "test@abc.test.com", "abc.test.com", ".test.com" }; + + private readonly string[] testEmailIsNotConstraint = { ".abc.test.com", "www.test.com", "test1@abc.test.com", "bc.test.com" }; + + private readonly string[] email1 = { + "test@test.com", "test@test.com", "test@test.com", "test@abc.test.com", + "test@test.com", "test@test.com", ".test.com", ".test.com", + ".test.com", ".test.com", "test.com", "abc.test.com", + "abc.test1.com", "test.com", "test.com", ".test.com" }; + + private readonly string[] email2 = { + "test@test.abc.com", "test@test.com", ".test.com", ".test.com", + "test.com", "test1.com", "test@test.com", ".test.com", + ".test1.com", "test.com", "test.com", ".test.com", ".test.com", + "test1.com", ".test.com", "abc.test.com" }; + + private readonly string[] emailintersect = { + null, "test@test.com", null, "test@abc.test.com", "test@test.com", null, + null, ".test.com", null, null, "test.com", "abc.test.com", null, + null, null, "abc.test.com" }; + + private readonly string[][] emailunion = new string[16][] { + new string[] { "test@test.com", "test@test.abc.com" }, + new string[] { "test@test.com" }, + new string[] { "test@test.com", ".test.com" }, + new string[] { ".test.com" }, + new string[] { "test.com" }, + new string[] { "test@test.com", "test1.com" }, + new string[] { ".test.com", "test@test.com" }, + new string[] { ".test.com" }, + new string[] { ".test.com", ".test1.com" }, + new string[] { ".test.com", "test.com" }, + new string[] { "test.com" }, + new string[] { ".test.com" }, + new string[] { ".test.com", "abc.test1.com" }, + new string[] { "test1.com", "test.com" }, + new string[] { ".test.com", "test.com" }, + new string[] { ".test.com" } }; + + private readonly string[] dn1 = { "O=test org, OU=test org unit, CN=John Doe" }; + + private readonly string[] dn2 = { "O=test org, OU=test org unit" }; + + private readonly string[][] dnUnion = new string[1][] { + new string[] { "O=test org, OU=test org unit" } }; + + private readonly string[] dnIntersection = { "O=test org, OU=test org unit, CN=John Doe" }; + + private readonly string testDN = "O=test org, OU=test org unit, CN=John Doe"; + + private readonly string[] testDNIsConstraint = { + "O=test org, OU=test org unit", + "O=test org, OU=test org unit, CN=John Doe" }; + + private readonly string[] testDNIsNotConstraint = { + "O=test org, OU=test org unit, CN=John Doe2", + "O=test org, OU=test org unit2", + "OU=test org unit, O=test org, CN=John Doe", + "O=test org, OU=test org unit, CN=John Doe, L=USA" }; + + private readonly string testDNS = "abc.test.com"; + + private readonly string[] testDNSIsConstraint = { "test.com", "abc.test.com", "test.com" }; + + private readonly string[] testDNSIsNotConstraint = { "wwww.test.com", "ww.test.com", "www.test.com" }; + + private readonly string[] dns1 = { "www.test.de", "www.test1.de", "www.test.de" }; + + private readonly string[] dns2 = { "test.de", "www.test.de", "www.test.de" }; + + private readonly string[] dnsintersect = { "www.test.de", null, null }; + + private readonly string[][] dnsunion = new string[3][] { + new string[] { "test.de" }, + new string[] { "www.test1.de", "www.test.de" }, + new string[] { "www.test.de" } }; + + private readonly string testURI = "http://karsten:password@abc.test.com:8080"; + + private readonly string[] testURIIsConstraint = { "abc.test.com", ".test.com" }; + + private readonly string[] testURIIsNotConstraint = { "xyz.test.com", ".abc.test.com" }; + + private readonly string[] uri1 = { "www.test.de", ".test.de", "test1.de", ".test.de" }; + + private readonly string[] uri2 = { "test.de", "www.test.de", "test1.de", ".test.de" }; + + private readonly string[] uriintersect = { null, "www.test.de", "test1.de", ".test.de" }; + + private readonly string[][] uriunion = new string[4][] { + new string[] { "www.test.de", "test.de" }, + new string[] { ".test.de" }, + new string[] { "test1.de" }, + new string[] { ".test.de" } }; + + private readonly byte[] testIP = { (byte)192, (byte)168, 1, 2 }; + + private readonly byte[][] testIPIsConstraint = new byte[2][] { + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0 }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 4 } }; + + private readonly byte[][] testIPIsNotConstraint = new byte[2][] { + new byte[] { (byte) 192, (byte) 168, 3, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 2 }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 3 } }; + + private readonly byte[][] ip1 = new byte[3][] { + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFE, (byte) 0xFF }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0x00 } }; + + private readonly byte[][] ip2 = new byte[3][] { + new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFC, 3 }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF }, + new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0x00 } }; + + private readonly byte[][] ipintersect = new byte[3][] { + new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFE, (byte) 0xFF }, + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF }, null }; + + private readonly byte[][][] ipunion = new byte[3][][] { + new byte[2][] { + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFE, (byte) 0xFF }, + new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFC, 3 } }, + new byte[1][] { + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF } }, + new byte[2][] { + new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0x00 }, + new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0x00 } } }; + + public override string Name + { + get { return "PkixNameConstraintsTest"; } + } + + public override void PerformTest() + { + TestConstraints(GeneralName.Rfc822Name, testEmail, + testEmailIsConstraint, testEmailIsNotConstraint, email1, email2, + emailunion, emailintersect); + TestConstraints(GeneralName.DnsName, testDNS, testDNSIsConstraint, + testDNSIsNotConstraint, dns1, dns2, dnsunion, dnsintersect); + TestConstraints(GeneralName.DirectoryName, testDN, testDNIsConstraint, + testDNIsNotConstraint, dn1, dn2, dnUnion, dnIntersection); + TestConstraints(GeneralName.UniformResourceIdentifier, testURI, + testURIIsConstraint, testURIIsNotConstraint, uri1, uri2, uriunion, + uriintersect); + TestConstraints(GeneralName.IPAddress, testIP, testIPIsConstraint, + testIPIsNotConstraint, ip1, ip2, ipunion, ipintersect); + } + + /** + * Tests string based GeneralNames for inclusion or exclusion. + * + * @param nameType The {@link GeneralName} type to test. + * @param testName The name to test. + * @param testNameIsConstraint The names where testName must + * be included and excluded. + * @param testNameIsNotConstraint The names where testName + * must not be excluded and included. + * @param testNames1 Operand 1 of test names to use for union and + * intersection testing. + * @param testNames2 Operand 2 of test names to use for union and + * intersection testing. + * @param testUnion The union results. + * @param testInterSection The intersection results. + * @throws Exception If an unexpected exception occurs. + */ + private void TestConstraints( + int nameType, + string testName, + string[] testNameIsConstraint, + string[] testNameIsNotConstraint, + string[] testNames1, + string[] testNames2, + string[][] testUnion, + string[] testInterSection) + { + for (int i = 0; i < testNameIsConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, testNameIsConstraint[i])))); + constraintValidator.checkPermitted(new GeneralName(nameType, testName)); + } + for (int i = 0; i < testNameIsNotConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, testNameIsNotConstraint[i])))); + try + { + constraintValidator.checkPermitted(new GeneralName(nameType, testName)); + Fail("not permitted name allowed: " + nameType); + } + catch (PkixNameConstraintValidatorException) + { + // expected + } + } + for (int i = 0; i < testNameIsConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, testNameIsConstraint[i]))); + try + { + constraintValidator.checkExcluded(new GeneralName(nameType, testName)); + Fail("excluded name missed: " + nameType); + } + catch (PkixNameConstraintValidatorException) + { + // expected + } + } + for (int i = 0; i < testNameIsNotConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, testNameIsNotConstraint[i]))); + constraintValidator.checkExcluded(new GeneralName(nameType, testName)); + } + for (int i = 0; i < testNames1.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, testNames1[i]))); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, testNames2[i]))); + PkixNameConstraintValidator constraints2 = new PkixNameConstraintValidator(); + for (int j = 0; j < testUnion[i].Length; j++) + { + constraints2.AddExcludedSubtree(new GeneralSubtree( + new GeneralName(nameType, testUnion[i][j]))); + } + if (!constraints2.Equals(constraintValidator)) + { + Fail("union wrong: " + nameType); + } + constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, testNames1[i])))); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, testNames2[i])))); + constraints2 = new PkixNameConstraintValidator(); + if (testInterSection[i] != null) + { + constraints2.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, testInterSection[i])))); + } + else + { + constraints2.IntersectEmptyPermittedSubtree(nameType); + } + if (!constraints2.Equals(constraintValidator)) + { + Fail("intersection wrong: " + nameType); + } + } + } + + /** + * Tests byte array based GeneralNames for inclusion or exclusion. + * + * @param nameType The {@link GeneralName} type to test. + * @param testName The name to test. + * @param testNameIsConstraint The names where testName must + * be included and excluded. + * @param testNameIsNotConstraint The names where testName + * must not be excluded and included. + * @param testNames1 Operand 1 of test names to use for union and + * intersection testing. + * @param testNames2 Operand 2 of test names to use for union and + * intersection testing. + * @param testUnion The union results. + * @param testInterSection The intersection results. + * @throws Exception If an unexpected exception occurs. + */ + private void TestConstraints( + int nameType, + byte[] testName, + byte[][] testNameIsConstraint, + byte[][] testNameIsNotConstraint, + byte[][] testNames1, + byte[][] testNames2, + byte[][][] testUnion, + byte[][] testInterSection) + { + for (int i = 0; i < testNameIsConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString( + testNameIsConstraint[i]))))); + constraintValidator.checkPermitted(new GeneralName(nameType, + new DerOctetString(testName))); + } + for (int i = 0; i < testNameIsNotConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString( + testNameIsNotConstraint[i]))))); + try + { + constraintValidator.checkPermitted(new GeneralName(nameType, + new DerOctetString(testName))); + Fail("not permitted name allowed: " + nameType); + } + catch (PkixNameConstraintValidatorException) + { + // expected + } + } + for (int i = 0; i < testNameIsConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, new DerOctetString(testNameIsConstraint[i])))); + try + { + constraintValidator.checkExcluded(new GeneralName(nameType, + new DerOctetString(testName))); + Fail("excluded name missed: " + nameType); + } + catch (PkixNameConstraintValidatorException) + { + // expected + } + } + for (int i = 0; i < testNameIsNotConstraint.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, new DerOctetString(testNameIsNotConstraint[i])))); + constraintValidator.checkExcluded(new GeneralName(nameType, + new DerOctetString(testName))); + } + for (int i = 0; i < testNames1.Length; i++) + { + PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, new DerOctetString(testNames1[i])))); + constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName( + nameType, new DerOctetString(testNames2[i])))); + PkixNameConstraintValidator constraints2 = new PkixNameConstraintValidator(); + for (int j = 0; j < testUnion[i].Length; j++) + { + constraints2.AddExcludedSubtree(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString( + testUnion[i][j])))); + } + if (!constraints2.Equals(constraintValidator)) + { + Fail("union wrong: " + nameType); + } + constraintValidator = new PkixNameConstraintValidator(); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString(testNames1[i]))))); + constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString(testNames2[i]))))); + constraints2 = new PkixNameConstraintValidator(); + if (testInterSection[i] != null) + { + constraints2.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree( + new GeneralName(nameType, new DerOctetString( + testInterSection[i]))))); + } + else + { + constraints2.IntersectEmptyPermittedSubtree(nameType); + } + + if (!constraints2.Equals(constraintValidator)) + { + Fail("intersection wrong: " + nameType); + } + } + } + + public static void Main( + string[] args) + { + RunTest(new PkixNameConstraintsTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PkixPolicyMappingTest.cs b/crypto/test/src/test/PkixPolicyMappingTest.cs new file mode 100644 index 000000000..47e2c3120 --- /dev/null +++ b/crypto/test/src/test/PkixPolicyMappingTest.cs @@ -0,0 +1,419 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class PkixPolicyMappingTest : SimpleTest + { + static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + public override string Name + { + get { return "PkixPolicyMapping"; } + } + + /** + * TrustAnchor's Cert + */ + private X509Certificate CreateTrustCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter privKey) + { + string issuer = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor"; + string subject = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor"; + v3CertGen.SetSerialNumber(BigInteger.ValueOf(10)); + v3CertGen.SetIssuerDN(new X509Name(issuer)); + v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30)); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30)); + v3CertGen.SetSubjectDN(new X509Name(subject)); + v3CertGen.SetPublicKey(pubKey); + v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + X509Certificate cert = v3CertGen.Generate(privKey); + return cert; + } + + /** + * intermediate cert + */ + private X509Certificate CreateIntmedCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter caPrivKey, + AsymmetricKeyParameter caPubKey, + Asn1EncodableVector policies, + Hashtable policyMap) + { + string issuer = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor"; + string subject = "C=JP, O=policyMappingAdditionalTest, OU=intmedCA"; + v3CertGen.Reset(); + v3CertGen.SetSerialNumber(BigInteger.ValueOf(20)); + v3CertGen.SetIssuerDN(new X509Name(issuer)); + v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30)); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30)); + v3CertGen.SetSubjectDN(new X509Name(subject)); + v3CertGen.SetPublicKey(pubKey); + v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + v3CertGen.AddExtension(X509Extensions.CertificatePolicies, true, new DerSequence(policies)); + v3CertGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true)); + v3CertGen.AddExtension(X509Extensions.PolicyMappings, true, new PolicyMappings(policyMap)); + X509Certificate cert = v3CertGen.Generate(caPrivKey); + return cert; + } + + /** + * endEntity cert + */ + private X509Certificate CreateEndEntityCert( + AsymmetricKeyParameter pubKey, + AsymmetricKeyParameter caPrivKey, + AsymmetricKeyParameter caPubKey, + Asn1EncodableVector policies) + { + string issuer = "C=JP, O=policyMappingAdditionalTest, OU=intMedCA"; + string subject = "C=JP, O=policyMappingAdditionalTest, OU=endEntity"; + v3CertGen.Reset(); + v3CertGen.SetSerialNumber(BigInteger.ValueOf(20)); + v3CertGen.SetIssuerDN(new X509Name(issuer)); + v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30)); + v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30)); + v3CertGen.SetSubjectDN(new X509Name(subject)); + v3CertGen.SetPublicKey(pubKey); + v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption"); + v3CertGen.AddExtension(X509Extensions.CertificatePolicies, true, new DerSequence(policies)); + X509Certificate cert = v3CertGen.Generate(caPrivKey); + return cert; + } + + private string TestPolicies( + int index, + X509Certificate trustCert, + X509Certificate intCert, + X509Certificate endCert, + ISet requirePolicies, + bool okay) + { + ISet trust = new HashSet(); + trust.Add(new TrustAnchor(trustCert, null)); + X509CertStoreSelector targetConstraints = new X509CertStoreSelector(); + targetConstraints.Subject = endCert.SubjectDN; + PkixBuilderParameters pbParams = new PkixBuilderParameters(trust, targetConstraints); + + ISet certs = new HashSet(); + certs.Add(intCert); + certs.Add(endCert); + + IX509Store store = X509StoreFactory.Create( + "CERTIFICATE/COLLECTION", + new X509CollectionStoreParameters(certs)); + pbParams.AddStore(store); + + pbParams.IsRevocationEnabled = false; + if (requirePolicies != null) + { + pbParams.IsExplicitPolicyRequired = true; + pbParams.SetInitialPolicies(requirePolicies); + } + +// CertPathBuilder cpb = CertPathBuilder.GetInstance("PKIX"); + PkixCertPathBuilder cpb = new PkixCertPathBuilder(); + PkixCertPathBuilderResult result = null; + + try + { + result = (PkixCertPathBuilderResult)cpb.Build(pbParams); + + if (!okay) + { + Fail(index + ": path validated when failure expected."); + } + +// if (result.getPolicyTree() != null) +// { +// Console.WriteLine("OK"); +// Console.WriteLine("policy: " + result.getPolicyTree()); +// } +// else +// { +// Console.WriteLine("OK: policy tree = null"); +// } + + return ""; + } + catch (TestFailedException e) + { + throw e; + } + catch (Exception e) + { + if (okay) + { + Fail(index + ": path failed to validate when success expected."); + } + + Exception ee = e.InnerException; + if (ee != null) + { + return ee.Message; + } + + return e.Message; + } + } + + public override void PerformTest() + { + // + // personal keys + // + RsaPublicKeyStructure pubKeySpec = new RsaPublicKeyStructure( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + RsaPrivateCrtKeyParameters privKeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + // + // intermediate keys. + // + RsaPublicKeyStructure intPubKeySpec = new RsaPublicKeyStructure( + new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), + new BigInteger("ffff", 16)); + + + RsaPrivateCrtKeyParameters intPrivKeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), + new BigInteger("ffff", 16), + new BigInteger("7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff", 16), + new BigInteger("ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649", 16), + new BigInteger("97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721", 16), + new BigInteger("6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f", 16), + new BigInteger("70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f", 16), + new BigInteger("e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d", 16)); + + // + // ca keys + // + RsaPublicKeyStructure caPubKeySpec = new RsaPublicKeyStructure( + new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), + new BigInteger("11", 16)); + + RsaPrivateCrtKeyParameters caPrivKeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), + new BigInteger("11", 16), + new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16), + new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16), + new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16), + new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16), + new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16), + new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16)); + + // + // set up the keys + // + AsymmetricKeyParameter caPrivKey = caPrivKeySpec; + RsaKeyParameters caPubKey = new RsaKeyParameters(false, caPubKeySpec.Modulus, caPubKeySpec.PublicExponent); + AsymmetricKeyParameter intPrivKey = intPrivKeySpec; + RsaKeyParameters intPubKey = new RsaKeyParameters(false, intPubKeySpec.Modulus, intPubKeySpec.PublicExponent); + AsymmetricKeyParameter privKey = privKeySpec; + RsaKeyParameters pubKey = new RsaKeyParameters(false, pubKeySpec.Modulus, intPubKeySpec.PublicExponent); + + X509Certificate trustCert = CreateTrustCert(caPubKey, caPrivKeySpec); + Asn1EncodableVector intPolicies = null; + Hashtable map = null; + Asn1EncodableVector policies = null; + ISet requirePolicies = null; + X509Certificate intCert = null; + X509Certificate endCert = null; + + // valid test_00 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = null; + string msg = TestPolicies(0, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(0, msg, ""); + + // test_01 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.1"); + msg = TestPolicies(1, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(1, msg, ""); + + // test_02 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.5.29.32.0"); + msg = TestPolicies(2, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(2, msg, ""); + + // test_03 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3"))); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.1"); + msg = TestPolicies(3, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(3, msg, ""); + + // test_04 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3"))); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.3"); + msg = TestPolicies(4, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(4, msg, ""); + + // test_05 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.2"); + msg = TestPolicies(5, trustCert, intCert, endCert, requirePolicies, false); + CheckMessage(5, msg, "Path processing failed on policy."); + + // test_06 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.1"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.1"); + msg = TestPolicies(6, trustCert, intCert, endCert, requirePolicies, true); + CheckMessage(6, msg, ""); + + // test_07 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.3"); + msg = TestPolicies(7, trustCert, intCert, endCert, requirePolicies, false); + CheckMessage(7, msg, "Path processing failed on policy."); + + // test_08 + intPolicies = new Asn1EncodableVector(); + intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0"))); + map = new Hashtable(); + map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2"; + intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map); + + policies = new Asn1EncodableVector(); + policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3"))); + endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies); + + requirePolicies = new HashSet(); + requirePolicies.Add("2.16.840.1.101.3.2.1.48.1"); + msg = TestPolicies(8, trustCert, intCert, endCert, requirePolicies, false); + CheckMessage(8, msg, "Path processing failed on policy."); + } + + private void CheckMessage( + int index, + string msg, + string expected) + { + if (!msg.Equals(expected)) + { + Fail("test " + index + " failed got: " + msg + " expected: " + expected); + } + } + + public static void Main( + string[] args) + { + RunTest(new PkixPolicyMappingTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/PkixTest.cs b/crypto/test/src/test/PkixTest.cs new file mode 100644 index 000000000..882319610 --- /dev/null +++ b/crypto/test/src/test/PkixTest.cs @@ -0,0 +1,248 @@ +using System; +using System.IO; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.X509; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class PkixTest + : SimpleTest + { + /* + * The following certs and crls are described in: + * http://www.ietf.org/internet-drafts/draft-ietf-pkix-new-part1-08.txt + * + * This section contains four examples: three certificates and a CRL. + * The first two certificates and the CRL comprise a minimal + * certification path. + * + * Section C.1 contains an annotated hex dump of a "self-signed" + * certificate issued by a CA whose distinguished name is + * cn=us,o=gov,ou=nist. The certificate contains a DSA public key with + * parameters, and is signed by the corresponding DSA private key. + * + * Section C.2 contains an annotated hex dump of an end entity + * certificate. The end entity certificate contains a DSA public key, + * and is signed by the private key corresponding to the "self-signed" + * certificate in section C.1. + * + * Section C.3 contains a dump of an end entity certificate which + * contains an RSA public key and is signed with RSA and MD5. This + * certificate is not part of the minimal certification path. + * + * Section C.4 contains an annotated hex dump of a CRL. The CRL is + * issued by the CA whose distinguished name is cn=us,o=gov,ou=nist and + * the list of revoked certificates includes the end entity certificate + * presented in C.2. + */ + + /** + * C.1 Certificate + * + * This section contains an annotated hex dump of a 699 byte version 3 + * certificate. The certificate contains the following information: + * (a) the serial number is 23 (17 hex); + * (b) the certificate is signed with DSA and the SHA-1 hash algorithm; + * (c) the issuer's distinguished name is OU=NIST; O=gov; C=US + * (d) and the subject's distinguished name is OU=NIST; O=gov; C=US + * (e) the certificate was issued on June 30, 1997 and will expire on + * December 31, 1997; + * (f) the certificate contains a 1024 bit DSA public key with + * parameters; + * (g) the certificate contains a subject key identifier extension + * generated using method (1) of section 4.2.1.2; and + * (h) the certificate is a CA certificate (as indicated through the + * basic constraints extension.) + */ + static byte[] rootCertBin = Hex.Decode( + "308202bb3082027ba003020102020111300906072a8648ce380403302a310b30" + + "09060355040613025553310c300a060355040a1303676f76310d300b06035504" + + "0b13044e495354301e170d3937303633303030303030305a170d393731323331" + + "3030303030305a302a310b3009060355040613025553310c300a060355040a13" + + "03676f76310d300b060355040b13044e495354308201b83082012c06072a8648" + + "ce3804013082011f02818100b68b0f942b9acea525c6f2edfcfb9532ac011233" + + "b9e01cad909bbc48549ef394773c2c713555e6fe4f22cbd5d83e8993334dfcbd" + + "4f41643ea29870ec31b450deebf198280ac93e44b3fd22979683d018a3e3bd35" + + "5bffeea321726a7b96dab93f1e5a90af24d620f00d21a7d402b91afcac21fb9e" + + "949e4b42459e6ab24863fe43021500b20db0b101df0c6624fc1392ba55f77d57" + + "7481e5028181009abf46b1f53f443dc9a565fb91c08e47f10ac30147c2444236" + + "a99281de57c5e0688658007b1ff99b77a1c510a580917851513cf6fcfccc46c6" + + "817892843df4933d0c387e1a5b994eab1464f60c21224e28089c92b9669f40e8" + + "95f6d5312aef39a262c7b26d9e58c43aa81181846daff8b419b4c211aed0223b" + + "aa207fee1e57180381850002818100b59e1f490447d1dbf53addca0475e8dd75" + + "f69b8ab197d6596982d3034dfd3b365f4af2d14ec107f5d12ad378776356ea96" + + "614d420b7a1dfbab91a4cedeef77c8e5ef20aea62848afbe69c36aa530f2c2b9" + + "d9822b7dd9c4841fde0de854d71b992eb3d088f6d6639ba7e20e82d43b8a681b" + + "065631590b49eb99a5d581417bc955a3323030301d0603551d0e0416041486ca" + + "a5228162efad0a89bcad72412c2949f48656300f0603551d130101ff04053003" + + "0101ff300906072a8648ce380403032f00302c0214431bcf292545c04e52e77d" + + "d6fcb1664c83cf2d7702140b5b9a241198e8f3869004f608a9e18da5cc3ad4"); + + + /** + * C.2 Certificate + * + * This section contains an annotated hex dump of a 730 byte version 3 + * certificate. The certificate contains the following information: + * (a the serial number is 18 (12 hex); + * (b) the certificate is signed with DSA and the SHA-1 hash algorithm; + * (c) the issuer's distinguished name is OU=nist; O=gov; C=US + * (d) and the subject's distinguished name is CN=Tim Polk; OU=nist; + * O=gov; C=US + * (e) the certificate was valid from July 30, 1997 through December 1, + * 1997; + * (f) the certificate contains a 1024 bit DSA public key; + * (g) the certificate is an end entity certificate, as the basic + * constraints extension is not present; + * (h) the certificate contains an authority key identifier extension + * matching the subject key identifier of the certificate in Appendix + * C.1; and + * (i) the certificate includes one alternative name - an RFC 822 + * address of "wpolk@nist.gov". + */ + static byte[] userCert1Bin = Hex.Decode( + "308202da30820299a003020102020112300906072a8648ce380403302a310b30" + + "09060355040613025553310c300a060355040a1303676f76310d300b06035504" + + "0b13044e495354301e170d3937303733303030303030305a170d393731323031" + + "3030303030305a303d310b3009060355040613025553310c300a060355040a13" + + "03676f76310d300b060355040b13044e4953543111300f060355040313085469" + + "6d20506f6c6b308201b73082012c06072a8648ce3804013082011f02818100b6" + + "8b0f942b9acea525c6f2edfcfb9532ac011233b9e01cad909bbc48549ef39477" + + "3c2c713555e6fe4f22cbd5d83e8993334dfcbd4f41643ea29870ec31b450deeb" + + "f198280ac93e44b3fd22979683d018a3e3bd355bffeea321726a7b96dab93f1e" + + "5a90af24d620f00d21a7d402b91afcac21fb9e949e4b42459e6ab24863fe4302" + + "1500b20db0b101df0c6624fc1392ba55f77d577481e5028181009abf46b1f53f" + + "443dc9a565fb91c08e47f10ac30147c2444236a99281de57c5e0688658007b1f" + + "f99b77a1c510a580917851513cf6fcfccc46c6817892843df4933d0c387e1a5b" + + "994eab1464f60c21224e28089c92b9669f40e895f6d5312aef39a262c7b26d9e" + + "58c43aa81181846daff8b419b4c211aed0223baa207fee1e5718038184000281" + + "8030b675f77c2031ae38bb7e0d2baba09c4bdf20d524133ccd98e55f6cb7c1ba" + + "4abaa9958053f00d72dc3337f4010bf5041f9d2e1f62d8843a9b25095a2dc846" + + "8e2bd4f50d3bc72dc66cb998c1253a444e8eca9561357cce15315c23131ea205" + + "d17a241ccbd3720990ff9b9d28c0a10aec469f0db8d0dcd018a62b5ef98fb595" + + "bea33e303c30190603551d1104123010810e77706f6c6b406e6973742e676f76" + + "301f0603551d2304183016801486caa5228162efad0a89bcad72412c2949f486" + + "56300906072a8648ce380403033000302d02143697cbe3b42ce1bb61a9d3cc24" + + "cc22929ff4f587021500abc979afd2161ca9e368a91410b4a02eff225a73"); + + /** + * C.3 End Entity Certificate Using RSA + * + * This section contains an annotated hex dump of a 654 byte version 3 + * certificate. The certificate contains the following information: + * (a) the serial number is 256; + * (b) the certificate is signed with RSA and the SHA-1 hash algorithm; + * (c) the issuer's distinguished name is OU=NIST; O=gov; C=US + * (d) and the subject's distinguished name is CN=Tim Polk; OU=NIST; + * O=gov; C=US + * (e) the certificate was issued on May 21, 1996 at 09:58:26 and + * expired on May 21, 1997 at 09:58:26; + * (f) the certificate contains a 1024 bit RSA public key; + * (g) the certificate is an end entity certificate (not a CA + * certificate); + * (h) the certificate includes an alternative subject name of + * "<http://www.itl.nist.gov/div893/staff/polk/index.html>" and an + * alternative issuer name of "<http://www.nist.gov/>" - both are URLs; + * (i) the certificate include an authority key identifier extension + * and a certificate policies extension psecifying the policy OID + * 2.16.840.1.101.3.2.1.48.9; and + * (j) the certificate includes a critical key usage extension + * specifying that the public key is intended for verification of + * digital signatures. + */ + static byte[] userCert2Bin = Hex.Decode( + "3082028e308201f7a00302010202020100300d06092a864886f70d0101050500" + + "302a310b3009060355040613025553310c300a060355040b1303676f76310d30" + + "0b060355040a13044e495354301e170d3936303532313039353832365a170d39" + + "37303532313039353832365a303d310b3009060355040613025553310c300a06" + + "0355040b1303676f76310d300b060355040a13044e4953543111300f06035504" + + "03130854696d20506f6c6b30819f300d06092a864886f70d010101050003818d" + + "0030818902818100e16ae4033097023cf410f3b51e4d7f147bf6f5d078e9a48a" + + "f0a375ecedb656967f8899859af23e687787eb9ed19fc0b417dcab8923a41d7e" + + "16234c4fa84df531b87caae31a4909f44b26db2767308212014ae91ab6c10c53" + + "8b6cfc2f7a43ec33367e32b27bd5aacf0114c612ec13f22d147a8b215814134c" + + "46a39af21695ff230203010001a381af3081ac303f0603551d11043830368634" + + "687474703a2f2f7777772e69746c2e6e6973742e676f762f6469763839332f73" + + "746166662f706f6c6b2f696e6465782e68746d6c301f0603551d120418301686" + + "14687474703a2f2f7777772e6e6973742e676f762f301f0603551d2304183016" + + "80140868af8533c8394a7af882938e706a4a20842c3230170603551d20041030" + + "0e300c060a60864801650302013009300e0603551d0f0101ff04040302078030" + + "0d06092a864886f70d0101050500038181008e8e3656788bbfa13975172ee310" + + "dc832b6834521cf66c1d525e5420105e4ca940f94b729e82b961dceb32a5bdb1" + + "b148f99b01bbebaf9b83f6528cb06d7cd09a39543e6d206fcdd0debe275f204f" + + "b6ab0df5b7e1bab4dfdf3dd4f6ed01fb6ecb9859ac41fb489c1ff65b46e029e2" + + "76ecc43a0afc92c5c0d2a9c9d32952876533"); + + /** + * This section contains an annotated hex dump of a version 2 CRL with + * one extension (cRLNumber). The CRL was issued by OU=NIST; O=gov; C=US + * on August 7, 1997; the next scheduled issuance was September 7, 1997. + * The CRL includes one revoked certificates: serial number 18 (12 hex), + * which was revoked on July 31, 1997 due to keyCompromise. The CRL + * itself is number 18, and it was signed with DSA and SHA-1. + */ + static byte[] crlBin = Hex.Decode( + "3081cb30818c020101300906072a8648ce380403302a310b3009060355040613025553310c300a060355040a1303676f76310d300b060355040b13044e495354170d3937303830373030303030305a170d3937303930373030303030305a30223020020112170d3937303733313030303030305a300c300a0603551d1504030a0101a00e300c300a0603551d14040302010c300906072a8648ce380403032f00302c0214224e9f43ba950634f2bb5e65dba68005c03a29470214591a57c982d7022114c3d40b321b9616b11f465a"); + + public override void PerformTest() + { + try + { + X509CertificateParser certParser = new X509CertificateParser(); + X509CrlParser crlParser = new X509CrlParser(); + + X509Certificate rootCert = certParser.ReadCertificate(rootCertBin); + X509Certificate userCert1 = certParser.ReadCertificate(userCert1Bin); + X509Certificate userCert2 = certParser.ReadCertificate(userCert2Bin); + + X509Crl crl = crlParser.ReadCrl(crlBin); + + rootCert.Verify(rootCert.GetPublicKey()); + userCert1.Verify(rootCert.GetPublicKey()); + + crl.Verify(rootCert.GetPublicKey()); + + if (!crl.IsRevoked(userCert1)) + { + Fail(this.Name + ": usercert1 not revoked."); + } + + if (crl.IsRevoked(userCert2)) + { + Fail(this.Name + ": usercert2 revoked."); + } + + } + catch (Exception e) + { + Fail(this.Name + ": exception - " + e.ToString()); + } + } + + public override String Name + { + get { return "PkixTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new PkixTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/RSATest.cs b/crypto/test/src/test/RSATest.cs new file mode 100644 index 000000000..a765ff138 --- /dev/null +++ b/crypto/test/src/test/RSATest.cs @@ -0,0 +1,685 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.TeleTrust; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class RsaTest + : SimpleTest + { + /** + * a fake random number generator - we just want to make sure the random numbers + * aren't random so that we get the same output, while still getting to test the + * key generation facilities. + */ + // TODO Use FixedSecureRandom instead? + private class MyFixedSecureRandom + : SecureRandom + { + 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 + }; + + public override void NextBytes( + byte[] bytes) + { + int offset = 0; + + while ((offset + seed.Length) < bytes.Length) + { + seed.CopyTo(bytes, offset); + offset += seed.Length; + } + + Array.Copy(seed, 0, bytes, offset, bytes.Length - offset); + } + } + + private static readonly 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 RsaKeyParameters pubKeySpec = new RsaKeyParameters( + false, + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16)); + + private RsaPrivateCrtKeyParameters privKeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), + new BigInteger("11", 16), + new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), + new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), + new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), + new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), + new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), + new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); + + private RsaKeyParameters isoPubKeySpec = new RsaKeyParameters( + false, + new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16), + new BigInteger("03", 16)); + + private RsaKeyParameters isoPrivKeySpec = new RsaKeyParameters( + true, + new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16), + new BigInteger("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7", 16)); + + internal static RsaKeyParameters pub2048KeySpec = new RsaKeyParameters( + false, + new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af66825656d43238b75503231500753f4e421e3c57", 16), + new BigInteger("10001", 16)); + + internal static RsaPrivateCrtKeyParameters priv2048KeySpec = new RsaPrivateCrtKeyParameters( + new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af66825656d43238b75503231500753f4e421e3c57", 16), + new BigInteger("10001", 16), + new BigInteger("65dad56ac7df7abb434e4cb5eeadb16093aa6da7f0033aad3815289b04757d32bfee6ade7749c8e4a323b5050a2fb9e2a99e23469e1ed4ba5bab54336af20a5bfccb8b3424cc6923db2ffca5787ed87aa87aa614cd04cedaebc8f623a2d2063017910f436dff18bb06f01758610787f8b258f0a8efd8bd7de30007c47b2a1031696c7d6523bc191d4d918927a7e0b09584ed205bd2ff4fc4382678df82353f7532b3bbb81d69e3f39070aed3fb64fce032a089e8e64955afa5213a6eb241231bd98d702fba725a9b205952fda186412d9e0d9344d2998c455ad8c2bae85ee672751466d5288304032b5b7e02f7e558c7af82c7fbf58eea0bb4ef0f001e6cd0a9", 16), + new BigInteger("d4fd9ac3474fb83aaf832470643609659e511b322632b239b688f3cd2aad87527d6cf652fb9c9ca67940e84789444f2e99b0cb0cfabbd4de95396106c865f38e2fb7b82b231260a94df0e01756bf73ce0386868d9c41645560a81af2f53c18e4f7cdf3d51d80267372e6e0216afbf67f655c9450769cca494e4f6631b239ce1b", 16), + new BigInteger("c8eaa0e2a1b3a4412a702bccda93f4d150da60d736c99c7c566fdea4dd1b401cbc0d8c063daaf0b579953d36343aa18b33dbf8b9eae94452490cc905245f8f7b9e29b1a288bc66731a29e1dd1a45c9fd7f8238ff727adc49fff73991d0dc096206b9d3a08f61e7462e2b804d78cb8c5eccdb9b7fbd2ad6a8fea46c1053e1be75", 16), + new BigInteger("10edcb544421c0f9e123624d1099feeb35c72a8b34e008ac6fa6b90210a7543f293af4e5299c8c12eb464e70092805c7256e18e5823455ba0f504d36f5ccacac1b7cd5c58ff710f9c3f92646949d88fdd1e7ea5fed1081820bb9b0d2a8cd4b093fecfdb96dabd6e28c3a6f8c186dc86cddc89afd3e403e0fcf8a9e0bcb27af0b", 16), + new BigInteger("97fc25484b5a415eaa63c03e6efa8dafe9a1c8b004d9ee6e80548fefd6f2ce44ee5cb117e77e70285798f57d137566ce8ea4503b13e0f1b5ed5ca6942537c4aa96b2a395782a4cb5b58d0936e0b0fa63b1192954d39ced176d71ef32c6f42c84e2e19f9d4dd999c2151b032b97bd22aa73fd8c5bcd15a2dca4046d5acc997021", 16), + new BigInteger("4bb8064e1eff7e9efc3c4578fcedb59ca4aef0993a8312dfdcb1b3decf458aa6650d3d0866f143cbf0d3825e9381181170a0a1651eefcd7def786b8eb356555d9fa07c85b5f5cbdd74382f1129b5e36b4166b6cc9157923699708648212c484958351fdc9cf14f218dbe7fbf7cbd93a209a4681fe23ceb44bab67d66f45d1c9d", 16)); + + public override void PerformTest() + { + byte[] input = new byte[] + { (byte)0x54, (byte)0x85, (byte)0x9b, (byte)0x34, (byte)0x2c, (byte)0x49, (byte)0xea, (byte)0x2a }; + byte[][] output = new byte[][] + { + Hex.Decode("8b427f781a2e59dd9def386f1956b996ee07f48c96880e65a368055ed8c0a8831669ef7250b40918b2b1d488547e72c84540e42bd07b03f14e226f04fbc2d929"), + Hex.Decode("2ec6e1a1711b6c7b8cd3f6a25db21ab8bb0a5f1d6df2ef375fa708a43997730ffc7c98856dbbe36edddcdd1b2d2a53867d8355af94fea3aeec128da908e08f4c"), + Hex.Decode("0850ac4e5a8118323200c8ed1e5aaa3d5e635172553ccac66a8e4153d35c79305c4440f11034ab147fccce21f18a50cf1c0099c08a577eb68237a91042278965"), + Hex.Decode("1c9649bdccb51056751fe43837f4eb43bada472accf26f65231666d5de7d11950d8379b3596dfdf75c6234274896fa8d18ad0865d3be2ac4d6687151abdf01e93941dcef18fa63186c9351d1506c89d09733c5ff4304208c812bdd21a50f56fde115e629e0e973721c9fcc87e89295a79853dee613962a0b2f2fc57163fd99057a3c776f13c20c26407eb8863998d7e53b543ba8d0a295a9a68d1a149833078c9809ad6a6dad7fc22a95ad615a73138c54c018f40d99bf8eeecd45f5be526f2d6b01aeb56381991c1ab31a2e756f15e052b9cd5638b2eff799795c5bae493307d5eb9f8c21d438de131fe505a4e7432547ab19224094f9e4be1968bd0793b79d"), + Hex.Decode("4c4afc0c24dddaedd4f9a3b23be30d35d8e005ffd36b3defc5d18acc830c3ed388ce20f43a00e614fd087c814197bc9fc2eff9ad4cc474a7a2ef3ed9c0f0a55eb23371e41ee8f2e2ed93ea3a06ca482589ab87e0d61dcffda5eea1241408e43ea1108726cdb87cc3aa5e9eaaa9f72507ca1352ac54a53920c94dccc768147933d8c50aefd9d1da10522a40133cd33dbc0524669e70f771a88d65c4716d471cd22b08b9f01f24e4e9fc7ffbcfa0e0a7aed47b345826399b26a73be112eb9c5e06fc6742fc3d0ef53d43896403c5105109cfc12e6deeaf4a48ba308e039774b9bdb31a9b9e133c81c321630cf0b4b2d1f90717b24c3268e1fea681ea9cdc709342"), + Hex.Decode("06b5b26bd13515f799e5e37ca43cace15cd82fd4bf36b25d285a6f0998d97c8cb0755a28f0ae66618b1cd03e27ac95eaaa4882bc6dc0078cd457d4f7de4154173a9c7a838cfc2ac2f74875df462aae0cfd341645dc51d9a01da9bdb01507f140fa8a016534379d838cc3b2a53ac33150af1b242fc88013cb8d914e66c8182864ee6de88ce2879d4c05dd125409620a96797c55c832fb2fb31d4310c190b8ed2c95fdfda2ed87f785002faaec3f35ec05cf70a3774ce185e4882df35719d582dd55ac31257344a9cba95189dcbea16e8c6cb7a235a0384bc83b6183ca8547e670fe33b1b91725ae0c250c9eca7b5ba78bd77145b70270bf8ac31653006c02ca9c"), + Hex.Decode("135f1be3d045526235bf9d5e43499d4ee1bfdf93370769ae56e85dbc339bc5b7ea3bee49717497ee8ac3f7cd6adb6fc0f17812390dcd65ac7b87fef7970d9ff9"), + Hex.Decode("03c05add1e030178c352face07cafc9447c8f369b8f95125c0d311c16b6da48ca2067104cce6cd21ae7b163cd18ffc13001aecebdc2eb02b9e92681f84033a98"), + Hex.Decode("00319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c") + }; + SecureRandom rand = new MyFixedSecureRandom(); + +// KeyFactory fact = KeyFactory.GetInstance("RSA"); +// +// PrivateKey privKey = fact.generatePrivate(privKeySpec); +// PublicKey pubKey = fact.generatePublic(pubKeySpec); + AsymmetricKeyParameter privKey = privKeySpec; + AsymmetricKeyParameter pubKey = pubKeySpec; + +// PrivateKey priv2048Key = fact.generatePrivate(priv2048KeySpec); +// PublicKey pub2048Key = fact.generatePublic(pub2048KeySpec); + AsymmetricKeyParameter priv2048Key = priv2048KeySpec; + AsymmetricKeyParameter pub2048Key = pub2048KeySpec; + + // + // No Padding + // +// Cipher c = Cipher.GetInstance("RSA"); + IBufferedCipher c = CipherUtilities.GetCipher("RSA"); + +// c.init(Cipher.ENCRYPT_MODE, pubKey, rand); + c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand)); + + byte[] outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[0])) + { + Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes)); + } + +// c.init(Cipher.DECRYPT_MODE, privKey); + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // No Padding - incremental + // +// c = Cipher.GetInstance("RSA"); + c = CipherUtilities.GetCipher("RSA"); + +// c.init(Cipher.ENCRYPT_MODE, pubKey, rand); + c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand)); + + c.ProcessBytes(input); + + outBytes = c.DoFinal(); + + if (!AreEqual(outBytes, output[0])) + { + Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes)); + } + +// c.init(Cipher.DECRYPT_MODE, privKey); + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // No Padding - incremental - explicit use of NONE in mode. + // + c = CipherUtilities.GetCipher("RSA/NONE/NoPadding"); + +// c.init(Cipher.ENCRYPT_MODE, pubKey, rand); + c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand)); + + c.ProcessBytes(input); + + outBytes = c.DoFinal(); + + if (!AreEqual(outBytes, output[0])) + { + Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes)); + } + +// c.init(Cipher.DECRYPT_MODE, privKey); + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // No Padding - maximum.Length + // + c = CipherUtilities.GetCipher("RSA"); + + byte[] modBytes = ((RsaKeyParameters) pubKey).Modulus.ToByteArray(); + + byte[] maxInput = new byte[modBytes.Length - 1]; + + maxInput[0] |= 0x7f; + + c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(maxInput); + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, maxInput)) + { + Fail("NoPadding test failed on decrypt expected " + + Hex.ToHexString(maxInput) + " got " + + Hex.ToHexString(outBytes)); + } + + // + // PKCS1 V 1.5 + // + c = CipherUtilities.GetCipher("RSA//PKCS1Padding"); + + c.Init(true, new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[1])) + { + Fail("PKCS1 test failed on encrypt expected " + Hex.ToHexString(output[1]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("PKCS1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // PKCS1 V 1.5 - NONE + // + c = CipherUtilities.GetCipher("RSA/NONE/PKCS1Padding"); + + c.Init(true, new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[1])) + { + Fail("PKCS1 test failed on encrypt expected " + Hex.ToHexString(output[1]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("PKCS1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // OAEP - SHA1 + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding"); + + c.Init(true, new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[2])) + { + Fail("OAEP test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes)); + } + + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding"); + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("OAEP test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // TODO +// AlgorithmParameters oaepP = c.getParameters(); + byte[] rop = new RsaesOaepParameters( + new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded(), rop.getEncoded())) +// { +// Fail("OAEP test failed default sha-1 parameters"); +// } + + // + // OAEP - SHA224 + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA224AndMGF1Padding"); + + c.Init(true, new ParametersWithRandom(pub2048Key, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[3])) + { + Fail("OAEP SHA-224 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, priv2048Key); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("OAEP SHA-224 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + +// oaepP = c.getParameters(); + rop = new RsaesOaepParameters( + new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded(), rop.getEncoded()) +// { +// Fail("OAEP test failed default sha-224 parameters"); +// } + + // + // OAEP - SHA 256 + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA256AndMGF1Padding"); + + c.Init(true, new ParametersWithRandom(pub2048Key, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[4])) + { + Fail("OAEP SHA-256 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, priv2048Key); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("OAEP SHA-256 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + +// oaepP = c.getParameters(); + rop = new RsaesOaepParameters( + new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded(), rop.getEncoded()) +// { +// Fail("OAEP test failed default sha-256 parameters"); +// } + + // + // OAEP - SHA 384 + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA384AndMGF1Padding"); + + c.Init(true, new ParametersWithRandom(pub2048Key, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[5])) + { + Fail("OAEP SHA-384 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, priv2048Key); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("OAEP SHA-384 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + +// oaepP = c.getParameters(); + rop = new RsaesOaepParameters( + new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded(), rop.getEncoded()) +// { +// Fail("OAEP test failed default sha-384 parameters"); +// } + + // + // OAEP - MD5 + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithMD5AndMGF1Padding"); + + c.Init(true, new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(input); + + if (!AreEqual(outBytes, output[6])) + { + Fail("OAEP MD5 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("OAEP MD5 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + +// oaepP = c.getParameters(); + rop = new RsaesOaepParameters( + new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded(), rop.getEncoded()) +// { +// Fail("OAEP test failed default md5 parameters"); +// } + + // + // OAEP - SHA1 with default parameters + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding"); + + // TODO +// c.init(Cipher.ENCRYPT_MODE, pubKey, OAEPParameterSpec.DEFAULT, rand); +// +// outBytes = c.DoFinal(input); +// +// if (!AreEqual(outBytes, output[2])) +// { +// Fail("OAEP test failed on encrypt expected " + Encoding.ASCII.GetString(Hex.Encode(output[2])) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes))); +// } +// +// c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding"); +// +// c.Init(false, privKey); +// +// outBytes = c.DoFinal(outBytes); +// +// if (!AreEqual(outBytes, input)) +// { +// Fail("OAEP test failed on decrypt expected " + Encoding.ASCII.GetString(Hex.Encode(input)) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes))); +// } +// +// oaepP = c.getParameters(); +// +// if (!AreEqual(oaepP.getEncoded(), new byte[] { 0x30, 0x00 })) +// { +// Fail("OAEP test failed default parameters"); +// } + + // + // OAEP - SHA1 with specified string + // + c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding"); + + // TODO +// c.init(Cipher.ENCRYPT_MODE, pubKey, new OAEPParameterSpec("SHA1", "MGF1", new MGF1ParameterSpec("SHA1"), new PSource.PSpecified(new byte[] { 1, 2, 3, 4, 5 })), rand); +// +// outBytes = c.DoFinal(input); +// +// oaepP = c.getParameters(); + rop = new RsaesOaepParameters( + new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance)), + new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[] { 1, 2, 3, 4, 5 }))).GetEncoded(); + +// if (!AreEqual(oaepP.getEncoded()) +// { +// Fail("OAEP test failed changed sha-1 parameters"); +// } +// +// if (!AreEqual(outBytes, output[7])) +// { +// Fail("OAEP test failed on encrypt expected " + Encoding.ASCII.GetString(Hex.Encode(output[2])) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes))); +// } + + c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding"); + + // TODO +// c.init(Cipher.DECRYPT_MODE, privKey, oaepP); +// +// outBytes = c.DoFinal(outBytes); +// +// if (!AreEqual(outBytes, input)) +// { +// Fail("OAEP test failed on decrypt expected " + Encoding.ASCII.GetString(Hex.Encode(input)) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes))); +// } + + // + // iso9796-1 + // + byte[] isoInput = Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"); +// PrivateKey isoPrivKey = fact.generatePrivate(isoPrivKeySpec); +// PublicKey isoPubKey = fact.generatePublic(isoPubKeySpec); + AsymmetricKeyParameter isoPrivKey = isoPrivKeySpec; + AsymmetricKeyParameter isoPubKey = isoPubKeySpec; + + c = CipherUtilities.GetCipher("RSA/NONE/ISO9796-1Padding"); + + c.Init(true, isoPrivKey); + + outBytes = c.DoFinal(isoInput); + + if (!AreEqual(outBytes, output[8])) + { + Fail("ISO9796-1 test failed on encrypt expected " + Hex.ToHexString(output[3]) + " got " + Hex.ToHexString(outBytes)); + } + + c.Init(false, isoPubKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, isoInput)) + { + Fail("ISO9796-1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // + // generation with parameters test. + // + IAsymmetricCipherKeyPairGenerator keyPairGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + + // + // 768 bit RSA with e = 2^16-1 + // + keyPairGen.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), + new SecureRandom(), + 768, + 25)); + + AsymmetricCipherKeyPair kp = keyPairGen.GenerateKeyPair(); + + pubKey = kp.Public; + privKey = kp.Private; + + c.Init(true, new ParametersWithRandom(pubKey, rand)); + + outBytes = c.DoFinal(input); + + c.Init(false, privKey); + + outBytes = c.DoFinal(outBytes); + + if (!AreEqual(outBytes, input)) + { + Fail("key generation test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes)); + } + + // + // comparison check + // +// KeyFactory keyFact = KeyFactory.GetInstance("RSA"); +// +// RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)keyFact.translateKey(privKey); + RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters) privKey; + + if (!privKey.Equals(crtKey)) + { + Fail("private key equality check failed"); + } + +// RSAPublicKey copyKey = (RSAPublicKey)keyFact.translateKey(pubKey); + RsaKeyParameters copyKey = (RsaKeyParameters) pubKey; + + if (!pubKey.Equals(copyKey)) + { + Fail("public key equality check failed"); + } + + SecureRandom random = new SecureRandom(); + rawModeTest("SHA1withRSA", X509ObjectIdentifiers.IdSha1, priv2048Key, pub2048Key, random); + rawModeTest("MD5withRSA", PkcsObjectIdentifiers.MD5, priv2048Key, pub2048Key, random); + rawModeTest("RIPEMD128withRSA", TeleTrusTObjectIdentifiers.RipeMD128, priv2048Key, pub2048Key, random); + } + + private void rawModeTest(string sigName, DerObjectIdentifier digestOID, + AsymmetricKeyParameter privKey, AsymmetricKeyParameter pubKey, SecureRandom random) + { + byte[] sampleMessage = new byte[1000 + random.Next() % 100]; + random.NextBytes(sampleMessage); + + ISigner normalSig = SignerUtilities.GetSigner(sigName); + normalSig.Init(true, privKey); + normalSig.BlockUpdate(sampleMessage, 0, sampleMessage.Length); + byte[] normalResult = normalSig.GenerateSignature(); + + byte[] hash = DigestUtilities.CalculateDigest(digestOID.Id, sampleMessage); + byte[] digInfo = derEncode(digestOID, hash); + + ISigner rawSig = SignerUtilities.GetSigner("RSA"); + rawSig.Init(true, privKey); + rawSig.BlockUpdate(digInfo, 0, digInfo.Length); + byte[] rawResult = rawSig.GenerateSignature(); + + if (!Arrays.AreEqual(normalResult, rawResult)) + { + Fail("raw mode signature differs from normal one"); + } + + rawSig.Init(false, pubKey); + rawSig.BlockUpdate(digInfo, 0, digInfo.Length); + + if (!rawSig.VerifySignature(rawResult)) + { + Fail("raw mode signature verification failed"); + } + } + + private byte[] derEncode(DerObjectIdentifier oid, byte[] hash) + { + AlgorithmIdentifier algId = new AlgorithmIdentifier(oid, DerNull.Instance); + DigestInfo dInfo = new DigestInfo(algId, hash); + + return dInfo.GetEncoded(Asn1Encodable.Der); + } + + public override string Name + { + get { return "RSATest"; } + } + + public static void Main( + string[] args) + { + ITest test = new RsaTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/RegressionTest.cs b/crypto/test/src/test/RegressionTest.cs new file mode 100644 index 000000000..0ffde72e4 --- /dev/null +++ b/crypto/test/src/test/RegressionTest.cs @@ -0,0 +1,80 @@ +using System; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + public class RegressionTest + { + // These tests were ported from org.bouncycastle.jce.provider.test in Java build + public static ITest[] tests = new ITest[] + { + new FipsDesTest(), + new DesEdeTest(), + new AesTest(), + new CamelliaTest(), + new SeedTest(), + new AesSicTest(), + new Gost28147Test(), + new PbeTest(), + new BlockCipherTest(), + new MacTest(), + new HMacTest(), +// new SealedTest(), + new RsaTest(), + new DHTest(), + new DsaTest(), +// new ImplicitlyCaTest(), + new ECNRTest(), + new ECDsa5Test(), + new Gost3410Test(), + new ElGamalTest(), + new IesTest(), + new SigTest(), + new AttrCertTest(), + new CertTest(), + new Pkcs10CertRequestTest(), + new EncryptedPrivateKeyInfoTest(), // Also in Org.BouncyCastle.Pkcs.Tests +// new KeyStoreTest(), +// new Pkcs12StoreTest(), // Already in Org.BouncyCastle.Pkcs.Tests + new DigestTest(), + new PssTest(), + new WrapTest(), +// new DoFinalTest(), + new CipherStreamTest(), + new NamedCurveTest(), + new PkixTest(), +// new NetscapeCertRequestTest(), + new X509StoreTest(), +// new X509StreamParserTest(), + new X509CertificatePairTest(), + new CertPathTest(), +// new CertStoreTest(), + new CertPathValidatorTest(), + new CertPathBuilderTest(), + new ECEncodingTest(), +// new AlgorithmParametersTest(), + new NistCertPathTest(), + new PkixPolicyMappingTest(), +// new SlotTwoTest(), + new PkixNameConstraintsTest(), + new NoekeonTest(), + new AttrCertSelectorTest(), +// new SerialisationTest(), + new MqvTest(), + new CMacTest(), + new Crl5Test(), + }; + + public static void Main( + string[] args) + { + for (int i = 0; i != tests.Length; i++) + { + ITestResult result = tests[i].Perform(); + + Console.WriteLine(result); + } + } + } +} diff --git a/crypto/test/src/test/SEEDTest.cs b/crypto/test/src/test/SEEDTest.cs new file mode 100644 index 000000000..2b380d5b7 --- /dev/null +++ b/crypto/test/src/test/SEEDTest.cs @@ -0,0 +1,190 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Kisa; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Tests +{ + /// Basic test class for SEED + [TestFixture] + public class SeedTest + : BaseBlockCipherTest + { + internal static readonly string[] cipherTests = + { + "128", + "28DBC3BC49FFD87DCFA509B11D422BE7", + "B41E6BE2EBA84A148E2EED84593C5EC7", + "9B9B7BFCD1813CB95D0B3618F40F5122" + }; + + public SeedTest() + : base("SEED") + { + } + + [Test] + public void TestCiphers() + { + for (int i = 0; i != cipherTests.Length; i += 4) + { + doCipherTest(int.Parse(cipherTests[i]), + Hex.Decode(cipherTests[i + 1]), + Hex.Decode(cipherTests[i + 2]), + Hex.Decode(cipherTests[i + 3])); + } + } + + [Test] + public void TestWrap() + { + byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f"); + byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff"); + byte[] out1 = Hex.Decode("bf71f77138b5afea05232a8dad54024e812dc8dd7d132559"); + + wrapTest(1, "SEEDWrap", kek1, in1, out1); + } + + [Test] + public void TestOids() + { + string[] oids = { + KisaObjectIdentifiers.IdSeedCbc.Id + }; + + string[] names = { + "SEED/CBC/PKCS7Padding" + }; + + oidTest(oids, names, 1); + } + + [Test] + public void TestWrapOids() + { + string[] wrapOids = { + KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id + }; + + wrapOidTest(wrapOids, "SEEDWrap"); + } + + public void doCipherTest( + int strength, + byte[] keyBytes, + byte[] input, + byte[] output) + { + KeyParameter key = ParameterUtilities.CreateKeyParameter("SEED", keyBytes); + + IBufferedCipher inCipher = CipherUtilities.GetCipher("SEED/ECB/NoPadding"); + IBufferedCipher outCipher = CipherUtilities.GetCipher("SEED/ECB/NoPadding"); + + try + { + outCipher.Init(true, key); + } + catch (Exception e) + { + Fail("SEED failed initialisation - " + e.ToString(), e); + } + + try + { + inCipher.Init(false, key); + } + catch (Exception e) + { + Fail("SEED failed initialisation - " + e.ToString(), e); + } + + // + // encryption pass + // + MemoryStream bOut = new MemoryStream(); + CipherStream cOut = new CipherStream(bOut, null, outCipher); + + try + { + for (int i = 0; i != input.Length / 2; i++) + { + cOut.WriteByte(input[i]); + } + cOut.Write(input, input.Length / 2, input.Length - input.Length / 2); + cOut.Close(); + } + catch (IOException e) + { + Fail("SEED failed encryption - " + e.ToString(), e); + } + + byte[] bytes = bOut.ToArray(); + + if (!AreEqual(bytes, output)) + { + Fail("SEED failed encryption - expected " + + Hex.ToHexString(output) + " got " + + Hex.ToHexString(bytes)); + } + + // + // decryption pass + // + MemoryStream bIn = new MemoryStream(bytes, false); + CipherStream cIn = new CipherStream(bIn, inCipher, null); + + try + { +// DataInputStream dIn = new DataInputStream(cIn); + BinaryReader dIn = new BinaryReader(cIn); + + bytes = new byte[input.Length]; + + for (int i = 0; i != input.Length / 2; i++) + { +// bytes[i] = (byte)dIn.read(); + bytes[i] = dIn.ReadByte(); + } + + int remaining = bytes.Length - input.Length / 2; +// dIn.readFully(bytes, input.Length / 2, remaining); + byte[] extra = dIn.ReadBytes(remaining); + if (extra.Length < remaining) + throw new EndOfStreamException(); + extra.CopyTo(bytes, input.Length / 2); + } + catch (Exception e) + { + Fail("SEED failed encryption - " + e.ToString(), e); + } + + if (!AreEqual(bytes, input)) + { + Fail("SEED failed decryption - expected " + + Hex.ToHexString(input) + " got " + + Hex.ToHexString(bytes)); + } + } + + public override void PerformTest() + { + TestCiphers(); + TestWrap(); + TestOids(); + TestWrapOids(); + } + + public static void Main( + string[] args) + { + RunTest(new SeedTest()); + } + } +} diff --git a/crypto/test/src/test/SigTest.cs b/crypto/test/src/test/SigTest.cs new file mode 100644 index 000000000..803a24493 --- /dev/null +++ b/crypto/test/src/test/SigTest.cs @@ -0,0 +1,378 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class SigTest + : SimpleTest + { + /** + * signature with a "forged signature" (sig block not at end of plain text) + */ + private void doTestBadSig( + AsymmetricKeyParameter priv, + AsymmetricKeyParameter pub) + { + IDigest sha1 = DigestUtilities.GetDigest("SHA1"); + IBufferedCipher signer = CipherUtilities.GetCipher("RSA//PKCS1Padding"); + + signer.Init(true, priv); + + byte[] block = new byte[signer.GetBlockSize()]; + + sha1.Update((byte)0); + + byte[] sigHeader = Hex.Decode("3021300906052b0e03021a05000414"); + Array.Copy(sigHeader, 0, block, 0, sigHeader.Length); + +// byte[] dig = sha1.digest(); + byte[] dig = DigestUtilities.DoFinal(sha1); + + Array.Copy(dig, 0, block, sigHeader.Length, dig.Length); + + Array.Copy(sigHeader, 0, block, + sigHeader.Length + dig.Length, sigHeader.Length); + + byte[] sig = signer.DoFinal(block); + + ISigner verifier = SignerUtilities.GetSigner("SHA1WithRSA"); + + verifier.Init(false, pub); + + verifier.Update((byte)0); + + if (verifier.VerifySignature(sig)) + { + Fail("bad signature passed"); + } + } + + public override void PerformTest() + { + ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption"); + + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA"); + fact.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), + new SecureRandom(), + 768, + 25)); + + AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair(); + + AsymmetricKeyParameter signingKey = keyPair.Private; + AsymmetricKeyParameter verifyKey = keyPair.Public; + + doTestBadSig(signingKey, verifyKey); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + byte[] sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA1 verification failed"); + } + + sig = SignerUtilities.GetSigner("MD2WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("MD2 verification failed"); + } + + sig = SignerUtilities.GetSigner("MD5WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("MD5 verification failed"); + } + + sig = SignerUtilities.GetSigner("RIPEMD160WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("RIPEMD160 verification failed"); + } + + // + // RIPEMD-128 + // + sig = SignerUtilities.GetSigner("RIPEMD128WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("RIPEMD128 verification failed"); + } + + // + // RIPEMD256 + // + sig = SignerUtilities.GetSigner("RIPEMD256WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("RIPEMD256 verification failed"); + } + + // + // SHA-224 + // + sig = SignerUtilities.GetSigner("SHA224WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA224 verification failed"); + } + + // + // SHA-256 + // + sig = SignerUtilities.GetSigner("SHA256WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA256 verification failed"); + } + + // + // SHA-384 + // + sig = SignerUtilities.GetSigner("SHA384WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA384 verification failed"); + } + + // + // SHA-512 + // + sig = SignerUtilities.GetSigner("SHA512WithRSAEncryption"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA512 verification failed"); + } + + // + // ISO Sigs. + // + sig = SignerUtilities.GetSigner("MD5WithRSA/ISO9796-2"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("MD5/ISO verification failed"); + } + + sig = SignerUtilities.GetSigner("SHA1WithRSA/ISO9796-2"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("SHA1/ISO verification failed"); + } + + sig = SignerUtilities.GetSigner("RIPEMD160WithRSA/ISO9796-2"); + + sig.Init(true, signingKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + sig.Init(false, verifyKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("RIPEMD160/ISO verification failed"); + } + + // + // standard vector test - B.1.3 RIPEMD160, implicit. + // + BigInteger mod = new BigInteger("ffffffff78f6c55506c59785e871211ee120b0b5dd644aa796d82413a47b24573f1be5745b5cd9950f6b389b52350d4e01e90009669a8720bf265a2865994190a661dea3c7828e2e7ca1b19651adc2d5", 16); + BigInteger pub = new BigInteger("03", 16); + BigInteger pri = new BigInteger("2aaaaaaa942920e38120ee965168302fd0301d73a4e60c7143ceb0adf0bf30b9352f50e8b9e4ceedd65343b2179005b2f099915e4b0c37e41314bb0821ad8330d23cba7f589e0f129b04c46b67dfce9d", 16); + +// KeyFactory f = KeyFactory.getInstance("RSA"); +// AsymmetricKeyParameter privKey = f.generatePrivate(new RSAPrivateKeySpec(mod, pri)); +// AsymmetricKeyParameter pubKey = f.generatePublic(new RSAPublicKeySpec(mod, pub)); + AsymmetricKeyParameter privKey = new RsaKeyParameters(true, mod, pri); + AsymmetricKeyParameter pubKey = new RsaKeyParameters(false, mod, pub); + byte[] testSig = Hex.Decode("5cf9a01854dbacaec83aae8efc563d74538192e95466babacd361d7c86000fe42dcb4581e48e4feb862d04698da9203b1803b262105104d510b365ee9c660857ba1c001aa57abfd1c8de92e47c275cae"); + + data = Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"); + + sig = SignerUtilities.GetSigner("RIPEMD160WithRSA/ISO9796-2"); + + sig.Init(true, privKey); + + sig.BlockUpdate(data, 0, data.Length); + + sigBytes = sig.GenerateSignature(); + + if (!AreEqual(testSig, sigBytes)) + { + Fail("SigTest: failed ISO9796-2 generation Test"); + } + + sig.Init(false, pubKey); + + sig.BlockUpdate(data, 0, data.Length); + + if (!sig.VerifySignature(sigBytes)) + { + Fail("RIPEMD160/ISO verification failed"); + } + } + + public override string Name + { + get { return "SigTest"; } + } + + public static void Main( + string[] args) + { + RunTest(new SigTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/TestUtilities.cs b/crypto/test/src/test/TestUtilities.cs new file mode 100644 index 000000000..a79421207 --- /dev/null +++ b/crypto/test/src/test/TestUtilities.cs @@ -0,0 +1,264 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; + +namespace Org.BouncyCastle.Tests +{ + /** + * Test Utils + */ + internal class TestUtilities + { + /** + * Create a random 1024 bit RSA key pair + */ + public static AsymmetricCipherKeyPair GenerateRsaKeyPair() + { + IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA"); + + kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); + + return kpGen.GenerateKeyPair(); + } + + public static X509Certificate GenerateRootCert( + AsymmetricCipherKeyPair pair) + { + X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(new X509Name("CN=Test CA Certificate")); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name("CN=Test CA Certificate")); + certGen.SetPublicKey(pair.Public); + certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + return certGen.Generate(pair.Private); + } + + public static X509Certificate GenerateIntermediateCert( + AsymmetricKeyParameter intKey, + AsymmetricKeyParameter caKey, + X509Certificate caCert) + { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name("CN=Test Intermediate Certificate")); + certGen.SetPublicKey(intKey); + certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert)); + certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(intKey)); + certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(0)); + certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyCertSign | KeyUsage.CrlSign)); + + return certGen.Generate(caKey); + } + + public static X509Certificate GenerateEndEntityCert( + AsymmetricKeyParameter entityKey, + AsymmetricKeyParameter caKey, + X509Certificate caCert) + { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + certGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert)); + certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50)); + certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50)); + certGen.SetSubjectDN(new X509Name("CN=Test End Certificate")); + certGen.SetPublicKey(entityKey); + certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert)); + certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(entityKey)); + certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false)); + certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment)); + + return certGen.Generate(caKey); + } + + public static X509Crl CreateCrl( + X509Certificate caCert, + AsymmetricKeyParameter caKey, + BigInteger serialNumber) + { + X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); + DateTime now = DateTime.UtcNow; +// BigInteger revokedSerialNumber = BigInteger.Two; + + crlGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert)); + + crlGen.SetThisUpdate(now); + crlGen.SetNextUpdate(now.AddSeconds(100)); + crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption"); + + crlGen.AddCrlEntry(serialNumber, now, CrlReason.PrivilegeWithdrawn); + + crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert)); + crlGen.AddExtension(X509Extensions.CrlNumber, false, new CrlNumber(BigInteger.One)); + + return crlGen.Generate(caKey); + } + + public static X509Certificate CreateExceptionCertificate( + bool exceptionOnEncode) + { + return new ExceptionCertificate(exceptionOnEncode); + } + + private class ExceptionCertificate + : X509Certificate + { + private bool _exceptionOnEncode; + + public ExceptionCertificate( + bool exceptionOnEncode) + { + _exceptionOnEncode = exceptionOnEncode; + } + + public override void CheckValidity() + { + throw new CertificateNotYetValidException(); + } + + public override void CheckValidity( + DateTime date) + { + throw new CertificateExpiredException(); + } + + public override int Version + { + get { return 0; } + } + + public override BigInteger SerialNumber + { + get { return null; } + } + + public override X509Name IssuerDN + { + get { return null; } + } + + public override X509Name SubjectDN + { + get { return null; } + } + + public override DateTime NotBefore + { + get { return DateTime.MaxValue; } + } + + public override DateTime NotAfter + { + get { return DateTime.MinValue; } + } + + public override byte[] GetTbsCertificate() + { + throw new CertificateEncodingException(); + } + + public override byte[] GetSignature() + { + return new byte[0]; + } + + public override string SigAlgName + { + get { return null; } + } + + public override string SigAlgOid + { + get { return null; } + } + + public override byte[] GetSigAlgParams() + { + return new byte[0]; + } + + public override DerBitString IssuerUniqueID + { + get { return null; } + } + + public override DerBitString SubjectUniqueID + { + get { return null; } + } + + public override bool[] GetKeyUsage() + { + return new bool[0]; + } + + public override int GetBasicConstraints() + { + return 0; + } + + public override byte[] GetEncoded() + { + if (_exceptionOnEncode) + { + throw new CertificateEncodingException(); + } + + return new byte[0]; + } + + public override void Verify( + AsymmetricKeyParameter key) + { + throw new CertificateException(); + } + + public override string ToString() + { + return null; + } + + public override AsymmetricKeyParameter GetPublicKey() + { + return null; + } + + public override ISet GetCriticalExtensionOids() + { + return null; + } + + public override ISet GetNonCriticalExtensionOids() + { + return null; + } + + public override Asn1OctetString GetExtensionValue( + DerObjectIdentifier oid) + { + return null; + } + } + } +} diff --git a/crypto/test/src/test/WrapTest.cs b/crypto/test/src/test/WrapTest.cs new file mode 100644 index 000000000..bb49446e7 --- /dev/null +++ b/crypto/test/src/test/WrapTest.cs @@ -0,0 +1,94 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class WrapTest + : ITest + { + public ITestResult Perform() + { + try + { +// IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/PKCS5Padding"); + IWrapper cipher = WrapperUtilities.GetWrapper("DES/ECB/PKCS5Padding"); + + IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA"); + fact.Init( + new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), + new SecureRandom(), + 512, + 25)); + + AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair(); + + AsymmetricKeyParameter priKey = keyPair.Private; + AsymmetricKeyParameter pubKey = keyPair.Public; + + byte[] priKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey).GetDerEncoded(); + + CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator("DES"); + +// Key wrapKey = keyGen.generateKey(); + byte[] wrapKeyBytes = keyGen.GenerateKey(); + KeyParameter wrapKey = new DesParameters(wrapKeyBytes); + +// cipher.Init(IBufferedCipher.WRAP_MODE, wrapKey); + cipher.Init(true, wrapKey); +// byte[] wrappedKey = cipher.Wrap(priKey); + byte[] wrappedKey = cipher.Wrap(priKeyBytes, 0, priKeyBytes.Length); + +// cipher.Init(IBufferedCipher.UNWRAP_MODE, wrapKey); + cipher.Init(false, wrapKey); + +// Key key = cipher.unwrap(wrappedKey, "RSA", IBufferedCipher.PRIVATE_KEY); + byte[] unwrapped = cipher.Unwrap(wrappedKey, 0, wrappedKey.Length); + + //if (!Arrays.AreEqual(priKey.getEncoded(), key.getEncoded())) + if (!Arrays.AreEqual(priKeyBytes, unwrapped)) + { + return new SimpleTestResult(false, "Unwrapped key does not match"); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + catch (Exception e) + { + return new SimpleTestResult(false, Name + ": exception - " + e.ToString()); + } + } + + public string Name + { + get { return "WrapTest"; } + } + + public static void Main( + string[] args) + { + ITest test = new WrapTest(); + ITestResult result = test.Perform(); + + Console.WriteLine(result); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/X509CertificatePairTest.cs b/crypto/test/src/test/X509CertificatePairTest.cs new file mode 100644 index 000000000..a83de4cf0 --- /dev/null +++ b/crypto/test/src/test/X509CertificatePairTest.cs @@ -0,0 +1,149 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security.Certificates; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class X509CertificatePairTest + : SimpleTest + { + public override void PerformTest() + { + //CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509CertificateParser cf = new X509CertificateParser(); + + X509Certificate rootCert = (X509Certificate) cf.ReadCertificate(CertPathTest.rootCertBin); + X509Certificate interCert = (X509Certificate) cf.ReadCertificate(CertPathTest.interCertBin); + X509Certificate finalCert = (X509Certificate) cf.ReadCertificate(CertPathTest.finalCertBin); + + X509CertificatePair pair1 = new X509CertificatePair(rootCert, interCert); + X509CertificatePair pair2 = new X509CertificatePair(rootCert, interCert); + X509CertificatePair pair3 = new X509CertificatePair(interCert, finalCert); + X509CertificatePair pair4 = new X509CertificatePair(rootCert, finalCert); + X509CertificatePair pair5 = new X509CertificatePair(rootCert, null); + X509CertificatePair pair6 = new X509CertificatePair(rootCert, null); + X509CertificatePair pair7 = new X509CertificatePair(null, rootCert); + X509CertificatePair pair8 = new X509CertificatePair(null, rootCert); + + if (!pair1.Equals(pair2)) + { + Fail("pair1 pair2 equality test"); + } + + if (!pair5.Equals(pair6)) + { + Fail("pair1 pair2 equality test"); + } + + if (!pair7.Equals(pair8)) + { + Fail("pair1 pair2 equality test"); + } + + if (pair1.Equals(null)) + { + Fail("pair1 null equality test"); + } + + if (pair1.GetHashCode() != pair2.GetHashCode()) + { + Fail("pair1 pair2 hashCode equality test"); + } + + if (pair1.Equals(pair3)) + { + Fail("pair1 pair3 inequality test"); + } + + if (pair1.Equals(pair4)) + { + Fail("pair1 pair4 inequality test"); + } + + if (pair1.Equals(pair5)) + { + Fail("pair1 pair5 inequality test"); + } + + if (pair1.Equals(pair7)) + { + Fail("pair1 pair7 inequality test"); + } + + if (pair5.Equals(pair1)) + { + Fail("pair5 pair1 inequality test"); + } + + if (pair7.Equals(pair1)) + { + Fail("pair7 pair1 inequality test"); + } + + if (pair1.Forward != rootCert) + { + Fail("pair1 forward test"); + } + + if (pair1.Reverse != interCert) + { + Fail("pair1 reverse test"); + } + + if (!AreEqual(pair1.GetEncoded(), pair2.GetEncoded())) + { + Fail("encoding check"); + } + + pair4 = new X509CertificatePair(rootCert, TestUtilities.CreateExceptionCertificate(false)); + + try + { + pair4.GetEncoded(); + + Fail("no exception on bad GetEncoded()"); + } + catch (CertificateEncodingException) + { + // expected + } + + pair4 = new X509CertificatePair(rootCert, TestUtilities.CreateExceptionCertificate(true)); + + try + { + pair4.GetEncoded(); + + Fail("no exception on exception GetEncoded()"); + } + catch (CertificateEncodingException) + { + // expected + } + } + + public override string Name + { + get { return "X509CertificatePair"; } + } + + public static void Main( + string[] args) + { + RunTest(new X509CertificatePairTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/X509StoreTest.cs b/crypto/test/src/test/X509StoreTest.cs new file mode 100644 index 000000000..37673b8b4 --- /dev/null +++ b/crypto/test/src/test/X509StoreTest.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests +{ + [TestFixture] + public class X509StoreTest + : SimpleTest + { + private void certPairTest() + { + X509CertificateParser certParser = new X509CertificateParser(); + + X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin); + X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin); + X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin); + + // Testing CollectionCertStore generation from List + X509CertificatePair pair1 = new X509CertificatePair(rootCert, interCert); + + IList certList = new ArrayList(); + certList.Add(pair1); + certList.Add(new X509CertificatePair(interCert, finalCert)); + + IX509Store certStore = X509StoreFactory.Create( + "CertificatePair/Collection", + new X509CollectionStoreParameters(certList)); + + X509CertPairStoreSelector selector = new X509CertPairStoreSelector(); + X509CertStoreSelector fwSelector = new X509CertStoreSelector(); + + fwSelector.SerialNumber = rootCert.SerialNumber; + fwSelector.Subject = rootCert.IssuerDN; + + selector.ForwardSelector = fwSelector; + + IList col = new ArrayList(certStore.GetMatches(selector)); + + if (col.Count != 1 || !col.Contains(pair1)) + { + Fail("failed pair1 test"); + } + + col = new ArrayList(certStore.GetMatches(null)); + + if (col.Count != 2) + { + Fail("failed null test"); + } + } + + public override void PerformTest() + { + X509CertificateParser certParser = new X509CertificateParser(); + X509CrlParser crlParser = new X509CrlParser(); + + X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin); + X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin); + X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin); + X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin); + X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin); + + // Testing CollectionCertStore generation from List + IList certList = new ArrayList(); + certList.Add(rootCert); + certList.Add(interCert); + certList.Add(finalCert); + + IX509Store certStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + + // set default to be the same as for SUN X500 name + X509Name.DefaultReverse = true; + + // Searching for rootCert by subjectDN + + X509CertStoreSelector targetConstraints = new X509CertStoreSelector(); + targetConstraints.Subject = PrincipalUtilities.GetSubjectX509Principal(rootCert); + IList certs = new ArrayList(certStore.GetMatches(targetConstraints)); + if (certs.Count != 1 || !certs.Contains(rootCert)) + { + Fail("rootCert not found by subjectDN"); + } + + // Searching for rootCert by subjectDN encoded as byte + targetConstraints = new X509CertStoreSelector(); + targetConstraints.Subject = PrincipalUtilities.GetSubjectX509Principal(rootCert); + certs = new ArrayList(certStore.GetMatches(targetConstraints)); + if (certs.Count != 1 || !certs.Contains(rootCert)) + { + Fail("rootCert not found by encoded subjectDN"); + } + + X509Name.DefaultReverse = false; + + // Searching for rootCert by public key encoded as byte + targetConstraints = new X509CertStoreSelector(); + targetConstraints.SubjectPublicKey = + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rootCert.GetPublicKey()); + certs = new ArrayList(certStore.GetMatches(targetConstraints)); + if (certs.Count != 1 || !certs.Contains(rootCert)) + { + Fail("rootCert not found by encoded public key"); + } + + // Searching for interCert by issuerDN + targetConstraints = new X509CertStoreSelector(); + targetConstraints.Issuer = PrincipalUtilities.GetSubjectX509Principal(rootCert); + certs = new ArrayList(certStore.GetMatches(targetConstraints)); + if (certs.Count != 2) + { + Fail("did not found 2 certs"); + } + if (!certs.Contains(rootCert)) + { + Fail("rootCert not found"); + } + if (!certs.Contains(interCert)) + { + Fail("interCert not found"); + } + + // Searching for rootCrl by issuerDN + IList crlList = new ArrayList(); + crlList.Add(rootCrl); + crlList.Add(interCrl); + IX509Store store = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(crlList)); + + X509CrlStoreSelector targetConstraintsCRL = new X509CrlStoreSelector(); + + ArrayList issuers = new ArrayList(); + issuers.Add(rootCrl.IssuerDN); + targetConstraintsCRL.Issuers = issuers; + + IList crls = new ArrayList(store.GetMatches(targetConstraintsCRL)); + if (crls.Count != 1 || !crls.Contains(rootCrl)) + { + Fail("rootCrl not found"); + } + + crls = new ArrayList(certStore.GetMatches(targetConstraintsCRL)); + if (crls.Count != 0) + { + Fail("error using wrong selector (CRL)"); + } + certs = new ArrayList(store.GetMatches(targetConstraints)); + if (certs.Count != 0) + { + Fail("error using wrong selector (certs)"); + } + // Searching for attribute certificates + X509V2AttributeCertificate attrCert = new X509V2AttributeCertificate(AttrCertTest.attrCert); + IX509AttributeCertificate attrCert2 = new X509V2AttributeCertificate(AttrCertTest.certWithBaseCertificateID); + + IList attrList = new ArrayList(); + attrList.Add(attrCert); + attrList.Add(attrCert2); + store = X509StoreFactory.Create( + "AttributeCertificate/Collection", + new X509CollectionStoreParameters(attrList)); + + X509AttrCertStoreSelector attrSelector = new X509AttrCertStoreSelector(); + attrSelector.Holder = attrCert.Holder; + if (!attrSelector.Holder.Equals(attrCert.Holder)) + { + Fail("holder get not correct"); + } + IList attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on holder"); + } + attrSelector.Holder = attrCert2.Holder; + if (attrSelector.Holder.Equals(attrCert.Holder)) + { + Fail("holder get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert2)) + { + Fail("attrCert2 not found on holder"); + } + attrSelector = new X509AttrCertStoreSelector(); + attrSelector.Issuer = attrCert.Issuer; + if (!attrSelector.Issuer.Equals(attrCert.Issuer)) + { + Fail("issuer get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on issuer"); + } + attrSelector.Issuer = attrCert2.Issuer; + if (attrSelector.Issuer.Equals(attrCert.Issuer)) + { + Fail("issuer get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert2)) + { + Fail("attrCert2 not found on issuer"); + } + attrSelector = new X509AttrCertStoreSelector(); + attrSelector.AttributeCert = attrCert; + if (!attrSelector.AttributeCert.Equals(attrCert)) + { + Fail("attrCert get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on attrCert"); + } + attrSelector = new X509AttrCertStoreSelector(); + attrSelector.SerialNumber = attrCert.SerialNumber; + if (!attrSelector.SerialNumber.Equals(attrCert.SerialNumber)) + { + Fail("serial number get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on serial number"); + } + attrSelector = (X509AttrCertStoreSelector)attrSelector.Clone(); + if (!attrSelector.SerialNumber.Equals(attrCert.SerialNumber)) + { + Fail("serial number get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on serial number"); + } + + attrSelector = new X509AttrCertStoreSelector(); + attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotBefore); + if (attrSelector.AttributeCertificateValid.Value != attrCert.NotBefore) + { + Fail("valid get not correct"); + } + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 1 || !attrs.Contains(attrCert)) + { + Fail("attrCert not found on valid"); + } + attrSelector = new X509AttrCertStoreSelector(); + attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotBefore.AddMilliseconds(-100)); + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 0) + { + Fail("attrCert found on before"); + } + attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotAfter.AddMilliseconds(100)); + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 0) + { + Fail("attrCert found on after"); + } + attrSelector.SerialNumber = BigInteger.ValueOf(10000); + attrs = new ArrayList(store.GetMatches(attrSelector)); + if (attrs.Count != 0) + { + Fail("attrCert found on wrong serial number"); + } + + attrSelector.AttributeCert = null; + attrSelector.AttributeCertificateValid = null; + attrSelector.Holder = null; + attrSelector.Issuer = null; + attrSelector.SerialNumber = null; + if (attrSelector.AttributeCert != null) + { + Fail("null attrCert"); + } + if (attrSelector.AttributeCertificateValid != null) + { + Fail("null attrCertValid"); + } + if (attrSelector.Holder != null) + { + Fail("null attrCert holder"); + } + if (attrSelector.Issuer != null) + { + Fail("null attrCert issuer"); + } + if (attrSelector.SerialNumber != null) + { + Fail("null attrCert serial"); + } + + attrs = new ArrayList(certStore.GetMatches(attrSelector)); + if (attrs.Count != 0) + { + Fail("error using wrong selector (attrs)"); + } + + certPairTest(); + } + + public override string Name + { + get { return "IX509Store"; } + } + + public static void Main( + string[] args) + { + RunTest(new X509StoreTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/nist/NistCertPathTest.cs b/crypto/test/src/test/nist/NistCertPathTest.cs new file mode 100644 index 000000000..f42f64ca2 --- /dev/null +++ b/crypto/test/src/test/nist/NistCertPathTest.cs @@ -0,0 +1,847 @@ +using System; +using System.Collections; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Pkix; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tests.Nist +{ + [TestFixture] + public class NistCertPathTest + { + private static readonly string GOOD_CA_CERT = "GoodCACert"; + + private static readonly string GOOD_CA_CRL = "GoodCACRL"; + + private static readonly string TRUST_ANCHOR_ROOT_CRL = "TrustAnchorRootCRL"; + + private static readonly string TRUST_ANCHOR_ROOT_CERTIFICATE = "TrustAnchorRootCertificate"; + + private static readonly char[] PKCS12_PASSWORD = "password".ToCharArray(); + + private static readonly string ANY_POLICY = "2.5.29.32.0"; + private static readonly string NIST_TEST_POLICY_1 = "2.16.840.1.101.3.2.1.48.1"; + private static readonly string NIST_TEST_POLICY_2 = "2.16.840.1.101.3.2.1.48.2"; + private static readonly string NIST_TEST_POLICY_3 = "2.16.840.1.101.3.2.1.48.3"; + + private static IDictionary certs = new Hashtable(); + private static IDictionary crls = new Hashtable(); + + private static ISet noPolicies = new HashSet(); + private static ISet anyPolicy = new HashSet(); + private static ISet nistTestPolicy1 = new HashSet(); + private static ISet nistTestPolicy2 = new HashSet(); + private static ISet nistTestPolicy3 = new HashSet(); + private static ISet nistTestPolicy1And2 = new HashSet(); + + static NistCertPathTest() + { + anyPolicy.Add(ANY_POLICY); + + nistTestPolicy1.Add(NIST_TEST_POLICY_1); + nistTestPolicy2.Add(NIST_TEST_POLICY_2); + nistTestPolicy3.Add(NIST_TEST_POLICY_3); + nistTestPolicy1And2.Add(NIST_TEST_POLICY_1); + nistTestPolicy1And2.Add(NIST_TEST_POLICY_2); + + } + + [Test] + public void TestValidSignaturesTest1() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "ValidCertificatePathTest1EE", GOOD_CA_CERT }, + new string[] { GOOD_CA_CRL, TRUST_ANCHOR_ROOT_CRL }); + } + + [Test] + public void TestInvalidCASignatureTest2() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "ValidCertificatePathTest1EE", "BadSignedCACert" }, + new string[] { "BadSignedCACRL", TRUST_ANCHOR_ROOT_CRL }, + 1, + "TrustAnchor found but certificate validation failed."); + } + + [Test] + public void TestInvalidEESignatureTest3() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "InvalidEESignatureTest3EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }, + 0, + "Could not validate certificate signature."); + } + + [Test] + public void TestValidDSASignaturesTest4() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "DSACACert", "ValidDSASignaturesTest4EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL" }); + } + + [Test] + // 4.1.5 + public void TestValidDSAParameterInheritanceTest5() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "DSACACert", "DSAParametersInheritedCACert", "ValidDSAParameterInheritanceTest5EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL", "DSAParametersInheritedCACRL" }); + } + + [Test] + public void TestInvalidDSASignaturesTest6() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "DSACACert", "InvalidDSASignatureTest6EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL" }, + 0, + "Could not validate certificate signature."); + } + + [Test] + public void TestCANotBeforeDateTest1() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "BadnotBeforeDateCACert", "InvalidCAnotBeforeDateTest1EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "BadnotBeforeDateCACRL" }, + 1, + "Could not validate certificate: certificate not valid until 20470101120100GMT+00:00"); + } + + [Test] + public void TestInvalidEENotBeforeDateTest2() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "InvalidEEnotBeforeDateTest2EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }, + 0, + "Could not validate certificate: certificate not valid until 20470101120100GMT+00:00"); + } + + [Test] + public void TestValidPre2000UTCNotBeforeDateTest3() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "Validpre2000UTCnotBeforeDateTest3EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }); + } + + [Test] + public void TestValidGeneralizedTimeNotBeforeDateTest4() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "ValidGeneralizedTimenotBeforeDateTest4EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }); + } + + [Test] + public void TestInvalidCANotAfterDateTest5() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "BadnotAfterDateCACert", "InvalidCAnotAfterDateTest5EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "BadnotAfterDateCACRL" }, + 1, + "Could not validate certificate: certificate expired on 20020101120100GMT+00:00"); + } + + [Test] + public void TestInvalidEENotAfterDateTest6() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "InvalidEEnotAfterDateTest6EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }, + 0, + "Could not validate certificate: certificate expired on 20020101120100GMT+00:00"); + } + + [Test] + public void TestInvalidValidPre2000UTCNotAfterDateTest7() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "Invalidpre2000UTCEEnotAfterDateTest7EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }, + 0, + "Could not validate certificate: certificate expired on 19990101120100GMT+00:00"); + } + + [Test] + public void TestInvalidNegativeSerialNumberTest15() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "NegativeSerialNumberCACert", "InvalidNegativeSerialNumberTest15EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "NegativeSerialNumberCACRL" }, + 0, + "Certificate revocation after 4/19/2001 2:57:20 PM", + "reason: keyCompromise"); + } + + // + // 4.8 Certificate Policies + // + [Test] + public void TestAllCertificatesSamePolicyTest1() + { + string[] certList = new string[] { GOOD_CA_CERT, "ValidCertificatePathTest1EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + certList, + crlList, + noPolicies); + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + certList, + crlList, + nistTestPolicy1); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + certList, + crlList, + nistTestPolicy2, + -1, + "Path processing failed on policy."); + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + certList, + crlList, + nistTestPolicy1And2); + } + + [Test] + public void TestAllCertificatesNoPoliciesTest2() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "NoPoliciesCACert", "AllCertificatesNoPoliciesTest2EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "NoPoliciesCACRL" }); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { "NoPoliciesCACert", "AllCertificatesNoPoliciesTest2EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, "NoPoliciesCACRL" }, + noPolicies, + 1, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestDifferentPoliciesTest3() + { + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" }); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" }, + noPolicies, + 1, + "No valid policy tree found when one expected."); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" }, + nistTestPolicy1And2, + 1, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestDifferentPoliciesTest4() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "GoodsubCACert", "DifferentPoliciesTest4EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "GoodsubCACRL" }, + 0, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestDifferentPoliciesTest5() + { + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, + new string[] { GOOD_CA_CERT, "PoliciesP2subCA2Cert", "DifferentPoliciesTest5EE" }, + new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCA2CRL" }, + 0, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestOverlappingPoliciesTest6() + { + string[] certList = new string[] { "PoliciesP1234CACert", "PoliciesP1234subCAP123Cert", "PoliciesP1234subsubCAP123P12Cert", "OverlappingPoliciesTest6EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP1234CACRL", "PoliciesP1234subCAP123CRL", "PoliciesP1234subsubCAP123P12CRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestDifferentPoliciesTest7() + { + string[] certList = new string[] { "PoliciesP123CACert", "PoliciesP123subCAP12Cert", "PoliciesP123subsubCAP12P1Cert", "DifferentPoliciesTest7EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL", "PoliciesP123subCAP12CRL", "PoliciesP123subsubCAP12P1CRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, + 0, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestDifferentPoliciesTest8() + { + string[] certList = new string[] { "PoliciesP12CACert", "PoliciesP12subCAP1Cert", "PoliciesP12subsubCAP1P2Cert", "DifferentPoliciesTest8EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL", "PoliciesP12subCAP1CRL", "PoliciesP12subsubCAP1P2CRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, + 1, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestDifferentPoliciesTest9() + { + string[] certList = new string[] { "PoliciesP123CACert", "PoliciesP123subCAP12Cert", "PoliciesP123subsubCAP12P2Cert", "PoliciesP123subsubsubCAP12P2P1Cert", "DifferentPoliciesTest9EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL", "PoliciesP123subCAP12CRL", "PoliciesP123subsubCAP2P2CRL", "PoliciesP123subsubsubCAP12P2P1CRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, + 1, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestAllCertificatesSamePoliciesTest10() + { + string[] certList = new string[] { "PoliciesP12CACert", "AllCertificatesSamePoliciesTest10EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2); + } + + [Test] + public void TestAllCertificatesAnyPolicyTest11() + { + string[] certList = new string[] { "anyPolicyCACert", "AllCertificatesanyPolicyTest11EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "anyPolicyCACRL" }; + + PkixCertPathValidatorResult result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + + result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + } + + [Test] + public void TestDifferentPoliciesTest12() + { + string[] certList = new string[] { "PoliciesP3CACert", "DifferentPoliciesTest12EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP3CACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, + 0, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestAllCertificatesSamePoliciesTest13() + { + string[] certList = new string[] { "PoliciesP123CACert", "AllCertificatesSamePoliciesTest13EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy3); + } + + [Test] + public void TestAnyPolicyTest14() + { + string[] certList = new string[] { "anyPolicyCACert", "AnyPolicyTest14EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "anyPolicyCACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestUserNoticeQualifierTest15() + { + string[] certList = new string[] { "UserNoticeQualifierTest15EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestUserNoticeQualifierTest16() + { + string[] certList = new string[] { GOOD_CA_CERT, "UserNoticeQualifierTest16EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }; + + PkixCertPathValidatorResult result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + + result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestUserNoticeQualifierTest17() + { + string[] certList = new string[] { GOOD_CA_CERT, "UserNoticeQualifierTest17EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestUserNoticeQualifierTest18() + { + string[] certList = new string[] { "PoliciesP12CACert", "UserNoticeQualifierTest18EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2); + } + + [Test] + public void TestUserNoticeQualifierTest19() + { + string[] certList = new string[] { "UserNoticeQualifierTest19EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2, + -1, + "Path processing failed on policy."); + } + + [Test] + public void TestInvalidInhibitPolicyMappingTest1() + { + string[] certList = new string[] { "inhibitPolicyMapping0CACert", "inhibitPolicyMapping0subCACert", "InvalidinhibitPolicyMappingTest1EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitPolicyMapping0CACRL", "inhibitPolicyMapping0subCACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "No valid policy tree found when one expected."); + } + + [Test] + public void TestValidInhibitPolicyMappingTest2() + { + string[] certList = new string[] { "inhibitPolicyMapping1P12CACert", "inhibitPolicyMapping1P12subCACert", "ValidinhibitPolicyMappingTest2EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitPolicyMapping1P12CACRL", "inhibitPolicyMapping1P12subCACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1); + } + + // 4.12.7 + [Test] + public void TestValidSelfIssuedInhibitAnyPolicyTest7() + { + string[] certList = new string[] { "inhibitAnyPolicy1CACert", "inhibitAnyPolicy1SelfIssuedCACert", "inhibitAnyPolicy1subCA2Cert", "ValidSelfIssuedinhibitAnyPolicyTest7EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitAnyPolicy1CACRL", "inhibitAnyPolicy1subCA2CRL" }; + + doBuilderTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, false, false); + } + + // 4.4.19 + [Test] + public void TestValidSeparateCertificateandCRLKeysTest19() + { + string[] certList = new string[] { "SeparateCertificateandCRLKeysCertificateSigningCACert", "SeparateCertificateandCRLKeysCRLSigningCert", "ValidSeparateCertificateandCRLKeysTest19EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "SeparateCertificateandCRLKeysCRL" }; + + doBuilderTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, false, false); + } + + [Test] + public void TestValidpathLenConstraintTest13() + { + string[] certList = new string[] { "pathLenConstraint6CACert", "pathLenConstraint6subCA4Cert", "pathLenConstraint6subsubCA41Cert", "pathLenConstraint6subsubsubCA41XCert", "ValidpathLenConstraintTest13EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "pathLenConstraint6CACRL", "pathLenConstraint6subCA4CRL", "pathLenConstraint6subsubCA41CRL", "pathLenConstraint6subsubsubCA41XCRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null); + } + + // 4.4.10 + [Test] + public void TestInvalidUnknownCRLExtensionTest10() + { + string[] certList = new string[] { "UnknownCRLExtensionCACert", "InvalidUnknownCRLExtensionTest10EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "UnknownCRLExtensionCACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "CRL contains unsupported critical extensions."); + } + + // 4.14.3 + [Test] + public void TestInvaliddistributionPointTest3() + { + string[] certList = new string[] { "distributionPoint1CACert", "InvaliddistributionPointTest3EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint1CACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); + } + + // 4.14.5 + [Test] + public void TestValiddistributionPointTest5() + { + string[] certList = new string[] { "distributionPoint2CACert", "ValiddistributionPointTest5EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" }; + + DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null); + } + + // 4.14.8 + [Test] + public void TestInvaliddistributionPointTest8() + { + string[] certList = new string[] { "distributionPoint2CACert", "InvaliddistributionPointTest8EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); + } + + // 4.14.9 + [Test] + public void TestInvaliddistributionPointTest9() + { + string[] certList = new string[] { "distributionPoint2CACert", "InvaliddistributionPointTest9EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); + } + + // 4.14.17 + [Test] + public void TestInvalidonlySomeReasonsTest17() + { + string[] certList = new string[] { "onlySomeReasonsCA2Cert", "InvalidonlySomeReasonsTest17EE" }; + string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "onlySomeReasonsCA2CRL1", "onlySomeReasonsCA2CRL2" }; + + DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, + 0, + "Certificate status could not be determined."); + } + + // section 4.14: tests 17, 24, 25, 30, 31, 32, 33, 35 + + // section 4.15: tests 5, 7 + private void DoExceptionTest( + string trustAnchor, + string[] certs, + string[] crls, + int index, + string message) + { + try + { + DoTest(trustAnchor, certs, crls); + + Assert.Fail("path accepted when should be rejected"); + } + catch (PkixCertPathValidatorException e) + { + Assert.AreEqual(index, e.Index); + Assert.AreEqual(message, e.Message); + } + } + + private void DoExceptionTest( + string trustAnchor, + string[] certs, + string[] crls, + ISet policies, + int index, + string message) + { + try + { + DoTest(trustAnchor, certs, crls, policies); + Assert.Fail("path accepted when should be rejected"); + } + catch (PkixCertPathValidatorException e) + { + Assert.AreEqual(index, e.Index); + Assert.AreEqual(message, e.Message); + } + } + + private void DoExceptionTest( + string trustAnchor, + string[] certs, + string[] crls, + int index, + string mesStart, + string mesEnd) + { + try + { + DoTest(trustAnchor, certs, crls); + + Assert.Fail("path accepted when should be rejected"); + } + catch (PkixCertPathValidatorException e) + { + Assert.AreEqual(index, e.Index); + Assert.IsTrue(e.Message.StartsWith(mesStart)); + Assert.IsTrue(e.Message.EndsWith(mesEnd)); + } + } + + private PkixCertPathValidatorResult DoTest( + string trustAnchor, + string[] certs, + string[] crls) + { + return DoTest(trustAnchor, certs, crls, null); + } + + private PkixCertPathValidatorResult DoTest( + string trustAnchor, + string[] certs, + string[] crls, + ISet policies) + { + ISet trustedSet = new HashSet(); + trustedSet.Add(GetTrustAnchor(trustAnchor)); + + IList x509Certs = new ArrayList(); + IList x509Crls = new ArrayList(); + X509Certificate endCert = LoadCert(certs[certs.Length - 1]); + + for (int i = 0; i != certs.Length - 1; i++) + { + x509Certs.Add(LoadCert(certs[i])); + } + + x509Certs.Add(endCert); + + PkixCertPath certPath = new PkixCertPath(x509Certs); + + for (int i = 0; i != crls.Length; i++) + { + x509Crls.Add(LoadCrl(crls[i])); + } + + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(x509Certs)); + IX509Store x509CrlStore = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(x509Crls)); + +// CertPathValidator validator = CertPathValidator.GetInstance("PKIX"); + PkixCertPathValidator validator = new PkixCertPathValidator(); + PkixParameters parameters = new PkixParameters(trustedSet); + + parameters.AddStore(x509CertStore); + parameters.AddStore(x509CrlStore); + parameters.IsRevocationEnabled = true; + + if (policies != null) + { + parameters.IsExplicitPolicyRequired = true; + parameters.SetInitialPolicies(policies); + } + + // Perform validation as of this date since test certs expired + parameters.Date = new DateTimeObject(DateTime.Parse("1/1/2011")); + + return validator.Validate(certPath, parameters); + } + + private PkixCertPathBuilderResult doBuilderTest( + string trustAnchor, + string[] certs, + string[] crls, + ISet initialPolicies, + bool policyMappingInhibited, + bool anyPolicyInhibited) + { + ISet trustedSet = new HashSet(); + trustedSet.Add(GetTrustAnchor(trustAnchor)); + + IList x509Certs = new ArrayList(); + IList x509Crls = new ArrayList(); + X509Certificate endCert = LoadCert(certs[certs.Length - 1]); + + for (int i = 0; i != certs.Length - 1; i++) + { + x509Certs.Add(LoadCert(certs[i])); + } + + x509Certs.Add(endCert); + + for (int i = 0; i != crls.Length; i++) + { + x509Crls.Add(LoadCrl(crls[i])); + } + + IX509Store x509CertStore = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(x509Certs)); + IX509Store x509CrlStore = X509StoreFactory.Create( + "CRL/Collection", + new X509CollectionStoreParameters(x509Crls)); + +// CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX"); + PkixCertPathBuilder builder = new PkixCertPathBuilder(); + + X509CertStoreSelector endSelector = new X509CertStoreSelector(); + + endSelector.Certificate = endCert; + + PkixBuilderParameters builderParams = new PkixBuilderParameters(trustedSet, endSelector); + + if (initialPolicies != null) + { + builderParams.SetInitialPolicies(initialPolicies); + builderParams.IsExplicitPolicyRequired = true; + } + if (policyMappingInhibited) + { + builderParams.IsPolicyMappingInhibited = policyMappingInhibited; + } + if (anyPolicyInhibited) + { + builderParams.IsAnyPolicyInhibited = anyPolicyInhibited; + } + + builderParams.AddStore(x509CertStore); + builderParams.AddStore(x509CrlStore); + + // Perform validation as of this date since test certs expired + builderParams.Date = new DateTimeObject(DateTime.Parse("1/1/2011")); + + try + { + return (PkixCertPathBuilderResult) builder.Build(builderParams); + } + catch (PkixCertPathBuilderException e) + { + throw e.InnerException; + } + } + + private X509Certificate LoadCert( + string certName) + { + X509Certificate cert = (X509Certificate)certs[certName]; + + if (cert != null) + { + return cert; + } + + Stream fs = null; + + try + { + fs = SimpleTest.GetTestDataAsStream("PKITS.certs." + certName + ".crt"); + + cert = new X509CertificateParser().ReadCertificate(fs); + + certs[certName] = cert; + + return cert; + } + catch (Exception e) + { + throw new InvalidOperationException("exception loading certificate " + certName + ": " + e); + } + finally + { + fs.Close(); + } + } + + private X509Crl LoadCrl( + string crlName) + //throws Exception + { + X509Crl crl = (X509Crl)certs[crlName]; + + if (crl != null) + { + return crl; + } + + Stream fs = null; + + try + { + fs = SimpleTest.GetTestDataAsStream("PKITS.crls." + crlName + ".crl"); + + crl = new X509CrlParser().ReadCrl(fs); + + crls[crlName] = crl; + + return crl; + } + catch (Exception) + { + throw new InvalidOperationException("exception loading CRL: " + crlName); + } + finally + { + fs.Close(); + } + } + + private TrustAnchor GetTrustAnchor(string trustAnchorName) + { + X509Certificate cert = LoadCert(trustAnchorName); + Asn1OctetString extBytes = cert.GetExtensionValue(X509Extensions.NameConstraints); + + if (extBytes != null) + { + Asn1Encodable extValue = X509ExtensionUtilities.FromExtensionValue(extBytes); + + return new TrustAnchor(cert, extValue.GetDerEncoded()); + } + + return new TrustAnchor(cert, null); + } + } +} diff --git a/crypto/test/src/test/rsa3/RSA3CertTest.cs b/crypto/test/src/test/rsa3/RSA3CertTest.cs new file mode 100644 index 000000000..913f4f015 --- /dev/null +++ b/crypto/test/src/test/rsa3/RSA3CertTest.cs @@ -0,0 +1,127 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tests.Rsa3 +{ + /** + * Marius Schilder's Bleichenbacher's Forgery Attack Tests + */ + [TestFixture] + public class RSA3CertTest + //extends TestCase + { + [Test] + public void TestA() + { + doTest("self-testcase-A.pem"); + } + + [Test] + public void TestB() + { + doTest("self-testcase-B.pem"); + } + + [Test] + public void TestC() + { + doTest("self-testcase-C.pem"); + } + + [Test] + public void TestD() + { + doTest("self-testcase-D.pem"); + } + + [Test] + public void TestE() + { + doTest("self-testcase-E.pem"); + } + + [Test] + public void TestF() + { + doTest("self-testcase-F.pem"); + } + + [Test] + public void TestG() + { + doTest("self-testcase-G.pem"); + } + + [Test] + public void TestH() + { + doTest("self-testcase-H.pem"); + } + + [Test] + public void TestI() + { + doTest("self-testcase-I.pem"); + } + + [Test] + public void TestJ() + { + doTest("self-testcase-J.pem"); + } + + [Test] + public void TestL() + { + doTest("self-testcase-L.pem"); + } + + private void doTest( + string certName) + { + X509Certificate cert = loadCert(certName); + byte[] tbs = cert.GetTbsCertificate(); + ISigner sig = SignerUtilities.GetSigner(cert.SigAlgName); + + sig.Init(false, cert.GetPublicKey()); + + sig.BlockUpdate(tbs, 0, tbs.Length); + + Assert.IsFalse(sig.VerifySignature(cert.GetSignature())); + } + + private X509Certificate loadCert( + string certName) + { + Stream s = SimpleTest.GetTestDataAsStream("rsa3." + certName); + TextReader tr = new StreamReader(s); + PemReader rd = new PemReader(tr); + + return (X509Certificate) rd.ReadObject(); + } + +// public static void main (string[] args) +// throws Exception +// { +// junit.textui.TestRunner.run(suite()); +// } +// +// public static Test suite() +// throws Exception +// { +// TestSuite suite = new TestSuite("Bleichenbacher's Forgery Attack Tests"); +// +// suite.addTestSuite(RSA3CertTest.class); +// +// return suite; +// } + } +} diff --git a/crypto/test/src/tsp/test/AllTests.cs b/crypto/test/src/tsp/test/AllTests.cs new file mode 100644 index 000000000..66dc9c480 --- /dev/null +++ b/crypto/test/src/tsp/test/AllTests.cs @@ -0,0 +1,32 @@ +using System; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Tsp.Tests +{ + public class AllTests + { + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + suite().Run(el); + } + + public static TestSuite suite() + { + TestSuite suite = new TestSuite("TSP Tests"); + + suite.Add(new GenTimeAccuracyUnitTest()); + suite.Add(new ParseTest()); + suite.Add(new TimeStampTokenInfoUnitTest()); + suite.Add(new TspTest()); + + return suite; + } + } +} diff --git a/crypto/test/src/tsp/test/GenTimeAccuracyTest.cs b/crypto/test/src/tsp/test/GenTimeAccuracyTest.cs new file mode 100644 index 000000000..01cc83d53 --- /dev/null +++ b/crypto/test/src/tsp/test/GenTimeAccuracyTest.cs @@ -0,0 +1,116 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Tsp; + +namespace Org.BouncyCastle.Tsp.Tests +{ + [TestFixture] + public class GenTimeAccuracyUnitTest + { + private static readonly DerInteger ZERO_VALUE = new DerInteger(0); + private static readonly DerInteger ONE_VALUE = new DerInteger(1); + private static readonly DerInteger TWO_VALUE = new DerInteger(2); + private static readonly DerInteger THREE_VALUE = new DerInteger(3); + + [Test] + public void TestOneTwoThree() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ONE_VALUE, TWO_VALUE, THREE_VALUE)); + + checkValues(accuracy, ONE_VALUE, TWO_VALUE, THREE_VALUE); + + checkTostring(accuracy, "1.002003"); + } + + [Test] + public void TestThreeTwoOne() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(THREE_VALUE, TWO_VALUE, ONE_VALUE)); + + checkValues(accuracy, THREE_VALUE, TWO_VALUE, ONE_VALUE); + + checkTostring(accuracy, "3.002001"); + } + + [Test] + public void TestTwoThreeTwo() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(TWO_VALUE, THREE_VALUE, TWO_VALUE)); + + checkValues(accuracy, TWO_VALUE, THREE_VALUE, TWO_VALUE); + + checkTostring(accuracy, "2.003002"); + } + + [Test] + public void TestZeroTwoThree() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ZERO_VALUE, TWO_VALUE, THREE_VALUE)); + + checkValues(accuracy, ZERO_VALUE, TWO_VALUE, THREE_VALUE); + + checkTostring(accuracy, "0.002003"); + } + + [Test] + public void TestThreeTwoNull() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(THREE_VALUE, TWO_VALUE, null)); + + checkValues(accuracy, THREE_VALUE, TWO_VALUE, ZERO_VALUE); + + checkTostring(accuracy, "3.002000"); + } + + [Test] + public void TestOneNullOne() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ONE_VALUE, null, ONE_VALUE)); + + checkValues(accuracy, ONE_VALUE, ZERO_VALUE, ONE_VALUE); + + checkTostring(accuracy, "1.000001"); + } + + [Test] + public void TestZeroNullNull() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ZERO_VALUE, null, null)); + + checkValues(accuracy, ZERO_VALUE, ZERO_VALUE, ZERO_VALUE); + + checkTostring(accuracy, "0.000000"); + } + + [Test] + public void TestNullNullNull() + { + GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(null, null, null)); + + checkValues(accuracy, ZERO_VALUE, ZERO_VALUE, ZERO_VALUE); + + checkTostring(accuracy, "0.000000"); + } + + private void checkValues( + GenTimeAccuracy accuracy, + DerInteger secs, + DerInteger millis, + DerInteger micros) + { + Assert.AreEqual(secs.Value.IntValue, accuracy.Seconds); + Assert.AreEqual(millis.Value.IntValue, accuracy.Millis); + Assert.AreEqual(micros.Value.IntValue, accuracy.Micros); + } + + private void checkTostring( + GenTimeAccuracy accuracy, + string expected) + { + Assert.AreEqual(expected, accuracy.ToString()); + } + } +} diff --git a/crypto/test/src/tsp/test/ParseTest.cs b/crypto/test/src/tsp/test/ParseTest.cs new file mode 100644 index 000000000..ec9ba72f6 --- /dev/null +++ b/crypto/test/src/tsp/test/ParseTest.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections; +using System.IO; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tsp.Tests +{ + [TestFixture] + public class ParseTest + { + private static readonly byte[] sha1Request = Base64.Decode("MDACAQEwITAJBgUrDgMCGgUABBT5UbEBmJssO3RxcQtOePxNvfoMpgIIC+GvYW2mtZQ="); + private static readonly byte[] sha1noNonse = Base64.Decode("MCYCAQEwITAJBgUrDgMCGgUABBT5UbEBmJssO3RxcQtOePxNvfoMpg=="); + private static readonly byte[] md5Request = Base64.Decode("MDoCAQEwIDAMBggqhkiG9w0CBQUABBDIl9FBCvjyx0+6EbHbUR6eBgkrBgEEAakHBQECCDQluayIxIzn"); + private static readonly byte[] ripemd160Request = Base64.Decode("MD8CAQEwITAJBgUrJAMCAQUABBSq03a/mk50Yd9lMF+BSqOp/RHGQQYJKwYBBAGpBwUBAgkA4SZs9NfqISMBAf8="); + + private static readonly byte[] sha1Response = Base64.Decode( + "MIICbDADAgEAMIICYwYJKoZIhvcNAQcCoIICVDCCAlACAQMxCzAJBgUrDgMC" + + "GgUAMIHaBgsqhkiG9w0BCRABBKCBygSBxzCBxAIBAQYEKgMEATAhMAkGBSsO" + + "AwIaBQAEFPlRsQGYmyw7dHFxC054/E29+gymAgEEGA8yMDA0MTIwOTA3NTIw" + + "NVowCgIBAYACAfSBAWQBAf8CCAvhr2FtprWUoGmkZzBlMRgwFgYDVQQDEw9F" + + "cmljIEguIEVjaGlkbmExJDAiBgkqhkiG9w0BCQEWFWVyaWNAYm91bmN5Y2Fz" + + "dGxlLm9yZzEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUx" + + "ggFfMIIBWwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNV" + + "BAYTAkFVAgECMAkGBSsOAwIaBQCggYwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3" + + "DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0wNDEyMDkwNzUyMDVaMCMGCSqGSIb3" + + "DQEJBDEWBBTGR1cbm94tWbcpDWrH+bD8UYePsTArBgsqhkiG9w0BCRACDDEc" + + "MBowGDAWBBS37aLzFcheqeJ5cla0gjNWHGKbRzANBgkqhkiG9w0BAQEFAASB" + + "gBrc9CJ3xlcTQuWQXJUqPEn6f6vfJAINKsn22z8LIfS/2p/CTFU6+W/bz8j8" + + "j+8uWEJe8okTsI0FflljIsspqOPTB/RrnXteajbkuk/rLmz1B2g/qWBGAzPI" + + "D214raBc1a7Bpd76PkvSSdjqrEaaskd+7JJiPr9l9yeSoh1AIt0N"); + + private static readonly byte[] sha1noNonseResponse = Base64.Decode( + "MIICYjADAgEAMIICWQYJKoZIhvcNAQcCoIICSjCCAkYCAQMxCzAJBgUrDgMC" + + "GgUAMIHQBgsqhkiG9w0BCRABBKCBwASBvTCBugIBAQYEKgMEATAhMAkGBSsO" + + "AwIaBQAEFPlRsQGYmyw7dHFxC054/E29+gymAgECGA8yMDA0MTIwOTA3MzQx" + + "MlowCgIBAYACAfSBAWQBAf+gaaRnMGUxGDAWBgNVBAMTD0VyaWMgSC4gRWNo" + + "aWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUub3JnMRYw" + + "FAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTGCAV8wggFbAgEB" + + "MCowJTEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUCAQIw" + + "CQYFKw4DAhoFAKCBjDAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJ" + + "KoZIhvcNAQkFMQ8XDTA0MTIwOTA3MzQxMlowIwYJKoZIhvcNAQkEMRYEFMNA" + + "xlscHYiByHL9DIEh3FewIhgSMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFLft" + + "ovMVyF6p4nlyVrSCM1YcYptHMA0GCSqGSIb3DQEBAQUABIGAaj46Tarrg7V7" + + "z13bbetrGv+xy159eE8kmIW9nPegru3DuK/GmbMx9W3l0ydx0zdXRwYi6NZc" + + "nNqbEZQZ2L1biJVTflgWq4Nxu4gPGjH/BGHKdH/LyW4eDcXZR39AkNBMnDAK" + + "EmhhJo1/Tc+S/WkV9lnHJCPIn+TAijBUO6EiTik="); + + private static readonly byte[] md5Response = Base64.Decode( + "MIICcDADAgEAMIICZwYJKoZIhvcNAQcCoIICWDCCAlQCAQMxCzAJBgUrDgMC" + + "GgUAMIHeBgsqhkiG9w0BCRABBKCBzgSByzCByAIBAQYJKwYBBAGpBwUBMCAw" + + "DAYIKoZIhvcNAgUFAAQQyJfRQQr48sdPuhGx21EengIBAxgPMjAwNDEyMDkw" + + "NzQ2MTZaMAoCAQGAAgH0gQFkAQH/Agg0JbmsiMSM56BppGcwZTEYMBYGA1UE" + + "AxMPRXJpYyBILiBFY2hpZG5hMSQwIgYJKoZIhvcNAQkBFhVlcmljQGJvdW5j" + + "eWNhc3RsZS5vcmcxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYT" + + "AkFVMYIBXzCCAVsCAQEwKjAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQsw" + + "CQYDVQQGEwJBVQIBAjAJBgUrDgMCGgUAoIGMMBoGCSqGSIb3DQEJAzENBgsq" + + "hkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMDQxMjA5MDc0NjE2WjAjBgkq" + + "hkiG9w0BCQQxFgQUFpRpaiRUUjiY7EbefbWLKDIY0XMwKwYLKoZIhvcNAQkQ" + + "AgwxHDAaMBgwFgQUt+2i8xXIXqnieXJWtIIzVhxim0cwDQYJKoZIhvcNAQEB" + + "BQAEgYBTwKsLLrQm+bvKV7Jwto/cMQh0KsVB5RoEeGn5CI9XyF2Bm+JRcvQL" + + "Nm7SgSOBVt4A90TqujxirNeyQnXRiSnFvXd09Wet9WIQNpwpiGlE7lCrAhuq" + + "/TAUe79VIpoQZDtyhbh0Vzxl24yRoechabC0zuPpOWOzrA4YC3Hv1J2tAA=="); + + private static readonly byte[] signingCert = Base64.Decode( + "MIICWjCCAcOgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3Vu" + + "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAeFw0wNDEyMDkwNzEzMTRaFw0wNTAzMTkw" + + "NzEzMTRaMGUxGDAWBgNVBAMTD0VyaWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJ" + + "ARYVZXJpY0Bib3VuY3ljYXN0bGUub3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxl" + + "MQswCQYDVQQGEwJBVTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqGAFO3dK" + + "jB7Ca7u5Z3CabsbGr2Exg+3sztSPiRCIba03es4295EhtDF5bXQvrW2R1Bg72vED" + + "5tWaQjVDetvDfCzVC3ErHLTVk3OgpLIP1gf2T0LcOH2pTh2LP9c5Ceta+uggK8zK" + + "9sYUUnzGPSAZxrqHIIAlPIgqk0BMV+KApyECAwEAAaNaMFgwHQYDVR0OBBYEFO4F" + + "YoqogtB9MjD0NB5x5HN3TrGUMB8GA1UdIwQYMBaAFPXAecuwLqNkCxYVLE/ngFQR" + + "7RLIMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBBAUAA4GBADGi" + + "D5/qmGvcBgswEM/z2dF4lOxbTNKUW31ZHiU8CXlN0IkFtNbBLBTbJOQIAUnNEabL" + + "T7aYgj813OZKUbJTx4MuGChhot/TEP7hKo/xz9OnXLsqYDKbqbo8iLOode+SI7II" + + "+yYghOtqvx32cL2Qmffi1LaMbhJP+8NbsIxowdRC"); + + private static readonly byte[] unacceptablePolicy = Base64.Decode( + "MDAwLgIBAjAkDCJSZXF1ZXN0ZWQgcG9saWN5IGlzIG5vdCBzdXBwb3J0ZWQuAwMAAAE="); + + private static readonly byte[] generalizedTime = Base64.Decode( + "MIIKPTADAgEAMIIKNAYJKoZIhvcNAQcCoIIKJTCCCiECAQMxCzAJBgUrDgMC" + + "GgUAMIIBGwYLKoZIhvcNAQkQAQSgggEKBIIBBjCCAQICAQEGCisGAQQBhFkK" + + "AwEwITAJBgUrDgMCGgUABBQAAAAAAAAAAAAAAAAAAAAAAAAAAAICUC8YEzIw" + + "MDUwMzEwMTA1ODQzLjkzM1owBIACAfQBAf8CAWSggaikgaUwgaIxCzAJBgNV" + + "BAYTAkdCMRcwFQYDVQQIEw5DYW1icmlkZ2VzaGlyZTESMBAGA1UEBxMJQ2Ft" + + "YnJpZGdlMSQwIgYDVQQKExtuQ2lwaGVyIENvcnBvcmF0aW9uIExpbWl0ZWQx" + + "JzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjozMjJBLUI1REQtNzI1QjEXMBUG" + + "A1UEAxMOZGVtby1kc2UyMDAtMDGgggaFMIID2TCCA0KgAwIBAgICAIswDQYJ" + + "KoZIhvcNAQEFBQAwgYwxCzAJBgNVBAYTAkdCMRcwFQYDVQQIEw5DYW1icmlk" + + "Z2VzaGlyZTESMBAGA1UEBxMJQ2FtYnJpZGdlMSQwIgYDVQQKExtuQ2lwaGVy" + + "IENvcnBvcmF0aW9uIExpbWl0ZWQxGDAWBgNVBAsTD1Byb2R1Y3Rpb24gVEVT" + + "VDEQMA4GA1UEAxMHVEVTVCBDQTAeFw0wNDA2MTQxNDIzNTlaFw0wNTA2MTQx" + + "NDIzNTlaMIGiMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hp" + + "cmUxEjAQBgNVBAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jw" + + "b3JhdGlvbiBMaW1pdGVkMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046MzIy" + + "QS1CNURELTcyNUIxFzAVBgNVBAMTDmRlbW8tZHNlMjAwLTAxMIGfMA0GCSqG" + + "SIb3DQEBAQUAA4GNADCBiQKBgQC7zUamCeLIApddx1etW5YEFrL1WXnlCd7j" + + "mMFI6RpSq056LBkF1z5LgucLY+e/c3u2Nw+XJuS3a2fKuBD7I1s/6IkVtIb/" + + "KLDjjafOnottKhprH8K41siJUeuK3PRzfZ5kF0vwB3rNvWPCBJmp7kHtUQw3" + + "RhIsJTYs7Wy8oVFHVwIDAQABo4IBMDCCASwwCQYDVR0TBAIwADAWBgNVHSUB" + + "Af8EDDAKBggrBgEFBQcDCDAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l" + + "cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFDlEe9Pd0WwQrtnEmFRI2Vmt" + + "b+lCMIG5BgNVHSMEgbEwga6AFNy1VPweOQLC65bs6/0RcUYB19vJoYGSpIGP" + + "MIGMMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hpcmUxEjAQ" + + "BgNVBAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlv" + + "biBMaW1pdGVkMRgwFgYDVQQLEw9Qcm9kdWN0aW9uIFRFU1QxEDAOBgNVBAMT" + + "B1RFU1QgQ0GCAQAwDQYJKoZIhvcNAQEFBQADgYEASEMlrpRE1RYZPxP3530e" + + "hOYUDjgQbw0dwpPjQtLWkeJrePMzDBAbuWwpRI8dOzKP3Rnrm5rxJ7oLY2S0" + + "A9ZfV+iwFKagEHFytfnPm2Y9AeNR7a3ladKd7NFMw+5Tbk7Asbetbb+NJfCl" + + "9YzHwxLGiQbpKxgc+zYOjq74eGLKtcKhggKkMIICDQIBATCB0qGBqKSBpTCB" + + "ojELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDkNhbWJyaWRnZXNoaXJlMRIwEAYD" + + "VQQHEwlDYW1icmlkZ2UxJDAiBgNVBAoTG25DaXBoZXIgQ29ycG9yYXRpb24g" + + "TGltaXRlZDEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOjMyMkEtQjVERC03" + + "MjVCMRcwFQYDVQQDEw5kZW1vLWRzZTIwMC0wMaIlCgEBMAkGBSsOAwIaBQAD" + + "FQDaLe88TQvM+iMKmIXMmDSyPCZ/+KBmMGSkYjBgMQswCQYDVQQGEwJVUzEk" + + "MCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlvbiBMaW1pdGVkMRgwFgYDVQQL" + + "Ew9Qcm9kdWN0aW9uIFRlc3QxETAPBgNVBAMTCFRlc3QgVE1DMA0GCSqGSIb3" + + "DQEBBQUAAgjF2jVbAAAAADAiGA8yMDA1MDMxMDAyNTQxOVoYDzIwMDUwMzEz" + + "MDI1NDE5WjCBjTBLBgorBgEEAYRZCgQBMT0wOzAMAgTF2jVbAgQAAAAAMA8C" + + "BAAAAAACBAAAaLkCAf8wDAIEAAAAAAIEAAKV/DAMAgTF3inbAgQAAAAAMD4G" + + "CisGAQQBhFkKBAIxMDAuMAwGCisGAQQBhFkKAwGgDjAMAgQAAAAAAgQAB6Eg" + + "oQ4wDAIEAAAAAAIEAAPQkDANBgkqhkiG9w0BAQUFAAOBgQB1q4d3GNWk7oAT" + + "WkpYmZaTFvapMhTwAmAtSGgFmNOZhs21iHWl/X990/HEBsduwxohfrd8Pz64" + + "hV/a76rpeJCVUfUNmbRIrsurFx6uKwe2HUHKW8grZWeCD1L8Y1pKQdrD41gu" + + "v0msfOXzLWW+xe5BcJguKclN8HmT7s2odtgiMTGCAmUwggJhAgEBMIGTMIGM" + + "MQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hpcmUxEjAQBgNV" + + "BAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlvbiBM" + + "aW1pdGVkMRgwFgYDVQQLEw9Qcm9kdWN0aW9uIFRFU1QxEDAOBgNVBAMTB1RF" + + "U1QgQ0ECAgCLMAkGBSsOAwIaBQCgggEnMBoGCSqGSIb3DQEJAzENBgsqhkiG" + + "9w0BCRABBDAjBgkqhkiG9w0BCQQxFgQUi1iYx5H3ACnvngWZTPfdxGswkSkw" + + "geMGCyqGSIb3DQEJEAIMMYHTMIHQMIHNMIGyBBTaLe88TQvM+iMKmIXMmDSy" + + "PCZ/+DCBmTCBkqSBjzCBjDELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDkNhbWJy" + + "aWRnZXNoaXJlMRIwEAYDVQQHEwlDYW1icmlkZ2UxJDAiBgNVBAoTG25DaXBo" + + "ZXIgQ29ycG9yYXRpb24gTGltaXRlZDEYMBYGA1UECxMPUHJvZHVjdGlvbiBU" + + "RVNUMRAwDgYDVQQDEwdURVNUIENBAgIAizAWBBSpS/lH6bN/wf3E2z2X29vF" + + "2U7YHTANBgkqhkiG9w0BAQUFAASBgGvDVsgsG5I5WKjEDVHvdRwUx+8Cp10l" + + "zGF8o1h7aK5O3zQ4jLayYHea54E5+df35gG7Z3eoOy8E350J7BvHiwDLTqe8" + + "SoRlGs9VhL6LMmCcERfGSlSn61Aa15iXZ8eHMSc5JTeJl+kqy4I3FPP4m2ai" + + "8wy2fQhn7hUM8Ntg7Y2s"); + + private static readonly byte[] v2SigningCertResponse = Base64.Decode( + "MIIPPTADAgEAMIIPNAYJKoZIhvcNAQcCoIIPJTCCDyECAQMxDzANBglghkgBZQMEAgEFADCB6QYL" + + "KoZIhvcNAQkQAQSggdkEgdYwgdMCAQEGBgQAj2cBATAxMA0GCWCGSAFlAwQCAQUABCBcU0GN08TA" + + "LUFi7AAwQwVkSXqGu9tAzvJ7EXW7SMXHHQIRAM7Fa7g6tMvZI3dgllwMfpcYDzIwMDcxMjExMTAy" + + "MTU5WjADAgEBAgYBFsi5OlmgYqRgMF4xCzAJBgNVBAYTAkRFMSQwIgYDVQQKDBtEZXV0c2NoZSBS" + + "ZW50ZW52ZXJzaWNoZXJ1bmcxEzARBgNVBAsMClFDIFJvb3QgQ0ExFDASBgNVBAMMC1FDIFJvb3Qg" + + "VFNQoIILQjCCBwkwggXxoAMCAQICAwN1pjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJERTEk" + + "MCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2ljaGVydW5nMRMwEQYDVQQLDApRQyBSb290IENB" + + "MB4XDTA3MTEyMDE2MDcyMFoXDTEyMDcyNzIwMjExMVowXjELMAkGA1UEBhMCREUxJDAiBgNVBAoM" + + "G0RldXRzY2hlIFJlbnRlbnZlcnNpY2hlcnVuZzETMBEGA1UECwwKUUMgUm9vdCBDQTEUMBIGA1UE" + + "AwwLUUMgUm9vdCBUU1AwggEkMA0GCSqGSIb3DQEBAQUAA4IBEQAwggEMAoIBAQCv1vO+EtGnJNs0" + + "atv76BAJXs4bmO8yzVwe3RUtgeu5z9iefh8P46i1g3EL2CD15NcTfoHksr5KudNY30olfjHG7lIu" + + "MO3R5sAcrGDPP7riZJnaI6VD/e6kVR569VBid5z105fJAB7mID7+Bn7pdRwDW3Fy2CzfofXGuvrO" + + "GPNEWq8x8kqqf75DB5nAs5QP8H41obkdkap2ttHkkPZCiMghTs8iHfpJ0STn47MKq+QrUmuATMZi" + + "XrdEfb7f3TBMjO0UVJF64Mh+kC9GtUEHlcm0Tq2Pk5XIUxWEyL94rZ4UWcVdSVE7IjggV2MifMNx" + + "geZO3SwsDZk71AhDBy30CSzBAgUAx3HB5aOCA+IwggPeMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI" + + "MBMGA1UdIwQMMAqACECefuBmflfeMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwUAYIKwYBBQUH" + + "AQEERDBCMEAGCCsGAQUFBzABhjRodHRwOi8vb2NzcC1yb290cWMudGMuZGV1dHNjaGUtcmVudGVu" + + "dmVyc2ljaGVydW5nLmRlMHcGA1UdIARwMG4wbAYNKwYBBAGBrTwBCAEBAzBbMFkGCCsGAQUFBwIB" + + "Fk1odHRwOi8vd3d3LmRldXRzY2hlLXJlbnRlbnZlcnNpY2hlcnVuZy1idW5kLmRlL3N0YXRpYy90" + + "cnVzdGNlbnRlci9wb2xpY3kuaHRtbDCCATwGA1UdHwSCATMwggEvMHygeqB4hnZsZGFwOi8vZGly" + + "LnRjLmRldXRzY2hlLXJlbnRlbnZlcnNpY2hlcnVuZy5kZS9vdT1RQyUyMFJvb3QlMjBDQSxjbj1Q" + + "dWJsaWMsbz1EUlYsYz1ERT9hdHRybmFtZT1jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0MIGuoIGr" + + "oIGohoGlaHR0cDovL2Rpci50Yy5kZXV0c2NoZS1yZW50ZW52ZXJzaWNoZXJ1bmcuZGU6ODA4OS9z" + + "ZXJ2bGV0L0Rpclh3ZWIvQ2EveC5jcmw/ZG49b3UlM0RRQyUyMFJvb3QlMjBDQSUyQ2NuJTNEUHVi" + + "bGljJTJDbyUzRERSViUyQ2MlM0RERSZhdHRybmFtZT1jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0" + + "MIIBLQYDVR0SBIIBJDCCASCGdGxkYXA6Ly9kaXIudGMuZGV1dHNjaGUtcmVudGVudmVyc2ljaGVy" + + "dW5nLmRlL2NuPTE0NTUxOCxvdT1RQyUyMFJvb3QlMjBDQSxjbj1QdWJsaWMsbz1EUlYsYz1ERT9h" + + "dHRybmFtZT1jQUNlcnRpZmljYXRlhoGnaHR0cDovL2Rpci50Yy5kZXV0c2NoZS1yZW50ZW52ZXJz" + + "aWNoZXJ1bmcuZGU6ODA4OS9zZXJ2bGV0L0Rpclh3ZWIvQ2EveC5jZXI/ZG49Y24lM0QxNDU1MTgl" + + "MkNvdSUzRFFDJTIwUm9vdCUyMENBJTJDY24lM0RQdWJsaWMlMkNvJTNERFJWJTJDYyUzRERFJmF0" + + "dHJuYW1lPWNBQ2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgZAMDsGA1UdCQQ0MDIwMAYDVQQDMSkT" + + "J1FDIFRTUCBEZXV0c2NoZSBSZW50ZW52ZXJzaWNoZXJ1bmcgMTpQTjAMBgNVHRMBAf8EAjAAMA0G" + + "CSqGSIb3DQEBCwUAA4IBAQCCrWe3Pd3ioX7d8phXvVAa859Rvgf0k3pZ6R4GMj8h/k6MNjNIrdAs" + + "wgUVkBbXMLLBk0smsvTdFIVtTBdp1urb9l7vXjDA4MckXBOXPcz4fN8Oswk92d+fM9XU1jKVPsFG" + + "PV6j8lAqfq5jwaRxOnS96UBGLKG+NdcrEyiMp/ZkpqnEQZZfu2mkeq6CPahnbBTZqsE0jgY351gU" + + "9T6SFVvLIFH7cOxJqsoxPqv5YEcgiXPpOyyu2rpQqKYBYcnerF6/zx5hmWHxTd7MWaTHm0gJI/Im" + + "d8esbW+xyaJuAVUcBA+sDmSe8AAoRVxwBRY+xi9ApaJHpmwT+0n2K2GsL3wIMIIEMTCCAxmgAwIB" + + "AgIDAjhuMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNVBAYTAkRFMSQwIgYDVQQKDBtEZXV0c2NoZSBS" + + "ZW50ZW52ZXJzaWNoZXJ1bmcxEzARBgNVBAsMClFDIFJvb3QgQ0EwHhcNMDcwNzI3MjAyMTExWhcN" + + "MTIwNzI3MjAyMTExWjBIMQswCQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVy" + + "c2ljaGVydW5nMRMwEQYDVQQLDApRQyBSb290IENBMIIBJDANBgkqhkiG9w0BAQEFAAOCAREAMIIB" + + "DAKCAQEAzuhBdo9c84DdzsggjWOgfC4jJ2jYqpsOpBo3DVyem+5R26QK4feZdyFnaGvyG+TLcdLO" + + "iCecGmrRGD+ey4IhjCONb7hsQQhJWTyDEtBblzYB0yjY8+9fnNeR61W+M/KlMgC6Rw/w+zwzklTM" + + "MWwIbxLHm8l9jTSKFjAWTwjE8bCzpUCwN8+4JbFTwjwOJ5lsVA5Xa34wpgr6lgL3WrVTV1NSprqR" + + "ZYDWg477tht0KkyOJt3guF3RONKBBuTO2qCbpUeI8m4v3tznoopYbV5Gp5wu5gqd6lTfgju3ldql" + + "bxtuCLZd0nAI5rLEOPItDKl4vPXllmmtGIrtDZlwr86cbwIFAJvMJpGjggEgMIIBHDAPBgNVHRMB" + + "Af8EBTADAQH/MBEGA1UdDgQKBAhAnn7gZn5X3jB3BgNVHSAEcDBuMGwGDSsGAQQBga08AQgBAQEw" + + "WzBZBggrBgEFBQcCARZNaHR0cDovL3d3dy5kZXV0c2NoZS1yZW50ZW52ZXJzaWNoZXJ1bmctYnVu" + + "ZC5kZS9zdGF0aWMvdHJ1c3RjZW50ZXIvcG9saWN5Lmh0bWwwUwYDVR0JBEwwSjBIBgNVBAMxQRM/" + + "UUMgV3VyemVsemVydGlmaXppZXJ1bmdzc3RlbGxlIERldXRzY2hlIFJlbnRlbnZlcnNpY2hlcnVu" + + "ZyAxOlBOMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYDVR0PAQH/BAQDAgIEMA0GCSqGSIb3" + + "DQEBCwUAA4IBAQBNGs7Dnc1yzzpZrkuC+oLv+NhbORTEYNgpaOetB1JQ1EbUBoPuNN4ih0ngy/uJ" + + "D2O+h4JsNkmELgaehLWyFwATqCYZY4cTAGVoEwgn93x3aW8JbMDQf+YEJDSDsXcm4oIDFPqv5M6o" + + "HZUWfsPka3mxKivfKtWhooTz1/+BEGReVQ2oOAvlwXlkEab9e3GOqXQUcLPYDTl8BQxiYhtQtf3d" + + "kORiUkuGiGX1YJ5JnZnG3ElMjPgOl8rOiYU7oj9uv1HVb5sdAwuVw0BR/eiMVDBT8DNyfoJmPeQQ" + + "A9pXtoAYO0Ya7wNNmCY2Y63YfBlRCF+9VQv2RZ4TdO1KGWwxR98OMYIC1zCCAtMCAQEwTzBIMQsw" + + "CQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2ljaGVydW5nMRMwEQYDVQQL" + + "DApRQyBSb290IENBAgMDdaYwDQYJYIZIAWUDBAIBBQCgggFZMBoGCSqGSIb3DQEJAzENBgsqhkiG" + + "9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgO7FFODWWwF5RUjo6wjIkgkD5u7dH+NICiCpSgRRqd/Aw" + + "ggEIBgsqhkiG9w0BCRACLzGB+DCB9TCB8jB3BCAMMZqK/5pZxOb3ruCbcgxStaTDwDHaf2glEo6P" + + "+89t8TBTMEykSjBIMQswCQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2lj" + + "aGVydW5nMRMwEQYDVQQLDApRQyBSb290IENBAgMDdaYwdwQgl7vwI+P47kpxhWLoIdEco7UfGwZ2" + + "X4el3jaZ67q5/9IwUzBMpEowSDELMAkGA1UEBhMCREUxJDAiBgNVBAoMG0RldXRzY2hlIFJlbnRl" + + "bnZlcnNpY2hlcnVuZzETMBEGA1UECwwKUUMgUm9vdCBDQQIDAjhuMA0GCSqGSIb3DQEBCwUABIIB" + + "AIOYgpDI0BaeG4RF/EB5QzkUqAZ9nX6w895+m2hHyRKrAKdj3913j5QI+aEVIG3DVbFaAfdKeKfn" + + "xsTW48aWs6aARtPAc+1OXwoGUSYElOFqqVpSeTaXe+kjY5bsLSQeETB+EPvXl8EcKTaxTRCNOqJU" + + "XbnyYRgWTI55A2jH6IsQQVHc5DaIcmbdI8iATaRTHY5eUeVuI+Q/3RMVBFAb5qRhM61Ddcrjq058" + + "C0uiH9G2IB5QRyu6RsCUgrkeMTMBqlIBlnDBy+EgLouDU4Dehxy5uzEl5DBKZEewZpQZOTO/kAgL" + + "WruAAg/Lj4r0f9vN12wRlHoS2UKDjrE1DnUBbrM="); + + public string Name + { + get { return "ParseTest"; } + } + + private static void requestParse( + byte[] request, + string algorithm) + { + TimeStampRequest req = new TimeStampRequest(request); + + if (!req.MessageImprintAlgOid.Equals(algorithm)) + { + Assert.Fail("failed to get expected algorithm - got " + + req.MessageImprintAlgOid + " not " + algorithm); + } + + if (request != sha1Request && request != sha1noNonse) + { + if (!req.ReqPolicy.Equals(TspTestUtil.EuroPkiTsaTestPolicy.Id)) + { + Assert.Fail("" + algorithm + " failed policy check."); + } + + if (request == ripemd160Request) + { + if (!req.CertReq) + { + Assert.Fail("" + algorithm + " failed certReq check."); + } + } + } + + Assert.AreEqual(1, req.Version, "version not 1"); + + Assert.IsNull(req.GetCriticalExtensionOids(), "critical extensions found when none expected"); + + Assert.IsNull(req.GetNonCriticalExtensionOids(), "non-critical extensions found when none expected"); + + if (request != sha1noNonse) + { + if (req.Nonce == null) + { + Assert.Fail("" + algorithm + " nonse not found when one expected."); + } + } + else + { + if (req.Nonce != null) + { + Assert.Fail("" + algorithm + " nonse not found when one not expected."); + } + } + + try + { + req.Validate(TspAlgorithms.Allowed, null, null); + } + catch (Exception) + { + Assert.Fail("validation exception."); + } + + if (!Arrays.AreEqual(req.GetEncoded(), request)) + { + Assert.Fail("" + algorithm + " failed encode check."); + } + } + + private static void responseParse( + byte[] request, + byte[] response, + string algorithm) + { + TimeStampRequest req = new TimeStampRequest(request); + TimeStampResponse resp = new TimeStampResponse(response); + + resp.Validate(req); + + X509Certificate cert = new X509CertificateParser().ReadCertificate(signingCert); + + resp.TimeStampToken.Validate(cert); + } + + private static void unacceptableResponseParse( + byte[] response) + { + TimeStampResponse resp = new TimeStampResponse(response); + + if (resp.Status != (int) PkiStatus.Rejection) + { + Assert.Fail("request not rejected."); + } + + if (resp.GetFailInfo().IntValue != PkiFailureInfo.UnacceptedPolicy) + { + Assert.Fail("request not rejected."); + } + } + + private static void generalizedTimeParse( + byte[] response) + { + TimeStampResponse resp = new TimeStampResponse(response); + + if (resp.Status != (int) PkiStatus.Granted) + { + Assert.Fail("request not rejected."); + } + } + + [Test] + public void TestSha1() + { + requestParse(sha1Request, TspAlgorithms.Sha1); + requestParse(sha1noNonse, TspAlgorithms.Sha1); + responseParse(sha1Request, sha1Response, TspAlgorithms.Sha1); + responseParse(sha1noNonse, sha1noNonseResponse, TspAlgorithms.Sha1); + } + + [Test] + public void TestMD5() + { + requestParse(md5Request, TspAlgorithms.MD5); + responseParse(md5Request, md5Response, TspAlgorithms.MD5); + } + + [Test] + public void TestRipeMD160() + { + requestParse(ripemd160Request, TspAlgorithms.RipeMD160); + } + + [Test] + public void TestUnacceptable() + { + unacceptableResponseParse(unacceptablePolicy); + } + + [Test] + public void TestGeneralizedTime() + { + generalizedTimeParse(generalizedTime); + } + + [Test] + public void TestV2SigningResponseParse() + { + v2SigningResponseParse(v2SigningCertResponse); + } + + private void v2SigningResponseParse( + byte[] encoded) + { + TimeStampResponse response = new TimeStampResponse(encoded); + + IX509Store store = response.TimeStampToken.GetCertificates("Collection"); + X509Certificate cert = (X509Certificate) + new ArrayList(store.GetMatches(response.TimeStampToken.SignerID))[0]; + + response.TimeStampToken.Validate(cert); + } + +// public static void parse( +// byte[] encoded, +// bool tokenPresent) +// { +// TimeStampResponse response = new TimeStampResponse(encoded); +// +// if (tokenPresent && response.TimeStampToken == null) +// { +// Assert.Fail("token not found when expected."); +// } +// } + } +} diff --git a/crypto/test/src/tsp/test/TSPTest.cs b/crypto/test/src/tsp/test/TSPTest.cs new file mode 100644 index 000000000..e56d4ec9f --- /dev/null +++ b/crypto/test/src/tsp/test/TSPTest.cs @@ -0,0 +1,548 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Store; + +namespace Org.BouncyCastle.Tsp.Tests +{ + [TestFixture] + public class TspTest + { + private static AsymmetricKeyParameter privateKey; + private static X509Certificate cert; + private static IX509Store certs; + + static TspTest() + { + string signDN = "O=Bouncy Castle, C=AU"; + AsymmetricCipherKeyPair signKP = TspTestUtil.MakeKeyPair(); + X509Certificate signCert = TspTestUtil.MakeCACertificate(signKP, signDN, signKP, signDN); + + string origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; + AsymmetricCipherKeyPair origKP = TspTestUtil.MakeKeyPair(); + privateKey = origKP.Private; + + cert = TspTestUtil.MakeCertificate(origKP, origDN, signKP, signDN); + + IList certList = new ArrayList(); + certList.Add(cert); + certList.Add(signCert); + + certs = X509StoreFactory.Create( + "Certificate/Collection", + new X509CollectionStoreParameters(certList)); + } + + [Test] + public void TestBasic() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + tsToken.Validate(cert); + + AttributeTable table = tsToken.SignedAttributes; + + Assert.IsNotNull(table[PkcsObjectIdentifiers.IdAASigningCertificate], "no signingCertificate attribute found"); + } + + [Test] + public void TestResponseValidation() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.MD5, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + tsToken.Validate(cert); + + // + // check validation + // + tsResp.Validate(request); + + try + { + request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(101)); + + tsResp.Validate(request); + + Assert.Fail("response validation failed on invalid nonce."); + } + catch (TspValidationException) + { + // ignore + } + + try + { + request = reqGen.Generate(TspAlgorithms.Sha1, new byte[22], BigInteger.ValueOf(100)); + + tsResp.Validate(request); + + Assert.Fail("response validation failed on wrong digest."); + } + catch (TspValidationException) + { + // ignore + } + + try + { + request = reqGen.Generate(TspAlgorithms.MD5, new byte[20], BigInteger.ValueOf(100)); + + tsResp.Validate(request); + + Assert.Fail("response validation failed on wrong digest."); + } + catch (TspValidationException) + { + // ignore + } + } + + [Test] + public void TestIncorrectHash() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[16]); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + if (tsToken != null) + { + Assert.Fail("incorrectHash - token not null."); + } + + PkiFailureInfo failInfo = tsResp.GetFailInfo(); + + if (failInfo == null) + { + Assert.Fail("incorrectHash - failInfo set to null."); + } + + if (failInfo.IntValue != PkiFailureInfo.BadDataFormat) + { + Assert.Fail("incorrectHash - wrong failure info returned."); + } + } + + [Test] + public void TestBadAlgorithm() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate("1.2.3.4.5", new byte[20]); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + if (tsToken != null) + { + Assert.Fail("badAlgorithm - token not null."); + } + + PkiFailureInfo failInfo = tsResp.GetFailInfo(); + + if (failInfo == null) + { + Assert.Fail("badAlgorithm - failInfo set to null."); + } + + if (failInfo.IntValue != PkiFailureInfo.BadAlg) + { + Assert.Fail("badAlgorithm - wrong failure info returned."); + } + } + + [Test] + public void TestTimeNotAvailable() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate("1.2.3.4.5", new byte[20]); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator( + tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, new BigInteger("23"), null); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + if (tsToken != null) + { + Assert.Fail("timeNotAvailable - token not null."); + } + + PkiFailureInfo failInfo = tsResp.GetFailInfo(); + + if (failInfo == null) + { + Assert.Fail("timeNotAvailable - failInfo set to null."); + } + + if (failInfo.IntValue != PkiFailureInfo.TimeNotAvailable) + { + Assert.Fail("timeNotAvailable - wrong failure info returned."); + } + } + + [Test] + public void TestBadPolicy() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + + reqGen.SetReqPolicy("1.1"); + + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20]); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed, new ArrayList()); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + if (tsToken != null) + { + Assert.Fail("badPolicy - token not null."); + } + + PkiFailureInfo failInfo = tsResp.GetFailInfo(); + + if (failInfo == null) + { + Assert.Fail("badPolicy - failInfo set to null."); + } + + if (failInfo.IntValue != PkiFailureInfo.UnacceptedPolicy) + { + Assert.Fail("badPolicy - wrong failure info returned."); + } + } + + [Test] + public void TestCertReq() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.MD5, "1.2"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + + // + // request with certReq false + // + reqGen.SetCertReq(false); + + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + Assert.IsNull(tsToken.TimeStampInfo.GenTimeAccuracy); // check for abscence of accuracy + + Assert.AreEqual("1.2", tsToken.TimeStampInfo.Policy); + + try + { + tsToken.Validate(cert); + } + catch (TspValidationException) + { + Assert.Fail("certReq(false) verification of token failed."); + } + + IX509Store respCerts = tsToken.GetCertificates("Collection"); + + ICollection certsColl = respCerts.GetMatches(null); + + if (certsColl.Count != 0) + { + Assert.Fail("certReq(false) found certificates in response."); + } + } + + [Test] + public void TestTokenEncoding() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.Sha1, "1.2.3.4.5.6"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampResponse tsResponse = new TimeStampResponse(tsResp.GetEncoded()); + + if (!Arrays.AreEqual(tsResponse.GetEncoded(), tsResp.GetEncoded()) + || !Arrays.AreEqual(tsResponse.TimeStampToken.GetEncoded(), + tsResp.TimeStampToken.GetEncoded())) + { + Assert.Fail(); + } + } + + [Test] + public void TestAccuracyZeroCerts() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.MD5, "1.2"); + + tsTokenGen.SetCertificates(certs); + + tsTokenGen.SetAccuracySeconds(1); + tsTokenGen.SetAccuracyMillis(2); + tsTokenGen.SetAccuracyMicros(3); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + tsToken.Validate(cert); + + // + // check validation + // + tsResp.Validate(request); + + // + // check tstInfo + // + TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo; + + // + // check accuracy + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.AreEqual(1, accuracy.Seconds); + Assert.AreEqual(2, accuracy.Millis); + Assert.AreEqual(3, accuracy.Micros); + + Assert.AreEqual(BigInteger.ValueOf(23), tstInfo.SerialNumber); + + Assert.AreEqual("1.2", tstInfo.Policy); + + // + // test certReq + // + IX509Store store = tsToken.GetCertificates("Collection"); + + ICollection certificates = store.GetMatches(null); + + Assert.AreEqual(0, certificates.Count); + } + + [Test] + public void TestAccuracyWithCertsAndOrdering() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.MD5, "1.2.3"); + + tsTokenGen.SetCertificates(certs); + + tsTokenGen.SetAccuracySeconds(3); + tsTokenGen.SetAccuracyMillis(1); + tsTokenGen.SetAccuracyMicros(2); + + tsTokenGen.SetOrdering(true); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + + reqGen.SetCertReq(true); + + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100)); + + Assert.IsTrue(request.CertReq); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + tsToken.Validate(cert); + + // + // check validation + // + tsResp.Validate(request); + + // + // check tstInfo + // + TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo; + + // + // check accuracy + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.AreEqual(3, accuracy.Seconds); + Assert.AreEqual(1, accuracy.Millis); + Assert.AreEqual(2, accuracy.Micros); + + Assert.AreEqual(BigInteger.ValueOf(23), tstInfo.SerialNumber); + + Assert.AreEqual("1.2.3", tstInfo.Policy); + + Assert.AreEqual(true, tstInfo.IsOrdered); + + Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100)); + + // + // test certReq + // + IX509Store store = tsToken.GetCertificates("Collection"); + + ICollection certificates = store.GetMatches(null); + + Assert.AreEqual(2, certificates.Count); + } + + [Test] + public void TestNoNonce() + { + TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( + privateKey, cert, TspAlgorithms.MD5, "1.2.3"); + + tsTokenGen.SetCertificates(certs); + + TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); + TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20]); + + Assert.IsFalse(request.CertReq); + + TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed); + + TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(24), DateTime.UtcNow); + + tsResp = new TimeStampResponse(tsResp.GetEncoded()); + + TimeStampToken tsToken = tsResp.TimeStampToken; + + tsToken.Validate(cert); + + // + // check validation + // + tsResp.Validate(request); + + // + // check tstInfo + // + TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo; + + // + // check accuracy + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.IsNull(accuracy); + + Assert.AreEqual(BigInteger.ValueOf(24), tstInfo.SerialNumber); + + Assert.AreEqual("1.2.3", tstInfo.Policy); + + Assert.IsFalse(tstInfo.IsOrdered); + + Assert.IsNull(tstInfo.Nonce); + + // + // test certReq + // + IX509Store store = tsToken.GetCertificates("Collection"); + + ICollection certificates = store.GetMatches(null); + + Assert.AreEqual(0, certificates.Count); + } + } +} diff --git a/crypto/test/src/tsp/test/TSPTestUtil.cs b/crypto/test/src/tsp/test/TSPTestUtil.cs new file mode 100644 index 000000000..f7b0c833a --- /dev/null +++ b/crypto/test/src/tsp/test/TSPTestUtil.cs @@ -0,0 +1,200 @@ +using System; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Tsp.Tests +{ + public class TspTestUtil + { + public static SecureRandom rand = new SecureRandom(); + public static IAsymmetricCipherKeyPairGenerator kpg; + public static CipherKeyGenerator desede128kg; + public static CipherKeyGenerator desede192kg; + public static CipherKeyGenerator rc240kg; + public static CipherKeyGenerator rc264kg; + public static CipherKeyGenerator rc2128kg; + public static BigInteger serialNumber = BigInteger.One; + public static readonly bool Debug = true; + public static DerObjectIdentifier EuroPkiTsaTestPolicy = new DerObjectIdentifier("1.3.6.1.4.1.5255.5.1"); + + static TspTestUtil() + { + rand = new SecureRandom(); + + kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); + kpg.Init(new RsaKeyGenerationParameters( + BigInteger.ValueOf(0x10001), rand, 1024, 25)); + + desede128kg = GeneratorUtilities.GetKeyGenerator("DESEDE"); + desede128kg.Init(new KeyGenerationParameters(rand, 112)); + + desede192kg = GeneratorUtilities.GetKeyGenerator("DESEDE"); + desede192kg.Init(new KeyGenerationParameters(rand, 168)); + + rc240kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc240kg.Init(new KeyGenerationParameters(rand, 40)); + + rc264kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc264kg.Init(new KeyGenerationParameters(rand, 64)); + + rc2128kg = GeneratorUtilities.GetKeyGenerator("RC2"); + rc2128kg.Init(new KeyGenerationParameters(rand, 128)); + + serialNumber = BigInteger.One; + } + + public static string DumpBase64( + byte[] data) + { + StringBuilder buf = new StringBuilder(); + + data = Base64.Encode(data); + + for (int i = 0; i < data.Length; i += 64) + { + if (i + 64 < data.Length) + { + buf.Append(Encoding.ASCII.GetString(data, i, 64)); + } + else + { + buf.Append(Encoding.ASCII.GetString(data, i, data.Length - i)); + } + buf.Append('\n'); + } + + return buf.ToString(); + } + + public static AsymmetricCipherKeyPair MakeKeyPair() + { + return kpg.GenerateKeyPair(); + } + + public static KeyParameter MakeDesede128Key() + { + return new DesEdeParameters(desede128kg.GenerateKey()); + } + + public static KeyParameter MakeDesede192Key() + { + return new DesEdeParameters(desede192kg.GenerateKey()); + } + + public static KeyParameter MakeRC240Key() + { + return new RC2Parameters(rc240kg.GenerateKey()); + } + + public static KeyParameter MakeRC264Key() + { + return new RC2Parameters(rc264kg.GenerateKey()); + } + + public static KeyParameter MakeRC2128Key() + { + return new RC2Parameters(rc2128kg.GenerateKey()); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN) + { + return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true); + } + + public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP, + string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca) + { + AsymmetricKeyParameter _subPub = _subKP.Public; + AsymmetricKeyParameter _issPriv = _issKP.Private; + AsymmetricKeyParameter _issPub = _issKP.Public; + + X509V3CertificateGenerator _v3CertGen = new X509V3CertificateGenerator(); + + _v3CertGen.Reset(); + _v3CertGen.SetSerialNumber(allocateSerialNumber()); + _v3CertGen.SetIssuerDN(new X509Name(_issDN)); + _v3CertGen.SetNotBefore(DateTime.UtcNow); + _v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100)); + _v3CertGen.SetSubjectDN(new X509Name(_subDN)); + _v3CertGen.SetPublicKey(_subPub); + _v3CertGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + + _v3CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, + createSubjectKeyId(_subPub)); + + _v3CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, + createAuthorityKeyId(_issPub)); + + if (_ca) + { + _v3CertGen.AddExtension(X509Extensions.BasicConstraints, false, + new BasicConstraints(_ca)); + } + else + { + _v3CertGen.AddExtension(X509Extensions.ExtendedKeyUsage, true, + ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.IdKPTimeStamping))); + } + + X509Certificate _cert = _v3CertGen.Generate(_issPriv); + + _cert.CheckValidity(DateTime.UtcNow); + _cert.Verify(_issPub); + + return _cert; + } + + /* + * + * INTERNAL METHODS + * + */ + private static AuthorityKeyIdentifier createAuthorityKeyId( + AsymmetricKeyParameter _pubKey) + { + return new AuthorityKeyIdentifier( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey)); + } + +// private static AuthorityKeyIdentifier createAuthorityKeyId( +// AsymmetricKeyParameter _pubKey, X509Name _name, int _sNumber) +// { +// SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey); +// +// GeneralName _genName = new GeneralName(_name); +// +// return new AuthorityKeyIdentifier(_info, GeneralNames.GetInstance( +// new DerSequence(_genName)), BigInteger.ValueOf(_sNumber)); +// } + + private static SubjectKeyIdentifier createSubjectKeyId( + AsymmetricKeyParameter _pubKey) + { + return new SubjectKeyIdentifier( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey)); + } + + private static BigInteger allocateSerialNumber() + { + BigInteger _tmp = serialNumber; + serialNumber = serialNumber.Add(BigInteger.One); + return _tmp; + } + } +} \ No newline at end of file diff --git a/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs new file mode 100644 index 000000000..5a26f5ef6 --- /dev/null +++ b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs @@ -0,0 +1,145 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Date; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Tsp.Tests +{ + [TestFixture] + public class TimeStampTokenInfoUnitTest + { + private static readonly byte[] tstInfo1 = Hex.Decode( + "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000" + + "020118180f32303035313130313038313732315a"); + + private static readonly byte[] tstInfo2 = Hex.Decode( + "304c02010106022a033021300906052b0e03021a05000414ffffffffffffffffffffffffffffffffffffffff" + + "020117180f32303035313130313038323934355a3009020103800101810102020164"); + + private static readonly byte[] tstInfo3 = Hex.Decode( + "304f02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000" + + "020117180f32303035313130313038343733355a30090201038001018101020101ff020164"); + + private static readonly byte[] tstInfoDudDate = Hex.Decode( + "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000" + + "020118180f32303056313130313038313732315a"); + + [Test] + public void TestTstInfo1() + { + TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo1); + + // + // verify + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.IsNull(accuracy); + + Assert.AreEqual(new BigInteger("24"), tstInfo.SerialNumber); + + Assert.AreEqual(1130833041000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime)); + + Assert.AreEqual("1.2.3", tstInfo.Policy); + + Assert.AreEqual(false, tstInfo.IsOrdered); + + Assert.IsNull(tstInfo.Nonce); + + Assert.AreEqual(TspAlgorithms.Sha1, tstInfo.MessageImprintAlgOid); + + Assert.IsTrue(Arrays.AreEqual(new byte[20], tstInfo.GetMessageImprintDigest())); + + Assert.IsTrue(Arrays.AreEqual(tstInfo1, tstInfo.GetEncoded())); + } + + [Test] + public void TestTstInfo2() + { + TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo2); + + // + // verify + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.AreEqual(3, accuracy.Seconds); + Assert.AreEqual(1, accuracy.Millis); + Assert.AreEqual(2, accuracy.Micros); + + Assert.AreEqual(new BigInteger("23"), tstInfo.SerialNumber); + + Assert.AreEqual(1130833785000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime)); + + Assert.AreEqual("1.2.3", tstInfo.Policy); + + Assert.AreEqual(false, tstInfo.IsOrdered); + + Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100)); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("ffffffffffffffffffffffffffffffffffffffff"), tstInfo.GetMessageImprintDigest())); + + Assert.IsTrue(Arrays.AreEqual(tstInfo2, tstInfo.GetEncoded())); + } + + [Test] + public void TestTstInfo3() + { + TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo3); + + // + // verify + // + GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy; + + Assert.AreEqual(3, accuracy.Seconds); + Assert.AreEqual(1, accuracy.Millis); + Assert.AreEqual(2, accuracy.Micros); + + Assert.AreEqual(new BigInteger("23"), tstInfo.SerialNumber); + + Assert.AreEqual(1130834855000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime)); + + Assert.AreEqual("1.2.3", tstInfo.Policy); + + Assert.AreEqual(true, tstInfo.IsOrdered); + + Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100)); + + Assert.AreEqual(TspAlgorithms.Sha1, tstInfo.MessageImprintAlgOid); + + Assert.IsTrue(Arrays.AreEqual(new byte[20], tstInfo.GetMessageImprintDigest())); + + Assert.IsTrue(Arrays.AreEqual(tstInfo3, tstInfo.GetEncoded())); + } + + [Test] + public void TestTstInfoDudDate() + { + try + { + getTimeStampTokenInfo(tstInfoDudDate); + + Assert.Fail("dud date not detected."); + } + catch (TspException) + { + // expected + } + } + + private TimeStampTokenInfo getTimeStampTokenInfo( + byte[] tstInfo) + { + return new TimeStampTokenInfo( + TstInfo.GetInstance( + Asn1Object.FromByteArray(tstInfo))); + } + } +} diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs new file mode 100644 index 000000000..b44949383 --- /dev/null +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Text; + +using NUnit.Core; +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Utilities.IO.Pem.Tests +{ + [TestFixture] + public class AllTests + { + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("PEM Utilities Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] + public void TestPemLength() + { + for (int i = 1; i != 60; i++) + { + lengthTest("CERTIFICATE", new ArrayList(), new byte[i]); + } + + lengthTest("CERTIFICATE", new ArrayList(), new byte[100]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[101]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[102]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[103]); + + lengthTest("CERTIFICATE", new ArrayList(), new byte[1000]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[1001]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[1002]); + lengthTest("CERTIFICATE", new ArrayList(), new byte[1003]); + + IList 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, IList headers, byte[] data) + { + StringWriter sw = new StringWriter(); + PemWriter pWrt = new PemWriter(sw); + + PemObject pemObj = new PemObject(type, headers, data); + pWrt.WriteObject(pemObj); + pWrt.Writer.Close(); + + Assert.AreEqual(sw.ToString().Length, pWrt.GetOutputSize(pemObj)); + } + + public static void Main( + string[] args) + { + //junit.textui.TestRunner.run(suite()); + EventListener el = new NullListener(); + Suite.Run(el); + } + } +} diff --git a/crypto/test/src/util/net/test/IPAddressTest.cs b/crypto/test/src/util/net/test/IPAddressTest.cs new file mode 100644 index 000000000..ec40c528a --- /dev/null +++ b/crypto/test/src/util/net/test/IPAddressTest.cs @@ -0,0 +1,61 @@ +using System; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Utilities.Net.Tests +{ + [TestFixture] + public class IPTest + { + private static readonly string[] validIP4v = new string[] + { "0.0.0.0", "255.255.255.255", "192.168.0.0" }; + + private static readonly string[] invalidIP4v = new string[] + { "0.0.0.0.1", "256.255.255.255", "1", "A.B.C", "1:.4.6.5" }; + + private static readonly 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 readonly string[] invalidIP6v = new string[] + { "0.0.0.0:1", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFF" }; + + private void doTestIP( + string[] valid, + string[] invalid) + { + for (int i = 0; i < valid.Length; i++) + { + if (!IPAddress.IsValid(valid[i])) + { + Assert.Fail("Valid input string not accepted: " + valid[i] + "."); + } + } + + for (int i = 0; i < invalid.Length; i++) + { + if (IPAddress.IsValid(invalid[i])) + { + Assert.Fail("Invalid input string accepted: " + invalid[i] + "."); + } + } + } + + public string Name + { + get { return "IPTest"; } + } + + [Test] + public void TestIPv4() + { + doTestIP(validIP4v, invalidIP4v); + } + + [Test] + public void TestIPv6() + { + doTestIP(validIP6v, invalidIP6v); + } + } +} diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs new file mode 100644 index 000000000..15a2e9bb3 --- /dev/null +++ b/crypto/test/src/util/test/FixedSecureRandom.cs @@ -0,0 +1,64 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Utilities.Test +{ + public class FixedSecureRandom + : SecureRandom + { + private byte[] _data; + private int _index; + + protected FixedSecureRandom( + byte[] data) + { + _data = data; + } + + public static FixedSecureRandom From( + params byte[][] values) + { + MemoryStream bOut = new MemoryStream(); + + for (int i = 0; i != values.Length; i++) + { + try + { + byte[] v = values[i]; + bOut.Write(v, 0, v.Length); + } + catch (IOException) + { + throw new ArgumentException("can't save value array."); + } + } + + return new FixedSecureRandom(bOut.ToArray()); + } + + public override void NextBytes( + byte[] buf) + { + Array.Copy(_data, _index, buf, 0, buf.Length); + + _index += buf.Length; + } + + public override void NextBytes( + byte[] buf, + int off, + int len) + { + Array.Copy(_data, _index, buf, off, len); + + _index += len; + } + + public bool IsExhausted + { + get { return _index == _data.Length; } + } + } +} diff --git a/crypto/test/src/util/test/ITest.cs b/crypto/test/src/util/test/ITest.cs new file mode 100644 index 000000000..30ad82780 --- /dev/null +++ b/crypto/test/src/util/test/ITest.cs @@ -0,0 +1,17 @@ +using System; + +using NUnit.Framework; + +/* + Basic test interface + */ +namespace Org.BouncyCastle.Utilities.Test +{ + public interface ITest + { + string Name { get; } + + [Test] + ITestResult Perform(); + } +} diff --git a/crypto/test/src/util/test/ITestResult.cs b/crypto/test/src/util/test/ITestResult.cs new file mode 100644 index 000000000..25f0442de --- /dev/null +++ b/crypto/test/src/util/test/ITestResult.cs @@ -0,0 +1,13 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Test +{ + public interface ITestResult + { + bool IsSuccessful(); + + Exception GetException(); + + string ToString(); + } +} diff --git a/crypto/test/src/util/test/NumberParsing.cs b/crypto/test/src/util/test/NumberParsing.cs new file mode 100644 index 000000000..f9624ef0a --- /dev/null +++ b/crypto/test/src/util/test/NumberParsing.cs @@ -0,0 +1,40 @@ +using System; +using System.Globalization; + +namespace Org.BouncyCastle.Utilities.Test +{ + /** + * Parsing + */ + public sealed class NumberParsing + { + private NumberParsing() + { + // Hide constructor + } + + public static long DecodeLongFromHex( + string longAsString) + { + if ((longAsString[1] == 'x') + || (longAsString[1] == 'X')) + { + longAsString = longAsString.Substring(2); + } + + return long.Parse(longAsString, NumberStyles.HexNumber); + } + + public static int DecodeIntFromHex( + string intAsString) + { + if ((intAsString[1] == 'x') + || (intAsString[1] == 'X')) + { + intAsString = intAsString.Substring(2); + } + + return int.Parse(intAsString, NumberStyles.HexNumber); + } + } +} diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs new file mode 100644 index 000000000..be846e20f --- /dev/null +++ b/crypto/test/src/util/test/SimpleTest.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections; +using System.IO; +using System.Reflection; +using System.Text; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Utilities.Test +{ + public abstract class SimpleTest + : ITest + { + public abstract string Name + { + get; + } + + private ITestResult Success() + { + return SimpleTestResult.Successful(this, "Okay"); + } + + internal void Fail( + string message) + { + throw new TestFailedException(SimpleTestResult.Failed(this, message)); + } + + internal void Fail( + string message, + Exception throwable) + { + throw new TestFailedException(SimpleTestResult.Failed(this, message, throwable)); + } + + internal void Fail( + string message, + object expected, + object found) + { + throw new TestFailedException(SimpleTestResult.Failed(this, message, expected, found)); + } + + internal bool AreEqual( + byte[] a, + byte[] b) + { + return Arrays.AreEqual(a, b); + } + + public virtual ITestResult Perform() + { + try + { + PerformTest(); + + return Success(); + } + catch (TestFailedException e) + { + return e.GetResult(); + } + catch (Exception e) + { + return SimpleTestResult.Failed(this, "Exception: " + e, e); + } + } + + internal static void RunTest( + ITest test) + { + RunTest(test, Console.Out); + } + + internal static void RunTest( + ITest test, + TextWriter outStream) + { + ITestResult result = test.Perform(); + + outStream.WriteLine(result.ToString()); + if (result.GetException() != null) + { + outStream.WriteLine(result.GetException().StackTrace); + } + } + + internal static Stream GetTestDataAsStream( + string name) + { + string fullName = GetFullName(name); + + return Assembly.GetExecutingAssembly().GetManifestResourceStream(fullName); + } + + internal static string[] GetTestDataEntries( + string prefix) + { + string fullPrefix = GetFullName(prefix); + + ArrayList result = new ArrayList(); + string[] fullNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); + foreach (string fullName in fullNames) + { + if (fullName.StartsWith(fullPrefix)) + { + string name = GetShortName(fullName); + result.Add(name); + } + } + return (string[])result.ToArray(typeof(String)); + } + + private static string GetFullName( + string name) + { +// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent +#if BC_BUILD_MONODEVELOP + return "test.data." + name; +#else + return "crypto.test.data." + name; +#endif + } + + private static string GetShortName( + string fullName) + { +// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent +#if BC_BUILD_MONODEVELOP + return fullName.Substring("test.data.".Length); +#else + return fullName.Substring("crypto.test.data.".Length); +#endif + } + +#if NETCF_1_0 || NETCF_2_0 + private static string GetNewLine() + { + MemoryStream buf = new MemoryStream(); + StreamWriter w = new StreamWriter(buf, Encoding.ASCII); + w.WriteLine(); + w.Close(); + byte[] bs = buf.ToArray(); + return Encoding.ASCII.GetString(bs, 0, bs.Length); + } + + internal static string GetEnvironmentVariable( + string variable) + { + return null; + } +#else + private static string GetNewLine() + { + return Environment.NewLine; + } +#endif + + internal static readonly string NewLine = GetNewLine(); + + public abstract void PerformTest(); + } +} diff --git a/crypto/test/src/util/test/SimpleTestResult.cs b/crypto/test/src/util/test/SimpleTestResult.cs new file mode 100644 index 000000000..294f575b7 --- /dev/null +++ b/crypto/test/src/util/test/SimpleTestResult.cs @@ -0,0 +1,91 @@ +using System; +using System.Text; + +namespace Org.BouncyCastle.Utilities.Test +{ + public class SimpleTestResult : ITestResult + { + private static readonly string Separator = SimpleTest.NewLine; + + private bool success; + private string message; + private Exception exception; + + public SimpleTestResult( + bool success, + string message) + { + this.success = success; + this.message = message; + } + + public SimpleTestResult( + bool success, + string message, + Exception exception) + { + this.success = success; + this.message = message; + this.exception = exception; + } + + public static ITestResult Successful( + ITest test, + string message) + { + return new SimpleTestResult(true, test.Name + ": " + message); + } + + public static ITestResult Failed( + ITest test, + string message) + { + return new SimpleTestResult(false, test.Name + ": " + message); + } + + public static ITestResult Failed( + ITest test, + string message, + Exception t) + { + return new SimpleTestResult(false, test.Name + ": " + message, t); + } + + public static ITestResult Failed( + ITest 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) + { + StringBuilder sb = new StringBuilder(algorithm); + sb.Append(" failing ").Append(testName); + sb.Append(Separator).Append(" expected: ").Append(expected); + sb.Append(Separator).Append(" got : ").Append(actual); + return sb.ToString(); + } + + public bool IsSuccessful() + { + return success; + } + + public override string ToString() + { + return message; + } + + public Exception GetException() + { + return exception; + } + } +} diff --git a/crypto/test/src/util/test/TestFailedException.cs b/crypto/test/src/util/test/TestFailedException.cs new file mode 100644 index 000000000..ecd7e7d7a --- /dev/null +++ b/crypto/test/src/util/test/TestFailedException.cs @@ -0,0 +1,24 @@ +using System; + +namespace Org.BouncyCastle.Utilities.Test +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class TestFailedException + : Exception + { + private ITestResult _result; + + public TestFailedException( + ITestResult result) + { + _result = result; + } + + public ITestResult GetResult() + { + return _result; + } + } +} diff --git a/crypto/test/src/util/test/UncloseableStream.cs b/crypto/test/src/util/test/UncloseableStream.cs new file mode 100644 index 000000000..8b592cdd4 --- /dev/null +++ b/crypto/test/src/util/test/UncloseableStream.cs @@ -0,0 +1,22 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.Utilities; + +namespace Org.BouncyCastle.Utilities.Test +{ + public class UncloseableStream + : FilterStream + { + public UncloseableStream( + Stream s) + : base(s) + { + } + + public override void Close() + { + throw new Exception("Close() called on UncloseableStream"); + } + } +} diff --git a/crypto/test/src/x509/test/TestCertificateGen.cs b/crypto/test/src/x509/test/TestCertificateGen.cs new file mode 100644 index 000000000..8ec5929c7 --- /dev/null +++ b/crypto/test/src/x509/test/TestCertificateGen.cs @@ -0,0 +1,715 @@ +using System; +using System.Collections; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities.Collections; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.X509.Tests +{ + [TestFixture] + public class TestCertificateGen + { + public TestCertificateGen() + { + } + + [Test] + public void TestRsaDigestSigner() + { + 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.BlockUpdate(msg, 0, msg.Length); + byte[] sig = signer.GenerateSignature(); + + signer.Init(false,rsaPublic); + signer.BlockUpdate(msg, 0, msg.Length); + Assert.IsTrue(signer.VerifySignature(sig), "RSA IDigest Signer failed."); + } + + [Test] + public void TestCreationRSA() + { + 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); + + IDictionary attrs = new Hashtable(); + attrs[X509Name.C] = "AU"; + attrs[X509Name.O] = "The Legion of the Bouncy Castle"; + attrs[X509Name.L] = "Melbourne"; + attrs[X509Name.ST] = "Victoria"; + attrs[X509Name.E] = "feedback-crypto@bouncycastle.org"; + + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + + certGen.SetIssuerDN(new X509Name(ord, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1)); + certGen.SetNotAfter(DateTime.UtcNow.AddDays(1)); + certGen.SetSubjectDN(new X509Name(ord, attrs)); + certGen.SetPublicKey(rsaPublic); + certGen.SetSignatureAlgorithm("MD5WithRSAEncryption"); + + X509Certificate cert = certGen.Generate(rsaPrivate); + +// Assert.IsTrue((cert.IsValidNow && cert.Verify(rsaPublic)),"Certificate failed to be valid (RSA)"); + cert.CheckValidity(); + cert.Verify(rsaPublic); + + //Console.WriteLine(ASN1Dump.DumpAsString(cert.ToAsn1Object())); + + //ISet dummySet = cert.GetNonCriticalExtensionOids(); + + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + + //dummySet = cert.GetNonCriticalExtensionOids(); + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + } + + [Test] + public void TestCreationDSA() + { + BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM=")); + BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs=")); + BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx")); + BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw==")); + BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A=")); + + DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG); + DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para); + DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para); + + IDictionary attrs = new Hashtable(); + attrs[X509Name.C] = "AU"; + attrs[X509Name.O] = "The Legion of the Bouncy Castle"; + attrs[X509Name.L] = "Melbourne"; + attrs[X509Name.ST] = "Victoria"; + attrs[X509Name.E] = "feedback-crypto@bouncycastle.org"; + + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + + certGen.SetIssuerDN(new X509Name(ord, attrs)); + certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1)); + certGen.SetNotAfter(DateTime.UtcNow.AddDays(1)); + certGen.SetSubjectDN(new X509Name(ord, attrs)); + certGen.SetPublicKey(dsaPub); + certGen.SetSignatureAlgorithm("SHA1WITHDSA"); + + X509Certificate cert = certGen.Generate(dsaPriv); + +// Assert.IsTrue((cert.IsValidNow && cert.Verify(dsaPub)), "Certificate failed to be valid (DSA Test)"); + cert.CheckValidity(); + cert.Verify(dsaPub); + + //ISet dummySet = cert.GetNonCriticalExtensionOids(); + + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + + //dummySet = cert.GetNonCriticalExtensionOids(); + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + } + + [Test] + public void TestCreationECDSA() + { + BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv")); + BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R")); + BigInteger ECParraH = new BigInteger(Base64.Decode("AQ==")); + BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L")); + BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l")); + BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx")); + BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo")); + FpCurve curve = new FpCurve( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + ECDomainParameters ecDomain = + new ECDomainParameters(curve, new FpPoint(curve, curve.FromBigInteger(ECParraGX), curve.FromBigInteger(ECParraGY)), ECParraN); + ECPublicKeyParameters ecPub = new ECPublicKeyParameters( + "ECDSA", + new FpPoint(curve, + curve.FromBigInteger(ECPubQX), + curve.FromBigInteger(ECPubQY)), + ecDomain); + ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters("ECDSA", ECPrivD, ecDomain); + + + IDictionary attrs = new Hashtable(); + attrs[X509Name.C] = "AU"; + attrs[X509Name.O] = "The Legion of the Bouncy Castle"; + attrs[X509Name.L] = "Melbourne"; + attrs[X509Name.ST] = "Victoria"; + attrs[X509Name.E] = "feedback-crypto@bouncycastle.org"; + + IList ord = new ArrayList(); + ord.Add(X509Name.C); + ord.Add(X509Name.O); + ord.Add(X509Name.L); + ord.Add(X509Name.ST); + ord.Add(X509Name.E); + + IList values = new ArrayList(); + values.Add("AU"); + values.Add("The Legion of the Bouncy Castle"); + values.Add("Melbourne"); + values.Add("Victoria"); + values.Add("feedback-crypto@bouncycastle.org"); + + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.SetSerialNumber(BigInteger.One); + + certGen.SetIssuerDN(new X509Name(ord, attrs)); + certGen.SetNotBefore(DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0))); + certGen.SetNotAfter(DateTime.Today.AddDays(1)); + certGen.SetSubjectDN(new X509Name(ord, attrs)); + certGen.SetPublicKey(ecPub); + certGen.SetSignatureAlgorithm("SHA1WITHECDSA"); + + + X509Certificate cert = certGen.Generate(ecPriv); + +// Assert.IsTrue((cert.IsValidNow && cert.Verify(ecPub)), "Certificate failed to be valid (ECDSA)"); + cert.CheckValidity(); + cert.Verify(ecPub); + + //ISet dummySet = cert.GetNonCriticalExtensionOids(); + + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + + //dummySet = cert.GetNonCriticalExtensionOids(); + + //if (dummySet != null) + //{ + // foreach (string key in dummySet) + // { + // Console.WriteLine("\t{0}:\t{1}", key); + // } + //} + + //Console.WriteLine(); + } + + [Test] + public void TestCertLoading() + { + 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="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert1)); + } + catch (Exception) + { + Assert.Fail("Reading first test certificate."); + } + + + // 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=="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert2)); + } + catch (Exception) + { + Assert.Fail("Reading second test certificate."); + } + + + // + // testx509.pem + // + byte[] cert3 = Base64.Decode( + "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" + + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" + + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" + + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" + + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" + + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" + + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" + + "zl9HYIMxATFyqSiD9jsx"); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert3)); + } + catch (Exception) + { + Assert.Fail("Reading third test certificate. (X509.pem)"); + } + + + // + // 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"); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert4)); + } + catch (Exception) + { + Assert.Fail("Reading fourth test certificate. (X509 V3 Pem)"); + } + + + // + // 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="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert5)); + } + catch (Exception) + { + Assert.Fail("Reading fifth test certificate. (X509 V3 Pem)"); + } + + + // + // pem encoded pkcs7 + // + byte[] cert6 = Base64.Decode( + "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w" + + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG" + + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy" + + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw" + + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi" + + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A" + + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH" + + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF" + + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d" + + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix" + + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR" + + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD" + + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj" + + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy" + + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy" + + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j" + + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg" + + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B" + + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB" + + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc" + + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG" + + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv" + + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B" + + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0" + + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg" + + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ" + + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln" + + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB" + + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx" + + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy" + + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD" + + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl" + + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz" + + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m" + + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb" + + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK" + + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB" + + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0" + + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo" + + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB" + + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R" + + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y" + + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j" + + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu" + + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE" + + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg" + + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG" + + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU" + + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG" + + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w" + + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O" + + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy" + + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA=="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert6)); + } + catch (Exception) + { + Assert.Fail("Reading sixth test certificate. (Pkcs7)"); + } + + + // + // dsaWithSHA1 cert + // + byte[] cert7 = Base64.Decode( + "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7" + + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh" + + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj" + + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z" + + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa" + + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw" + + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj" + + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE" + + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3" + + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn" + + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc" + + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg" + + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q" + + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH" + + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC" + + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC" + + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY" + + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1" + + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ" + + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T" + + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU" + + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji" + + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID" + + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh" + + "cg=="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert7)); + } + catch (Exception) + { + Assert.Fail("Reading seventh test certificate. (DSAWITHSHA1)"); + } + + + // + // ecdsa cert with extra octet string. + // + byte[] oldEcdsa = Base64.Decode( + "MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ" + + "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw" + + "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV" + + "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w" + + "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb" + + "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ" + + "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5" + + "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///" + + "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////" + + "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/" + + "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq" + + "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw" + + "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G" + + "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR"); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(oldEcdsa)); + } + catch (Exception) + { + Assert.Fail("Reading old ECDSA Certificate."); + } + + + byte[] uncompressedPtEC = Base64.Decode( + "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ" + + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD" + + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw" + + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK" + + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G" + + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0" + + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ" + + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT" + + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2" + + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7" + + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA" + + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD" + + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn" + + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH" + + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB" + + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI" + + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt" + + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD" + + "z+fauEg="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(uncompressedPtEC)); + } + catch (Exception) + { + Assert.Fail("Reading uncompressed ECPoint Certificate."); + } + + + byte[] keyUsage = Base64.Decode( + "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE" + + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50" + + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs" + + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp" + + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0" + + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa" + + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV" + + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw" + + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50" + + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL" + + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv" + + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV" + + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173" + + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw" + + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50" + + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff" + + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE" + + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50" + + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD" + + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D" + + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx" + + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW" + + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG" + + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI" + + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ" + + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU" + + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE" + + "PHayXOw="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(keyUsage)); + } + catch (Exception) + { + Assert.Fail("Reading Cert with Key Usage."); + } + + + byte[] nameCert = Base64.Decode( + "MIIEFjCCA3+gAwIBAgIEdS8BozANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJE" + + "RTERMA8GA1UEChQIREFURVYgZUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRQ0Eg" + + "REFURVYgRDAzIDE6UE4wIhgPMjAwMTA1MTAxMDIyNDhaGA8yMDA0MDUwOTEwMjI0" + + "OFowgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIFAZCYXllcm4xEjAQBgNVBAcUCU7I" + + "dXJuYmVyZzERMA8GA1UEChQIREFURVYgZUcxHTAbBgNVBAUTFDAwMDAwMDAwMDA4" + + "OTU3NDM2MDAxMR4wHAYDVQQDFBVEaWV0bWFyIFNlbmdlbmxlaXRuZXIwgaEwDQYJ" + + "KoZIhvcNAQEBBQADgY8AMIGLAoGBAJLI/LJLKaHoMk8fBECW/od8u5erZi6jI8Ug" + + "C0a/LZyQUO/R20vWJs6GrClQtXB+AtfiBSnyZOSYzOdfDI8yEKPEv8qSuUPpOHps" + + "uNCFdLZF1vavVYGEEWs2+y+uuPmg8q1oPRyRmUZ+x9HrDvCXJraaDfTEd9olmB/Z" + + "AuC/PqpjAgUAwAAAAaOCAcYwggHCMAwGA1UdEwEB/wQCMAAwDwYDVR0PAQH/BAUD" + + "AwdAADAxBgNVHSAEKjAoMCYGBSskCAEBMB0wGwYIKwYBBQUHAgEWD3d3dy56cy5k" + + "YXRldi5kZTApBgNVHREEIjAggR5kaWV0bWFyLnNlbmdlbmxlaXRuZXJAZGF0ZXYu" + + "ZGUwgYQGA1UdIwR9MHuhc6RxMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1" + + "bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0" + + "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE6CBACm8LkwDgYHAoIG" + + "AQoMAAQDAQEAMEcGA1UdHwRAMD4wPKAUoBKGEHd3dy5jcmwuZGF0ZXYuZGWiJKQi" + + "MCAxCzAJBgNVBAYTAkRFMREwDwYDVQQKFAhEQVRFViBlRzAWBgUrJAgDBAQNMAsT" + + "A0VVUgIBBQIBATAdBgNVHQ4EFgQUfv6xFP0xk7027folhy+ziZvBJiwwLAYIKwYB" + + "BQUHAQEEIDAeMBwGCCsGAQUFBzABhhB3d3cuZGlyLmRhdGV2LmRlMA0GCSqGSIb3" + + "DQEBBQUAA4GBAEOVX6uQxbgtKzdgbTi6YLffMftFr2mmNwch7qzpM5gxcynzgVkg" + + "pnQcDNlm5AIbS6pO8jTCLfCd5TZ5biQksBErqmesIl3QD+VqtB+RNghxectZ3VEs" + + "nCUtcE7tJ8O14qwCb3TxS9dvIUFiVi4DjbxX46TdcTbTaK8/qr6AIf+l"); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(nameCert)); + } + catch (Exception) + { + Assert.Fail("Reading Named Certificate."); + } + + + byte[] probSelfSignedCert = Base64.Decode( + "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF" + + "MScwJQYDVQQKEx4gRElSRUNUSU9OIEdFTkVSQUxFIERFUyBJTVBPVFMxGjAYBgNV" + + "BAMTESBBQyBNSU5FRkkgQiBURVNUMB4XDTA0MDUwNzEyMDAwMFoXDTE0MDUwNzEy" + + "MDAwMFowRTEnMCUGA1UEChMeIERJUkVDVElPTiBHRU5FUkFMRSBERVMgSU1QT1RT" + + "MRowGAYDVQQDExEgQUMgTUlORUZJIEIgVEVTVDCBnzANBgkqhkiG9w0BAQEFAAOB" + + "jQAwgYkCgYEAveoCUOAukZdcFCs2qJk76vSqEX0ZFzHqQ6faBPZWjwkgUNwZ6m6m" + + "qWvvyq1cuxhoDvpfC6NXILETawYc6MNwwxsOtVVIjuXlcF17NMejljJafbPximEt" + + "DQ4LcQeSp4K7FyFlIAMLyt3BQ77emGzU5fjFTvHSUNb3jblx0sV28c0CAwEAAaOB" + + "tTCBsjAfBgNVHSMEGDAWgBSEJ4bLbvEQY8cYMAFKPFD1/fFXlzAdBgNVHQ4EFgQU" + + "hCeGy27xEGPHGDABSjxQ9f3xV5cwDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIB" + + "AQQEAwIBBjA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vYWRvbmlzLnBrNy5jZXJ0" + + "cGx1cy5uZXQvZGdpLXRlc3QuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" + + "AQEFBQADgYEAmToHJWjd3+4zknfsP09H6uMbolHNGG0zTS2lrLKpzcmkQfjhQpT9" + + "LUTBvfs1jdjo9fGmQLvOG+Sm51Rbjglb8bcikVI5gLbclOlvqLkm77otjl4U4Z2/" + + "Y0vP14Aov3Sn3k+17EfReYUZI4liuB95ncobC4e8ZM++LjQcIM0s+Vs="); + + try + { + Assert.IsNotNull(new X509CertificateParser().ReadCertificate(probSelfSignedCert)); + } + catch (Exception) + { + Assert.Fail("Reading busted Certificate."); + } + } + } +} diff --git a/crypto/testcfg.nunit b/crypto/testcfg.nunit new file mode 100644 index 000000000..e4061da06 --- /dev/null +++ b/crypto/testcfg.nunit @@ -0,0 +1,6 @@ + + + + + + diff --git a/csharp.mds b/csharp.mds new file mode 100644 index 000000000..7e0c099dd --- /dev/null +++ b/csharp.mds @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp.sln b/csharp.sln new file mode 100644 index 000000000..ce64a084a --- /dev/null +++ b/csharp.sln @@ -0,0 +1,29 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "crypto", "crypto\crypto.csproj", "{38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "crypto-test", "crypto-test\crypto-test.csproj", "{C857AD68-8F1B-4C7A-A76B-3DC03CBE4FB0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}.Debug.ActiveCfg = Debug|.NET + {38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}.Debug.Build.0 = Debug|.NET + {38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}.Release.ActiveCfg = Release|.NET + {38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}.Release.Build.0 = Release|.NET + {C857AD68-8F1B-4C7A-A76B-3DC03CBE4FB0}.Debug.ActiveCfg = Debug|.NET + {C857AD68-8F1B-4C7A-A76B-3DC03CBE4FB0}.Debug.Build.0 = Debug|.NET + {C857AD68-8F1B-4C7A-A76B-3DC03CBE4FB0}.Release.ActiveCfg = Release|.NET + {C857AD68-8F1B-4C7A-A76B-3DC03CBE4FB0}.Release.Build.0 = Release|.NET + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal -- cgit 1.4.1